欢迎阅读本系列文章!我将带你一起探索如何利用 OpenAI API 开发 GPT 应用。无论你是编程新手还是资深开发者,都能在这里获得灵感和收获。
本文,我们将继续展示聊天 API 中插件的使用方法,让你能够轻松驾驭这个强大的工具。
插件运行效果
首先给大家展示下插件的运行效果,如下图所示:
可以看到,每次询问 GPT,它都会返回指定城市的实时天气信息,这个天气是真实的,不是 GPT 瞎编的,是 GPT 通过一个实时天气插件查询到的。
插件运行原理
知己知彼,百战不殆!首先让我们来了解下插件的运行原理。如下图所示:
首先我们在客户端发起一个聊天会话,比如询问 GPT:“今天天气怎么样?”
为了使用我们自己的插件,我们还需要告诉 GPT 有哪些插件可用,目前这需要我们在发起聊天时传递一个支持的插件列表给 GPT。
然后 GPT 收到我们的聊天后,它会根据用户的聊天内容去匹配插件,并在返回的消息中指示命中了哪些插件,这个匹配是根据 GPT 的语言理解能力做出的。
然后客户端就可以检查命中了哪些插件,并调用执行本地相应的插件方法。插件方法是在本地执行的,这也比较合理,如果放到 GPT 服务端,GPT 不仅要适配各种计算能力,还可能面临巨大的安全风险。
然后客户端将插件的执行结果附加到本次聊天会话中,再次发起聊天请求,GPT 收到后,会根据首次聊天请求和插件生成的内容组织本次聊天响应结果,再返回给用户。
这样就完成了一次基于插件的 GPT 会话。
插件使用示例
基于上面的运行原理,我们来编写一个 GPT 插件的示例程序。
在这个示例程序中,我将提供一个天气查询的插件,当用户询问 GPT 今天的天气时,GPT 就会命中这个插件,然后插件会调用外部 API 获取实时的天气情况,最后 GPT 会使用插件生成的结果组织一段文字回复返回给用户。
编写天气插件
这里我们将使用“心知天气”提供的免费天气查询服务,大家感兴趣的可以去这里注册个账号:https://www.seniverse.com/,注册成功后,需要复制账号的私钥,调用天气接口时会用到。
然后我们就可以编写天气查询插件了,这里直接给出我的代码:
def get_city_weather(param):
city = json.loads(param)["city"]
params = {
"key": "这里换成你的天气产品私钥",
"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+",当前天气:"+text+",温度:"+temperature+ "℃"
复制代码
可以看到就是一个 Python 函数,接收 json 格式的参数,返回天气描述信息。
注意这里的参数格式(包括有哪些参数)是和 GPT 大模型匹配过的,下文会讲到怎么定义参数。
接口的主要逻辑就是使用城市名称,调用实时天气接口获取天气信息,然后再拼接成一段话并返回。
我这里只使用了天气的部分指标,详细指标大家可以看接口文档:
https://seniverse.yuque.com/hyper_data/api_v3/nyiu3t?#%20%E3%80%8A%E5%A4%A9%E6%B0%94%E5%AE%9E%E5%86%B5%E3%80%8B
发起带插件的聊天
话不多说,看代码:
client = OpenAI(api_key='sk-xxx')
# 聊天消息上下文
messages=[{
"role": "user",
"content": "请问现在天气怎么样?",
}]
# 天气插件
weather_tool = {
"type": "function",
"function": {
"name": "get_city_weather",
"description": "获取某个城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称",
},
},
"required": ["city"],
},
}
}
# 发起聊天请求
response = client.chat.completions.create(
messages=messages,
model='gpt-3.5-turbo-1106',
stream=False,
# 插件相关
tool_choice="auto",
tools=[weather_tool]
)
复制代码
在上面这段代码中,我们首先声明了一个 OpenAI 客户端,没有 API Key 的同学可以看文章最后。
然后我们创建了一个很普通的聊天会话,就是以普通用户的身份询问 GPT 今天的天气情况。
然后我们定义了一个天气插件,其实就是一个 Json 对象。
最后我们向 GPT 发起本次聊天请求,其中增加了关于插件的两个参数:
处理插件命中
如果 GPT 大模型命中了插件,它会在返回值中携带一些信息。根据这些信息,我们可以知道要调用哪个插件的函数,然后再把函数的执行结果附加到消息上下文中,再请求 GPT 大模型,GPT 大模型会使用函数返回值组织文本内容,最终返回给用户。
相关代码如下:
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 不为空,因为这里只有一个插件,所以我们没有做进一步的判断;如果有多个插件,可以遍历 tool_calls,根据插件关联函数的 name,选择执行不同的方法。
注意这里我们把本次响应的消息又追加到了上下文中:messages.append(response_message)。
然后我们又追加了插件生成的消息,就是下面这段:
messages.append({
"role": "tool",
"content": get_city_weather(tool_call.function.arguments),
"tool_call_id": tool_call.id
})
复制代码
介绍下这几个字段:
然后我们又通过 client.chat.completions.create 向 GPT 大模型发起请求 ,并拿到最终的返回结果。
完整的代码示例
因为上文中两次请求 GPT 大模型的方法都是一样的,所以我们这里把它抽象为一个方法。
另外为了充分展现插件的使用方法,这里会向 GPT 询问三个城市的天气信息,通过循环发起。
from openai import OpenAI
import json
import requests
import time
# 获取天气的方法
def get_city_weather(param):
city = json.loads(param)["city"]
params = {
"key": "这里换成你的天气产品私钥",
"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+",当前天气:"+text+",温度:"+temperature+ "℃"
# 天气插件的定义
weather_tool = {
"type": "function",
"function": {
"name": "get_city_weather",
"description": "获取某个城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称",
},
},
"required": ["city"],
},
}
}
# 创建OpenAI客户端,获取API Key请看文章最后
client = OpenAI(api_key='sk-xxx')
# 定义请求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]
)
# 我的三个问题
questions = ["请问现在天气怎么样?","请问上海天气怎么样?","请问广州天气怎么样?"]
# 聊天上下文,初始为空
messages=[]
print("---GPT天气插件演示--- ")
# 遍历询问我的问题
for question in questions:
# 将问题添加到上下文中
messages.append({
"role": "user",
"content": question,
})
print("路人甲: ",question)
# 请求GPT,并拿到响应
response_message = create_completion().choices[0].message
# 把响应添加到聊天上下文中
messages.append(response_message)
#print(response_message)
# 根据插件命中情况,执行插件逻辑
if response_message.tool_calls is not None:
tool_call = response_message.tool_calls[0]
#print("tool_call: ",tool_call.id)
# 追加插件生成的天气内容到聊天上下文
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
})
# 再次发起聊天
second_chat_completion = create_completion()
gpt_output = second_chat_completion.choices[0].message.content
# 打印GPT合成的天气内容
print("GPT: ",gpt_output)
time.sleep(0.2)
# 将GPT的回答也追加到上下文中
messages.append({
"role": "assistant",
"content": gpt_output,
})
复制代码
以上就是本文的主要内容,有没有感受到插件的强大能力!
后续我还会继续分享图片、语音、文档助手等 API 的使用方法。
文章转载自:萤火架构
原文链接:https://www.cnblogs.com/bossma/p/17973843
体验地址:http://www.jnpfsoft.com/?from=001
评论