欢迎阅读本系列文章!我将带你一起探索如何利用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大模型匹配过的,下文会讲到怎么定义参数。

接口的主要逻辑就是使用城市名称,调用实时天气接口获取天气信息,然后再拼接成一段话并返回。

我这里只使用了天气的部分指标,详细指标大家可以看接口文档:

发起带插件的聊天

话不多说,看代码:

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对象。

  • type:目前只能传 fucntion,也就是说目前插件就是外置函数。
  • function:函数的定义。
    • name:函数的名称,这里就是我们上边定义的 get_city_weather。
    • description:函数的描述,GPT将使用这个描述来决定什么时候以及如何调用函数。
    • parameters:函数的参数。
      • type:固定object
      • properties:定义函数的各个参数,每个参数包含两个属性:type和description,description也很重要,让GPT模型知道怎么来提供这个参数。
      • required:数组,定义必填的参数。

最后我们向GPT发起本次聊天请求,其中增加了关于插件的两个参数:

  • tool_choice:开启插件,固定值 auto,设置为none则不使用插件。
  • tools:插件列表,包含我们上边定义的 weather_tool 插件。

处理插件命中

如果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
})

介绍下这几个字段:

  • role:指定这个消息来自插件。
  • content:指定消息的内容。get_city_weather 就是我们上边定义的插件方法,而它的参数 tool_call.function.arguments 则是大模型生成的 ,这个方法会在在本地执行,并生成一段天气信息描述。
  • tool_call_id:这段消息关联的插件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的使用方法。

如需GPT账号、学习陪伴群、AI编程训练营,推荐关注小册:大模型应用开发 | API 实操

关注萤火架构,加速技术提升!

GPT应用开发:GPT插件开发指南的更多相关文章

  1. Elasticsearch5.5.1插件开发指南

    Elasticsearch5.5.1插件开发指南 原文地址: https://www.elastic.co/guide/en/elasticsearch/plugins/5.5/plugin-auth ...

  2. [置顶] PHP开发实战权威指南-读书总结

    从今年开始,断断续续学习PHP已经有4个月了. 最初,认真学习PHP几天,就弄WordPress搭建了一个个人博客,这也符合技术人的实践理念. 最近,重温PHP开发实战权威指南,做点总结,整理下自己学 ...

  3. 物联网操作系统HelloX开发人员入门指南

    HelloX开发人员入门指南 HelloX是聚焦于物联网领域的操作系统开发项目,能够通过百度搜索"HelloX".获取具体信息. 当前开发团队正在进一步招募中,欢迎您的了解和添加. ...

  4. mac电脑使用,开发环境配置指南

    mac电脑使用,开发环境配置指南 前端工具链,mac下都很好用 用brew来装软件 用brew cask来装应用 Introduction · macOS Setup Guidehttp://sour ...

  5. 【笔记】jQuery插件开发指南

    原文链接:http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html (有部分增删和修改) jQuery插件开发模式 软件开发过程中是需要一定 ...

  6. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  7. 李洪强iOS开发之-入门指南

    李洪强iOS开发之-入门指南 1零基础小白如何进行iOS系统学习 首先,学习目标要明确:其次,有了目标,要培养兴趣,经常给自己一些正面的反馈,比如对自己的进步进行鼓励,在前期小步快走:再次,学技术最重 ...

  8. PHP开发实战权威指南-读书总结

    从今年开始,断断续续学习PHP已经有4个月了.最初,认真学习PHP几天,就弄WordPress搭建了一个个人博客,这也符合技术人的实践理念. 最近,重温PHP开发实战权威指南,做点总结,整理下自己学习 ...

  9. Go 开发关键技术指南 | 敢问路在何方?(内含超全知识大图)

    作者 | 杨成立(忘篱) 阿里巴巴高级技术专家 Go 开发关键技术指南文章目录: 为什么你要选择 Go? Go 面向失败编程 带着服务器编程金刚经走进 2020 年 敢问路在何方? Go 开发指南大图 ...

  10. Windows下C,C++开发环境搭建指南

    Windows下C,C++开发环境搭建指南 前情提要 基于近一段时间很多网友发邮件反馈,说一些项目编译出现问题,诸如此类的情况. 就觉得很有必要写一篇C,C++开发环境的小指南,统一回复. 1.君欲善 ...

随机推荐

  1. [CF1748D] ConstructOR

    题目描述 You are given three integers $ a $ , $ b $ , and $ d $ . Your task is to find any integer $ x $ ...

  2. [ABC280F] Pay or Receive

    Problem Statement There are $N$ towns numbered $1,\ldots,N$ and $M$ roads numbered $1,\ldots,M$. Roa ...

  3. [ABC274E] Booster

    Problem Statement In a two-dimensional plane, there are $N$ towns and $M$ chests. Town $i$ is at the ...

  4. Kafka核心逻辑介绍

    1.概念 Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica)分布式消息系统(kafka2.8.0版本之后接触了对zk的依赖,使用自己 ...

  5. LeetCode15:三数之和(双指针)

     解题思路:常规解法很容易想到O(n^3)的解法,但是,n最大为1000,很显然会超时. 如何优化到O(n^2),a+b+c =0,我们只需要判断 a+b的相反数是否在数组中出现,而且元素的取值范围在 ...

  6. java框架Mybatis的第一个程序

    1:什么是MyBatis MyBatis 是一款优秀的持久层框架 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程 MyBatis 可以使用简单的 XML 或注解来配 ...

  7. 请注意,你的 Pulsar 集群可能有删除数据的风险

    在上一篇 Pulsar3.0新功能介绍中提到,在升级到 3.0 的过程中碰到一个致命的问题,就是升级之后 topic 被删除了. 正好最近社区也补充了相关细节,本次也接着这个机会再次复盘一下,毕竟这是 ...

  8. 文心一言 VS 讯飞星火 VS chatgpt (36)-- 算法导论5.3 6题

    六.请解释如何实现算法 PERMUTE-BY-SORTING,以处理两个或更多优先级相同的情形.也就是说,即使有两个或更多优先级相同,你的算法也应该产生一个均匀随机排列. 文心一言: 算法 PERMU ...

  9. root无法下载

    在 Linux 中,root 用户已经拥有系统中的最高权限.然而,如果你需要确保 root 用户具有所有权限,可以通过以下步骤来进行:(这是不对的) sudo chown -R root:root / ...

  10. .Net 系列:Attribute特性的高级使用及自定义验证实现

    一.特性是什么?特性有什么用? 特性(Attribute)是用于在运行时传递程序中各种元素(比如类.方法.结构.枚举.组件等)的行为信息的声明性标签. 您可以通过使用特性向程序添加声明性信息.一个声明 ...