函数调用:将您的GPT聊天机器人与任何内容集成
#教程 #python #ai #chatgpt

是的,我们做!

想象一下创建一个AI助手,您可以说“给我预订最近的泰国餐厅并更新我的日历”。语言模型继续推动界限并发展。 Chatgpt背后的公司Openai最近在其GPT车型中推出了一项功能强大的新功能,名为function calling。函数调用简化了与外部工具和API通信的聊天机器人的创建,为AI驱动的应用程序开辟了一个新的可能性领域。

在本文中,我们将深入研究函数呼叫的概念,其含义以及它通过创建 newsgpt 与AI系统互动的变革性影响,这是一个聊天机器人,它使您在全球范围内打破新闻。

Example run of NewsGPT. A command line interface shows the user asking, "What's the latest news in the US?" and receiving a list of five articles with links to the journals or sources.
新闻网的示例。命令行界面显示用户询问:“美国最新消息是什么?”并收到五篇文章的列表,其中链接到期刊或来源。

什么是函数调用?

函数调用是OpenAI的 GPT-4-0613 GPT-3.5 Turbo-0613 模型中的新功能。对这些AI模型进行了培训,以根据用户的提示检测功能呼叫的需求,并使用结构化的呼叫请求而不是常规文本响应。

函数调用允许聊天机器人与其他系统进行交互,从而使GPT模型能够回答他们原本无法的问题,例如那些需要实时信息或未包含在培训集中的数据的问题。换句话说,函数调用提供了另一种方法教AI模型如何与外部世界互动

函数调用的目的是什么?

在函数调用之前,只有两种方法可以增强GPT语言模型的功能:

  • 微调:通过提供示例响应来进一步培训语言模型。 Fine-tuning是一种强大的技术,但是准备培训数据需要大量工作(和成本)。此外,只有少数旧型号可以进行微调,直到OpenAI在GPT-3.5和GPT-4型号中启用此功能。
  • 嵌入enriching the prompt with context data可以扩展机器人的知识并创造更准确的响应。不利的一面是,这种环境可以占用大量令牌,增加成本,并为建立复杂的响应提供更少的代币。

函数调用添加了第三种扩展GPT功能的方法,它可以要求我们代表其运行功能。然后,该模型可以取得函数的结果并构建可读的响应,该响应无缝地适合当前对话。

如何使用函数调用

函数调用的引入改变了我们与GPT API互动的方式。在这些功能之前,相互作用很简单:

  1. 向API发送提示。
  2. 收到答复。
  3. 重复。

A diagram showing the basic interaction with the GPT API before function calling.
在函数调用之前,显示了与GPT API的基本相互作用的图。

随着函数调用,序列变得更加参与:

  1. 发送用户提示以及可召唤功能的列表。
  2. GPT模型以常规文本响应或功能调用请求的响应。
  3. 如果模型请求函数调用,则您的聊天机器人的工作是执行并将结果返回到API。
  4. 使用提供的数据,该模型然后形成一个连贯的文本响应。但是,在某些情况下,API可能会请求新功能调用。

A diagram showing the more complex interaction with the GPT API using function calling.
使用函数调用函数的图显示了与GPT API的更复杂交互的图。

使用聊天完成API调用功能

要允许模型调用功能,我们必须使用Chat Completions API。 API使用JSON有效载荷采用后请求,其中包含要处理的消息列表。发送给API的典型提示如下:

{
 "model": "gpt-3.5-turbo",
 "messages": [
 {
 "role": "user",
 "content": "How many planets does the solar system have?"
 }
 ]
}

role: user告知API content是用户生成的。 GPT API可能会沿着这些行回答:

{
   "id":"chatcmpl-7WVo3fYwerpAptzeqU46JamOvgBzh",
   "object":"chat.completion",
   "created":1687983115,
   "model":"gpt-3.5-turbo-0613",
   "choices":[
      {
         "index":0,
         "message":{
            "role":"assistant",
            "content":"There are eight planets in the solar system. They are:\n\n1. Mercury\n2. Venus\n3. Earth\n4. Mars\n5. Jupiter\n6. Saturn\n7. Uranus\n8. Neptune"
         },
         "finish_reason":"stop"
      }
   ],
   "usage":{
      "prompt_tokens":15,
      "completion_tokens":44,
      "total_tokens":59
   }
}

