6月14日ChatGPT剛剛更新了Function Call函數(shù)調(diào)用功能,用戶可以通過自定義函數(shù)代碼來擴(kuò)展ChatGPT的能力,讓ChatGPT可以做到除了問答以外的擴(kuò)展能力,比如官方舉例說可以調(diào)第三方API查詢天氣,還可以通過生成SQL語句幫你查數(shù)據(jù)庫等等。這篇文章我們通過官方的幾個例子以及我自己的一些嘗試介紹一下函數(shù)調(diào)用到底怎么玩。
函數(shù)調(diào)用
根據(jù)官方文檔的描述,14日新發(fā)布的兩個算法版本gpt-3.5-turbo-0613和gpt-4-0613支持該項(xiàng)功能,要主要的是,自定義的函數(shù)是在你本地執(zhí)行的,而不是在ChatGPT的服務(wù)器上,ChatGPT能做是理解你的問題,并且?guī)湍銢Q策要調(diào)用哪個函數(shù),以及幫你生成入?yún)?,理解了后面的例子這一點(diǎn)就明白了。
根據(jù)官方的描述,函數(shù)調(diào)用提供了一種從ChatGPT模型獲取格式化數(shù)據(jù)的能力,比如:
- 創(chuàng)建一個對話機(jī)器人,通過調(diào)用外部API進(jìn)行問答。e.g. 定義一個函數(shù)
send_email(to: string, body: string)或者get_current_weather(location: string, unit: 'celsius' | 'fahrenheit') - 把自然語言轉(zhuǎn)換成API調(diào)用,e.g. 把"Who are my top customers?"轉(zhuǎn)換為
get_customers(min_revenue: int, created_before: string, limit: int)然后調(diào)用外部API - 抽取結(jié)構(gòu)化數(shù)據(jù),e.g. 定義一個函數(shù)
extract_data(name: string, birthday: string)或者sql_query(query: string)
函數(shù)調(diào)用的整體流程如下:
- 使用user query調(diào)用模型,并且模型的入?yún)⒅兄付ㄒ粋€或一組"functions"調(diào)用。
- 模型會自己選擇調(diào)用哪個Function,這樣的話返回內(nèi)容將是一個符合自定義模式的字符串化的JSON對象(注意:模型可能生成無效的JSON或虛構(gòu)參數(shù))。
- 在您的代碼中將字符串解析為JSON,并根據(jù)提供的參數(shù)調(diào)用您的函數(shù)(如果存在)。
- 通過將函數(shù)響應(yīng)作為新消息附加,并讓模型將結(jié)果總結(jié)給用戶,再次調(diào)用模型。
示例:查詢IP信譽(yù)
這個例子我們先定義一個簡單的函數(shù)調(diào)用微步在線API,然后把這個函數(shù)傳給ChatGPT,最后向它花式提問讓它幫我們查這個IP的信譽(yù),相當(dāng)于一個智能助手(有點(diǎn)大炮打蚊子的趕腳=.=)
下面這段代碼傳入IP參數(shù),調(diào)用微步API查詢IP信譽(yù)
import requests
def query_ip_reputation(ip):
# 獲取一個微步APIkey,不會玩的去問ChatGPT
api_key = "<apikey>"
url = f"https://api.threatbook.cn/v3/scene/ip_reputation?apikey={api_key}&resource={ip}"
resp = requests.get(url)
if resp.status_code == 200:
print(resp.text)
return resp.text
else:
raise Exception(resp.text)
#ip_address = "8.8.8.8"
輸出
{"data":{"8.8.8.8":{"severity":"info","judgments":["IDC","Whitelist","CDN"],"tags_classes":[{"tags":["GoogleCloud"],"tags_type":"public_info"}],"basic":{"carrier":"Google LLC","location":{"country":"United States","province":"","city":"","lng":"-101.407912","lat":"39.765054","country_code":"US"}},"asn":{"rank":4,"info":"GOOGLE, US","number":15169},"scene":"Cloud Provider","confidence_level":"high","is_malicious":false,"update_time":"2023-06-01 08:29:11"}},"response_code":0,"verbose_msg":"OK"}
接下來我們看看如何調(diào)用ChatGPT,當(dāng)然你可以用request調(diào)用openai的url,但是這里我們選擇使用它的SDK,先安裝:
pip install openai
下面這段代碼可以用來測試你的ChatGPT api_key是否有效(沒有的自己想辦法吧)
import openai
openai.api_key = "sk-<apikey>"
# confirm authentication was successful
openai.Engine.list()['data'][0]
下面這段相當(dāng)于是我們前面定義python函數(shù)的一個Schema,這個格式基本是固定的,包含函數(shù)名、描述、參數(shù)以及參數(shù)類型和描述,這里的描述一定要盡可能準(zhǔn)確,因?yàn)檫@段描述是ChatGPT做決策的依據(jù),ChatGPT會根據(jù)它理解的語義選擇調(diào)用或不調(diào)用這個函數(shù),總之決策權(quán)在它不在你。
query_ip_reputation_func = {
"name": "ip_reputation",
"description": "Query the reputation of IP address",
"parameters": {
"type": "object",
"properties": {
"ip": {
"type": "string",
"description": "The target IP address that you need to query for the reputation"
}
},
"required": ["ip"]
}
}
最后,我們調(diào)用對話接口用自然語言讓他查某個IP的信譽(yù),效果如下
import json
prompt = "給我查詢這個IP 8.8.8.8的信譽(yù)"
res = openai.ChatCompletion.create(
model='gpt-3.5-turbo-0613', # swap for gpt-3.5-turbo-0613 if needed
messages=[{"role": "user", "content": prompt}],
functions=[query_ip_reputation_func]
)
if res['choices'][0]["finish_reason"] == "function_call":
print("We should call a function!")
name = res['choices'][0]['message']['function_call']['name']
params = json.loads(res['choices'][0]['message']['function_call']['arguments'])
name, params
print(query_ip_reputation(**params))
輸出
We should call a function!
{"data":{"8.8.8.8":{"severity":"info","judgments":["IDC","Whitelist","CDN"],"tags_classes":[{"tags":["GoogleCloud"],"tags_type":"public_info"}],"basic":{"carrier":"Google LLC","location":{"country":"United States","province":"","city":"","lng":"-101.407912","lat":"39.765054","country_code":"US"}},"asn":{"rank":4,"info":"GOOGLE, US","number":15169},"scene":"Cloud Provider","confidence_level":"high","is_malicious":false,"update_time":"2023-06-01 08:29:11"}},"response_code":0,"verbose_msg":"OK"}
可以看到ChatGPT理解了我們的問題,也理解了這個函數(shù)的作用,并最終選擇調(diào)用我們定義的函數(shù)。當(dāng)然,我們可以定義一系列Function用來完成不同的工作,然后在調(diào)用對話接口的時候把所有的Function都綁定進(jìn)去,讓ChatGPT自己決定
總結(jié)
官方還提供了一個讓CHatGPT生成SQL并借助函數(shù)查詢本地數(shù)據(jù)庫的一個例子傳送門。總的來講還是蠻有創(chuàng)意的,通過本地執(zhí)行函數(shù)即保證了數(shù)據(jù)安全性又能方便的使用線上的生成式大語言模型,只是如果函數(shù)全都自己寫還是感覺有點(diǎn)費(fèi)勁,畢竟來使用AI的都是想偷懶的人,不過據(jù)說Langchain在openai發(fā)布新版本后十分鐘你內(nèi)就立即宣布支持Function Call,相信有了專業(yè)人士的加持,F(xiàn)unction call會孵化出很多千奇百怪的玩法。