news 2026/5/3 0:38:29

Tool Use实战:用 Function Calling 让 Agent 调用外部工具,我踩了 6 个坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Tool Use实战:用 Function Calling 让 Agent 调用外部工具,我踩了 6 个坑

搞了大模型快两年了,我觉得真正让 AI 从"聊天机器人"变成"能干活的人"的,不是模型有多聪明,而是它能不能调用工具

Function Calling 就是干这个的。

简单说,它让大模型不只是输出文字,而是输出一个结构化的"工具调用请求",然后你的程序去执行这个请求,再把结果喂给模型。

听起来简单,实际落地的时候踩了一堆坑。今天聊一聊我踩过的和解决了的。

先看一个具体场景

上周在做一个内部运维助手,需求很直接:让用户用自然语言查服务器状态。

用户说"帮我查一下线上服务的 QPS 和错误率",Agent 需要做三件事:

  1. 调用监控 API 查 QPS
  2. 调用日志 API 查错误率
  3. 把结果汇总回复给用户

没有 Function Calling 之前,你只能做关键词匹配——写死一堆 if-else。有了 Function Calling,模型自己决定要调什么工具、按什么顺序调。

这就是 Tool Use 的意义:把"判断"和"执行"分开。

实战:从零搭一套 Tool Use 系统

Step 1: 定义工具描述

最关键的一步。工具描述写得烂,模型就乱调用。

{"type":"function","function":{"name":"query_qps","description":"查询指定服务的每秒请求数(QPS),用于监控服务负载","parameters":{"type":"object","properties":{"service_name":{"type":"string","description":"服务名称,如 api-gateway、user-service"},"time_range":{"type":"string","enum":["5min","1hour","24hour"],"description":"查询的时间范围"}},"required":["service_name"]}}}

踩坑1:description 要写人话,别写空话

我一开始写的 description 是"查询 QPS 数据",结果模型老是在不该调用的时候调用。

改成"查询指定服务的每秒请求数(QPS),用于监控服务负载,一般与错误率查询配合使用"之后,准确率提升了不止一点半点。

模型是通过 description 来理解什么时候调用这个工具的。写得越具体越好。

Step 2: Multi-turn 工具调用

一个请求可能需要调用多个工具。核心伪代码如下:

messages=[{"role":"user","content":"查一下 API 网关的 QPS 和错误率"}]whileTrue:response=client.chat.completions.create(model="gpt-4o",messages=messages,tools=TOOLS,tool_choice="auto")choice=response.choices[0]ifchoice.finish_reason=="stop":# 模型直接回复了,流程结束print(choice.message.content)breakelifchoice.finish_reason=="tool_calls":# 模型想调用工具messages.append(choice.message)fortool_callinchoice.message.tool_calls:func_name=tool_call.function.name args=json.loads(tool_call.function.arguments)result=execute_tool(func_name,args)messages.append({"role":"tool","tool_call_id":tool_call.id,"content":json.dumps(result)})

这个循环就是 Tool Use 的核心。

踩坑2:Timeout 怎么处理

这是个大坑。一个工具调用可能跑很久(比如查全量日志),模型在那儿等着,用户很暴躁。

我的解决方案:给每个工具调用设超时,超时后返回 “timeout” 给模型,让模型决定是重试还是换个方案。

