为什么Agent经常出现幻觉或乱调工具?怎么缓解?
为什么Agent经常出现幻觉或乱调工具?
本质上,幻觉和乱调工具是同一个根因的两种表现:模型在生成 token 时,概率分布偏离了正确路径。区别只在于——幻觉发生在"文本空间"(编造事实),乱调工具发生在"动作空间"(调错工具、填错参数)。
5个核心原因
训练数据的"时间错位"
模型训练数据有截止日期。当你让它调用一个新版 SDK 时,它没见过真实 API,但不会说"我不知道",而是基于见过的类似库去"推测"——用旧版参数格式调新版 API,或调用一个"觉得应该存在"但实际不存在的函数。
注意力衰减
现代 LLM 支持 200K token 上下文,但模型对开头和结尾关注度最高,中间部分会明显衰减。当系统提示词几百行、工具定义几十个、对话历史数万 token 时,模型"看不清"某个工具的描述,就会基于工具名去猜用途——猜错就是乱调。
工具定义的语义冲突
当多个工具功能描述重叠时(如 search_code、find_files、grep_content),模型很难精确选择。更隐蔽的是参数层面的冲突——两个工具都有 path 参数,但一个期望绝对路径,一个期望相对路径。
自回归生成的误差累积
LLM 逐 token 生成,如果模型在生成工具名时就偏了(选了 Write 而不是 Read),后续参数会在这个错误基础上继续生成,且模型不会"回头检查"。这就是为什么有时会看到 Agent 用完全不合适的工具,但参数填得"有模有样"。
强化学习的"奖励黑客"
模型可能在 RLHF 中学到捷径:调用更多工具 = 评分更高(显得"努力")、输出更长 = 评分更高、"做了总比不做好" → 即使不确定也强行调用工具。
6个可落地的缓解方向
工具设计"极简原则"
- 合并同类工具:
ReadFile+ReadJSON+ReadYAML不如一个Read工具,通过参数区分行为 - 砍掉低频工具:一个"用不到 1% 场景"的工具,对模型的干扰远大于它的价值
- 工具名即契约:
Analyze是坏名字,RunStaticAnalysis才是好名字
工具描述的"强制区隔"
在每个工具描述中显式写出"不要用这个工具做什么",模型对否定句的注意力往往高于肯定句:
Tool: SearchCode
Description: Search for code PATTERNS (regex) in file CONTENTS.
Use this when you know WHAT code you're looking for.
DO NOT use this to find files by name — use Glob instead.
Tool: Glob
Description: Find files by NAME pattern (glob).
Use this when you know the FILE NAME or PATH pattern.
DO NOT use this to search inside file contents — use SearchCode instead.
还可以加入默认意图归属:用户说"查 X"且没有历史限定时,默认只调当前工具;只有出现"曾经/历史"等关键词才调历史工具。
分阶段提示(Chain-of-Thought for Tool Selection)
在调用工具前,强制模型先输出推理过程:
在调用任何工具之前,请先回答:
1. 用户的核心意图是什么?
2. 哪些工具能完成这个意图?
3. 这些工具之间有什么区别?选哪个最合适?
然后再执行工具调用。
检索增强生成(RAG)
让 Agent 在回答前先从可信知识库中检索权威资料,相当于把"闭卷考试"变成"开卷考试",可将幻觉率降低 60%-80%。
工具返回结果"脱水"
不要返回原始 JSON 堆,返回"摘要先导 + 按需明细",减少信息过载型幻觉。工具描述只陈述客观事实,绝不替用户写业务决策。
多Agent验证 + 置信度评估
- 为执行、验证和批准分配不同的 Agent,验证器能发现执行器遗漏的幻觉
- 对低置信度的输出触发重新生成或人工复核
- 用"AI 测试 AI"的方式主动跑批验证,而不是等用户报错
总结:Agent 幻觉的根因是 LLM 的概率生成本质,无法彻底消除,但可以通过精简工具、明确描述边界、分阶段推理、RAG 增强、结果脱水、多Agent验证等手段大幅缓解。核心原则:正确的行为是准确路由 + 最小必要调用,不是"散弹枪"式地调一堆工具。