role: assistant对应于GPT模型生成的消息。为了保持对话流,我们必须在每个请求上向API提供整个消息历史记录。例如,如果我们想深入研究我们的上一个问题,相应的JSON有效载荷将是:

{
   "model":"gpt-3.5-turbo",
   "messages":[
      {
         "role":"user",
         "content":"How many planets does the solar system have?"
      },
      {
         "role":"assistant",
         "content":"There are eight planets in the solar system. They are:\n\n1. Mercury\n2. Venus\n3. Earth\n4. Mars\n5. Jupiter\n6. Saturn\n7. Uranus\n8. Neptune"
      },
      {
         "role":"user",
         "content":"Tell me more about the second planet."
      }
   ]
}

要让语言模型知道它可以调用函数,我们需要在有效载荷中添加它们的列表。例如:

{
   "model":"gpt-3.5-turbo-0613",
   "messages":[
      {
         "role":"user",
         "content":"How is the weather in NYC?"
      }
   ],
   "functions":[
      {
         "name":"get_current_weather",
         "description":"Get the current weather in a given location",
         "parameters":{
            "type":"object",
            "properties":{
               "location":{
                  "type":"string",
                  "description":"The city and state, e.g. San Francisco, CA"
               },
               "unit":{
                  "type":"string",
                  "enum":[
                     "celsius",
                     "fahrenheit"
                  ]
               }
            },
            "required":[
               "location"
            ]
         }
      }
   ]
}

您可能已经注意到,我们将模型切换为“ GPT-3.5-Turbo-0613”,因为它支持函数调用。如果该模型决定调用该函数,我们将收到类型role: assistant的响应,该响应像这样定义了function_call属性:

{
   "id":"chatcmpl-7WWG94C1DCFlAk5xmUwrZ9OOhFnOq",
   "object":"chat.completion",
   "created":1687984857,
   "model":"gpt-3.5-turbo-0613",
   "choices":[
      {
         "index":0,
         "message":{
            "role":"assistant",
            "content":null,
            "function_call":{
               "name":"get_current_weather",
               "arguments":"{\n \"location\": \"New York, NY\"\n}"
            }
         },
         "finish_reason":"function_call"
      }
   ],
   "usage":{
      "prompt_tokens":81,
      "completion_tokens":19,
      "total_tokens":100
   }
}

我们的任务是用提供的参数执行get_current_weather。 OpenAI 执行该功能。相反,运行聊天机器人并解析返回的数据是我们的聊天机器人的工作。

我们检索天气数据后,我们将使用称为function的新型角色将其发送回模型。例如:

{
   "model":"gpt-3.5-turbo-0613",
   "messages":[
      {
         "role":"user",
         "content":"How is the weather in NYC?"
      },
      {
         "role":"assistant",
         "content":null,
         "function_call":{
            "name":"get_current_weather",
            "arguments":"{\n \"location\": \"New York, NY\"\n}"
         }
      },
      {
         "role":"function",
         "name":"get_current_weather",
         "content":"Temperature: 57F, Condition: Raining"
      }
   ],
   "functions":[
      {
         "name":"get_current_weather",
         "description":"Get the current weather in a given location",
         "parameters":{
            "type":"object",
            "properties":{
               "location":{
                  "type":"string",
                  "description":"The city and state, e.g. San Francisco, CA"
               },
               "unit":{
                  "type":"string",
                  "enum":[
                     "celsius",
                     "fahrenheit"
                  ]
               }
            },
            "required":[
               "location"
            ]
         }
      }
   ]
}

请注意,我们将整个消息历史记录传递给API,包括我们的原始提示,模型的功能调用以及在代码中执行天气功能的结果。这使语言模型能够理解称为函数的上下文。