try:result=awaitasyncio.wait_for(execute_tool(func_name,args),timeout=15# 最多等 15 秒)exceptasyncio.TimeoutError:result={"error":"timeout","message":"查询超时,请缩小时间范围后重试"}

模型收到 timeout 后会主动问用户"要不缩小一下时间范围?"——体验好很多。

Step 3: 工具执行结果的处理

踩坑3:返回结果太大

查一次全量日志,返回几十 MB 的 JSON,你传回模型?token 直接爆炸。

解决方案:自动摘要。工具执行的结果不直接返回,先做摘要:

defsummarize_for_model(result,max_tokens=2000):"""把工具返回的大结果压缩成模型能看的版本"""ifisinstance(result,list)andlen(result)>20:return{"total":len(result),"summary":f"共{len(result)}条记录","sample":result[:5],"stats":compute_stats(result)}returnresult

踩坑4:错误要优雅

工具挂了返回个 500 错误页,模型看到会一脸懵。API 返回的错误信息一般是给程序看的,不是给模型看的。

我做了个统一的错误包装层:

defwrap_error(exception):ifisinstance(exception,ConnectionError):return{"error":"service_unavailable","message":"该服务暂时不可用,请稍后重试"}elifisinstance(exception,PermissionError):return{"error":"permission_denied","message":"你没有该操作的权限"}else:return{"error":"unknown","message":f"操作失败:{str(exception)[:100]}"}

模型看到这种格式的错误信息,能更好地向用户解释问题。

Step 4: 安全性

踩坑5:模型生成的参数可能是 SQL 注入

如果工具是直接拼接 SQL 的,模型调用时可能传一个恶意的参数值。

解决方案:所有工具执行前做参数校验,特别是有数据库操作的工具。

defvalidate_tool_args(func_name,args):iffunc_name=="query_database":assert"table_name"inargsassertisinstance(args["table_name"],str)# 白名单:只允许查询预定义的表assertargs["table_name"]inALLOWED_TABLES

不要信任模型生成的参数,该校验的得校验。

Step 5: 让工具真正好用

*踩坑6:工具太多模型选不对
*

工具数量超过 15 个时,模型选错的概率明显上升。

我试过的几个策略:

策略A:分组
把工具按功能分组(监控组、数据库组、消息组),先调用路由工具决定用哪个组,再调具体工具。效果最好,但延迟多一轮。

策略B:降采样
每次只用最相关的 5-8 个工具。基于用户当前的对话上下文做语义匹配。工程复杂度高,但效果最稳。

策略C:rank 排序
我最后的方案——给每个工具加一个热度分数,根据历史调用频率排序,热门工具优先级更高。简单粗暴,但实用。

实际效果数据

这套系统跑了一周后的数据:

  • 工具调用准确率:91.3%
  • 工具超时率:2.1%
  • 用户满意度(人工标注):89%
  • 平均每次用户请求调用工具数:2.3 次
  • 最常用的工具 Top 3:query_logs(34%)、get_metric(28%)、send_notification(12%)

写在最后

Function Calling 让 Agent 真正"有了手"。但从能调用工具到调得好用,中间有一堆工程化的坑。

我的核心建议是:不要把工具调用当黑盒。每步都做校验、摘要、错误处理,这些"不性感"的工作才是系统稳定运行的保障。

如果你刚开始做 Tool Use,建议从 3-5 个工具开始试,跑通了再慢慢加。一口吃不成胖子,工具多了模型也懵。

有问题评论区聊。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 0:32:47

Pandas数据清洗避坑指南:别再让inf和nan悄悄搞乱你的分析结果

Pandas数据清洗避坑指南:别再让inf和nan悄悄搞乱你的分析结果 刚完成一份数据分析报告,却发现关键指标出现异常?明明检查过代码逻辑,但统计结果依然偏离预期?这很可能是数据中的inf和nan值在暗中作祟。在真实业务场景中…

作者头像 李华
网站建设 2026/5/3 0:31:42

Python剪映自动化终极指南:5步实现高效视频剪辑API控制

Python剪映自动化终极指南:5步实现高效视频剪辑API控制 【免费下载链接】JianYingApi Third Party JianYing Api. 第三方剪映Api 项目地址: https://gitcode.com/gh_mirrors/ji/JianYingApi 想要通过Python代码自动化控制剪映软件吗?JianYingApi作…

作者头像 李华
网站建设 2026/5/3 0:25:09

终极iOS微信红包插件指南:如何不错过任何一个红包

终极iOS微信红包插件指南:如何不错过任何一个红包 【免费下载链接】WeChatRedEnvelopesHelper iOS版微信抢红包插件,支持后台抢红包 项目地址: https://gitcode.com/gh_mirrors/we/WeChatRedEnvelopesHelper 你是否曾经因为错过微信群里的红包而感到懊恼&…

作者头像 李华
网站建设 2026/5/3 0:23:57

从Wireframe到TP-LSD:手把手带你复现一个端到端的深度学习直线检测模型

从Wireframe到TP-LSD:手把手构建端到端深度学习直线检测模型 直线检测作为计算机视觉的基础任务,在建筑测绘、工业质检、自动驾驶等领域具有广泛应用。传统算法如霍夫变换和LSD虽经典但依赖人工调参,而基于深度学习的方案通过数据驱动实现了更…

作者头像 李华