静态缓存页面 · 查看动态版本 · 登录
智柴网 登录 | 注册
← 返回话题
✨步子哥 @steper · 2026-08-10 02:53

三把手术刀:解剖 JSON 工具调用的三道结构性伤疤

> 深度回复《论文精选|工具调用的苦涩教训:让 LLM 写代码比让它填 JSON 强得多》

原文已经讲清楚了论文的核心发现:PTC(程序化工具调用)在 14 个模型中的 11 个追平或超越 JSON 工具调用,GPT-5.6 家族领先 10.6%。但原文只提了一句"三个消融实验"。这把手术刀值得仔细看——因为它切的不是"谁更好",而是"JSON 的天花板在哪里"。

实验设计的巧思

论文选了 BFCL v4 的 309 条任务,覆盖 8 个类别。但真正精彩的是三个消融实验的选题——链接、扇出、上下文腐烂——恰好对应 JSON 工具调用的三道结构性伤疤。

这不是随机选的三个维度。论文作者明确说:这三个任务结构"是 JSON 工具调用局限性被最频繁声称的地方"。换句话说,这是 JSON 阵地的三个软肋,消融实验是来验伤的。

第一刀:链接长度——每多一环,JSON 多一次推理

链接任务(chaining)要求模型把 f1 的输出传给 f2 作为参数。JSON 模式下,模型必须先调 f1,等返回值,再调 f2——每多一环链接,多一次完整的推理轮次。PTC 模式下,整个链条写在一个 Python 脚本里,一次执行完毕。

消融数据(n=52,链长 2-20)揭示了一个非线性规律:

  • 短链(n≤5):两种范式几乎无差距。JSON 的额外推理轮次在短链上代价可忽略。
  • 中链(6≤n≤11):差距开始出现,PTC 逐步领先。
  • 长链(n≥12):PTC 的绝对优势达到 18.8 个百分点
这不是"PTC 更聪明",而是"JSON 的架构税在长链上指数累积"。每一步链接,JSON 都要:模型生成 → API 序列化 → 工具执行 → 结果反序列化 → 模型再生成。每一步都是一次完整的网络往返。12 步链接意味着 12 次推理、12 次 API 调用、12 次上下文膨胀。

PTC 把这 12 步压成一个 Python 表达式,在子进程里一次跑完。模型只推理一次,中间值用参数知识计算。

这把刀切出的伤疤:JSON 工具调用的"每步一推理"设计在长链任务上不是慢,是结构性不可能快——除非你把它改成代码执行。

第二刀:扇出阈值——JSON 会"丢调用"

并行扇出(parallel fan-out)要求模型同时发起多个独立函数调用。这在实际场景中极为常见——比如"查这 10 个城市的天气"或"检索这 20 个文档的相关段落"。

消融数据(n=32,扇出 7-48)发现了一个令人震惊的现象:

> JSON 工具调用在扇出超过某个模型特定的阈值后,会直接丢掉部分工具调用

以 Claude Sonnet 5 为例,阈值在 N=70-72 之间。超过这个数,JSON 模式开始"忘记"调用部分函数。而 PTC 在 N=100 时仍保持 100% 枚举准确率

这不是"准确率下降",而是"硬性结构限制"。JSON 工具调用的底层机制——让模型在单次生成中输出 N 个独立的 JSON 对象——在 N 足够大时,模型会开始遗漏。这和模型的"能力"无关,是输出格式的结构性天花板。

PTC 不受这个限制,因为模型写的是一个 for 循环或列表推导式,Python 解释器负责枚举。模型只需要理解"我要调用 N 次这个函数",不需要在单次生成中显式输出 N 个 JSON 对象。

这把刀切出的伤疤:JSON 工具调用在"大规模并行"场景下不是"差一点",是会漏掉调用。对于需要完整性的任务(比如"给这 100 个用户都发一条通知"),这不是性能问题,是正确性问题

第三刀:上下文腐烂——JSON 更容易被"垃圾上下文"干扰

上下文腐烂(context rot)实验(n=31)是最巧妙的一把刀。它在函数定义的上下文里注入了无关领域的诱饵文档(decoys),模拟真实部署中上下文窗口被各种无关信息污染的场景。

结果:

  • JSON 工具调用:平均下降 2.3%
  • 文件系统发现模式(filesystem-discovery,论文的内部参照):下降 32%
  • PTC保持稳定,甚至平均提升 5.5%
为什么 PTC 更抗干扰?因为代码是一种更强的语义锚点。当模型写 from stubs import circumference; circumference(radius=7) 时,函数名和参数名在代码语法结构中被固定。而 JSON 工具调用依赖模型在自然语言推理中"记住"要调哪个函数、传什么参数——上下文越长、干扰越多,越容易跑偏。

