AI宝库-ChatGPT插件能力

2023-12-12 09:46:18 浏览数 (1)

相信作为编程人员或AI应用的每一位关注者,都苦于ChatGPT之前的知识只能到2021年,而且我们作为开发者大多数人其实都希望能通过给ChatGPT写更多的通用能力,非常眼馋ChatGPT的插件能力。

终于OpenAI后来发布会宣布可以通过API来实现插件能力了,无疑给ChatGPT的应用插上了翅膀。

实现插件能力的基础就是本次的主角-Function Call,让我们一起揭开其神秘面纱吧!

什么是Function Call

Function Call是GPT API中的一项新能力。

它可以让开发者在调用GPT-4和GPT-3.5-turbo模型时,通过描述函数能让模型智能的输出包含调用这些函数所需参数的JSON对象。这是一种更可靠地将 GPT 的功能与外部工具和 API 相连接的新方法。函数调用使开发者能够更可靠地从模型中获得结构化数据。通俗点讲,能把自然语言的世界和现在的机器世界打通了,虽然整个世界最终的走向将会是自然语言的世界,但现在所有的计算机系统都还是代码的世界,Function Call将两个世界完美的搭配了起来。

通过插件体系的建立,ChatGPT不仅可以获取最新的新闻,还可以查询天气、酒店等信息,规划旅行及电商下单等,使得ChatGPT在更多领域发挥有更多的用武之地。

Function Call本质

Function Call的本质就是把原来ChatGPT API中completetions的调用,从原来只支持messages(三种角色:system、user、assistant),扩展到了还可以提供functions。ChatGPT会根据functions里面每个单独的function描述的意思,进行简单的逻辑判断用户的问题用某个函数回答是否合适。如果可以它将会把用户的问题中间可以作为参数的部分提出出来,并返回一个结构化的函数调用数据结构。代码世界再通过严格的JSON格式定义的函数调用方法调用函数,将最终结果返回给ChatGPT,ChatGPT根据返回的信息继续回答用户的问题,我们可以实现所有的计算机函数接口都有了人类语言的能力!

举个例子

  • 开发者可以利用调用外部工具创建聊天机器人(如 ChatGPT 插件)来回答问题

将查询如“今天的天气如何?”转换为像 getCurrentWeather(location: string) 这样的函数调用

  • 将自然语言转换为 API 调用或数据库查询

将“某段时间前十位客户是谁?”转换为内部 API 调用,如 get_customers(start_date: string, end_date: string, limit: int),或者将“公司上个月下了多少订单?”转换为使用 sql_query(query: string) 的 SQL 查询。

  • 从文本中提取结构化数据

定义一个extract_user_data(name: string, birthday: string) 的函数,提取在维基百科文章中提到的所有人物。

这些例子通过我们的 /v1/chat/completions 端点中的新 API 参数 functions 和 function_call 得以实现,开发者可以通过 JSON Schema 描述函数,并可选择要求模型调用特定函数。 一句话解释就是:我们可以把自己的函数集成到GPT里了

Function Calling帮我们能解决什么问题

Function Calling本质上就是插件!插件功能相当于给OpenAI增加了一个武器库,开发者可以随意给它安装武器提升它的能力。

  • 数据实时性问题

问他langchain是什么?由于训练集是截止2021年(目前最新版的已更新至2023年04月)的,他会回答不知道。但是有了Function Callling,我们就可以写一个函数集成谷歌/百度搜索API,给GPT加上联网能力,这样就借助搜索引擎的能力支持了数据的动态更新。

  • 跟已有应用系统集成问题

问他今天天气如何?由于ChatGPT数据集是离线的,无法满足获取实时天气的需求。但是有了Function Calling,我们可以编写一个函数来调用天气获取的API,从而获取实时天气信息,然后再与大模型的对话能力进行自然语言交互。

Function Calling如何使用

与普通chat对话的区别是增加了两个额外参数

  • functions: 声明自定义函数库
  • funcion_call: 控制大模型什么时机使用通Function Calling 功能
