[论文解读] 代码的复仇——当Sutton的苦涩教训遇上工具调用
论文信息 - 标题: The Bitter Lesson of Tool Calling - arXiv: 2608.06370 - 作者: Ishan Patel, Sahil Sen, Elias Lumer, Vamse Kumar Subbiah - 领域: NLP / 工具学习 / Agent
论文信息
- 标题: The Bitter Lesson of Tool Calling
- arXiv: 2608.06370
- 作者: Ishan Patel, Sahil Sen, Elias Lumer, Vamse Kumar Subbiah
- 领域: NLP / 工具学习 / Agent
🎭 引言:两个工匠的故事
想象两个木匠。
木匠A是一个传统派。他有一个精美的工具箱,里面每样工具都有固定的位置和用途。他用刨子刨平面,用凿子凿榫眼,用锯子锯木头。每次需要做一个新零件,他就从工具箱里取出对应的工具,按照既定的步骤操作。他的工作精确、可靠,但面对复杂或 novel 的任务时,常常需要创造性地组合多种工具——而这超出了他的"标准流程"。
木匠B是一个革新派。他不那么在意"工具的固定用途"。对他来说,刨子不仅可以刨平面,还可以当临时的尺子;凿子不仅可以凿榫眼,还可以当小锤子用;甚至一块废弃的砂纸,他都能想出三种不同的用法。他的工具箱里没有"标准流程",只有"当下的最佳解法"。
多年来,木匠A嘲笑木匠B"不专业"、"乱来"。但慢慢地,人们发现木匠B不仅能做传统家具,还能做各种奇形怪状的定制作品,而且做得更快、更灵活。
这个故事,某种程度上就是程序化工具调用(Programmatic Tool Calling, PTC)与传统JSON工具调用之争的缩影。
🧠 第一章:Sutton的苦涩教训——一个AI领域的"天问"
1.1 什么是"苦涩教训"?
要理解本文的核心论点,我们必须先回到2019年,DeepMind研究员Rich Sutton写的一篇著名博客文章——《The Bitter Lesson》(苦涩教训)。
Sutton在文章中提出了一个令人不安的观察:在AI发展的70年历史中,那些依赖人类知识注入的方法,最终都被那些依赖大规模计算和通用学习的方法所超越。
他用国际象棋、围棋、语音识别、计算机视觉等领域的例子说明:
- 早期研究者试图将人类的专业知识编码到系统中("人类知识方法")
- 这些方法在短期内表现不错,但很快遇到瓶颈
- 最终胜出的,往往是那些看似简单、通用、但能够利用海量计算资源的方法("搜索和学习方法")
"我们应该从中吸取的苦涩教训是:① 人类知识倾向的引入从长远来看总是适得其反;② 让AI通过大规模计算自己学习,比让人类精心设计知识表示更有效。"
这个"苦涩教训"成为了AI领域的一个根本性张力:我们是要精心设计系统,还是让它自己从数据中学习?
1.2 从通用AI到工具调用
Sutton的原始论述主要针对的是核心AI能力(如棋类游戏、视觉识别、语言理解)。但本文的作者们提出了一个自然的问题:
"苦涩教训"是否也适用于工具调用这个领域?
工具调用(Tool Use)是LLM Agent的核心能力之一。简单来说,就是让AI不仅能"说话",还能"做事"——调用计算器、查询数据库、执行代码、调用API等等。
目前的主流做法是JSON工具调用:
1. 开发者预先定义一组工具(每个工具有名称、参数、描述) 2. 当AI需要调用工具时,它输出一个格式化的JSON字符串 3. 系统解析这个JSON,调用对应的工具,把结果返回给AI
这种方法就像木匠A的工具箱——每样工具都有固定的位置(JSON格式),固定的用途(预定义的功能)。优点是规范、可控、易于调试。缺点是僵化、不灵活、难以处理复杂或 novel 的场景。
本文提出的程序化工具调用(PTC)则更像木匠B的做法:
1. 工具被暴露为类型化的Python函数存根(stubs) 2. AI通过生成代码来调用工具——可以在一个代码片段中链式调用多个工具、并行调用、条件调用 3. 代码在一个受控的环境中执行,结果返回给AI
这种方法的核心优势在于表达力的解放:代码是一种图灵完备的编程语言,它能够表达任何计算逻辑,而不仅仅是固定的参数传递。
🔧 第二章:PTC vs JSON——两种范式的深层对比
2.1 JSON工具调用:秩序的美与代价
让我们先看看JSON工具调用的"工作原理",以及为什么它在过去两年成为了行业标准。
JSON工具调用的典型流程:
{
"tool": "calculator",
"arguments": {
"expression": "15 * 23 + 7"
}
}
系统收到这个JSON后,调用计算器工具,计算结果,返回给AI。
这种方法的优点非常明显:
优点一:结构化与可预测性 JSON是严格格式化的。每个工具调用都有明确的结构:工具名称、参数列表、参数类型。这使得:
- 开发者容易验证AI的输出是否合法
- 系统容易解析和执行
- 错误容易定位和修复
优点三:与现有基础设施兼容 JSON是Web世界的通用语言。REST API、GraphQL、各种微服务之间的通信都使用JSON。JSON工具调用天然地与这些基础设施兼容。
但是,JSON工具调用也有深层的局限:
局限一:表达力的天花板 JSON本质上是一个键值对结构。它能表达"调用A工具,参数是X"。但它难以表达:
- "先调用A,如果结果大于10就调用B,否则调用C"
- "并行调用A、B、C,等所有结果回来后,用D处理它们的组合"
- "循环调用E,直到满足某个条件"
局限二:组合性的缺失 JSON工具调用是"原子性"的——每次调用一个工具。如果AI需要完成一个多步骤任务,它必须: 1. 输出第一个工具调用 2. 等待结果 3. 基于结果,输出第二个工具调用 4. 等待结果 5. ...
这导致交互轮次爆炸。一个简单的数据分析任务,可能需要5-10轮工具调用才能完成。每轮调用都涉及:
- AI生成输出(推理成本)
- 网络延迟(等待成本)
- 上下文窗口的占用(记忆成本)
- 开发者必须预见到AI可能需要的所有操作
- 工具的粒度(粗粒度 vs 细粒度)需要人工权衡
- 工具之间的组合方式需要人工设计
2.2 程序化工具调用:混乱中的自由
PTC的核心思想是:不要给AI一套固定的工具使用规则,而是给它一套工具和一个编程环境,让它自己学会怎么组合使用。
PTC的典型流程:
# AI生成的代码
weather = get_weather(location="北京")
if weather.temperature > 30:
suggestion = "太热了,建议室内活动"
events = search_events(city="北京", indoor=True)
else:
suggestion = "天气不错,可以出去走走"
events = search_events(city="北京", outdoor=True)
return {
"suggestion": suggestion,
"events": events[:3]
}
这段代码展示了PTC的几个核心优势:
优势一:原生支持控制流 条件判断(if/else)、循环(for/while)、异常处理(try/except)——这些都是编程语言的基本能力。AI可以在一次代码生成中,表达复杂的决策逻辑。
优势二:自然组合 代码天然支持组合。一个函数可以调用另一个函数,可以把多个工具的结果组合起来,可以把中间结果存储在变量中供后续使用。
优势三:减少交互轮次 在上面的例子中,如果是JSON工具调用,AI需要至少3轮交互: 1. 调用get_weather 2. 基于结果,调用search_events 3. 格式化输出
而在PTC中,这一切都在一轮代码执行中完成。虽然代码生成本身可能比单个JSON复杂,但总体的交互成本大幅降低。
优势四:通用性与可扩展性 PTC不需要为每个新场景预定义工具接口。只要工具被暴露为Python函数,AI就可以用任何方式调用它们——包括开发者从未预料到的方式。
但是,PTC也有其挑战:
挑战一:安全性 让AI生成并执行代码,天然比让AI输出JSON更危险。需要严格隔离的执行环境(沙箱)、资源限制(时间、内存)、权限控制等。
挑战二:调试复杂性 当AI生成的代码出错时,调试比调试JSON工具调用更复杂。错误可能是:语法错误、运行时错误、逻辑错误、无限循环等等。
挑战三:模型能力要求 生成正确的代码比生成正确的JSON对模型的能力要求更高。模型需要理解:Python语法、类型系统、错误处理、各种库的API等等。
📊 第三章:实验——用数据说话
3.1 实验设计:BFCL v4上的全面评测
为了公正地比较PTC和JSON工具调用,本文的研究者们在BFCL v4(Berkeley Function Calling Leaderboard)上进行了系统性的实验。
BFCL是一个广受认可的工具调用基准测试,它评估LLM在各种场景下的工具调用能力,包括:
- 简单调用:单个工具调用
- 多工具调用:一次调用多个工具
- 并行调用:并行执行多个独立的工具调用
- 链式调用:工具调用的输出作为下一个工具调用的输入
- 条件调用:基于前面结果的条件性工具调用
3.2 核心发现:PTC在大多数模型上优于JSON
实验结果可以用一句话概括:在14个模型中的11个上,PTC达到或超过了JSON工具调用的表现。
具体来说:
GPT-5.6系列:PTC相比JSON基线实现了10.6%的提升。这个提升幅度相当可观,说明对于最先进的模型,PTC能够显著释放其潜力。
并行调用场景:在需要并行执行多个工具调用的场景中,PTC在14个模型中的13个上达到或超过了基线。这说明PTC的"原生并行支持"确实有效。
上下文退化场景:研究者还测试了一种"上下文退化"(Context Rot)的场景——当对话历史变长、上下文变得嘈杂时,模型的表现如何。
结果发现:在这种条件下,JSON工具调用的基线平均下降了2.3%,而PTC保持稳定。这说明PTC对上下文的敏感度更低,更鲁棒。
3.3 深入分析:PTC的优势来自哪里?
为了理解PTC为什么有效,研究者进行了更细致的分析:
分析一:迭代能力不是关键
研究者设计了一个对照实验:给AI同样的"循环+工具调用"能力,但一个使用PTC接口,一个使用JSON接口。
结果发现:PTC的优势主要来自接口本身,而不是"迭代能力"。即使给JSON工具调用的AI迭代能力,它仍然无法达到PTC的表现。
这说明,PTC的优势不仅仅是"能写代码",而是代码这种表达形式本身带来的结构性优势——自然的控制流、变量绑定、组合性等等。
分析二:模型能力追踪
研究者还发现一个有趣的规律:PTC的优势随着模型代际的提升而增大。
在较老的模型上,PTC和JSON的差距不大(有时甚至JSON更好,因为老模型生成代码的能力较弱)。但在新模型上,PTC的优势变得明显。
这说明:PTC是一种"面向未来"的方法。随着模型代码生成能力的持续提升,PTC的优势会越来越大。
🎭 第四章:苦涩教训的延续——从历史看未来
4.1 历史的回响
Sutton的"苦涩教训"不仅是一个观察,更是一个预测。让我们看看AI历史中几个类似的"范式转换":
例一:计算机视觉的特征工程
2012年之前,计算机视觉的主流方法是人工设计特征——SIFT、HOG、SURF等等。研究者们花大量时间设计、调优这些特征,认为人类的视觉知识可以帮助机器"更好地看"。
2012年,AlexNet横空出世。它用的是最朴素的卷积神经网络,没有任何人工设计的特征。但它有6000万个参数,在GPU上训练了两周。
结果?它在ImageNet竞赛上碾压了所有使用人工特征的方法。
例二:自然语言处理的句法分析
在深度学习之前,NLP的主流方法是句法分析。研究者们构建了复杂的句法树、语义角色标注、依存关系分析。他们认为,理解语言需要先理解其结构。
然后Transformer出现了。它没有任何显式的句法分析模块,只是用注意力机制在大规模文本上训练。结果?它在几乎所有NLP任务上都超过了精心设计的方法。
例三:围棋的蒙特卡洛树搜索
在AlphaGo之前,围棋AI的主流方法是人类知识的编码——定式、棋型判断、厚势/实地的评估。研究者们把职业棋手的知识编码到程序中。
AlphaGo和后来的AlphaZero则完全不同。AlphaZero从零开始,只通过自我对弈学习。它没有人类棋谱,没有定式库,没有人工评估函数。但它在训练了几小时后,就超过了所有人类棋手和所有之前的AI。
这三个例子都印证了Sutton的"苦涩教训":通用方法+大规模计算 > 人类知识注入。
4.2 工具调用:下一个"苦涩教训"?
本文的核心论点是:工具调用正在经历同样的范式转换。
JSON工具调用,本质上是一种"人类知识注入"的方法:
- 开发者定义工具的接口(人类知识的编码)
- 开发者设计工具的组合方式(人类工作流的编码)
- AI被限制在预定义的框架内操作
- 给AI一个编程环境和一套工具
- 让AI自己学会如何组合使用
- AI可以创造出开发者从未预料到的使用模式
4.3 但"苦涩教训"也有边界
值得注意的是,Sutton本人也承认,"苦涩教训"不是绝对的。他在原文中写道:
"这并不意味着我们不应该追求人类的理解。我们仍然应该追求它,只是我们应该追求那种通过搜索和学习获得的理解,而不是那种通过人类知识注入获得的理解。"
同样,PTC也不是JSON工具调用的"完全替代"。在某些场景下,JSON仍然有其价值:
- 高度安全敏感的场景:如果工具调用的安全性至关重要(比如金融交易、医疗诊断),JSON的严格限制可能更可控
- 简单场景:如果只需要简单的单次工具调用,JSON的简洁性可能更优
- 与遗留系统的集成:如果现有基础设施都是基于JSON的,迁移成本可能很高
🚀 第五章:实践指南——如何拥抱PTC
5.1 技术实现要点
如果你决定在项目中使用PTC,以下是一些关键的实现考虑:
安全隔离 AI生成的代码必须在沙箱环境中执行。这包括:
- 容器化隔离(Docker、gVisor等)
- 资源限制(CPU时间、内存、网络访问)
- 权限控制(文件系统访问、系统调用过滤)
- 超时机制(防止无限循环)
from typing import Optional, List
def search_weather(location: str, date: Optional[str] = None) -> dict:
"""
查询指定位置和日期的天气信息。
Args:
location: 城市名称或坐标
date: 日期(YYYY-MM-DD格式),默认为今天
Returns:
包含温度、湿度、天气状况等信息的字典
"""
... # 实际实现
def calculate(expression: str) -> float:
"""
计算数学表达式。
Args:
expression: 数学表达式字符串,如"15 * 23 + 7"
Returns:
计算结果
"""
... # 实际实现
注意类型注解和文档字符串——这些对AI理解工具的用法至关重要。
错误处理 代码执行可能失败。系统需要:
- 捕获所有异常(SyntaxError、RuntimeError、Timeout等)
- 将错误信息返回给AI,让它有机会修正
- 限制重试次数,防止无限循环
5.2 迁移策略
如果你已经在使用JSON工具调用,不必一次性全部迁移。可以考虑:
渐进式迁移
- 从最简单的工具开始,先让AI用PTC调用它们
- 逐步增加复杂工具,观察AI的表现
- 保留JSON作为Fallback,当PTC失败时使用
- 简单工具调用继续使用JSON
- 复杂的多步骤任务使用PTC
- 让AI自己决定什么时候用哪种方式(这需要额外的训练或提示工程)
- 在实际生产环境中,对PTC和JSON进行A/B测试
- 比较成功率、延迟、成本、用户满意度等指标
- 基于数据做决策,而不是先入为主的假设
🎬 结语:代码的复仇
回到本文开头的两个木匠。
多年来,木匠A(JSON工具调用)的"规范"和"可控"赢得了行业的信任。它是标准的制定者,是最佳实践的代言人。
但木匠B(PTC)正在用结果说话。它的作品更灵活、更高效、更能应对复杂的需求。
这不是说木匠A错了——在简单、标准化、安全敏感的场景中,它仍然有价值。但Sutton的"苦涩教训"提醒我们:不要高估人类设计的精巧性,不要低估通用方法的潜力。
代码正在复仇。不是作为人类的替代品,而是作为AI表达能力的解放者。
当AI能够用代码思考,它不再是一个"按固定规则操作工具"的执行者,而是一个"创造性地组合工具解决问题"的思考者。
这,或许就是工具调用的"苦涩教训"——也是它的甜蜜未来。
📚 参考文献
Patel, I., Sen, S., Lumer, E., & Subbiah, V. K. (2026). The Bitter Lesson of Tool Calling. *arXiv preprint arXiv:2608.06370*.
Sutton, R. S. (2019). The Bitter Lesson. *Blog post*. http://www.incompleteideas.net/IncIdeas/BitterLesson.html
#论文 #arXiv #工具调用 #Agent #苦涩教训 #小凯