函数调用(Function Call)

更新时间:2023/08/24, 15:07

函数调用

在API调用中,你可以向 gpt-3.5-turbo-0613gpt-4-0613 描述函数,并让模型智能地选择输出一个包含调用这些函数的参数的 JSON 对象。聊天完成 API 不会调用函数;相反,模型生成的JSON可以在你的代码中用来调用函数。

最新模型(gpt-3.5-turbo-0613gpt-4-0613)已经微调过,既可以检测何时应该调用一个函数(取决于输入),也可以用遵循函数签名的JSON进行响应。随之而来的还有潜在的风险。我们强烈建议在代表用户执行影响世界的操作之前(发送电子邮件、在线发布内容、进行购买等),建立用户确认流程。

在底层,函数以模型经过训练的语法注入系统消息中。这意味着函数计入模型的上下文限制,并作为输入标记进行计费。如果遇到上下文限制,我们建议限制函数的数量或缩短你为函数参数提供的文档长度。

函数调用使你能够更可靠地从模型获取结构化数据。例如,你可以:

  • 创建通过调用外部API来回答问题的聊天机器人(例如像 ChatGPT 插件)
    • 例如定义函数像 send_email(to: string, body: string), 或 get_current_weather(location: string, unit: 'celsius' | 'fahrenheit')
  • 将自然语言转换为API调用
    • 例如把“谁是我的顶级客户?”转换为 get_customers(min_revenue: int, created_before: string, limit: int) 并调用你的内部API
  • 从文本中提取结构化数据
    • 例如定义一个名为 extract_data(name: string, birthday: string) 的函数,或 sql_query(query: string)

等等!

函数调用的基本步骤如下:

  1. 使用用户查询和一组在 functions 参数中定义的函数调用模型。
  2. 模型可以选择调用一个函数;如果是这样,内容将是一个遵循你的自定义模式的字符串化 JSON 对象(注意:模型可能会生成无效的 JSON 或幻想参数)。
  3. 在你的代码中解析字符串为 JSON,如果存在提供的参数,使用提供的参数调用你的函数。
  4. 通过将函数响应作为新消息追加来再次调用模型,并让模型将结果汇总回用户。

你可以通过下面的例子看到这些步骤的实际操作:


import openai
import json

# 示例假函数硬编码为返回相同的天气
# 在生产环境中,这可以是你的后端 API 或外部 API
def get_current_weather(location, unit="fahrenheit"):
    """获取某个位置的当前天气"""
    weather_info = {
        "location": location, 
        "temperature": "72""unit": unit,
        "forecast": ["sunny""windy"],  
    }
    return json.dumps(weather_info)

def run_conversation():
    # 第1步:将对话和可用函数发送给GPT
    messages = [{"role": "user""content": "波士顿的天气怎么样?"}]
    functions = [
        {
            "name": "get_current_weather""description": "获取某个位置的当前天气""parameters": {
                "type": "object""properties": {
                    "location": {
                        "type": "string""description": "城市和州,例如旧金山,加州",
                    },
                    "unit": {"type": "string""enum": ["celsius""fahrenheit"]},
                },
                "required": ["location"],
            },
        }
    ]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions,
        function_call="auto"# 默认为auto,但我们会明确声明
    )
    response_message = response["choices"][0]["message"]
    
    # 第2步:检查GPT是否想要调用一个函数
    if response_message.get("function_call"):
        # 第3步:调用函数
        # 注意:JSON响应可能并不总是有效的;一定要处理错误
        available_functions = {
            "get_current_weather": get_current_weather,  
        } # 本例中只有一个函数,但你可以有多个
        function_name = response_message["function_call"]["name"]
        fuction_to_call = available_functions[function_name]
        function_args = json.loads(response_message["function_call"]["arguments"])
        function_response = fuction_to_call(
            location=function_args.get("location"),
            unit=function_args.get("unit"),
        )

        # 第4步:将函数调用和函数响应的信息发送给GPT
        messages.append(response_message) # 用助手的回复扩展对话
        messages.append(
            {
                "role": "function""name": function_name,
                "content": function_response, 
            }
        ) # 用函数响应扩展对话
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=messages,
        ) # 在GPT可以看到函数响应的地方获取新的GPT响应
        return second_response


print(run_conversation())

函数调用中的虚构输出(幻觉)通常可以通过系统消息进行缓解。例如,如果你发现模型正在生成未向其提供的函数的函数调用,请尝试使用这样的系统消息:“只使用你已经被提供的函数”。

在上面的例子中,我们将函数响应发送回模型,并让它决定下一步。它以告知用户波士顿的温度的面向用户的消息做出响应,但根据查询,它可能会再次选择调用一个函数。

例如,如果你问模型“查找这个周末波士顿的天气,为两人订餐厅,并更新我的日历”,并为这些查询提供相应的函数,它可以依次调用它们,只在最后创建一个面向用户的消息。

如果你想强制模型调用一个特定的函数,你可以通过设置 function_call: {"name": "<insert-function-name>"} 来实现。你也可以通过设置 function_call: "none" 强制模型生成一个面向用户的消息。请注意,默认行为(function_call: "auto")是让模型自己决定是否调用函数以及调用哪个函数。

你可以在 OpenAI cookbook 中找到更多函数调用的例子: 更多 demo 演示函数调用

AI奇想空间
AI奇想空间
https://aimazing.site
AI惊奇站是一个汇聚人工智能工具、资源和教程的导航网站。 在这里,你可以发现最新的AI技术、工具和应用,学习如何使用各种AI平台和框架,获取丰富的AI资源。 欢迎广大AI爱好者加入我们的社区,开启你的AI之旅!
AI交流群
Copyright © 2024 AI奇想空间.微信