代码语言:python代码运行次数:0复制
# 普通代码
# 注意新版的python SDK中openai函数已经发生了更新
# 历史版本
messages = [
    {"role": "user", "content": "Hello stone!"}
]
completion = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=messages
)

# 新版中
completion = openai.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "user", "content": "Hello stone!"}
    ],
)

# Function calling
completion = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=messages,
  
  # 增加额外两个参数
  functions=functions,
  function_call="auto", # auto is default, but we'll be explicit
)

实时天气查询实践

调用流程

1.定义函数

定义本地函数get_current_weather实现从API拉取,这里直接写一个简单对参数输出进行模拟。

然后按照OpenAI的文档要求格式定义get_current_weather的接口函数的json参数。

代码语言:python代码运行次数:0复制
# 1.1 定义模拟获取天气的本地函数
def get_current_weather(location, unit):
    # 可以对接第三方应用系统的API
    return f"It's 0 {unit} in {location}"
  1. 第一次调用接口

返回大模型分析出的函数名称和参数。

代码语言:python代码运行次数:0复制
  ChatCompletion(
  id='chatcmpl-8K54AkuSdoiwk8Jw2B8zcPs5VibAZ', 
  choices=[
    Choice(
      finish_reason='function_call', 
      index=0, 
      message=ChatCompletionMessage(
        content=None, role='assistant', 
        function_call=FunctionCall(
          arguments='{n  "location": "Xian",n  "unit": "celsius"n}', 
          name='get_current_weather'
        ), 
        tool_calls=None
      ))
    ], 
    created=1699796726, 
    model='gpt-3.5-turbo-0613', 
    object='chat.completion', 
    system_fingerprint=None,
    usage=CompletionUsage(
      completion_tokens=25, 
      prompt_tokens=89, 
      total_tokens=114
    )
  )
  1. 调用本地函数

获取返回值,进行本地python方法调用

  1. 第二次调用接口

将第一次接口的返回值message与本地函数调用的接口拼装起来,然后再次调用接口。

代码语言:python代码运行次数:0复制
ChatCompletionMessage(
    content='The weather in Xian today is 0 degrees Celsius.', 
    role='assistant', 
    function_call=None, 
    tool_calls=None
)
代码语言:python代码运行次数:0复制
# function_calling.py
import openai
import json

openai.api_key = 'sk-xxxxxxxx' # 密钥

# 1. 定义函数
# 1.1 定义模拟获取天气的本地函数
def get_current_weather(location, unit):
    # Call the weather API
    return f"It's 0 {unit} in {location}"

# 1.2 定义函数字典方便调用
function_dict = {
    "get_current_weather": get_current_weather,
}

# 1.3 定义chat接口需要的函数
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. ShaanXi, Xian",
                },
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
            },
            "required": ["location"],
        },
    }
]

# 2. 第一次调用chat接口,返回的是函数调用的提示
messages = [
    {"role": "user", "content": "What's the weather like in Xian today with celsius?"}]
completion = openai.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=messages,
    functions=functions,
    function_call="auto",  # auto is default, but we'll be explicit
)
print(completion)

# 3. 从结果接口的结果中获取函数调用的参数 进行本地函数调用
# 3.1 获取函数调用的参数
response_message = completion.choices[0].message
function_name = response_message.function_call.name
function_args = json.loads(response_message.function_call.arguments)
# 3.2 调用本地函数
function_response = function_dict.get(function_name)(**function_args)
# 3.3 将本地函数的结果作为chat接口的输入
messages.append(response_message)
messages.append({
    "role": "function",
    "name": function_name,
    "content": function_response,
})

# 4. 第二次调用chat接口,返回的是chat的最终结果
completion_final = openai.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=messages,
)

print(completion_final.choices[0].message)

参考文献

  • OpenAI Chat API官方文档
  • Function Calling

准备工作

  • 准备自己的ChatGPT账号

0 人点赞