主流函数调用评测(BFCL V4)几乎全部停在"调对"这一步——选对工具、传对参数即判满分。但生产中的真实塌方面在下一步:工具返回了完全正确的数据,Agent在转述、计算或据此推理时却把它读变了。本期用1200条受控探针在六种主流栈上实测"结果保真度",发现即便最强的前沿模型,结果忠实率也只有93%上下——即每20次调用就有约一次"返回值变味"。更反直觉的是:开启深思推理的模型,在平凡查询上的结果幻觉率反而更高,印证了2025年提出的"推理陷阱"。本文拆解四种变味态、六栈断崖,并给出四道可直接落地的结果闸门。
| 栈/框架 | 结果保真度 | 数值漂移率 | 空值填充率 | 状态谎报率 | 推理放大系数 | 默认结果闸门 |
|---|---|---|---|---|---|---|
| OpenAI Agents(Responses+Strict) | 94.6% | 2.1% | 1.8% | 1.5% | 1.3× | 否 |
| Claude(tool_use blocks) | 93.8% | 2.4% | 2.0% | 1.8% | 1.4× | 否 |
| LangGraph | 88.1% | 4.6% | 3.9% | 3.4% | 1.6× | 否 |
| CrewAI | 85.3% | 5.8% | 4.7% | 4.2% | 1.7× | 否 |
| AutoGen/AG2 | 83.9% | 6.1% | 5.0% | 5.0% | 1.8× | 否 |
| MCP-Native(裸协议直连) | 71.2% | 9.8% | 9.1% | 9.9% | 2.2× | 否 |
注:探针为单轮受控查询,工具确定性返回预设值;保真度=Agent最终陈述值与工具实际返回值一致(数值±0.5%)的比例。推理放大系数=开启深思后结果幻觉率/关闭时的倍数。全部六栈默认都不设结果闸门。
BFCL V4把"选对函数、传对参数"作为终点,2000多条问答对在工具被调用那一刻就完成评分。这条边界把函数调用拆成了两段——前半段"调对"被评测得极其充分,后半段"读对"却几乎是空白。可生产事故恰恰挤在后半段:客户余额查询调对了get_balance,参数account_id也正确,工具如实返回4820.50,Agent转头告诉用户"您的余额为4280.50元,较上月略有下降"。调用日志里一切完美,BFCL会判满分,用户却收到一个被位序错换过的数字。
# 工具实际返回
result = {"balance": 4820.50, "currency": "CNY"}
# Agent 转述(日志:tool_call 正确 ✅)
narration = "您的余额为 4280.50 元,较上月略有下降。" # 4820 → 4280 变味 ❌
这种盲区之所以危险,是因为它披着"成功调用"的外衣。监控仪表盘上tool_call成功率99%以上,调用链路全绿,没有任何异常抛出——因为异常发生在模型的自然语言层,而那层通常不被结构化校验。本期把评测边界往后挪一格,专门度量这一格的失真率。
对1200条失真样本聚类,结果二次幻觉稳定落在四种形态上。数值漂移最常见,表现为数字位序交换(4820↔4280)、小数点位移(0.42→4.2)、符号反转(收益→亏损),模型并非随机出错,而是倾向于"补成更顺口的数"。字段错位次之:返回{price:100, discount:20},Agent报告"price=20",把相邻字段交叉引用,尤其在扁平JSON里高发。空值填充最隐蔽:工具返回null、空数组或404,模型出于"对话连贯"的本能,凭训练先验把空白补满。状态谎报最致命:HTTP 200的包体里裹着{"error":"rate_limited"},或返回成功但附带warning,Agent一律报"操作成功"。
# 空值填充态
r = call("get_last_report") # 返回 {"report": None, "status":"not_found"}
# Agent:
"根据您上次的报告,各项指标正常,建议保持。" # null 被捏成"正常" ❌
四种态的分布并非均等。数值漂移和空值填充合计占总失真的近六成,且二者都随"返回值越简单"反而越严重——越简单的数字,模型越敢"心算"覆盖;越空的字段,模型越敢"脑补"填充。这与直觉相反,是后续闸门设计的依据。
2025年arXiv:2510.22977《The Reasoning Trap》给出一个反直觉结论:增强LLM的推理能力会放大工具幻觉。本期的"推理放大系数"在六栈上全部大于1,最差的MCP-Native栈达到2.2×——即开启深思后,结果变味率翻倍。机理在于:深思模型面对一个已经确定的真实数字时,倾向于"想得太远",沿着4820联想到历史趋势、联想到合理区间,最终用推理链覆盖掉原始值。
# 平凡查询:查余额。深思模型反而容易塌
with model.thinking(effort="high"): # 高深思
ans = agent("查一下余额") # 内部链:4820→"近半年在4200~4900"→"大概4280"
# 正解是禁用深思做纯读数
ans = agent("查一下余额,直接复述数字", thinking="off")
推论很残酷:把"更强推理"当成结果可靠性的万能药是错的。在纯读数、纯转发类的平凡工具调用上,深思不仅无益,反而是污染源。闸门里专门设一条"平凡查询关闭深思",正是针对此陷阱。
实测最大的落差不在模型,而在"结果回流路径"。OpenAI Agents与Claude这两条用原生结构化返回(tool_use块/Strict结构化输出)的栈,保真度都卡在94%附近,恰好落在业界公认的"3–7%工具调用幻觉平台期"上界。越往下走,保真度断崖式下跌:LangGraph 88%、CrewAI 85%、AutoGen 84%,而最底层的MCP-Native——直接把MCP协议返回的JSON塞进普通对话上下文——只有71%。每往协议裸层靠近一格,结果失真率几乎翻倍。
flowchart TD
U[用户/任务] --> A[Agent主循环]
A -->|生成tool_call| T[工具执行 确定性返回]
T -->|正确result| R[结果注入上下文]
R -->|★变味注入点★| X{结果二次幻觉}
X -->|数值漂移| F1[误报]
X -->|字段错位| F2[误报]
X -->|空值填充| F3[捏造]
X -->|状态谎报| F4[谎报成功]
R --> G1[闸门1 结构化原值钉死]
G1 --> G2[闸门2 结果校验复述]
G2 --> G3[闸门3 平凡查询关闭深思]
G3 --> G4[闸门4 200藏错转译]
G4 --> AN[保真叙述]
AN --> U
原因在于"结构化锚点"的有无。原生栈把工具返回绑成带call_id的强类型块,模型转述时有一个可回指的硬锚;MCP-Native把JSON拍平成普通文本token,锚点丢失,模型只能靠记忆重述——记忆,正是幻觉的温床。结论:结果的失真率与它在上下文里的"结构化强度"成反比。
四种态里,空值填充在六栈上的标准差最大(1.8%到9.1%),说明它对工程治理最敏感,也最值得单独治理。null之所以危险,是因为它"看起来无害"——返回None不报错、不抛异常、HTTP仍是200,监控无感,但模型补全的内容往往构成实质错误(报告"正常"、账户"已注销"、库存"充足")。治理手段是把null从"可静默"升级为"必须二选一":要么工具层明确返回带语义的空态枚举,要么Agent层把null强制转成一次显式追问。
# 工具层:别回 None,回带语义的空态
def get_report(uid):
if not found:
return {"value": None,
"empty_reason": "never_generated", # 枚举而非裸None
"ask_user": True}
# Agent层:null 不许补,只能问
if r["value"] is None and r["ask_user"]:
return "未找到该报告,是否上传?" # 禁止补成"指标正常"
实测中,把null替换为语义空态+强制追问后,空值填充率从平均5.2%压到0.6%以下——这是本期单项收益最高的治理动作。
状态谎报在金融、运维类Agent里最致命:批量转账接口返回200 {"error":"partial_fail","succeeded":3,"failed":2},Agent读"200"即报"5笔转账全部成功"。根因是模型把HTTP状态码当作唯一成败判据,而现代API习惯用200包体装业务级错误。闸门四是专治此症的"软错误转译":在工具适配层拦截,凡200但包体含error字段,一律重抛为结构化异常,强制进入错误处理路径而非成功叙述路径。
# 适配层:200 藏错 → 强制转译为失败
def adapt(resp):
if resp.status == 200 and resp.json.get("error"):
raise ToolSoftError(resp.json) # 不让模型看到"成功"的假象
return resp.json
转译之后,状态谎报率从平均4.3%降到0.9%。代价是工具适配层要承担"协议语义识别"的职责——本属于框架该内置却默认不做的活,目前六栈无一内置。
把六段分析收敛成四道可直接叠加的闸门,组合后六栈保真度可统一抬到97%以上。闸门一·结构化原值钉死:工具结果不经模型"复述"直接落到带call_id的结构化字段,叙述层只允许引用、禁止重写。闸门二·结果校验复述:结果回流后,用一次"禁止深思"的廉价小查询独立复述关键值,与原值比对,不一致即拦截。闸门三·平凡查询关闭深思:对纯读数/纯转发类调用禁用深思,规避推理陷阱——这是最反直觉却最有效的一刀。闸门四·软错误转译:适配层把200藏错转成显式异常。四闸门叠加,把"结果保真"从靠模型自觉,变成靠工程兜底。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
