news 2026/9/28 20:26:05

【Agent 学习笔记 03】工具调用:Schema 怎么写、工具幻觉怎么防、参数错了怎么办

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Agent 学习笔记 03】工具调用:Schema 怎么写、工具幻觉怎么防、参数错了怎么办

这是 Agent 学习笔记的第 3 篇,讲工具调用。我一开始卡住的三个术语(stakes、Schema 校验、Few-shot)也在这篇里讲清。

先记住一个判断:

没有工具调用,严格来说不算 Agent。工具是 Agent 的"手和脚",也是工程上最容易出错的地方。


本系列导航

  • 00 开篇:Agent 是什么?与 Chatbot / Workflow / RAG 的边界
  • 01 推理范式:ReAct / Plan-and-Execute / Reflexion
  • 02 记忆系统:四类记忆与冲突处理
  • 03 工具调用:Schema 设计与工具幻觉防护(本篇)
  • 04 可靠性工程:循环、假终止、多 Agent 与安全
  • 05 成本、上下文、评测与项目故事

一、Schema 怎么写:写"什么时候用",不是"是什么"

反例(差):

get_weather:获取天气

正例(好):

get_weather:当用户问天气、温度、是否适合出行时使用;参数 city 必填,如"北京"

为什么差别这么大?

因为 Schema 是给模型看的,模型要根据它决定"该不该调、调哪个"。只写"获取天气",模型不知道"适不适合跑步"这种间接意图该不该调它;写上触发场景,意图匹配就准了。

我的理解:工具描述本质上是"路由提示词"。写得好,模型选工具就准;写得含糊,就会出现"该调不调"和"乱调"。

Schema 的结构(用天气工具举例)

{"name":"get_weather","parameters":{"city":{"type":"string","required":true,"description":"城市名,如北京"},"date":{"type":"string","required":false,"description":"日期,默认今天"}}}

它规定了三件事:

  • 工具名是get_weather;
  • city必须是字符串,必填;
  • date是字符串,可选。

二、三个高频术语(我当时问的)

1. stakes = 风险 / 利害关系

原意是赌博里押的钱,引申为"这件事搞砸了后果有多严重"。

  • high stakes:高风险,搞错了后果很严重;
  • low stakes:低风险,搞错了也没啥大不了。
场景stakes原因
推荐餐厅low推荐错了,用户换一家就行
推荐电影low不喜欢就不看
修改用户昵称low改错了再改回来
退款 500 元high钱的事,错了有损失
医疗建议high可能影响健康甚至生命
法律意见high可能影响官司
删除生产数据库high数据没了就没了
支付转账high钱直接出去

为什么高 stakes 要转人工?因为 Agent 会犯错:低 stakes 犯错可以容忍,高 stakes 犯错代价太大。

面试口述版:“stakes 就是风险等级。high stakes 指搞错了后果严重的场景,比如涉及金额、医疗、法律、安全,这类操作不能完全交给 Agent,需要人工审批或兜底。我们系统退款超过 500 元就转人工。”
补一句加分:stakes 不仅用于"转人工",也用于"要不要自动更新记忆"(见上一篇)。

2. Schema 校验 = 检查参数是否符合定义

Schema可以理解成"表格模板":规定有哪些字段、每个字段什么类型、哪些必填。

Schema 校验就是:Agent 调用工具之前,检查它传的参数是否符合 Schema。

{"tool":"get_weather","parameters":{"city":123}}

→city应该是字符串,传了 123(整数)→校验失败,拦截。

{"tool":"get_weather","parameters":{}}

→city必填但没传 →校验失败。

用什么做校验:Python 里常用Pydantic:

frompydanticimportBaseModelclassWeatherParams(BaseModel):city:strdate:str="today"try:params=WeatherParams(**agent_output)exceptValidationErrorase:returnf"参数错误:{e}"

3. Few-shot = 给几个示例,让模型照着学

方式给几个例子
zero-shot不给例子,直接问
one-shot给一个例子
few-shot给几个例子(通常 2–5 个)

例子:工具调用

Zero-shot:

用户:北京天气 Agent:? ← 模型可能不知道怎么调工具

Few-shot:

用户:北京天气 正确调用:get_weather(city="北京") 用户:上海明天天气 正确调用:get_weather(city="上海", date="明天") 用户:杭州天气 正确调用:? ← 模型看到前两个例子,就知道第三个怎么调

为什么有用:LLM 是"模仿机器"。Few-shot 能告诉模型工具名怎么写、参数格式什么样、什么时候该调。

关键关系(面试爱问):Few-shot 让模型"尽量写对",Schema 校验负责"兜底拦住错的"。两者不是二选一,而是配合使用。


三、工具幻觉:四层防护

工具幻觉 = Agent 编了一个不存在的工具,或者参数乱填。

例子:Agent 想发邮件,生成了{ "tool": "send_email", ... },但系统里只有send_sms。

四层防护:

层做法作用
① 白名单只允许调用列表里的工具(allowed_tools: [get_weather, get_order, send_sms])不存在的工具直接拦截
② Schema 校验检查参数类型、必填项拦住类型/缺参错误
③ Prompt 约束系统提示写明"只能用以下工具,不要编造"从源头降低概率
④ Few-shot给 3 个"用户问 X → 正确调用 Y"的示例让模型模仿正确格式

校验失败之后怎么办?(这一步很关键)

不能只是报错,要返回错误 + 可用工具列表:

“工具 send_email 不存在,可用工具:[send_sms, send_wechat]”

Agent 看到后重新规划,改成send_sms。

这就是"可恢复的错误处理":拦截的目的不是让任务失败,而是把模型导回正确路径。


四、另外两类真实故障

1. 参数类型错误

例子:order_id="12345"是字符串,但 API 要整数。

处理:

  • 用Pydantic 自动转换(能转就转);
  • 转换失败 →把错误信息交回 LLM 重新生成参数。

2. 工具结果过长

例子:搜索 API 返回 50 篇论文、共 25000 字,直接塞进上下文会挤爆窗口、拉高成本。

处理:只取Top-5、每篇摘要 200 字,总长控制在1000 字左右。

这条我特别有共鸣——它和 RAG 那边"只放最相关的 3–5 个 chunk"是同一个思路:上下文是预算,不是垃圾桶。


五、面试口述版

“工具幻觉是 Agent 生成了不存在的工具名或错误参数。防护四层:白名单限制可用工具、Schema 校验参数类型和必填项、Prompt 约束只能用提供的工具、Few-shot 给正确示例。校验失败时返回错误和可用工具列表,触发重规划。我们系统工具幻觉率从 12% 降到 1%。”

被追问"怎么保证不传错参数"(文档最后留的那道题),我的答法:

“三个角度:Few-shot 让模型照着正确格式写;Schema + Pydantic 做类型和必填校验;校验失败把错误和可用工具返回给 Agent,触发重新生成。另外工具描述要写清’什么时候用’,减少选错工具的概率。”


六、我的复盘

这一篇让我把"工具调用"理解成一条流水线,而不是一个动作:

工具描述(路由提示)→ 模型选择工具 → 参数生成 → Schema 校验 → 执行 → 结果处理(截断/摘要) ↑ ↓ └──── 失败时返回错误并要求重规划 ────┘

每一环都有对应的兜底:

环节失败模式兜底
选择工具工具幻觉白名单 + Prompt 约束 + Few-shot
生成参数类型错、缺参Schema/Pydantic + 重新生成
执行结果结果过长Top-K + 摘要 + 长度上限
整体反复失败转人工(见下一篇)

下一篇讲可靠性工程:无限循环与假终止怎么治、多 Agent 的死锁和成本爆炸、以及 Prompt 注入和越权怎么防。

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

写方案、做报表、重复操作、自主任务,分别该用什么 AI 工具

同事工位上开着六个AI工具的标签页,产出效率却没比只用一个工具的人高多少——工具数量从来不是效率的决定因素,选择顺序才是。市面上能用来提效的AI工具,大致可以按"能力层级"分成四层:内容生成、格式整理、流程自动化…

作者头像 李华
网站建设 2026/9/28 20:25:06

Airtest 与 Poco 手游自动化测试(上篇)

前言 准备篇我们把环境跑通了,还截了第一张屏。从这篇开始正式干活:用 Airtest 的"眼睛和手"操作 App。我们会先搞懂 Airtest 找图的原理,再逐个学会六个核心 API,最后在官方 AirtestDemo 上跑通第一个完整用例。学完这…

作者头像 李华
网站建设 2026/9/28 20:24:15

功能安全Hypervisor:域控制器混合关键性隔离架构的落地之道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 20:24:11

WorkBuddy+deepseek-v4-flash+微信订阅消息构建AI日报工作流

1. 这不是“发个消息”,而是一套闭环工作流的落地实践“我给 WorkBuddy 设了个闹钟:每天上午十点半,一份 AI 日报自动送进微信”——这句话乍看像一句轻松的个人分享,但在我拆解过二十多个类似自动化需求后,它背后藏着…

作者头像 李华
网站建设 2026/9/28 20:22:21

BIM 动画 VS 三维施工动画:基建项目选型分析,施工单位别再混淆

1 引言 工程投标、危大方案评审、现场技术交底时,经常听到项目管理人员说:“我们项目需要做一段施工动画。” 很多工程人默认动画都是同一类成果,实际上BIM 动画和三维施工动画是完全不同的两类可视化产品。从视频画面观感上二者很接近&#…

作者头像 李华
网站建设 2026/9/28 20:22:18

getPhoneNumber 旧接口停用迁移记:code 换手机号的新写法与三类报错

getPhoneNumber 旧接口停用迁移记:code 换手机号的新写法与三类报错 适用读者:正在维护微信小程序登录、注册、绑定手机号链路的前后端工程师,尤其是还在用 encryptedData 解密拿手机号的存量项目维护者。 一、老代码是在一个周三早上集体罢工…

作者头像 李华