OpenAI API進(jìn)階-Function Calling實現(xiàn)插件!
Function Calling介紹
Function Calling是什么
OpenAI Chat API官方文檔:Chat API[1]
Function Calling官方介紹:Function Calling[2]
圖片
開發(fā)者現(xiàn)在可以向 gpt-4-0613 和 gpt-3.5-turbo-0613 描述函數(shù),并讓模型智能地選擇輸出一個包含調(diào)用這些函數(shù)參數(shù)的 JSON 對象。這是一種更可靠地將 GPT 的功能與外部工具和 API 相連接的新方法。
這些模型經(jīng)過了微調(diào),既可以檢測到何時需要調(diào)用函數(shù)(根據(jù)用戶的輸入),又可以回復(fù)符合函數(shù)簽名的 JSON。函數(shù)調(diào)用使開發(fā)者能夠更可靠地從模型中獲得結(jié)構(gòu)化數(shù)據(jù)。例如,開發(fā)者可以:
- 利用外部工具調(diào)用的聊天機器人(如 ChatGPT 插件)來回答問題
將查詢?nèi)纭癊mail Anya看看她下周五是否想喝咖啡”轉(zhuǎn)換為像 send_email(to: string, body: string) 這樣的函數(shù)調(diào)用,或者將“波士頓的天氣如何?”轉(zhuǎn)換為 get_current_weather(location: string, unit: 'celsius' | 'fahrenheit')。
- 將自然語言轉(zhuǎn)換為 API 調(diào)用或數(shù)據(jù)庫查詢
將“這個月我的前十位客戶是誰?”轉(zhuǎn)換為內(nèi)部 API 調(diào)用,如 get_customers_by_revenue(start_date: string, end_date: string, limit: int),或者將“Acme 公司上個月下了多少訂單?”轉(zhuǎn)換為使用 sql_query(query: string) 的 SQL 查詢。
- 從文本中提取結(jié)構(gòu)化數(shù)據(jù)
定義一個名為 extract_people_data(people: [{name: string, birthday: string, location: string}]) 的函數(shù),以提取在維基百科文章中提到的所有人物。
這些用例通過我們的 /v1/chat/completions 端點中的新 API 參數(shù) functions 和 function_call 得以實現(xiàn),開發(fā)者可以通過 JSON Schema 描述函數(shù),并可選擇要求模型調(diào)用特定函數(shù)。
一句戶解釋就是:我們可以把自己的函數(shù)集成到GPT里了
Function Calling解決什么問題
Function Calling本質(zhì)上就是插件!
插件功能相當(dāng)于給OpenAI增加了一個武器庫,開發(fā)者可以隨意給它安裝武器提升它的能力。
數(shù)據(jù)實時性問題
圖片
問他langchain是什么?由于訓(xùn)練集是截止2021年的,他會回答不知道。但是有了Function Callling,我們就可以寫一個函數(shù)集成谷歌/百度搜索API,給GPT加上聯(lián)網(wǎng)能力,這樣就借助搜索引擎的能力支持了數(shù)據(jù)的動態(tài)更新。
跟已有系統(tǒng)集成問題
圖片
問他今天天氣如何?由于ChatGPT數(shù)據(jù)集是離線的,無法滿足獲取實時天氣的需求。但是有了Function Calling,我們可以編寫一個函數(shù)來調(diào)用天氣獲取的API,從而獲取實時天氣信息,然后再與大模型的對話能力進(jìn)行自然語言交互。
Function Calling如何使用
使用介紹
與普通chat對話的區(qū)別是增加了兩個額外參數(shù)
- functions: 聲明自定義函數(shù)庫
- funcion_call: 控制大模型什么時機使用通Function Calling功能
圖片
普通代碼:
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages
)
Function calling:
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
# 增加額外兩個參數(shù)
functinotallow=functions,
function_call="auto", # auto is default, but we'll be explicit
)
實時天氣查詢實踐
整體要經(jīng)過兩次的OpenAI Chat接口調(diào)用。
調(diào)用流程
1.定義函數(shù)
定義本地函數(shù)get_current_weather實現(xiàn)從API拉取,這里直接寫一個簡單對參數(shù)輸出進(jìn)行模擬。
然后按照OpenAI的文檔要求格式定義get_current_weather的接口函數(shù)的json參數(shù)。
2.第一次調(diào)用接口
返回大模型分析出的函數(shù)名稱和參數(shù)。
結(jié)果如下:
{
"id": "chatcmpl-8EIYxuSvhxmvYRE2UZI19fodbhXGv",
"object": "chat.completion",
"created": 1698418639,
"model": "gpt-3.5-turbo-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"function_call": {
"name": "get_current_weather",
"arguments": "{\n \"location\": \"Boston, MA\",\n \"unit\": \"celsius\"\n}"
}
},
"finish_reason": "function_call"
}
],
"usage": {
"prompt_tokens": 86,
"completion_tokens": 26,
"total_tokens": 112
}
}
3.調(diào)用本地函數(shù)
獲取返回值,進(jìn)行本地python方法調(diào)用
4.第二次調(diào)用接口
將第一次接口的返回值message與本地函數(shù)調(diào)用的接口拼裝起來,然后再次調(diào)用接口。
結(jié)果如下:
{
"role": "assistant",
"content": "The weather in Boston today is 20 degrees Celsius."
}
代碼實現(xiàn)
完整代碼鏈接:Fuction Calling 示例[3]
# function_calling.py
import openai
import json
openai.api_key = 'sk-NYsoG3VBKDiTuvdtC969F95aFc4f45379aD3854a93602327'
openai.api_base = "https://key.wenwen-ai.com/v1"
# 1. 定義函數(shù)
# 1.1 定義模擬獲取天氣的本地函數(shù)
def get_current_weather(location, unit):
# Call the weather API
return f"It's 20 {unit} in {location}"
# 1.2 定義函數(shù)字典方便調(diào)用
function_dict = {
"get_current_weather": get_current_weather,
}
# 1.3 定義chat接口需要的函數(shù)
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"],
},
}
]
# 2. 第一次調(diào)用chat接口,返回的是函數(shù)調(diào)用的提示
messages = [
{"role": "user", "content": "What's the weather like in Boston today with celsius?"}]
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
functinotallow=functions,
function_call="auto", # auto is default, but we'll be explicit
)
print(completion)
# 3. 從結(jié)果接口的結(jié)果中獲取函數(shù)調(diào)用的參數(shù) 進(jìn)行本地函數(shù)調(diào)用
# 3.1 獲取函數(shù)調(diào)用的參數(shù)
response_message = completion.choices[0].message
function_name = response_message["function_call"]["name"]
function_args = json.loads(response_message["function_call"]["arguments"])
# 3.2 調(diào)用本地函數(shù)
function_response = function_dict.get(function_name)(**function_args)
# 3.3 將本地函數(shù)的結(jié)果作為chat接口的輸入
messages.append(response_message)
messages.append({
"role": "function",
"name": function_name,
"content": function_response,
})
# 4. 第二次調(diào)用chat接口,返回的是chat的最終結(jié)果
completion_final = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
)
print(completion_final.choices[0].message)
上面的代碼中的key是我自己維護(hù)的,免費給大家使用,代碼可以直接運行!
python3.9 function_calling.py
參考資料
[1]Chat API: https://platform.openai.com/docs/api-reference/chat
[2]Function Calling: https://openai.com/blog/function-calling-and-other-api-updates
[3]Fuction Calling 示例: https://github.com/hehan-wang/openai-demo/blob/main/function_calling.py