最后,该模型可以以正确格式的答案回答,以回答我们的最初问题:

{
   "id":"chatcmpl-7WWQUccvLUfjhbIcuvFrj2MDJVEiN",
   "object":"chat.completion",
   "created":1687985498,
   "model":"gpt-3.5-turbo-0613",
   "choices":[
      {
         "index":0,
         "message":{
            "role":"assistant",
            "content":"The weather in New York City is currently raining with a temperature of 57 degrees Fahrenheit."
         },
         "finish_reason":"stop"
      }
   ],
   "usage":{
      "prompt_tokens":119,
      "completion_tokens":19,
      "total_tokens":138
   }
}

建立新闻节

要了解有关功能呼叫的更多信息,我们将构建 newsgpt ,这是一个能够实时访问突发新闻的Python Chatbot。该机器人将使用调用函数来确定从NewsAPI.org获取哪种类型的数据。

要构建机器人,您将需要以下内容:

  • OpenAI API键。这需要信用卡,因为API请求有成本。但是,新帐户在头三个月获得\ 5美元的信用额度。
  • Newsapi API密钥。在NewsAPI.org注册,免费获取一个入门密钥。
  • python 3。

设置项目

安装所需的依赖项:

$ pip install openai tiktoken

该项目仅由一个文件组成;让我们命名为newsgpt.py。我将首先添加所有必要的导入:

import openai
import tiktoken
import json
import os
import requests

接下来,我将定义一些常数:

  • GPT模型要使用。我将使用gpt-3.5-turbo-16k,因为它具有16K令牌限制,使我可以使用更多上下文处理更长的对话。
  • 系统提示以其基本目的指示模型。
  • 用于计数字符串和消息中的代币的编码;确保我们不超过语言模型限制所需。
  • 在链中调用的最大功能数量(稍后再详细介绍)。
llm_model = "gpt-3.5-turbo-16k"
llm_max_tokens = 15500
llm_system_prompt = "You are an assistant that provides news and headlines to user requests. Always try to get the lastest breaking stories using the available function calls."
encoding_model_messages = "gpt-3.5-turbo-0613"
encoding_model_strings = "cl100k_base"
function_call_limit = 3

所有OpenAI型号都具有令牌限制。如果超过此限制,API将丢弃错误,而不是响应我们的请求。因此,我们需要一个函数来计算令牌数量。我将从官方示例文档中使用此功能:

def num_tokens_from_messages(messages):
 """Returns the number of tokens used by a list of messages."""
 try:
 encoding = tiktoken.encoding_for_model(encoding_model_messages)
 except KeyError:
 encoding = tiktoken.get_encoding(encoding_model_strings)

 num_tokens = 0
 for message in messages:
 num_tokens += 4
 for key, value in message.items():
 num_tokens += len(encoding.encode(str(value)))
 if key == "name":
 num_tokens += -1
 num_tokens += 2
 return num_tokens

定义呼叫的函数

现在,我将定义一个函数来查询NewsAPI.org API以获取突发新闻:


def get_top_headlines(query: str = None, country: str = None, category: str = None):
 """Retrieve top headlines from newsapi.org (API key required)"""

    base_url = "https://newsapi.org/v2/top-headlines"
    headers = {
    "x-api-key": os.environ['NEWS_API_KEY']
    }
    params = { "category": "general" }
    if query is not None:
    params['q'] = query
    if country is not None:
    params['country'] = country
    if category is not None:
    params['category'] = category

    # Fetch from newsapi.org - reference: https://newsapi.org/docs/endpoints/top-headlines
    response = requests.get(base_url, params=params, headers=headers)
    data = response.json()

    if data['status'] == 'ok':
    print(f"Processing {data['totalResults']} articles from newsapi.org")
    return json.dumps(data['articles'])
    else:
    print("Request failed with message:", data['message'])
    return 'No articles found'

要通知GPT此功能,我们需要使用特定的JSON结构来描述。格式在official documentation中描述如下:

signature_get_top_headlines = {
   "name":"get_top_headlines",
   "description":"Get top news headlines by country and/or category",
   "parameters":{
      "type":"object",
      "properties":{
         "query":{
            "type":"string",
            "description":"Freeform keywords or a phrase to search for."
         },
         "country":{
            "type":"string",
            "description":"The 2-letter ISO 3166-1 code of the country you want to get headlines for"
         },
         "category":{
            "type":"string",
            "description":"The category you want to get headlines for",
            "enum":[
               "business",
               "entertainment",
               "general",
               "health",
               "science",
               "sports",
               "technology"
            ]
         }
      },
      "required":[

      ]
   }
}

使用聊天完成API与函数调用

接下来,我将定义complete函数,该功能执行多个任务:

  1. 在消息结束时添加了系统提示。此系统消息有助于定义GPT模型将履行的角色。
  2. 如果总的令牌计数超过模型的限制,则删除旧消息。
  3. 将请求发送到GPT API。
  4. 从列表的末尾删除系统消息。
def complete(messages, function_call: str = "auto"):
 """Fetch completion from OpenAI's GPT"""

 messages.append({"role": "system", "content": llm_system_prompt})

 # delete older completions to keep conversation under token limit
 while num_tokens_from_messages(messages) >= llm_max_tokens:
 messages.pop(0)

 print('Working...')
 res = openai.ChatCompletion.create(
 model=llm_model,
 messages=messages,
 functions=[signature_get_top_headlines],
 function_call=function_call
 )

 # remove system message and append response from the LLM
 messages.pop(-1)
 response = res["choices"][0]["message"]
 messages.append(response)

 # call functions requested by the model
 if response.get("function_call"):
 function_name = response["function_call"]["name"]
 if function_name == "get_top_headlines":
 args = json.loads(response["function_call"]["arguments"])
 headlines = get_top_headlines(
 query=args.get("query"),
 country=args.get("country"),
 category=args.get("category") 
 )
 messages.append({ "role": "function", "name": "get_top_headline", "content": headlines})

要完成机器人,我们将创建不断提示用户输入并提供答案的主循环:

print("\nHi, I'm a NewsGPT, a breaking news AI assistant. I can give you news for most countries over a wide range of categories.")
print("Here are some example prompts:\n - Tell me about the recent science discoveries\n - What is the latest news in the US?\n - What has Elon Musk been up to recently?")

messages = []
while True:
    prompt = input("\nWhat would you like to know? => ")
    messages.append({"role": "user", "content": prompt})
    complete(messages)

    # the LLM can chain function calls, this implements a limit
    call_count = 0
    while messages[-1]['role'] == "function":
    call_count = call_count + 1
    if call_count < function_call_limit:
    complete(messages)
    else:
    complete(messages, function_call="none")

    # print last message
    print("\n\n==Response==\n")
    print(messages[-1]["content"].strip())
    print("\n==End of response==")

接下来,我们需要为OpenAI和Newsapi API密钥定义环境变量:

export OPENAI_API_KEY=YOUR_API_KEY
export NEWS_API_KEY=YOUR_API_KEY

最后,加载文件并运行聊天机器人。

$ source .env
$ python newsgpt.py

测试Newsgpt

我们可以询问一个特定的主题或人。例如:

=> What is Elon Musk up these days?
Working...
Processing 1 articles from newsapi.org
Working...


==Response==

Elon Musk has been in the news recently regarding a feud with Mark Zuckerberg, the CEO of Meta. According to an article from The Washington Post, Mark Zuckerberg is trying to make himself more relevant to the tech elite, and there seems to be a rivalry between him and Elon Musk. The article discusses their ongoing fight and how Zuckerberg is trying to compete with Musk's online antagonism and offline antics. You can read more about it [here](https://www.washingtonpost.com/technology/2023/06/24/elon-musk-mark-zuckerberg-fight-meta-twitter-rival/).

==End of response==

该机器人也能够识别类别,使我们能够请求与健康有关的新闻:

