大模型 Function Call 的实现步骤及示例详解

      • 一、Function Call的核心流程拆解
      • 二、结合代码详解Function Call实现
        • 步骤1:定义工具(对应代码中的`tools`列表)
        • 步骤2:实现工具函数(对应代码中的`get_current_weather`和`get_current_time`)
        • 步骤3:模型交互与工具调用判断(对应`call_with_messages`函数)
          • 子步骤3.1:初始化对话消息
          • 子步骤3.2:首次调用模型,判断是否需要调用工具
          • 子步骤3.3:解析工具调用指令并执行工具
          • 子步骤3.4:多轮调用模型,整合工具结果生成最终回答
      • 三、总结:代码如何实现Function Call的核心逻辑

Function Call(函数调用)是大模型与外部工具/函数交互的核心机制,其核心逻辑是:让大模型根据用户需求判断是否需要调用预设工具,若需要则生成标准化的调用指令(包含工具名、参数等),执行工具后将结果返回给模型,最终由模型整合结果生成自然语言回答。

一、Function Call的核心流程拆解

Function Call的完整流程可分为5个关键步骤,每个步骤对应具体的逻辑和目标:

  1. 定义工具(Tool Definition)
    提前告诉大模型“有哪些工具可用”“工具的功能是什么”“需要传入哪些参数”,通常以结构化格式(如JSON Schema)描述,确保模型能精准理解工具的调用规则。

  2. 用户提问与初始判断
    接收用户输入后,大模型结合问题和工具定义,判断“是否需要调用工具”:

    • 若问题可直接回答(如“1+1等于几”),则直接返回结果;
    • 若问题需要外部信息(如“现在几点了”“北京天气如何”),则生成工具调用指令。
  3. 生成工具调用指令
    若需要调用工具,大模型会生成标准化的调用指令(包含工具名、参数等),格式需严格匹配工具定义,确保后续能被正确解析执行。

  4. 执行工具并返回结果
    解析模型生成的调用指令,调用对应的工具函数,执行逻辑(如查询数据库、API调用等),并将结果以固定格式(如“tool角色”消息)返回给模型。

  5. 整合结果生成最终回答
    大模型接收工具返回的结果后,结合问题和结果,生成自然语言回答,完成交互。

二、结合代码详解Function Call实现

下面结合完整的代码,逐步骤解析每个环节的具体实现,示例代码来自大模型服务平台百炼 Function Calling:

