歡迎閱讀本系列文章!我將帶你一起探索如何利用OpenAI API開(kāi)發(fā)GPT應(yīng)用。無(wú)論你是編程新手還是資深開(kāi)發(fā)者,都能在這里獲得靈感和收獲。
本文,我們將繼續(xù)展示聊天API中插件的使用方法,讓你能夠輕松駕馭這個(gè)強(qiáng)大的工具。
插件運(yùn)行效果
首先給大家展示下插件的運(yùn)行效果,如下圖所示:
可以看到,每次詢問(wèn)GPT,它都會(huì)返回指定城市的實(shí)時(shí)天氣信息,這個(gè)天氣是真實(shí)的,不是GPT瞎編的,是GPT通過(guò)一個(gè)實(shí)時(shí)天氣插件查詢到的。
插件運(yùn)行原理
知己知彼,百戰(zhàn)不殆!首先讓我們來(lái)了解下插件的運(yùn)行原理。如下圖所示:
首先我們?cè)诳蛻舳税l(fā)起一個(gè)聊天會(huì)話,比如詢問(wèn)GPT:“今天天氣怎么樣?”
為了使用我們自己的插件,我們還需要告訴GPT有哪些插件可用,目前這需要我們?cè)诎l(fā)起聊天時(shí)傳遞一個(gè)支持的插件列表給GPT。
然后GPT收到我們的聊天后,它會(huì)根據(jù)用戶的聊天內(nèi)容去匹配插件,并在返回的消息中指示命中了哪些插件,這個(gè)匹配是根據(jù)GPT的語(yǔ)言理解能力做出的。
然后客戶端就可以檢查命中了哪些插件,并調(diào)用執(zhí)行本地相應(yīng)的插件方法。插件方法是在本地執(zhí)行的,這也比較合理,如果放到GPT服務(wù)端,GPT不僅要適配各種計(jì)算能力,還可能面臨巨大的安全風(fēng)險(xiǎn)。
然后客戶端將插件的執(zhí)行結(jié)果附加到本次聊天會(huì)話中,再次發(fā)起聊天請(qǐng)求,GPT收到后,會(huì)根據(jù)首次聊天請(qǐng)求和插件生成的內(nèi)容組織本次聊天響應(yīng)結(jié)果,再返回給用戶。
這樣就完成了一次基于插件的GPT會(huì)話。
插件使用示例
基于上面的運(yùn)行原理,我們來(lái)編寫(xiě)一個(gè)GPT插件的示例程序。
在這個(gè)示例程序中,我將提供一個(gè)天氣查詢的插件,當(dāng)用戶詢問(wèn)GPT今天的天氣時(shí),GPT就會(huì)命中這個(gè)插件,然后插件會(huì)調(diào)用外部API獲取實(shí)時(shí)的天氣情況,最后GPT會(huì)使用插件生成的結(jié)果組織一段文字回復(fù)返回給用戶。
編寫(xiě)天氣插件
這里我們將使用“心知天氣”提供的免費(fèi)天氣查詢服務(wù),大家感興趣的可以去這里注冊(cè)個(gè)賬號(hào):https://www.seniverse.com/,注冊(cè)成功后,需要復(fù)制賬號(hào)的私鑰,調(diào)用天氣接口時(shí)會(huì)用到。
然后我們就可以編寫(xiě)天氣查詢插件了,這里直接給出我的代碼:
def get_city_weather(param):
city = json.loads(param)["city"]
params = {
"key": "這里換成你的天氣產(chǎn)品私鑰",
"location": city,
"language": "zh-Hans",
"unit": "c",
}
url = "https://api.seniverse.com/v3/weather/now.json"
r = requests.get(url, params=params)
data = r.json()["results"]
address = data[0]["location"]['path']
temperature = data[0]['now']["temperature"]
text = data[0]['now']["text"]
return address+",當(dāng)前天氣:"+text+",溫度:"+temperature+ "℃"
可以看到就是一個(gè)Python函數(shù),接收json格式的參數(shù),返回天氣描述信息。
注意這里的參數(shù)格式(包括有哪些參數(shù))是和GPT大模型匹配過(guò)的,下文會(huì)講到怎么定義參數(shù)。
接口的主要邏輯就是使用城市名稱(chēng),調(diào)用實(shí)時(shí)天氣接口獲取天氣信息,然后再拼接成一段話并返回。
我這里只使用了天氣的部分指標(biāo),詳細(xì)指標(biāo)大家可以看接口文檔:
發(fā)起帶插件的聊天
話不多說(shuō),看代碼:
client = OpenAI(api_key='sk-xxx')
# 聊天消息上下文
messages=[{
"role": "user",
"content": "請(qǐng)問(wèn)現(xiàn)在天氣怎么樣?",
}]
# 天氣插件
weather_tool = {
"type": "function",
"function": {
"name": "get_city_weather",
"description": "獲取某個(gè)城市的天氣",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名稱(chēng)",
},
},
"required": ["city"],
},
}
}
# 發(fā)起聊天請(qǐng)求
response = client.chat.completions.create(
messages=messages,
model='gpt-3.5-turbo-1106',
stream=False,
# 插件相關(guān)
tool_choice="auto",
tools=[weather_tool]
)
在上面這段代碼中,我們首先聲明了一個(gè)OpenAI客戶端,沒(méi)有API Key的同學(xué)可以看文章最后。
然后我們創(chuàng)建了一個(gè)很普通的聊天會(huì)話,就是以普通用戶的身份詢問(wèn)GPT今天的天氣情況。
然后我們定義了一個(gè)天氣插件,其實(shí)就是一個(gè)Json對(duì)象。
- type:目前只能傳 fucntion,也就是說(shuō)目前插件就是外置函數(shù)。
- function:函數(shù)的定義。
- name:函數(shù)的名稱(chēng),這里就是我們上邊定義的 get_city_weather。
- description:函數(shù)的描述,GPT將使用這個(gè)描述來(lái)決定什么時(shí)候以及如何調(diào)用函數(shù)。
- parameters:函數(shù)的參數(shù)。
- type:固定object
- properties:定義函數(shù)的各個(gè)參數(shù),每個(gè)參數(shù)包含兩個(gè)屬性:type和description,description也很重要,讓GPT模型知道怎么來(lái)提供這個(gè)參數(shù)。
- required:數(shù)組,定義必填的參數(shù)。
最后我們向GPT發(fā)起本次聊天請(qǐng)求,其中增加了關(guān)于插件的兩個(gè)參數(shù):
- tool_choice:開(kāi)啟插件,固定值 auto,設(shè)置為none則不使用插件。
- tools:插件列表,包含我們上邊定義的 weather_tool 插件。
處理插件命中
如果GPT大模型命中了插件,它會(huì)在返回值中攜帶一些信息。根據(jù)這些信息,我們可以知道要調(diào)用哪個(gè)插件的函數(shù),然后再把函數(shù)的執(zhí)行結(jié)果附加到消息上下文中,再請(qǐng)求GPT大模型,GPT大模型會(huì)使用函數(shù)返回值組織文本內(nèi)容,最終返回給用戶。
相關(guān)代碼如下:
response_message = response.choices[0].message
if response_message.tool_calls is not None:
tool_call = response_message.tool_calls[0]
messages.append(response_message)
messages.append({
"role": "tool",
"content": get_city_weather(tool_call.function.arguments),
"tool_call_id": tool_call.id
})
response = client.chat.completions.create(
messages=messages,
model='gpt-3.5-turbo-1106',
stream=False,
tool_choice="auto",
tools=[weather_tool]
)
print(response_message.choices[0].message.content)
判斷是否命中插件使用的是 response_message.tool_calls is not None,也就是返回值中的 tool_calls 不為空,因?yàn)檫@里只有一個(gè)插件,所以我們沒(méi)有做進(jìn)一步的判斷;如果有多個(gè)插件,可以遍歷tool_calls,根據(jù)插件關(guān)聯(lián)函數(shù)的 name,選擇執(zhí)行不同的方法。
注意這里我們把本次響應(yīng)的消息又追加到了上下文中:messages.append(response_message)。
然后我們又追加了插件生成的消息,就是下面這段:
messages.append({
"role": "tool",
"content": get_city_weather(tool_call.function.arguments),
"tool_call_id": tool_call.id
})
介紹下這幾個(gè)字段:
- role:指定這個(gè)消息來(lái)自插件。
- content:指定消息的內(nèi)容。get_city_weather 就是我們上邊定義的插件方法,而它的參數(shù) tool_call.function.arguments 則是大模型生成的 ,這個(gè)方法會(huì)在在本地執(zhí)行,并生成一段天氣信息描述。
- tool_call_id:這段消息關(guān)聯(lián)的插件id,需要讓大模型了解這個(gè)數(shù)據(jù)關(guān)系。
然后我們又通過(guò) client.chat.completions.create 向GPT大模型發(fā)起請(qǐng)求 ,并拿到最終的返回結(jié)果。
完整的代碼示例
因?yàn)樯衔闹袃纱握?qǐng)求GPT大模型的方法都是一樣的,所以我們這里把它抽象為一個(gè)方法。
另外為了充分展現(xiàn)插件的使用方法,這里會(huì)向GPT詢問(wèn)三個(gè)城市的天氣信息,通過(guò)循環(huán)發(fā)起。
from openai import OpenAI
import json
import requests
import time
# 獲取天氣的方法
def get_city_weather(param):
city = json.loads(param)["city"]
params = {
"key": "這里換成你的天氣產(chǎn)品私鑰",
"location": city,
"language": "zh-Hans",
"unit": "c",
}
url = "https://api.seniverse.com/v3/weather/now.json"
r = requests.get(url, params=params)
data = r.json()["results"]
#print(json.dumps(data))
address = data[0]["location"]['path']
temperature = data[0]['now']["temperature"]
text = data[0]['now']["text"]
return address+",當(dāng)前天氣:"+text+",溫度:"+temperature+ "℃"
# 天氣插件的定義
weather_tool = {
"type": "function",
"function": {
"name": "get_city_weather",
"description": "獲取某個(gè)城市的天氣",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名稱(chēng)",
},
},
"required": ["city"],
},
}
}
# 創(chuàng)建OpenAI客戶端,獲取API Key請(qǐng)看文章最后
client = OpenAI(api_key='sk-xxx')
# 定義請(qǐng)求GPT的通用方法
def create_completion():
return client.chat.completions.create(
messages=messages,
model='gpt-3.5-turbo-1106',
stream=False,
tool_choice="auto",
tools=[weather_tool]
)
# 我的三個(gè)問(wèn)題
questions = ["請(qǐng)問(wèn)現(xiàn)在天氣怎么樣?","請(qǐng)問(wèn)上海天氣怎么樣?","請(qǐng)問(wèn)廣州天氣怎么樣?"]
# 聊天上下文,初始為空
messages=[]
print("---GPT天氣插件演示--- ")
# 遍歷詢問(wèn)我的問(wèn)題
for question in questions:
# 將問(wèn)題添加到上下文中
messages.append({
"role": "user",
"content": question,
})
print("路人甲: ",question)
# 請(qǐng)求GPT,并拿到響應(yīng)
response_message = create_completion().choices[0].message
# 把響應(yīng)添加到聊天上下文中
messages.append(response_message)
#print(response_message)
# 根據(jù)插件命中情況,執(zhí)行插件邏輯
if response_message.tool_calls is not None:
tool_call = response_message.tool_calls[0]
#print("tool_call: ",tool_call.id)
# 追加插件生成的天氣內(nèi)容到聊天上下文
weather_info = get_city_weather(tool_call.function.arguments)
#print(weather_info)
messages.append({
"role": "tool",
"content": weather_info,
"tool_call_id": tool_call.id
})
# 再次發(fā)起聊天
second_chat_completion = create_completion()
gpt_output = second_chat_completion.choices[0].message.content
# 打印GPT合成的天氣內(nèi)容
print("GPT: ",gpt_output)
time.sleep(0.2)
# 將GPT的回答也追加到上下文中
messages.append({
"role": "assistant",
"content": gpt_output,
})
以上就是本文的主要內(nèi)容,有沒(méi)有感受到插件的強(qiáng)大能力!
后續(xù)我還會(huì)繼續(xù)分享圖片、語(yǔ)音、文檔助手等API的使用方法。
如需GPT賬號(hào)、學(xué)習(xí)陪伴群、AI編程訓(xùn)練營(yíng),推薦關(guān)注小冊(cè):大模型應(yīng)用開(kāi)發(fā) | API 實(shí)操文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-807271.html
關(guān)注螢火架構(gòu),加速技術(shù)提升!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-807271.html
到了這里,關(guān)于GPT應(yīng)用開(kāi)發(fā):編寫(xiě)插件獲取實(shí)時(shí)天氣信息的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!