6月14日清晨,OpenAI发布了几项重大更新,其中就包括一项名为「函数调用」的功用更新。

ChatGPT迎来新的开发方式:为什么这个功能让开发者为之狂喜?

这项全新功用得到了众多网友——尤其是开发者的青睐,纷纷表明这将极大地协助他们更好地运用API,以及更好地与自己的东西无缝集成。

ChatGPT迎来新的开发方式:为什么这个功能让开发者为之狂喜?

ChatGPT迎来新的开发方式:为什么这个功能让开发者为之狂喜?

那么,函数调用功用终究有什么奇特之处,能让众多开发者为之狂喜呢?

通过阅览本文,你将:

  1. 了解函数调用的根本原理,以及可运用的场景;
  2. 了解函数调用功用的根本完成进程;
  3. 了解函数调用恳求内容的格局标准,以及参数含义;
  4. 了解函数调用呼应内容的提取办法,以及成果判别;
  5. 了解函数调用对于开发者的含义,以及或许的危险。

函数调用是什么?

函数调用是一种让模型能够智能地挑选并执行外部函数的新办法。

开发者只需求向模型描绘他们供给的函数,模型就能依据用户输入,判别需求调用哪一个函数,并输出一个包括所需参数的 JSON 目标

这样,就能使 GPT 的功用与外部的东西和 API 更紧密地连接起来。

新的模型经过微调,既能识别用户输入中的函数调用意图,又能生成契合函数签名的 JSON 目标

函数调用使开发者能够更可靠地从模型中获取结构化的数据,比如:

创立调用外部东西来回答问题的聊天机器人

例如:

输入 函数 外部东西
给 Anya 发电子邮件,看看她下周五是否想喝咖啡 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查询
Acme, Inc. 上个月下了多少订单? sql_query(query: string) 数据库查询

从文本中提取结构化数据

例如:

文本 函数 目的
(某篇维基百科文章) extract_people_data(people: [{name: string, birthday: string, location: string}]) 提取文章中提到的所有人

函数调用的根本进程顺序

ChatGPT迎来新的开发方式:为什么这个功能让开发者为之狂喜?

进程1:运用函数和用户输入调用模型

咱们需求将用户输入的指令,以及咱们供给的一组预界说的函数,作为参数传入并调用模型。