点击展开代码
from openai import OpenAI
from datetime import datetime
import json
import os
import randomclient = OpenAI(# 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",api_key=os.getenv("DASHSCOPE_API_KEY"),base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",  # 填写DashScope SDK的base_url
)# 定义工具列表,模型在选择使用哪个工具时会参考工具的name和description
tools = [# 工具1 获取当前时刻的时间{"type": "function","function": {"name": "get_current_time","description": "当你想知道现在的时间时非常有用。",# 因为获取当前时间无需输入参数,因此parameters为空字典"parameters": {},},},# 工具2 获取指定城市的天气{"type": "function","function": {"name": "get_current_weather","description": "当你想查询指定城市的天气时非常有用。","parameters": {"type": "object","properties": {# 查询天气时需要提供位置,因此参数设置为location"location": {"type": "string","description": "城市或县区,比如北京市、杭州市、余杭区等。",}},"required": ["location"],},},},
]# 模拟天气查询工具。返回结果示例:“北京今天是雨天。”
def get_current_weather(arguments):# 定义备选的天气条件列表weather_conditions = ["晴天", "多云", "雨天"]# 随机选择一个天气条件random_weather = random.choice(weather_conditions)# 从 JSON 中提取位置信息location = arguments["location"]# 返回格式化的天气信息return f"{location}今天是{random_weather}。"# 查询当前时间的工具。返回结果示例:“当前时间:2024-04-15 17:15:18。“
def get_current_time():# 获取当前日期和时间current_datetime = datetime.now()# 格式化当前日期和时间formatted_time = current_datetime.strftime("%Y-%m-%d %H:%M:%S")# 返回格式化后的当前时间return f"当前时间:{formatted_time}。"# 封装模型响应函数
def get_response(messages):completion = client.chat.completions.create(model="qwen-plus",  # 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/modelsmessages=messages,tools=tools,)return completiondef call_with_messages():print("\n")messages = [{"content": input("请输入:"),  # 提问示例:"现在几点了?" "一个小时后几点" "北京天气如何?""role": "user",}]print("-" * 60)# 模型的第一轮调用i = 1first_response = get_response(messages)assistant_output = first_response.choices[0].messageprint(f"\n第{i}轮大模型输出信息:{first_response}\n")if assistant_output.content is None:assistant_output.content = ""messages.append(assistant_output)# 如果不需要调用工具,则直接返回最终答案if (assistant_output.tool_calls == None):  # 如果模型判断无需调用工具,则将assistant的回复直接打印出来,无需进行模型的第二轮调用print(f"无需调用工具,我可以直接回复:{assistant_output.content}")return# 如果需要调用工具,则进行模型的多轮调用,直到模型判断无需调用工具while assistant_output.tool_calls != None:# 如果判断需要调用查询天气工具,则运行查询天气工具tool_info = {"content": "","role": "tool","tool_call_id": assistant_output.tool_calls[0].id,}if assistant_output.tool_calls[0].function.name == "get_current_weather":# 提取位置参数信息argumens = json.loads(assistant_output.tool_calls[0].function.arguments)tool_info["content"] = get_current_weather(argumens)# 如果判断需要调用查询时间工具,则运行查询时间工具elif assistant_output.tool_calls[0].function.name == "get_current_time":tool_info["content"] = get_current_time()tool_output = tool_info["content"]print(f"工具输出信息:{tool_output}\n")print("-" * 60)messages.append(tool_info)assistant_output = get_response(messages).choices[0].messageif assistant_output.content is None:assistant_output.content = ""messages.append(assistant_output)i += 1print(f"第{i}轮大模型输出信息:{assistant_output}\n")print(f"最终答案:{assistant_output.content}")if __name__ == "__main__":call_with_messages()
步骤1:定义工具(对应代码中的tools列表)

代码中通过tools列表定义了两个工具,这是大模型判断“是否调用工具”和“如何调用”的依据。每个工具的定义包含3个核心要素:

  • name:工具函数的唯一标识(需与实际函数名一致,如get_current_weather);
  • description:工具的功能描述(帮助模型判断何时该用这个工具,如“查询指定城市的天气时使用”);
  • parameters:工具所需参数的结构化定义(包含参数名、类型、描述、是否必填等,确保模型传入正确参数)。

示例解析:

tools = [# 工具1:获取当前时间(无参数){"type": "function","function": {"name": "get_current_time","description": "当你想知道现在的时间时非常有用。","parameters": {}  # 无参数,因此为空字典},},# 工具2:获取指定城市天气(需location参数){"type": "function","function": {"name": "get_current_weather","description": "当你想查询指定城市的天气时非常有用。","parameters": {"type": "object","properties": {"location": {  # 参数名:location"type": "string",  # 参数类型:字符串"description": "城市或县区,比如北京市、杭州市"  # 参数描述}},"required": ["location"]  # 该参数为必填项}},}
]

作用:大模型会读取tools中的信息,例如当用户问“北京天气如何”时,模型会匹配到get_current_weatherdescription,并根据parameters知道需要传入location="北京"

步骤2:实现工具函数(对应代码中的get_current_weatherget_current_time

工具函数是实际执行逻辑的“执行者”,接收模型传入的参数,返回具体结果。代码中这两个函数是模拟实现(实际场景可能是调用天气API、时间接口等)。

  • get_current_time:无参数,返回当前格式化时间(如“2025-07-19 15:30:00”);
  • get_current_weather:接收location参数,随机返回天气结果(如“北京今天是晴天”)。

示例解析:

def get_current_weather(arguments):weather_conditions = ["晴天", "多云", "雨天"]random_weather = random.choice(weather_conditions)location = arguments["location"]  # 从参数中提取城市return f"{location}今天是{random_weather}。"  # 返回工具结果
步骤3:模型交互与工具调用判断(对应call_with_messages函数)

这是Function Call的核心流程,负责协调用户输入、模型判断、工具执行和结果整合,具体分为以下子步骤:

子步骤3.1:初始化对话消息

用户输入作为初始消息(role="user"),存入messages列表,用于传递给模型。

messages = [{"content": input("请输入:"),  # 例如用户输入“杭州天气如何?”"role": "user",}
]
子步骤3.2:首次调用模型,判断是否需要调用工具

通过get_response函数调用大模型(这里对接的是阿里云DashScope的千问模型),传入messages(用户问题)和tools(工具列表),模型会返回判断结果:

  • 若无需调用工具:assistant_output.tool_callsNone,直接返回回答;
  • 若需要调用工具:assistant_output.tool_calls包含调用指令(工具名、参数等)。

示例解析:

first_response = get_response(messages)  # 调用模型
assistant_output = first_response.choices[0].message  # 获取模型输出
if assistant_output.tool_calls is None:  # 无需调用工具print(f"无需调用工具,我可以直接回复:{assistant_output.content}")return
子步骤3.3:解析工具调用指令并执行工具

若模型返回tool_calls,则需解析指令并执行对应工具:

  • tool_calls中提取工具名(function.name)和参数(function.arguments);
  • 调用对应的工具函数(如get_current_weather),传入参数,获取工具返回结果;
  • 将工具结果以role="tool"的格式存入messages,并关联tool_call_id(确保模型知道结果对应哪个调用)。

示例解析:

# 循环处理工具调用(可能多轮,直到模型无需调用)
while assistant_output.tool_calls is not None:tool_call = assistant_output.tool_calls[0]  # 获取第一个工具调用指令tool_info = {"role": "tool","tool_call_id": tool_call.id,  # 关联调用ID"content": ""  # 存储工具返回结果}# 若调用的是天气工具if tool_call.function.name == "get_current_weather":arguments = json.loads(tool_call.function.arguments)  # 解析参数(如{"location":"杭州"})tool_info["content"] = get_current_weather(arguments)  # 执行工具,获取结果# 若调用的是时间工具elif tool_call.function.name == "get_current_time":tool_info["content"] = get_current_time()  # 执行工具messages.append(tool_info)  # 将工具结果加入对话历史
子步骤3.4:多轮调用模型,整合工具结果生成最终回答

工具结果存入messages后,再次调用模型,模型会基于“用户问题+工具结果”生成最终回答。若仍需进一步调用工具(如参数缺失),则重复“解析→执行→返回”流程,直到模型判断无需调用工具,输出最终结果。

示例解析:

# 再次调用模型,传入工具结果
assistant_output = get_response(messages).choices[0].message
messages.append(assistant_output)  # 更新对话历史# 直到模型不再返回tool_calls,输出最终结果
print(f"最终答案:{assistant_output.content}")  # 例如“杭州今天是晴天。”

三、总结:代码如何实现Function Call的核心逻辑

  1. 工具定义:通过tools列表让模型“认识”可用工具及调用规则;
  2. 模型判断:大模型结合用户问题和工具定义,决定是否调用工具;
  3. 指令解析与执行:解析模型生成的tool_calls,调用对应工具函数并获取结果;
  4. 多轮交互:将工具结果反馈给模型,反复迭代直到生成最终回答。

这种机制让大模型突破“仅依赖内部知识”的限制,能通过外部工具获取实时信息(如时间、天气)、执行复杂计算等,极大扩展了应用场景。

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

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

相关文章

Linux运维新手的修炼手扎之第24天

mysql服务1 mysql命令客户端(mysql.cnf)命令 \c--ctrl c \s--显示当前状态 \r--客户端重新连接 \h--查看帮助信息 exit退出客户端 \G--垂直格式显示查询结果连接MySQL服务器--[rootrocky9 ~]# mysql(mysql -u用户名 - p密码 -h服务端ip -P服务端port -S服务端sock -e "my…

面向对象分析与设计40讲(7)设计原则之合成复用原则

文章目录 一、概念 二、示例(C++ 实现) 1. 违反合成复用原则的示例(过度使用继承) 2. 遵循合成复用原则的示例(使用组合) 三、总结 1. 继承是“强绑定”,组合是“弱关联” 2. 继承固化“静态结构”,组合支持“动态变化” 3. 继承放大“设计缺陷”,组合隔离“局部问题”…

Git 完全手册:从入门到团队协作实战(4)

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《C修炼之路》、《Linux修炼&#xff1a;终端之内 洞悉真理…

解决Spring事务中RPC调用无法回滚的问题

文章目录问题分析解决方案实现原理解析执行流程说明运行实例正常流程执行执行异常流程关键优势在分布式系统开发中&#xff0c;我们经常会遇到本地事务与远程服务调用结合的场景。当本地事务包含RPC调用时&#xff0c;如果事务回滚&#xff0c;RPC调用已经执行就会导致数据不一…

sqli-labs通关笔记-第13关 POST报错型注入(单引号括号闭合 手工注入+脚本注入两种方法)

目录 一、字符型注入 二、limit函数 三、GET方法与POST方法 四、源码分析 1、代码审计 2、SQL注入安全分析 3、报错型注入与联合注入 五、渗透实战 1、进入靶场 2、注入点分析 &#xff08;1&#xff09;SQL语句 &#xff08;2&#xff09;admin) #注入探测 &…

康复器材动静态性能测试台:精准检测,为康复器械安全保驾护航

在康复医疗领域&#xff0c;无论是轮椅、拐杖、假肢还是康复床&#xff0c;每一件器械的强度与稳定性都直接关系到使用者的安全与康复效果。如何确保这些器械在实际使用中经得起反复考验&#xff1f;Delta德尔塔仪器推出的康复器材动静态性能测试台&#xff0c;凭借其高精度、智…

vue3中el-table表头筛选

效果如下&#xff0c;可以勾选表头进行隐藏&#xff0c;也可以对表头进行拖动排序index主界面 <script> let tempHead []; const showFilter ref<boolean>(false); let tableHeadList ref<TableHeadItem[]>([{ prop: "displayId", label: "…

数据结构 之 【排序】(直接选择排序、堆排序、冒泡排序)

目录 1.直接选择排序 1.1直接选择排序的思想 1.2直接选择排序的代码逻辑 1.3完整排序代码 1.3.1一次只选一个最值 1.3.2一次筛选出两个最值 1.4直接选择排序的时间复杂度与空间复杂度 2.堆排序 2.1堆排序的思想 2.2堆排序的具体步骤 2.3堆排序图解 2.4完整排序代码…

用手机当外挂-图文并茂做报告纪要

前阵参加一个峰会,看到演讲嘉宾每翻一页PPT,下面的观察就举起手机一顿拍。实话说这种拍下来的,难说还会拿出来看,而且再看的时候也未必能对应到当时主讲人的一些解释 。 如果现场将图片保存到笔记本电脑,并快速记录关键信息,这样听完一个报告可能就直接输出一篇报道了。 有…

Vue的ubus emit/on使用

这段代码是 Vue.js 组件中的 mounted 生命周期钩子函数&#xff0c;主要作用是监听一个名为 “macSelectData” 的全局事件。具体行为如下&#xff1a;分步解释&#xff1a;mounted() 生命周期钩子 当组件被挂载到 DOM 后&#xff0c;Vue 会自动调用 mounted() 方法。这里常用于…

rsync报错解决

问题说明 [rootlocalhost shyn]# rsync -avz --checksum "root192.168.159.133:/tmp/shyn" "/tmp /shyn"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! …

ArKTS: DAL,Model,BLL,Interface,Factory using SQLite

HarmonyOS 用ohos.data.rdb 用DBHelper.ets 共用调用SQLite 库&#xff0c;进行DAL,Model,BLL,Interface,Factory 框架模式&#xff0c;表为CREATE TABLE IF NOT EXISTS signInRecord ( id INTEGER PRIMARY KEY AUTOINCREMENT, employeeId TEXT NOT NULL, employeeName TEXT NO…

MySQL JSON 数据类型用法及与传统JSON字符串的对比 JSON数据类型简介

文章目录前言1. 基本用法JSON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引支持JSON存储对象和数组的性能考虑1. 存储对象2. 存储数组性能对比总结最佳实践建议前言 MySQL从 5.7 版本开始引入了 JSON 数据类型&#xff0c;专门用于存储 JSON 格式的数据。与传…

C++:list(1)list的使用

list的使用一.list基本的结构1.环状双向链表2.哨兵节点3.迭代器4.节点结构5.链表遍历6.迭代器失效二.list的基本使用1.test01函数&#xff1a;主要测试std::list的初始化方式及遍历2.test02函数&#xff1a;主要测试std::list的常用成员函数操作3.测试结果如下三.list的其他操作…

ArcGIS地形起伏度计算

地形起伏度计算地形起伏度步骤1&#xff1a;计算最大值。步骤2&#xff1a;计算最小值。步骤3&#xff1a;计算地形起伏度。地形起伏度、地形粗糙度、地表切割深度和高程变异系数均为坡面复杂度因子&#xff0c;是一种宏观的地形信息因子&#xff0c;反映的是较大的区域内地表坡…

llama factory新手初步运行完整版

1、新建conda环境名称为llama_factory&#xff0c;并激活 conda create -n llama_factory python3.10 conda activate llama_factory2、激活后可检查内部包是否纯净&#xff0c;要确保环境内包较纯净&#xff0c;不然后续安装对应包会出现一系列水土不服的问题&#xff0c;导致…

Tomcat与JDK版本对照全解析:避坑指南与生产环境选型最佳实践

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…

短视频矩阵的未来前景:机遇无限,挑战并存

在当今数字化信息飞速传播的时代&#xff0c;短视频以其独特的魅力迅速席卷全球&#xff0c;成为人们获取信息、娱乐消遣的重要方式之一。短视频矩阵作为一种高效的内容传播与运营模式&#xff0c;正逐渐展现出其强大的影响力和潜力。本文将深入探讨短视频矩阵的未来前景&#…

【数据结构】哈希——位图与布隆过滤器

目录 位图&#xff1a; 引入 位图实现&#xff1a; 位图的结构 插入数据(标记数据) 删除数据(重置数据) 查找数据 位图完整代码&#xff1a; 位图的优缺点&#xff1a; 布隆过滤器&#xff1a; 引入 布隆过滤器实现&#xff1a; 布隆过滤器的结构&#xff1a; 插入…

本地运行C++版StableDiffusion!开源应用StableVerce发布

本地运行C版StableDiffusion&#xff01;开源应用StableVerce发布 StableVerse是一个用C开发的本地运行的图形工具。适合初学者快速入门&#xff1b;适用于办公室工作人员的文本和图像制作的小规模计算能力场景。 开源地址&#xff1a;https://github.com/kelvin-luo/StableVer…