LangChain的函数,工具和代理(一):OpenAI的函数调用

一、什么是函数调用功能

几个月前OpenAI官方发布了其API的函数调用功能(Function calling), 在 API 调用中,您可以描述函数,并让模型智能地选择输出包含调用一个或多个函数的参数的 JSON 对象。API函数“ChatCompletion” 虽然不会实际调用该函数;但是模型会生成这些基于函数参数的JSON对象,您可以使用它来调用代码中的实际函数。

也就是说当用户和ChatGPT对话的过程中需要调用某些外部的函数或者API时,我们可以让ChatGPT生成调用外部函数所需的参数,然后我们再使用这些参数再去实际的调用外部函数,目前OpenAl 对 gpt-3.5-turbo-0613 和 gpt-4-0613 模型进行了微调,使它们具备了以下函数调用功能:

1. 接受额外的参数,用户可以通过这些参数传入函数的描述。
2. 如果相关,则返回要使用的函数的名称,以及带有适当输入参数的 JSON 对象。

二,如何实现OpenAI的函数调用功能

在实现OpenAI的函数调用功能之前,我们先定义一个外部函数,当用户和ChatGPT对话时,ChatGPT会自动判断是否需要调用外部函数,当需要调用外部函数时ChatGPT会返回调用函数的json对象给用户:

import json

# 查询天气的模拟函数示例
# 在生产中,这可能是您的后端 API 或外部 API
def get_current_weather(location, unit="fahrenheit"):
    """Get the current weather in a given location"""
    weather_info = {
        "location": location, #城市
        "temperature": "72", # 温度
        "unit": unit, #温度单位
        "forecast": ["sunny", "windy"], #天气情况
    }
    return json.dumps(weather_info)

这里我们定义一个外部函数get_current_weather,他用来查询特定城市的天气情况,并返回一个jons对象作为查询结果。接下来我们需要定义一个该函数的描述对象,该描述对象后面会作为参数传递给ChatGPT:

#函数描述对象
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"],
        },
    }
]

下面我们来说明一下函数描述对象的主要成员:

  • name: 外部函数名称如get_current_weather
  • description:外部函数功能的描述
  • parameters:外部函数的参数集
  • parameters-type:外部函数的参数集的类型
  • properties:外部函数的具体参数集
  • location:具体的外部函数的参数
  • location-type:外部函数的参数的类型
  • location-description:外部函数的参数的描述
  • unit:具体的外部函数的参数
  • unit-type:外部函数的参数的类型
  • enum:外部函数的参数的枚举值
  • required:必填的参数

这里我们生成了一个外部函数的描述对象,该描述对象会告诉ChatGPT该外部函数的作用,以及我们需要在恰当的时候来调用该函数,至于什么时候才是“恰当的时候”这需要由ChatGPT根据用户对话的上下文来判断。接下来我们向ChatGPT询问一个关于天气的问题:

import openai
openai.api_key = "XXXXXXXXX"

messages = [
    {
        "role": "user",
        "content": "上海的天气怎么样?"
    }
]

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions
)

print(response)

这里我们向ChatGPT提出了关于天气的问题:“上海的天气怎么样?”, 从ChatGPT的返回结果中我们看到"function_call",这告诉我们接下来我们该调用外部函数了,同时ChatGPT还返回了调用外部函数的参数location和unit,以及所需调用的外部函数名:get_current_weather,有意思的是这里返回的unit为“celsius”即摄氏度而非美国使用的"fahrenheit(华氏度)", 这似乎说明ChatGPT知道中国使用摄氏度作为温度的单位,下面我们询问一下美国城市的天气:

messages = [
    {
        "role": "user",
        "content": "What's the weather like in Boston?" #波士顿 的天气怎么样?
    }
]

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions
)

print(response)

这里我们用英语询问了美国城市波士顿的天气情况,从ChatGPT的返回结果中我们看到arguments中只包含了location,而没有包含unit, 而在我们的外部函数get_current_weather中unit为非必填参数,它有一个默认值为:unit="fahrenheit",因此在实际调用外部函数时我们只需将chatgpt返回结果中的arguments中取出对应的参数然后传递给外部函数即可,接下来我们从ChatGPT的返回结果中获取参数来实际调用外部函数get_current_weather:

args = json.loads(response_message["function_call"]["arguments"])
result=get_current_weather(args)
print(result)

 接下来我们来测试一下ChatGPT能否准确识别何时该调用外部函数,下面我们会对ChatGPT发送一个简单的问候语:hi,  当Chatgpt收到该问候语时不应该触发函数调用功能:

messages = [
    {
        "role": "user",
        "content": "hi!",
    }
]

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions,
)

print(response)

从上面的chatgpt的返回结果中我们看到不存在先前的“function_call"内容即没有生成外部函数的调用参数,这说明此时我们不需要调用外部函数。

三、设置OPAI API的默认参数

openai的API函数ChatCompletion.create中存在一个function_call的参数,该参数的默认值为“auto”即让模型自己来选择是否需要调用外部函数:

messages = [
    {
        "role": "user",
        "content": "hi!",
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions,
    function_call="auto",
)
print(response)

上面我们在openai.ChatCompletion.create的方法中加入了function_call="auto",意思是让模型根据上下文来确定是否调用外部函数,我们看到当我们向ChatGPT打招呼时,如输入“hi”时 ,chatgpt的返回结果中没有“function_call”的内容。这说明ChatGPT知道此时不应该调用外部函数。

messages = [
    {
        "role": "user",
        "content": "hi!",
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions,
    function_call="none",#禁止调用外部函数
)
print(response)

上面当我们将function_cal设置为"none"时(即禁止chatGPT调用外部函数),chatGPT的返回结果中也不会出现“function_call”的内容。

messages = [
    {
        "role": "user",
        "content": "What's the weather in Boston?",
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions,
    function_call="none", #禁止调用外部函数
)
print(response)

在上面的代码中我们向ChatGPT询问了波士顿的天气,但是我们设置了function_call="none",也就是说虽然我们询问了波士顿的天气情况,但我们却禁止chatgpt调用外部函数,从chatgpt的返回结果中我们看到仍然没有“function_cal”的相关内容。

下面我们设置chatgpt强制调用外部函数,看看会发生上面情况:

messages = [
    {
        "role": "user",
        "content": "hi!",
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions,
    function_call={"name": "get_current_weather"},#强制调用外部函数
)
print(response)

在上面的代码中我们在 ChatCompletion.create中设置了function_call={"name": "get_current_weather"}意思是让chatgpt强制生成调用get_current_weather函数的参数,但是我们向chatgpt发送的用户消息却是:hi!, 这时会让chatgpt产生困惑,因为用户消息中没有有关询问天气的内容,但是却要强制chatgpt去生成外部函数的调用参数,所以在chatgpt的返回结果中function_call中的arguments中给出了一个随机的location:San Francisco,CA。

下面我们向chatgpt询问波士顿的天气,并且让chatgpt强制调用get_current_weather,看看会发生什么情况:

messages = [
    {
        "role": "user",
        "content": "What's the weather like in Boston!",
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    functions=functions,
    function_call={"name": "get_current_weather"}, #强制调用外部函数
)
print(response)

从上面的chatgpt的返回结果中我们看到了“function_call”中的内容。这说明只要我们设置了chatgpt强制指定了外部调用函数时,它总会生成相应的函数参数。

四、外部函数的调用结果的应用

上面我们让chatgpt来判断是否应该调用外部函数,并且让chatgpt返回了调用外部函数的参数,接下来我们要做的是用chatgpt提供的参数去实际调用外部函数,并将外部函数的返回结果再喂给chatgpt,这样做的目的是让chatgpt来汇总所有的信息并产生最终对用户友好的返回信息。

#整合chatgpt的返回结果
messages.append(response["choices"][0]["message"])
#从chatgpt的返回结果中获取外部函数的调用参数
args = json.loads(response["choices"][0]["message"]['function_call']['arguments'])
#调用外部函数
observation = get_current_weather(args)

messages.append(
        {
            "role": "function",
            "name": "get_current_weather",
            "content": observation, #外部函数的返回结果
        }
)

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=messages,
)
print(response)

 这里我们看到ChatGPT最终返回了一个非常友好的回复,该回复是在外部函数调用结果的基础上经过整理后得到的。

关于token统计

我们知道chatgpt的API是通过token来收费的,这里我们在使用chatgpt的函数调用功能时我们创建了一个函数描述对象functions,因此functions也会作为上下文的一部分被统计token数,下面我们去掉ChatCompletion.create中的functions和function_call这两个参数看看最后chatgpt返回的总的token数是多少:

messages = [
    {
        "role": "user",
        "content": "What's the weather like in Boston!",
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-1106",
    messages=messages
)
print(response)

从上面的返回结果中我们看到当我们去掉了ChatCompletion.create中的functions和function_call这两个参数时,总token数为48,而先前的总token数为99,这说明外部函数描述对象functions被统计了token数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/173839.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FL Studio21怎么破解?2024年最新FLStudio21.2.0安装解锁特别版下载使用图文教程

用FL Studio编曲,让音乐成为你的翅膀,飞翔在无尽的创作海洋中吧! FL Studio作为一款功能强大且备受赞誉的音乐制作软件,为你提供了一个独特的创作平台。通过FL Studio,你可以自由地创作、编曲,制作属于自己…

【代数学习题4.1】从零理解范数与迹 —— 求极小多项式

从零理解范数与迹 —— 求极小多项式 写在前面概念解释题目解答 1. 极小多项式极小多项式的求法1. 对 α \alpha α 的极小多项式python求解 2. 对 α 1 \alpha 1 α1 的极小多项式python找到多项式python找到极小多项式 3. 对 α 2 α 1 \alpha^2 \alpha 1 α2α1 的…

Docker快速搭建RTMP服务(tiangolo/nginx-rtmp:Docker + Nginx+ nginx-rtmp-module)

Linux Docker快速搭建多媒体/视频流的 RTMP 服务 第一步 安装Docker 点击这里查看 第二步 拉取并运行镜像 tiangolo/nginx-rtmp/ docker pull tiangolo/nginx-rtmp docker run -d -p 1935:1935 --name nginx-rtmp tiangolo/nginx-rtmpOBS客户端测试 OBS客户端设置直播的推…

K8S精进之路-控制器Deployment-(1)

在K8S中,最小运行单位为POD,它是一个逻辑概念,其实是一组共享了某些资源的容器组。POD是能运行多个容器的,Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume。在POD中能够hold住网络…

3.基于多能互补的热电联供微网优化运行复现(matlab代码)

0.代码链接 基于多能互补的热电联供微电网/综合能源系统优化运行(Matlab程序Yalmip+Cplex求解)_工业综合能源系统资源-CSDN文库 2. 主要内容:代码主要做的是多能互补的热电联供型微网优化运行模型,在需求侧对负荷类型…

庖丁解牛:NIO核心概念与机制详解 07 _ 字符集

文章目录 Pre概述编码/解码处理文本的正确方式示例程序Code Pre 庖丁解牛:NIO核心概念与机制详解 01 庖丁解牛:NIO核心概念与机制详解 02 _ 缓冲区的细节实现 庖丁解牛:NIO核心概念与机制详解 03 _ 缓冲区分配、包装和分片 庖丁解牛&…

点击这里,获取数据治理加速器!

数据管理员:又双叒叕…盘一遍数据,这种工作究竟还要重复多少次?! • 上上个月,发现数据有些问题,我把数据盘了一遍,梳理完数据的关联表才定位到问题; • 上个月,进行数据…

Linux 系列之 在一个文本中查找指定的数据

我 | 在这里 🕵️ 读书 | 长沙 ⭐软件工程 ⭐ 本科 🏠 工作 | 广州 ⭐ Java 全栈开发(软件工程师) 🎃 爱好 | 研究技术、旅游、阅读、运动、喜欢流行歌曲 🏷️ 标签 | 男 自律狂人 目标明确 责任心强 ✈️公…

SO3 与so3 SE3与se3 SIM3

文章目录 1 旋转*叉乘1.1 旋转矩阵的导数1.2 物理意义1.3 实例1.4 角轴与反对称矩阵 2 SO3 与so32.1 so3 2 SO32.2 SO3 2 so3 3 SE3 与se33.1 se3 2 SE3:3.2 SE3 2 se3 4 SIM3 与sim35 Adjoint Map 1 旋转*叉乘 1.1 旋转矩阵的导数 根据旋转矩阵的性质: R R T I …

Python实现WOA智能鲸鱼优化算法优化Catboost分类模型(CatBoostClassifier算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 鲸鱼优化算法 (whale optimization algorithm,WOA)是 2016 年由澳大利亚格里菲斯大学的Mirjalili 等提…

windows11系统如何设置锁屏壁纸

1. 在开始页面里面找到设置 2. 在设置里面找到个性化 3. 按照红色圈出部分操作 个性化锁屏界面 选择 图片 浏览照片 选择一张你觉得好看的图片作为锁屏壁纸 注:如果需要在锁屏后的登录页面显示壁纸 请勾选第三个红圈部分

opencv-图像平滑

高斯平滑 高斯平滑即采用高斯卷积核对图像矩阵进行卷积操作。高斯卷积核是一个近似服从高斯分布的矩阵,随着距离中心点的距离增加,其值变小。这样进行平滑处理时,图像矩阵中锚点处像素值权重大,边缘处像素值权重小。 import cv2 …

工业领域的设备“监测”和“检测”有何区别?

在工业领域中,设备的监测和检测是关键的运维活动,它们在保障设备可靠性和生产效率方面发挥着重要作用。尽管这两个术语经常被人们混为一谈,但它们在含义和应用上存在一些关键区别。 "监测"与"检测"的概念 1. 监测&#…

【每日一题】设计循环队列(C语言)

循环队列是我们可以对队列有更深一步的理解的题目,而且可以进一步加强其他方面的知识(例如对循环数组的取模运算,指针的解引用),是个蛮不错的巩固习题,话不多说,进入正题。 链接在此&#xff1…

【漏洞复现】IP-guard WebServer 存在远程命令执行漏洞

漏洞描述 IP-guard是由溢信科技股份有限公司开发的一款终端安全管理软件,旨在帮助企业保护终端设备安全、数据安全、管理网络使用和简化IT系统管理。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危…

Fiddle抓包工具的安装

Fiddle抓包工具的安装 首先进入官网:https://www.telerik.com/download/fiddler/fiddler-everywhere-windows 然后Fiddle为我们提供了很多个版本,其中只有一个版本是免费的,如下图: 成功下载如下图:

requests解决HAR支持问题:引入第三方库提升开发效率

关于HAR支持的问题已关闭。HAR(HTTP Archive)是一种用于存储HTTP请求和响应的标准格式,广泛应用于网络调试和性能优化中。然而,HAR支持的缺失可能会给开发者带来不便,影响其工作效率。 解决方案 为了解决这个问题&…

【图数据库实战】图数据库基本概念

1、图数据库的概念 维基百科图书库的概念: 在计算机科学中,图数据库(英语:graph database,GDB)是一个使用图结构进行语义查询的数据库,它使用节点、边和属性来表示和存储数据。该系统的关键概念…

【vue】ant-design-vue的树结构实现节点增删改查

根据业务需要,实现树结构的节点新增编辑删除功能,主要逻辑是利用树节点的scopedSlots属性对其进行自定义改造,监听悬停事件在节点右侧出现增删改对应图标,点击图标出现弹窗表单对内容进行修改,具体代码如下&#xff1a…

prometheus基本介绍 prometheus和zabbix的区别 grafana可视化工具

一、 promethues概念prometheus介绍promethues的特点prometheus的工作原理prometheus的架构 二、promethues和zabbix的区别三、prometheus安装部署prometheus下载安装prometheus启动浏览器访问查看暴露指标将Prometheus配置为systemd管理 配置node_exporter监控项node_promethe…