GLM4——Function calling(函数调用)

作用:

Function Calling可以根据用户的输入自行判断何时需要调用哪些函数,并且可以根据目标函数的描述生成符合要求的请求参数。开发人员可以使用函数调用能力,通过GPT实现:

在进行自然语言交流时,通过调用外部工具回答问题(类似于ChatGPT插件);

将自然语言转换为调用API时使用的参数,或者查询数据库时使用的条件;

假设我们要创建一个具备查询航班功能的聊天机器人。我们定义如下两个外部函数供模型选择调用:

  1. 查询两地之间某日航班号函数:get_flight_number(departure: str, destination: str, date: str)

  2. 查询航班号以及日期查询票价函数:get_ticket_price(flight_number: str, date: str)

一、定义本地函数

为了向模型描述外部函数库,需要向 tools 字段传入可以调用的函数列表。参数如下表:

参数名称类型是否必填参数说明
typeString设置为function
functionObject
nameString函数名称
descriptionString用于描述函数功能。模型会根据这段描述决定函数调用方式
parametersObjectparameters Object是数所接受的参数。若调用函数时不需要传入参数,省略该参数即可

代码

tools = [{"type": "function","function": {"name": "get_flight_number","description": "根据始发地、目的地和日期,查询对应日期的航班号","parameters": {"type": "object","properties": {"departure": {"description": "出发地","type": "string"},"destination": {"description": "目的地","type": "string"},"date": {"description": "日期","type": "string",}},"required": [ "departure", "destination", "date" ]},}},{"type": "function","function": {"name": "get_ticket_price","description": "查询某航班在某日的票价","parameters": {"type": "object","properties": {"flight_number": {"description": "航班号","type": "string"},"date": {"description": "日期","type": "string",}},"required": [ "flight_number", "date"]},}},
] 

二、实现

import jsondef parse_function_call(model_response,messages):# 处理函数调用结果,根据模型返回参数,调用对应的函数。# 调用函数返回结果后构造tool message,再次调用模型,将函数结果输入模型# 模型会将函数调用结果以自然语言格式返回给用户。if model_response.choices[0].message.tool_calls:tool_call = model_response.choices[0].message.tool_calls[0]args = tool_call.function.argumentsfunction_result = {}if tool_call.function.name == "get_flight_number":function_result = get_flight_number(**json.loads(args))if tool_call.function.name == "get_ticket_price":function_result = get_ticket_price(**json.loads(args))messages.append({"role": "tool","content": f"{json.dumps(function_result)}","tool_call_id":tool_call.id})response = client.chat.completions.create(model="glm-4",  # 填写需要调用的模型名称messages=messages,tools=tools,)print(response.choices[0].message)messages.append(response.choices[0].message.model_dump()) 

三、大模型自动调用对应的函数
1、查询航班,并返回航班号

from zhipuai import ZhipuAIclient = ZhipuAI(api_key="") # 请填写您自己的APIKey
messages = []
messages.append({"role": "user", "content": "帮我查询从2024年1月20日,从北京出发前往上海的航班"})
response = client.chat.completions.create(model="glm-4",  # 填写需要调用的模型名称messages=messages,tools=tools,
)
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump()) 

执行结果

content=None role='assistant' tool_calls=[CompletionMessageToolCall(id='call_8252663420321749719', function=Function(arguments='{"date":"2024-01-20","departure":"北京","destination":"上海"}', name='get_flight_number'), type='function')]

根据航班号,查询航班票价

messages = []
messages.append({"role": "system", "content": "不要假设或猜测传入函数的参数值。如果用户的描述不明确,请要求用户提供必要信息"})
messages.append({"role": "user", "content": "帮我查询2024年1月20日1234航班的票价"})
response = client.chat.completions.create(model="glm-4",  # 填写需要调用的模型名称messages=messages,tools=tools,
)
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump()) 

执行结果:

content=None role='assistant' tool_calls=[CompletionMessageToolCall(id='call_8252648611274312180', function=Function(arguments='{"date":"2024-01-20","flight_number":"1234"}', name='get_ticket_price'), type='function')]

根据出发地、目的地及出发时间,自动调用2个函数返回票价(多 Function 调用)
首先,修改函数实现,get_flight_number返回date和flight_number2个结果

def get_flight_number(date:str , departure:str , destination:str):flight_number = {"北京":{"上海" : "1234","广州" : "8321",},"上海":{"北京" : "1233","广州" : "8123",}}return { "date":date,"flight_number":flight_number[departure][destination] }
def get_ticket_price(date:str , flight_number:str):print(date)print(flight_number)return {"ticket_price": "1000"}