# 一个虚拟的函数示例,总是回来相同的气候信息
# 在真实的场景中,这或许是你的后端 API 或许外部 API
def get_current_weather(location, unit="fahrenheit"):
    """Get the current weather in a given location"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["sunny", "windy"],
    }
    return json.dumps(weather_info)
def run_conversation():
    # 将会话历史与可用的函数发送到 GPT
    messages = [{"role": "user", "content": "What's the weather like in Boston?"}]
    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"],
            },
        }
    ]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions,
        function_call="auto",  # auto 是默认值,但咱们会明确阐明
    )

进程2:运用模型呼应调用 API

模型会依据用户输入,挑选一个适宜的函数,并回来一个包括参数的JSON字符串作为呼应。

咱们需求先将模型回来的字符串解析为JSON目标,再调用相应的函数并传入需求的参数。

    response_message = response["choices"][0]["message"]
    # 查看 GPT 是否要调用函数
    if response_message.get("function_call"):
        # 调用函数
        # 注意: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"),
        )

进程3:将呼应发送回模型进行汇总

最后,咱们将函数的回来成果作为新的音讯附加到会话中,然后再次调用模型,让模型生成一个更完整的回复,并回来给用户。

        # 将函数调用和函数呼应的信息发送给GPT
        messages.append(response_message)  # extend conversation with assistant's reply
        messages.append(
            {
                "role": "function",
                "name": function_name,
                "content": function_response,
            }
        )  # 用函数呼应扩展会话
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=messages,
        )  # 从 GPT 取得一个新的回复,它能够在其中看到函数呼应的内容
        return second_response['choices'][0]['message']['content']
print(run_conversation())

新的回复内容如下:

The weather in Boston is currently sunny and windy with a temperature of 72 degrees.

与函数调用相关的API阐明

Chat Completions API 是一个专门为多轮对话设计的API,它能够接纳一个音讯列表作为输入,并回来模型生成的音讯作为输出。

典型恳求格局

import openai
openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)

model参数

表明要运用的模型ID,不同版别的模型支持不同的API功用。比如要支持函数调用功用,则必须是 gpt-3.5-turbo-0613 或 gpt-4-0613 及之后的版别。

messages参数

表明到目前为止,构成会话的音讯列表。音讯列表是一组音讯目标,其中每个目标都包括一个人物和一条内容。

人物 职责 可选性
system(体系音讯) 指定模型整体的语言风格或许帮手的行为 可选
assistant(帮手音讯) 依据用户音讯要求内容,以及体系音讯的设定,输出一个适宜的回应 可选
user(用户音讯) 给出一个具体的指令 可选

支持函数调用的恳求格局

import openai
messages = [{"role": "user", "content": "What's the weather like in Boston?"}]
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"],
        },
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=messages,
    functions=functions,
    function_call="auto",  
)

functions参数

用于供给函数标准,使模型能够生成契合所供给标准的函数参数。

参数 阐明
name 要调用的函数的名称
description 对函数效果的描绘
parameters 函数接受的参数,以 JSON 目标描绘

function_call参数

用于控制模型如何呼应函数调用。

可选值 阐明
none 强制模型不运用任何函数
{“name”:\ “my_function”} 强制模型调用指定函数
auto(默认值) 由模型自己决定何时调用哪个函数

典型呼应格局

{
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "The 2020 World Series was played in Texas at Globe Life Field in Arlington.",
        "role": "assistant"
      }
    }
  ],
  "created": 1677664795,
  "id": "chatcmpl-7QyqpwdfhqwajicIEznoc6Q47XAyW",
  "model": "gpt-3.5-turbo-0613",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 17,
    "prompt_tokens": 57,
    "total_tokens": 74
  }
}

content参数

Python 中,能够运用 response['choices'][0]['message']['content'] 提取来自帮手音讯的回复。

finish_reason参数

每个呼应都会包括一个 finish_reason,其或许值为:

或许值 阐明
stop API 回来完整音讯
length 因为参数或符号约束,模型输出不完整
function_call 模型决定调用一个函数
content_filter 因为触发了来自咱们内容过滤器的符号,而省略了内容
null API 呼应仍在进行中或未完成

总结

你或许已经发现了,模型实践上并不会执行任何函数的调用。它只会依据用户的输入以及供给的函数,判别需求调用哪一个函数,并输出一个包括所需参数的 JSON 目标。

而开发者才是依据模型输出进行函数调用的真实执行者

本质上,函数调用和第三方插件相同,都是用来扩展 GPT 模型的功用的,两者都是使用了 GPT 的以下能力:

  • 知道何时需求使用外部东西解决问题的能力;
  • 输出代码、表格、JSON等结构化数据的能力;

只不过,曾经要完成这个目的,还需求凭借第三方插件,再由第三方插件调用外部东西或内部API,现在,则相当于省去了第三方插件这一步,直接就能够调用了。

通过把这套函数标准接入到正式的调用流程,能够极大地提升开发 GPT 使用的灵活性,省去编写杂乱提示的进程,提升反应速度的同时,也削减犯错的或许性。

可是,这种能力也带来了潜在的危险,强烈主张在代表用户采取举动(如发送电子邮件、发布内容、进行购买等)之前,得到用户的进一步承认。

另外,函数是以特定的语法注入到体系音讯中的,这意味着函数也会受模型上下文的约束,并计入输入符号的计费规矩。主张实践开发中要约束函数的数量,以及为函数参数所供给的文档的长度

引证

  • Function calling and other API updates

  • Developer Documentation-Function calling

  • API Reference-Create chat completion

  • Understanding JSON Schema

  • How to call functions with chat models