如何通过Function Calling 实现工具调用-大模型服务平台百炼(Model Studio)-阿里云帮助中心 --知识铺
工作原理
Function Calling 通过在应用程序和大模型之间的多步骤交互,使大模型可以参考外部工具信息进行回答。
-
发起第一次模型调用
应用程序首先向大模型发起一个包含用户问题与模型可调用工具清单的请求。
-
接收模型的工具调用指令(工具名称与入参)
若模型判断需要调用外部工具,会返回一个JSON格式的指令,用于告知应用程序需要执行的函数与入参。
若模型判断无需调用工具,会返回自然语言格式的回复。
-
在应用端运行工具
应用程序接收到工具指令后,需要运行工具,获得工具输出结果。
-
发起第二次模型调用
获取到工具输出结果后,需添加至模型的上下文(messages),再次发起模型调用。
-
接收来自模型的最终响应
模型将工具输出结果和用户问题信息整合,生成自然语言格式的回复。
工作流程示意图如下所示:
支持的模型
-
文本生成模型
-
多模态模型
快速开始
您需要已获取API Key并配置API Key到环境变量。如果通过 OpenAI SDK 或 DashScope SDK 进行调用,需要安装SDK。
以天气查询场景为例,介绍快速使用 Function Calling 的方法。
运行后得到如下输出:
|
|
如何使用
Function Calling 支持两种传入工具信息的方式:
-
方式一:通过 tools 参数传入(推荐)
请参见如何使用,按照定义工具、创建messages数组、发起 Function Calling、运行工具函数、大模型总结工具函数输出的步骤进行调用。
-
方式二:通过 System Message 传入
通过 tools 参数传入时,服务端会根据模型自动适配合适的 prompt 模板并组装,因此推荐您优先使用 tools 参数。 如果您在使用 Qwen 模型时不期望使用 tools 参数,请参见通过 System Message 传入工具信息。
以下内容以 OpenAI 兼容调用方式为例,通过 tools 参数传入工具信息,向您分步骤介绍 Function Calling 的详细用法。
假设业务场景中会收到天气查询与时间查询两类问题。
1. 定义工具
工具是连接大模型与外部世界的桥梁,首先需要定义工具。
1.1. 创建工具函数
创建两个工具函数:天气查询工具与时间查询工具。
-
天气查询工具
接收
arguments参数,arguments格式为{"location": "查询的地点"}。工具的输出为字符串,格式为:“{位置}今天是{天气}”。为了便于演示,此处定义的天气查询工具并不真正查询天气,会从晴天、多云、雨天随机选择。在实际业务中可使用如高德天气查询等工具进行替换。
-
时间查询工具
时间查询工具不需要输入参数。工具的输出为字符串,格式为:
“当前时间:{查询到的时间}。”。如果使用 Node.js,请运行
npm install date-fns安装获取时间的工具包 date-fns:
运行工具后,得到输出:
测试工具输出:
上海今天是多云。
当前时间:2025-01-08 20:21:45。
1.2 创建 tools 数组
人类在选择工具之前,需要对工具有全面的了解,包括工具的功能、何时使用以及输入参数等。大模型也需要这些信息才能更准确地选择工具。请根据以下 JSON 格式提供工具信息。
| - type字段固定为"function";
-
function字段为 Object 类型;-
name字段为自定义的工具函数名称,建议使用与函数相同的名称,如get_current_weather或get_current_time; -
description字段是对工具函数功能的描述,大模型会参考该字段来选择是否使用该工具函数。 -
parameters字段是对工具函数入参的描述,类型是 Object ,大模型会参考该字段来进行入参的提取。如果工具函数不需要输入参数,则无需指定parameters参数。-
type字段固定为"object"; -
properties字段描述了入参的名称、数据类型与描述,为 Object 类型,Key 值为入参的名称,Value 值为入参的数据类型与描述; -
required字段指定哪些参数为必填项,为 Array 类型。 | 对于天气查询工具来说,工具描述信息的格式如下:
-
-
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "当你想查询指定城市的天气时非常有用。",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市或县区,比如北京市、杭州市、余杭区等。"
}
},
"required": ["location"]
}
}
}
``` |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
在发起 Function Calling 前,需在代码中定义工具信息数组(tools),包含每个工具的函数名、描述和参数定义。这个数组在后续发起Function Calling请求时作为参数传入。
### **2\. 创建messages数组**
Function Calling 通过 messages 数组向大模型传入指令与上下文信息。发起 Function Calling 前,messages 数组需要包含 System Message 与 User Message。
#### **System Message**
尽管在[创建 tools 数组](https://help.aliyun.com/zh/model-studio/qwen-function-calling#b7c8a0e72a9d0)时已经对工具的作用与何时使用工具进行了描述,但在 System Message 中强调何时调用工具通常会提高工具调用的准确率。在当前场景下,可以将 System Prompt 设置为:
你是一个很有帮助的助手。如果用户提问关于天气的问题,请调用 ‘get_current_weather’ 函数; 如果用户提问关于时间的问题,请调用‘get_current_time’函数。 请以友好的语气回答问题。
#### **User Message**
User Message 用于传入用户提问的问题。假设用户提问“上海天气”,此时的 messages 数组为:
> 由于备选工具包含天气查询与时间查询,也可提问关于当前时间的问题。
### **3\. 发起 Function Calling**
将创建好的 `tools` 与 `messages` 传入大模型,即可发起一次 Function Calling。大模型会判断是否调用工具。若调用,则返回该工具的函数名与参数。
> 支持的模型参见[支持的模型](https://help.aliyun.com/zh/model-studio/qwen-function-calling#c8feada2328us)。
由于用户提问为上海天气,大模型指定需要使用的工具函数名称为:`"get_current_weather"`,函数的入参为:`"{\"location\": \"上海\"}"`。
```swift
{
"content": "",
"refusal": null,
"role": "assistant",
"audio": null,
"function_call": null,
"tool_calls": [
{
"id": "call_6596dafa2a6a46f7a217da",
"function": {
"arguments": "{\"location\": \"上海\"}",
"name": "get_current_weather"
},
"type": "function",
"index": 0
}
]
}
需要注意,如果问题被大模型判断为无需使用工具,会通过content参数直接回复。在输入“你好”时,tool_calls参数为空,返回对象格式为:
|
|
如果
tool_calls参数为空,可使程序直接返回content,无需运行以下步骤。
若希望每次发起 Function Calling 后大模型都可以选择指定工具,请参见强制工具调用。
4. 运行工具函数
运行工具函数是将大模型的决策转化为实际操作的关键步骤。
运行工具函数的过程由您的计算环境而非大模型来完成。
由于大模型只可以输出字符串格式的内容,因此在运行工具函数前,需要对字符串格式的工具函数与入参分别解析。
-
工具函数
建立一个工具函数名称到工具函数实体的映射
function_mapper,将返回的工具函数字符串映射到工具函数实体; -
入参
Function Calling 返回的入参为 JSON 字符串,使用工具将其解析为 JSON 对象,提取入参信息。
完成解析后,将参数传入工具函数并执行,获取输出结果。
运行后得到如下输出:
说明
在实际业务场景中,许多工具的核心功能是执行具体操作(如邮件发送、文件上传等),而非数据查询,这类工具执行后不会输出字符串。为帮助大模型了解工具运行状态,建议在设计此类工具时添加如“邮件发送完成”、“操作执行失败"等状态描述信息。
5. 大模型总结工具函数输出
工具函数的输出格式较为固定,如果直接返回给用户,可能会有语气生硬、不够灵活等问题。如果您希望大模型能够综合用户输入以及工具输出结果,生成自然语言风格的回复,可以将工具输出提交到模型上下文并再次向模型发出请求。
-
添加 Assistant Message
发起 Function Calling后,通过
completion.choices[0].message得到 Assistant Message,首先将它添加到 messages 数组中; -
添加 Tool Message
将工具的输出通过
{"role": "tool", "content": "工具的输出","tool_call_id": completion.choices[0].message.tool_calls[0].id}形式添加到 messages 数组。说明
-
请确保工具的输出为字符串格式。
-
tool_call_id是系统为每一次的工具调用请求生成的唯一标识符。模型可能一次性要求调用多个工具,将多个工具结果返回给模型时,tool_call_id可确保工具的输出结果能够与它的调用意图对应。
-
此时的 messages 数组为:
|
|
更新 messages 数组后,运行以下代码。
可从content得到回复内容:“上海今天的天气是多云。如果您有其他问题,欢迎继续提问。”
|
|
至此,您已完成了一次完整的 Function Calling 流程。
进阶用法
指定工具调用方式
并行工具调用
单一城市的天气查询经过一次工具调用即可。如果输入问题需要调用多次工具,如“北京上海的天气如何”或“杭州天气,以及现在几点了”,发起 Function Calling 后只会返回一个工具调用信息,以提问“北京上海的天气如何”为例:
|
|
返回结果中只有北京市的入参信息。为了解决这一问题,在发起 Function Calling时,可设置请求参数parallel_tool_calls为true,这样返回对象中将包含所有需要调用的工具函数与入参信息。
说明
并行工具调用适合任务之间无依赖的情况。若任务之间有依赖关系(工具A的输入与工具B的输出结果有关),请参见快速开始,通过while循环实现串行工具调用(一次调用一个工具)。
在返回对象的tool_calls数组中包含了北京上海的入参信息:
|
|
强制工具调用
大模型生成内容具有不确定性,有时会选择错误的工具进行调用。如果您希望对于某一类问题,大模型能够采取人为设定的策略(如强制使用某个工具、强制不使用工具),可修改tool_choice参数。tool_choice参数的默认值为"auto",表示由大模型自主判断如何进行工具调用。
大模型总结工具函数输出时,请将
tool_choice参数去除,否则 API 仍会返回工具调用信息。
-
强制使用某个工具
如果您希望对于某一类问题,Function Calling 能强制调用某个工具,可设定
tool_choice参数为{"type": "function", "function": {"name": "the_function_to_call"}},大模型将不参与工具的选择,只输出入参信息。假设当前场景中只包含天气查询的问题,可修改 function_calling 代码为:
无论输入什么问题,返回对象的工具函数都会是
get_current_weather。使用该策略前请确保问题与选择的工具相关,否则可能返回不符合预期的结果。
-
强制不使用工具
如果您希望无论输入什么问题,Function Calling 都不会进行工具调用(返回对象中包含回复内容
content而tool_calls参数为空),可设定tool_choice参数为"none",或不传入tools参数,Function Calling 返回的tool_calls参数将始终为空。假设当前场景中的问题均无需调用工具,可修改 function_calling 代码为:
多轮对话
用户可能在第一轮提问“北京天气”,第二轮提问“上海的呢?”若模型上下文中没有第一轮的信息,模型无法判断需要调用哪个工具。建议在多轮对话场景中,每轮结束后维持 messages 数组,在此基础上添加 User Message并发起 Function Calling以及后续步骤。messages 结构如下所示:
|
|
流式输出
为了提升用户体验和减少等待时间,可使用流式输出实时获取工具函数名称与入参信息。其中:
-
工具函数名称:仅在第一个流式返回的对象(delta)中出现。
-
入参信息:以流式方式输出。
运行后得到如下输出:
|
|
运行以下代码拼接入参信息(arguments):
获得如下输出:
|
|
在使用大模型总结工具函数输出步骤,添加的 Assistant Message 需要符合下方格式。仅需将下方的tool_calls中的元素替换为以上内容即可。
|
|
深度思考模型的工具调用
深度思考模型在输出工具调用信息前会进行思考,可以提升决策的可解释性与可靠性。
-
思考过程
模型逐步分析用户意图、识别所需工具、验证参数合法性,并规划调用策略;
-
工具调用
模型以结构化格式输出一个或多个函数调用请求。
支持并行工具调用。
以下展示流式调用深度思考模型的工具调用示例。
tool_choice参数只支持设置为"auto"(默认值,表示由模型自主选择工具)或"none"(强制模型不选择工具)。
示例代码
|
|
返回结果
输入“四个直辖市的天气”,得到以下返回结果:
|
|
应用于生产环境
测试工具调用准确率
-
建立评估体系:
构建贴近真实业务的测试数据集,并定义清晰的评估指标,如:工具选择准确率、参数提取准确率、端到端成功率等。
-
优化提示词
根据测试暴露出的具体问题(选错工具、参数错误),针对性地优化系统提示词、工具描述和参数描述,是核心的调优手段。
-
升级模型
当提示词工程调优无法提升性能时,升级到能力更强的模型版本(如
qwen3-max-preview)是提升指标最直接有效的方法。
动态控制工具数量
当应用集成的工具数量超过几十甚至上百个时,将整个工具库全部提供给模型会带来以下问题:
-
性能下降:模型在庞大的工具集中选择正确工具的难度剧增;
-
成本与延迟:大量的工具描述会消耗巨量的输入 Token,导致费用上升和响应变慢;
解决方案是在调用模型前,增加一个工具路由/检索层,根据用户当前查询,从完整的工具库中快速、精准地筛选出一个小而相关的工具子集,再将其提供给模型。
实现工具路由的几种主流方法:
-
语义检索
预先将所有工具的描述信息(
description)通过 Embedding 模型转化为向量,并存入向量数据库。当用户查询时,将查询向量通过向量相似度搜索,召回最相关的 Top-K 个工具。 -
混合检索
将语义检索的“模糊匹配”能力与传统关键词或元数据标签的“精确匹配”能力相结合。为工具添加
tags或keywords字段,检索时同时进行向量搜索和关键词过滤,可以大幅提升高频或特定场景下的召回精准度。 -
轻量级 LLM 路由器
对于更复杂的路由逻辑,可以使用一个更小、更快、更便宜的模型(如 Qwen-Flash)作为前置“路由模型”。它的任务是根据用户问题输出相关的工具名称列表。
实践建议
-
保持候选集精简:无论使用何种方法,最终提供给主模型的工具数量建议不超过 20 个。这是在模型认知负荷、成本、延迟和准确率之间的最佳平衡点。
-
分层过滤策略:可以构建一个漏斗式的路由策略。例如,先用成本极低的关键词/规则匹配进行第一轮筛选,过滤掉明显不相关的工具,再对剩余的工具进行语义检索,从而提高效率和质量。
工具安全性原则
将工具执行能力开放给大模型时,必须将安全置于首位。核心原则是“最小权限”和“人类确认”。
-
最小权限原则:为模型提供的工具集应严格遵守最小权限原则。默认情况下,工具应是只读的(如查询天气、搜索文档),避免直接提供任何涉及状态变更或资源操作的“写”权限。
-
危险工具隔离:请勿向大模型直接提供危险工具,例如执行任意代码(
code interpreter)、操作文件系统(fs.delete)、执行数据库删除或更新操作(db.drop_table)或涉及资金流转的工具(payment.transfer)。 -
人类参与:对于所有高权限或不可逆的操作,必须引入人工审核和确认环节。模型可以生成操作请求,但最终的执行“按钮”必须由人类用户点击。例如,模型可以准备好一封邮件,但发送操作需要用户确认。
用户体验优化
Function Calling 链路较长,任何一个环节出问题都可能导致用户体验下降。
处理工具运行失败
工具运行失败是常见情况。可采取以下策略:
-
最大重试次数:设置合理的重试上限(例如 3 次),避免因连续失败导致用户长时间等待或系统资源浪费。
-
提供兜底话术:当重试耗尽或遇到无法解决的错误时,应向用户返回清晰、友好的提示信息,例如:“抱歉,我暂时无法查询到相关信息,可能是服务有些繁忙,请您稍后再试。”
应对处理延迟
较高的延迟会降低用户满意度,需要通过前端交互和后端优化来改善。
-
设置超时时间:为 Function Calling 的每一步设置独立且合理的超时时间。一旦超时,应立即中断操作并给出反馈。
-
提供即时反馈:开始执行 Function Calling 时,建议在界面上给出提示,如“正在为您查询天气…”、“正在搜索相关信息…”,向用户实时反馈处理进度。
计费说明
除了 messages 数组中的 Token 外,工具描述信息也会作为输入 Token 拼接到提示词中进行计费。
通过 System Message 传入工具信息
错误码
如果模型调用失败并返回报错信息,请参见错误信息进行解决。
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/ai002/post/20251029/%E5%A6%82%E4%BD%95%E9%80%9A%E8%BF%87Function-Calling-%E5%AE%9E%E7%8E%B0%E5%B7%A5%E5%85%B7%E8%B0%83%E7%94%A8-%E5%A4%A7%E6%A8%A1%E5%9E%8B%E6%9C%8D%E5%8A%A1%E5%B9%B3%E5%8F%B0%E7%99%BE%E7%82%BCModel-Studio-%E9%98%BF%E9%87%8C%E4%BA%91%E5%B8%AE%E5%8A%A9%E4%B8%AD%E5%BF%83/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com
See Also
- 大模型LLM 如何选择AI Agent框架?五种主流AI Agent框架对比(LangChain、LangGraph、CrewAI、Semantic Kernel、AutoGen)_autogen langchain 对比-CSDN博客 --知识铺
- 告别瞎写!AI Agent 提示词撰写指南 (内附模仿技巧+实例) - 腾讯云开发者社区-腾讯云 --知识铺
- 大模型应用不同提示词范式和ReAct Agent智能体实现原理分析_react agent 提示词-CSDN博客 --知识铺
- 关于智能体(AI Agent)入门,一篇超详细的总结! --知识铺
- 超越 OpenAI Altas,Agent 操作系统 FlowithOS 发布,一手实测 --知识铺