其次,修改parse_function_call,支持多次调用函数

import jsondef parse_function_call(model_response,messages):# 处理函数调用结果,根据模型返回参数,调用对应的函数。# 调用函数返回结果后构造tool message,再次调用模型,将函数结果输入模型# 模型会将函数调用结果以自然语言格式返回给用户。if model_response.choices[0].message.tool_calls is not None:tool_call = model_response.choices[0].message.tool_calls[0]args = tool_call.function.argumentsprint(tool_call)print(args)function_result = {}if tool_call.function.name == "get_flight_number":function_result = get_flight_number(**json.loads(args))print("---get_flight_number返回结果---")print(json.dumps(function_result))if tool_call.function.name == "get_ticket_price":function_result = get_ticket_price(**json.loads(args))print("---get_flight_number返回结果---")print(json.dumps(function_result))messages.append({"role": "tool","content": f"{json.dumps(function_result)}","tool_call_id":tool_call.id})print(messages)response = client.chat.completions.create(model="glm-4",  # 填写需要调用的模型名称messages=messages,tools=tools,)print("---第二次调用---")print(response.choices[0].message)messages.append(response.choices[0].message.model_dump())parse_function_call(response,messages) 

最后,修改大模型prompt为“帮我查询2024年3月23日,北京到广州的航班的票价”

import json
# 清空对话
messages = []messages.append({"role": "system", "content": "不要假设或猜测传入函数的参数值。如果用户的描述不明确,请要求用户提供必要信息"})
messages.append({"role": "user", "content": "帮我查询2024年3月23日,北京到广州的航班的票价"})response = client.chat.completions.create(model="glm-4",  # 填写需要调用的模型名称messages=messages,tools=tools,tool_choice="auto",
)
print("---第一次调用get_flight_number")
print(response.choices[0].message)
messages.append(response.choices[0].message.model_dump())
parse_function_call(response,messages) 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[图解敏捷口号]普天之下皆我妈-01-新手一次走两步

0 00:00:00,830 --> 00:00:03,750 今天我们来看一句敏捷口号 1 00:00:04,030 --> 00:00:05,660 后面我们会 2 00:00:06,300 --> 00:00:09,570 列一些比较幼稚的口号 3 00:00:09,970 --> 00:00:11,145 一句一句 4 00:00:11,145 --> 00:00:12,790 我们来剖析一…

超级牛逼 专业的 js 汉字拼音转换库

pinyin-pro 是一个专业的 js 汉字拼音转换库,功能丰富、准确率高、性能优异。 🎨 特色功能 支持拼音/声母/韵母/首字母/音调/全部信息支持人名姓氏模式支持文本和拼音匹配支持自定义拼音支持获取带拼音汉字的 HTML 字符串支持获取汉字的所有拼音支持拼音…

SpringBoot 启动控制台 --banner.txt实现打印炫酷控制台图案

文章目录 目录 文章目录 安装流程 小结 概要安装流程技术细节小结 概要 分析源代码,banner.txt实现打印控制台 控制台图案生成网址:Ascii艺术字实现个性化Spring Boot启动banner图案,轻松修改更换banner.txt文件内容,收集了丰富…

SSL证书安装失败怎么办?

在互联网时代,SSL(Secure Sockets Layer)证书已成为保障网站数据传输安全、提升用户信任度的重要工具。然而,在实际操作过程中,SSL证书的安装并非总能一帆风顺,有时会遇到各种导致安装失败的问题。本文将详…

munge服务启动异常问题记录

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、问题一:cannot canonicalize "/var/run/munge"二、问题二:Failed to create "/var/run/munge/munge.socket.2.lock": Perm…

微前端集成模式:独立部署与共享依赖

微前端是一种将复杂的前端应用程序拆分为多个独立的、可独立部署的子应用的架构模式。在微前端中,每个子应用都可以独立开发、测试和部署,而不会影响其他子应用的运行。 在微前端中,有两种常见的集成模式:独立部署和共享依赖。 独…

美硕科技授权世强硬创代理,继电器具备控制功率小、电磁干扰小特点