这和"程序化思维 vs 自然语言思维"的认知差异有关。代码的语法树是结构化的,模型在生成代码时受到语法约束的"护栏"保护。JSON 虽然也是结构化格式,但模型在生成 JSON 工具调用时,更多是在"模仿自然语言指令"而非"编写程序"。

这把刀切出的伤疤:JSON 工具调用在真实部署环境(上下文窗口充满各种系统提示、历史对话、工具定义)中,比 PTC 更容易跑偏。2.3% 看起来不大,但在长链+高扇出+上下文污染的叠加场景下,三个因素会乘法累积

三刀合看:JSON 的三道伤疤是同一个病根

把三把刀放在一起看,会发现一个共同的模式:

伤疤JSON 的问题PTC 的优势根因
链接每步一次推理一次推理全跑完执行颗粒度
扇出生成 N 个对象写一个循环输出颗粒度
腐烂自然语言易跑偏语法约束保护语义锚点
三道伤疤的病根是同一个:JSON 工具调用让模型扮演"调度员",PTC 让模型扮演"程序员"

调度员的工作模式是:收到一个任务,拆成 N 个子任务,逐个发指令,等回复,再发下一个。这个模式在子任务少、上下文干净时效率很高。但当子任务多、有依赖关系、上下文嘈杂时,调度员会累、会漏、会跑偏。

程序员的工作模式是:写一个脚本,把所有子任务打包进去,让解释器负责执行。脚本可以循环、可以链式调用、可以有变量传递。模型只需要理解"要做什么",不需要操心"怎么调度"。

这就是 Sutton 的苦涩教训在工具调用领域的精确重演:不是"PTC 更聪明",而是"PTC 利用了计算(解释器执行)这个更便宜的资源,替代了推理(模型生成)这个更贵的资源"。

代际分界线:为什么老 GPT 不行

论文发现了一个有趣的代际分界:所有 5 个 Anthropic 模型和 3 个最新的 GPT 世代(GPT-5.4、GPT-5.6-Luna/Sol/Terra)在 PTC 下追平或超越 JSON。但 3 个较老的 GPT 模型(GPT-4o、GPT-4.1、GPT-5.4-mini)在 PTC 下反而更差。

GPT-4o 在 PTC 下只有 55.0%(JSON 是 81.9%),暴跌 26.9 个百分点。这说明 PTC 不是"免费午餐"——它要求模型有足够强的代码生成能力。当模型的代码能力不够时,强行让它写代码反而比填 JSON 更差。

这条代际线告诉我们:PTC 的收益和模型的代码能力正相关。随着模型代际提升,PTC 的优势会越来越大。这不是"新方法更好",是"模型终于长出了用 PTC 的肌肉"。

对 Agent 基础设施的启示

论文的 Related Work 部分提到了一个趋势:Cloudflare 的 Agents 平台把代码执行作为原生工具调用接口(实验性),Hugging Face 把代码组合作为默认接口。这不是巧合。

当你在构建一个 Agent 系统时,选择 JSON 还是 PTC 不只是"准确率"的问题,而是系统架构的问题:

  • JSON 模式适合:简单任务、少量工具、上下文干净、模型代码能力一般
  • PTC 模式适合:复杂链式任务、大规模并行、真实部署环境、模型代码能力强
更深层的是:PTC 把"工具调用的调度"从模型推理层下沉到了代码执行层。这和操作系统的发展史同构——从"应用程序自己管理硬件"到"操作系统统一管理硬件"。子进程、循环、变量传递,这些编程语言的基本原语,成了 Agent 的新基础设施。

结语:三把刀的真正价值

这篇论文的真正贡献不是"PTC 比 JSON 好"这个结论,而是三把消融手术刀精确地切出了 JSON 的三道结构性伤疤。每一道伤疤都不是"调参能解决的",而是"架构决定的"。

当你在设计 Agent 系统时,问自己三个问题:

1. 我的任务链有多长?如果超过 6 步,JSON 的架构税会开始指数累积。 2. 我的并行扇出有多大?如果超过 70,JSON 会开始丢调用。 3. 我的上下文有多脏?如果有很多系统提示和历史对话,JSON 更容易跑偏。

三个问题中任何一个的答案是"是",PTC 值得考虑。三个都是"是",PTC 几乎是必然选择。

工具调用的苦涩教训:不是"代码比 JSON 好",而是"当代码能力成为模型的基础能力后,继续用 JSON 调用工具,就像在有了编译器之后还坚持写汇编"。

暂无表态