Are there important developments in health?
Working...
Processing 1000 articles from newsapi.org
Working...


==Response==

Based on the latest headlines in the health category, here are some important developments:

1. [A Case of Herpes Zoster Ophthalmicus in a Recently Transplanted Renal Patient](https://www.cureus.com/articles/164429-a-case-of-herpes-zoster-ophthalmicus-in-a-recently-transplanted-renal-patient?score_article=true) - This case study presents the clinical course of a 51-year-old male who underwent a renal transplant and developed Herpes Zoster Ophthalmicus.

2. [Cuáles son los principales consejos a seguir para mejorar el estado de ánimo a base de una buena alimentación](https://news.google.com/rss/articles/CBMilQFodHRwczovL3d3dy5jYW5hbDI2LmNvbS9nZW5lcmFsL2N1YWxlcy1zb24tbG9zLXByaW5jaXBhbGVzLWNvbnNlam9zLWEtc2VndWlyLXBhcmEtbWVqb3Jhci1lbC1lc3RhZG8tZGUtYW5pbW8tYS1iYXNlLWRlLXVuYS1idWVuYS1hbGltZW50YWNpb24tLTM0NTMwM9IBAA?oc=5) (in Spanish) - This article provides tips on improving mood through a good diet.

3. [Как да стопите коремните мазнини за лятото](https://news.google.com/rss/articles/CBMiXmh0dHBzOi8vbS5hei1qZW5hdGEuYmcvYS81LXpkcmF2ZS1pLWtyYXNvdGEvNjM1Mzkta2FrLWRhLXN0b3BpdGUta29yZW1uaXRlLW1hem5pbmktemEtbGlhdG90by_SAWJodHRwczovL20uYXotamVuYXRhLmJnL2EvNS16ZHJhdmUtaS1rcmFzb3RhLzYzNTM5LWthay1kYS1zdG9waXRlLWtvcmVtbml0ZS1tYXpuaW5pLXphLWxpYXRvdG8vYW1wLw?oc=5) (in Bulgarian) - This article provides tips on losing belly fat for the summer.

4. [Recap: From RCC Diagnosis to Treatment, Toxicity Management, and Beyond](https://news.google.com/rss/articles/CBMiZ2h0dHBzOi8vd3d3LmNhbmNlcm5ldHdvcmsuY29tL3ZpZXcvcmVjYXAtZnJvbS1yY2MtZGlhZ25vc2lzLXRvLXRyZWF0bWVudC10b3hpY2l0eS1tYW5hZ2VtZW50LWFuZC1iZXlvbmTSAQA?oc=5) - This article discusses the diagnosis, treatment, and management of renal cell carcinoma.

5. [Review Highlights Progress, Challenges With CRS in Cancer Immunotherapies](https://news.google.com/rss/articles/CBMiYmh0dHBzOi8vd3d3LmFqbWMuY29tL3ZpZXcvcmV2aWV3LWhpZ2hsaWdodHMtcHJvZ3Jlc3MtY2hhbGxlbmdlcy13aXRoLWNycy1pbi1jYW5jZXItaW1tdW5vdGhlcmFwaWVz0gEA?oc=5) - This review highlights the progress and challenges in cancer immunotherapies targeting CRS (cytokine release syndrome).

These are just a few of the recent developments in the field of health. For more detailed information, you can read the full articles by clicking on the provided links.

==End of response==

它也可以国家,使我们能够查询机器人有关特定地区的新闻:

What is the latest news from France?
Working...
Processing 34 articles from newsapi.org
Working...


==Response==

Here are some of the latest news headlines in France:

1. "Diplôme national du brevet session 2023" - The Ministry of National Education announces the national diploma for the 2023 session. [Read more](https://news.google.com/rss/articles/CBMiTGh0dHBzOi8vd3d3LmVkdWNhdGlvbi5nb3V2LmZyL2RpcGxvbWUtbmF0aW9uYWwtZHUtYnJldmV0LXNlc3Npb24tMjAyMy0zNzg1NjDSAQA?oc=5)

2. "Cyclisme: la Nordiste Victoire Berteau sacrée championne de France après sa victoire sur les routes de Cassel" - Victoire Berteau from Nord wins the championship in cycling in France. [Read more](https://news.google.com/rss/articles/CBMiiQFodHRwczovL3d3dy5mcmFuY2V0dmluZm8uZnIvc3BvcnRzL2N5Y2xpc21lL2N5Y2xpc21lLXZpY3RvaXJlLWJlcnRlYXUtc2FjcmVlLWNoYW1waW9ubmUtZGUtZnJhbmNlLWFwcmVzLXNhLXZpY3RvaXJlLWEtY2Fzc2VsXzU5MDg4NDcuaHRtbNIBAA?oc=5)

3. "Guerre en Ukraine: comment les capitales étrangères réagissent-elles à la rébellion de la milice Wagner en Ru" - Foreign capitals' reactions to the rebellion of the Wagner militia in Ukraine. [Read more](https://news.google.com/rss/articles/CBMiwAFodHRwczovL3d3dy5mcmFuY2V0dmluZm8uZnIvbW9uZGUvZXVyb3BlL21hbmlmZXN0YXRpb25zLWVuLXVrcmFpbmUvZ3VlcnJlLWVuLXVrcmFpbmUtY29tbWVudC1sZXMtY2FwaXRhbGVzLWV0cmFuZ2VyZXMtcmVhZ2lzc2VudC1lbGxlcy1hLXJlYmVsbGlvbi1kZS1sYS1taWxpY2Utd2FnbmVyLWVuLXJ1c3NpZV81OTA4NzY2Lmh0bWzSAQA?oc=5)

4. "Marche des fiertés LGBT+: six jeunes mineurs interpellés pour homophobie" - Six minors arrested for homophobia during the LGBT+ Pride March. [Read more](https://news.google.com/rss/articles/CBMifmh0dHBzOi8vd3d3LnJ0bC5mci9hY3R1L2p1c3RpY2UtZmFpdHMtZGl2ZXJzL21hcmNoZS1kZXMtZmllcnRlcy1sZ2J0LXNpeC1qZXVuZXMtbWluZXVycy1pbnRlcnBlbGxlcy1wb3VyLWhvbW9waG9iaWUtNzkwMDI3Nzg4M9IBAA?oc=5)

5. "ATP 500 Queen's - De Minaur a dominé Rune avec autorité: le film de la demi-finale" - Alex de Minaur dominates Rune in the ATP 500 Queen's semifinals. [Read more](https://news.google.com/rss/articles/CBMimwFodHRwczovL3d3dy5ldXJvc3BvcnQuZnIvdGVubmlzL2F0cC1sb25kcmVzLzIwMjMvYXRwLTUwMC1xdWVlbi1zLXN1aXZlei1sYS1kZW1pLWZpbmFsZS1lbnRyZS1hbGV4LWRlLW1pbmF1ci1ldC1ob2xnZXItcnVuZS1lbi1kaXJlY3Rfc3RvOTY3MTM4My9zdG9yeS5zaHRtbNIBAA?oc=5)

These are just a few of the latest news headlines in France. Let me know if you want more information about any specific news article.

==End of response==

改进的想法

即使使用一个函数调用,这个简单的机器人也非常有能力。现在,想象一下,如果我们集成了更多功能,可能会有可能。以下是增加新闻网的一些想法:

  • 检索原始文章以获取摘要并分析新闻。我们需要导航付费墙,执行网络刮擦或检查RSS feed或API是否提供内容。
  • 添加更多端点。 Newsapi提供了按日期,类别进行搜索新闻的端点,并通过sources进行过滤。
  • 合并额外的集成,例如从天气或金融等来源获取实时数据。

结论

函数调用是OpenAI的GPT模型中的一个强大功能,使它们能够以更确定性和结构化的方式与外部工具和API进行交互。此功能为能够提供当前信息和执行以外的任务的更具动态和响应的AI应用程序奠定了基础。

快乐建筑!