受工业自动化、智能制造、物联网以及可再生能源等领域发展的推动,全球继电器市场在过去几年中持续增长,预计未来几年将继续保持这一趋势。 为满足日益增长的市场需求,世强先进(深圳)科技股份有限公司(下称…

jvm中的引用类型

Java中的引用类型 1.强引用 一个对象A被局部变量、静态变量引用了就产生了强引用。因为局部变量、静态变量都是被GC Root对象关联上的,所以被引用的对象A,就在GC Root的引用链上了。只要这一层关系存在,对象A就不会被垃圾回收器回收。所以只要…

Linux shell编程学习笔记47:lsof命令

0 前言 今天国产电脑提示磁盘空间已耗尽,使用用df命令检查文件系统情况,发现/dev/sda2已使用100%。 Linux shell编程学习笔记39:df命令https://blog.csdn.net/Purpleendurer/article/details/135577571于是开始清理磁盘空间。 第一步是查看…

第二篇、SD真人视频转卡通动画 学习笔记

接着第一篇 2K转4K 生成玩卡通视频后,如何转换成更高分辨率的视频 1、将第一篇生成的工作目录下的output目录改成output-old,新建一个output目录 2、进入0,1子目录,把EbSynth生成的Outputxxx都删掉,frames和keys下…

IP5306 2.1A充电2.4 A放电电高集成度移动电源SOC IC,为移动电源提供完美电源解决方案

IP5306是一款集成升压转换器、锂电池充电管 理、电池电量指示的多功能电源管理 SOC,为移动 电源提供完整的电源解决方案。 IP5306的高集成度与丰富功能,使其在应用时 仅需极少的外围器件,并有效减小整体方案的尺寸, 降低 BOM 成本…

Unity射击游戏开发教程:(5)使用 GetComponent 在 Unity 中进行脚本通信

我认为脚本通信是刚开始使用 Unity 时较难掌握的概念之一,我将继续讨论这个概念。在本文中,我将介绍如何在游戏对象发生碰撞时使用 GetComponent 来访问另一个脚本。 在这个游戏场景中,我有两个游戏对象,它们都有自己的脚本,需要进行通信。我们有玩家脚本和敌人脚本。Enem…

MP:There is no getter for property named ‘null‘ in ‘class XXX‘异常

在使用主键进行更新或者删除的时候,报下面错误 There is no getter for property named ‘null’ in class 。。。 代码如下 Builder Data public class Course implements Serializable {private static final long serialVersionUID -16929324809307129L;privat…

CC++的内存管理

C&C的内存管理 栈:即用即销毁 堆:有需求再申请空间,手动销毁 注意:const 修饰可以使变量有常性,但是变量存储的域与没有const修饰是相同的。 即: 在 main函数中, const int a 0; int b…

1个月,从估值3.5亿美元到卷款3000万,ZKasino做了什么?

项目rug跑路,对于加密圈的人而言,并不少见。 但rug得这么理直气壮,甚至在圈内掀起了一波对投资机构和KOL的口诛笔伐的项目,ZKasino,也算是头几个。 短短一个月时间,从估值3.5亿美元、众人吹捧的明星级项目&…

深入了解Redis内存淘汰策略中的LRU算法应用

LRU算法简析 LRU(Least Recently Used,最近最少使用)算法是一种常见的内存淘汰策略,它根据数据的访问时间来决定哪些数据会被淘汰。LRU算法的核心思想是:最久未被访问的数据,被认为是最不常用的数据&#…

基于Tensorflow完成mnist数据集的数字手写体识别

基于Tensorflow完成mnist数据集的数字手写体识别 关于知识背景CNNFCNN 关于数据集新的改变 关于知识背景 CNN 卷积神经网络(Convolutional Neural Networks,简称CNN)是一种具有局部连接、权值共享等特点的深层前馈神经网络(Feed…

【大数据】LSM树,专为海量数据读写而生的数据结构

目录 1.什么是LSM树? 2.LSM树的落地实现 1.什么是LSM树? LSM树(Log-Structured Merge Tree)是一种专门针对大量写操作做了优化的数据存储结构,尤其适用于现代大规模数据处理系统,如NoSQL数据库&#xff…

缓解程序员工作压力的小窍门:从身心健康出发

随着信息技术的迅速发展,程序员成为了现代社会中不可或缺的一部分。然而,与之伴随而来的是高强度的工作压力,长时间的坐姿工作和快节奏的生活方式可能会对程序员的身心健康产生负面影响。因此,了解并采取有效的方法缓解工作压力对…

C# winform OpenProtocol中数据中的UI是什么类型?

C# winform OpenProtocol中数据中的UI是什么类型?