把工具调用数据反着造:ToolGrad 用 500 条样本追平闭源大模型的那件事

ToolBench 用 12.6 万条 SFT 数据把开源模型教会 tool-use,方式是「先给用户问题、DFS 搜工具链」。ToolGrad 反着来:先造链、再回头写用户 query。500 条样本训练出的 Gemma-3-12B 在 BFCL 上 83.1 分,等于 gemini-2.5-pro、高于 GPT-5。这篇把它的四模块管线拆到源码位置,把「textual gradient」追溯到 TextGrad,并和 APIGen、ToolACE 拉一张四家决策矩阵。

ToolBench 用 12.6 万条 SFT 数据把开源模型教会 tool-use,方法是「先给一个用户问题、然后 DFS 搜可行的工具链」,标准做法。ToolGrad(Zhou et al. 2025,arXiv 2508.04086,ACL 2026 Findings)反过来做:先让 LLM 自己把工具链攒出来,再回头给它编一个自然的用户 query。这么造出来的 500 条样本训 Gemma-3-12B,在 BFCL 上 83.1 分,等于 gemini-2.5-pro(83.2)、高于 GPT-5(74.4)——Google Research 官方博客给出的对比。

500 条样本追平闭源顶级模型这件事本身值得停下来想一下。这篇把它的四模块管线拆到源码文件、把「textual gradient」这个词的血脉追到 TextGrad、和 APIGen / ToolACE 拉一张四家决策矩阵,最后手算一笔账说明这份数据的效率究竟省在哪、又没省在哪。

名词速查

术语一句话解释
tool-use / function callingLLM 在回答前先调用外部 API/函数,把结果拼进上下文再输出——不再全靠模型参数记事实
BFCLBerkeley Function-Calling Leaderboard,社区最常用的 function-calling 基准;有单轮、并行、多轮、幻觉四类题(本站 v3 深读
ToolBench / ToolLLM2023 年 Qin 等做的 16K RapidAPI 工具库 + 12.6 万条 SFT 数据集,ICLR 2024 spotlight,此前是开源 tool-use SFT 数据的事实基线
DFSDTToolBench 用的深度优先搜索决策树:给定用户问题,LLM 探路径、失败回溯、成功即封样本;过程失败率高,标注贵
RapidAPI一个真实的公开 API 市场,ToolBench 从上面爬了 16,464 个 REST API 当作工具池
textual gradientTextGrad(Yuksekgonul et al. 2024,Nature)提出的说法:LLM 对某个输出的自然语言批评,可以像数值梯度一样反向传导去修改输入变量

一句话根本约束

先把这篇的核心压成一句可反驳的话:

ToolGrad 之所以能长成 answer-first 的样子,是因为「工具调用轨迹的验证成本远低于搜索成本」这个物理事实。

这句话怎么反驳?如果验证一个工具链的正确性和搜索一个正确工具链一样贵——比如工具执行成本高于 LLM 调用、或者验证需要人参与——那答案-first 的收益会被验证代价吃掉,ToolBench 那种 query-first 反而更划算。它可反驳,因此有信息。

把它挂到一个共同祖先上:这是 NP 家族的老套路在工具调用里的又一次实例化——「给定候选解的验证」比「找出候选解的搜索」便宜一个数量级。ToolBench 是搜索,ToolGrad 是「先随机生成一个候选、再拿去反向标注」,其实就是把工程重心从搜索侧挪到生成-验证侧。

崩点在哪?把 ToolGrad 的 SELECTOR 换成「随机选一个提议 API 就往链上贴」,你会得到一堆语义支离破碎的调用序列——工具能跑成功但工具之间没有信息流。先崩在语义连贯性上,pass rate 不会立刻掉(每个 API 独立执行仍成功),但生成出的 query 会读起来像「先查天气再翻译一段无关的中文再看股价」,训练下游模型时反而害了它。这解释了 SELECTOR 为什么必须是那个几百字的详细 prompt 而不是一个打分器——它承担的是「工具之间的语义粘合」,不是「工具单点可执行」。

四模块拆到源码位置

论文说 ToolGrad 有四个模块:API Proposer / API Executors / API Selector / LLM Updater。听起来抽象,翻到 toolgrad/modules/prompt_lib.py 就看得清清楚楚——每个模块就是一个 ChatPromptTemplate,一共 4 个主 prompt,加起来约 220 行 Python。

flowchart TD
  A["1. API Proposer"] -->|top-k 候选| B["2. API Executors"]
  B -->|执行报告 api_reports| C["3. API Selector"]
  C -->|挑一个 API<br/>或拒绝| D["更新 workflow"]
  D -->|循环 N 步| A
  D -.->|终止时一次性触发| F["4. LLM Updater<br/>(PREDICT_WORKFLOW)"]
  F -->|反向生成<br/>user query + response| G[("样本落盘")]

四个模块干的事和源码对应位置(都在同一个文件):

模块源码位置干什么输入 → 输出
API Proposerprompt_lib.py:6-26 (TOOLUSE_PROPOSER_WOO)从 15,368 个 API 池里挑 num_proposals 个候选来扩展当前 workflow(workflow_cur, api_all) → 若干 API 提议 + 执行 instruction
API Executorsprompt_lib.py:70-108 (API_EXECUTOR + system prompt)并行跑候选 API,每个自己判断 success = True/False 并给出 justificationplan + 环境 → 执行报告(含 success 标志 + 说明)
API Selectorprompt_lib.py:129-151 (SELECTOR)读所有执行报告,选一个 API 追加到 workflow,或拒绝所有候选;同时决定是「append 到现有链」还是「开新链」(workflow_cur, api_reports) → 一个选择 + 追加/新建决策
LLM Updaterprompt_lib.py:153-220 (PREDICT_WORKFLOW)循环结束后,给定完整 API 执行轨迹,反向生成一个自然的用户 query + 一段助手回复api_use_chains(query, response)

「textual gradient」到底长什么样,就在 SELECTOR 这一个 prompt 里。 我把 129-151 行贴出来读一读——这不是数学梯度,就是一段大白话指令:

You are an API selector.
You need to select one API or refuse to select any API from the given list of APIs to augment the current workflow.

The current API-use workflow:
{workflow_cur}

Reports from the proposed APIs:
{api_reports}

When you select an API, you need to make the following decisions:
1. Determine whether any API can be used to augment the current workflow.
2. If yes, select one API to augment the current workflow.
3. Decide whether to append the selected API to an existing API-use chain or create a new API-use chain:
    3.1 **Append to existing chain**: Choose this when the API logically should follow another call in an existing chain...
    3.2 **Create new chain**: Choose this when the API is independent...

所谓「梯度」,就是 {api_reports} 这段填进去的自然语言执行报告——每个候选 API 跑完后自己吐一段 justification,SELECTOR 读了这些描述、挑一个继续贴到链上。如果 TextGrad 是「LLM 对输出的批评能当梯度」,那 ToolGrad 就是「LLM 对候选执行结果的评价能当梯度」——粒度换了、方向换了、骨架一模一样。

真正 answer-first 的动作发生在最后一步 PREDICT_WORKFLOW(L153-220)。这个 prompt 明确要求:

  • 「Write queries like a real human would ask」(要像真人问的样子)
  • 「NEVER mention APIs, tools, functions, or technical implementation」(绝不能出现 API 名字
  • 「If 3 APIs were called, the query should naturally require all 3」(3 个 API 全部隐式地被这个问题覆盖)

也就是说:先有 API 轨迹,再有一个从未见过这些 API 名字、只按业务需求描述任务的自然 query。这就是 answer-first——链是骨架,query 是从骨架反向生成的皮肤。

textual gradient 的血脉

「梯度」在这里是借喻,不是隐喻。追一下 TextGrad 到 ToolGrad 这一路走过来做了什么:

阶段论文谁产生「梯度」谁被「梯度」更新更新方式
起点TextGrad(Yuksekgonul et al. 2024, Nature;arXiv:2406.07496LLM critic 对输出的自然语言批评prompt / 代码 / 分子式(文本变量)计算图反向传导,「backpropagation of text」
中转各种基于 TextGrad 的 prompt 优化工作LLM 批评当前 prompt 在 val set 上的错误prompt 本身类似 SGD 的迭代改写
ToolGrad本文(Zhou et al. 2025, arXiv 2508.04086)LLM 对 K 个候选 API 执行结果的评价(api_reports当前 API-use workflow(一个逐步生长的图)SELECTOR 挑一个 API 贴上去,或拒绝所有

共同祖先是 ProTeGi(Pryzant 2023) 提出的「用 LLM 给出自然语言反馈来迭代改进 prompt」——TextGrad 把它一般化成了整个计算图的反向传导范式;ToolGrad 又把它从「优化一段静态文本」推进到「构造一个动态生长的 API 工作流」。同一条谱系上走的三步。

顺带看下 TextGrad 上一辈就有的 DSPy(Khattab 2023):DSPy 也用 LLM 反馈优化 prompt,但方式是编译期用训练集去优化整条 pipeline;TextGrad 是推理时对单个难例逐步 refine。ToolGrad 更像 TextGrad 那一支——推理式的、逐样本地把 API 一层层贴上去,直到链自然生成、再一次性生成用户 query。

决策矩阵:ToolBench / APIGen / ToolACE / ToolGrad 四家

四篇论文全在解决同一个问题:怎么给 tool-use SFT 造数据。但每一步都做了不同的选择。把决策点排开:

决策点ToolBench (ICLR’24)APIGen / xLAM (2024)ToolACE (ICLR’25)ToolGrad (ACL’26)
生成方向query → 搜工具链query ↔ answer 并行采样多 agent 对话生成 query 和调用链 → query(反着来)
搜索反馈DFSDT:LLM 探路、失败回溯无搜索,直接采样复杂度评估器 + 多 agent 反驳textual gradient:SELECTOR 读执行报告选 API
验证时机事后:跑不通就丢三阶段验证(格式/执行/语义)双层:规则 + LLM 判别每步内嵌:每个 API 都执行过才可能被选
API 生态RapidAPI 16,464 个真实 API3,673 个可执行 API,21 类自造 26,507 API,390 域过滤后的 ToolBench 15,368 个
数据规模12.6 万 SFT 样本6 万条 (xlam-function-calling-60k)10 万条500 条
训练模型ToolLLaMA (LLaMA-2-7B)xLAM 系列 (1.3B / 7B)LLaMA-3.1-8BGemma-3 (1B / 4B / 12B)
单样本 pass rate低(DFSDT 30%+ 提升但仍远低于 100%)人类抽 600 条 >95% 正确未在同框架下报告~100%(每步都执行过)

四家可以按「怎么信任生成出来的样本」分成两派:

  • 搜索派(ToolBench):先给目标、再搜出满足目标的解——像做完形填空。
  • 生成-验证派(APIGen、ToolACE、ToolGrad):先造一个候选、再验证。区别只在「候选是怎么来的」和「验证放在哪一步」。ToolACE 用多 agent 对抗产生候选、事后双层验证;ToolGrad 用逐步贴 API 产生候选、每步都验证;APIGen 一次性采样、三阶段验证。

这里最有意思的对比不是 ToolGrad vs ToolBench,而是 ToolGrad vs ToolACE——两个 2025 年的工作,一个追求「大而全」(26K API、10 万条数据),一个追求「小而准」(15K API 过滤、500 条数据)。ToolACE 在 BFCL 上历史成绩更高(~91.4,8B 模型),但 ToolGrad 展示了另一条路:如果每一条样本都是干净的,可以用两个数量级更少的数据顶到同一档模型能力。这两条路径其实兼容——把 ToolACE 的产量和 ToolGrad 的过滤结合起来是显然可做的下一步,只是没人做。

一笔亲手算的账:省在哪、没省在哪

论文里有两个数字容易被读串,我用一次性脚本亲手核算过:

账 A:单样本工具调用成本

ToolGrad 单样本平均 20.0 次 tool 调用,DFS baseline 是 34.3 次(论文 §5 报的对比数字)。

saving_per_sample = (34.3 - 20.0) / 34.3 = 41.7%

每造一条样本,工具调用成本便宜 1.7 倍。 直观解释:DFS 会走错路、回溯、重来,很多 tool 调用是白跑;ToolGrad 的 SELECTOR 每次只 commit 一个已知能跑通的 API,走过的路都算数。

账 B:LLM 调用成本

同样口径:ToolGrad 63.9 vs DFS 64.5

saving_LLM = (64.5 - 63.9) / 64.5 = 0.9%

LLM 端几乎没省。 这是一个诚实的重要发现——「textual gradient」不便宜,因为 SELECTOR 每步都要读一大段执行报告。ToolGrad 的效率增益全在工具 API 侧(真实 API 才收钱、才会 rate limit),不在 LLM 推理侧。

账 C:达到同等能力所需的总样本量

这条是我做的推算,标注为「我认为」而非论文原文数字:

样本数:  500 (ToolGrad-500) vs 126,000 (ToolBench)  →  252×
每样本 tool 成本:  20.0 vs 34.3  →  1.7×

如果两者训出的模型能力可比(论文的实验主张),那么造整份数据集的 API 调用总量差距 = 252 × 1.7 ≈ 432 倍。我推测这个数字对 API 花钱的团队意义很大——真实的 RapidAPI 或商业 API 是按调用计费的,几百倍差距不是零头。但这一步要标注不确定性:论文没有在同一份 evaluation 下对齐 ToolLLaMA 和 ToolGrad-12B 的 BFCL 分数(BFCL 版本、评测协议都不一样),所以「能力可比」是我基于 ToolGrad 在 BFCL 上的绝对分数(83.1)反推的定性结论,不是严格意义下的实验对齐。

三个我读完之后想动手验证的问题

论文的实验设置很值得深挖,但也有几处我读完后想自己动手做才能真信的地方:

  1. 500 条真的够吗? 论文只训到 12B,没做 500 vs 5000 vs 50000 的样本数-能力曲线。「500 条 = 顶级闭源模型」是不是刚好卡在了曲线上一个甜点、放大规模反而收益递减?还是继续加会持续走高?未验证。
  2. BFCL 只测单轮/并行,多轮会怎样? ToolGrad 生成的链平均只有 3-4 个 API 步,BFCL v3 的多轮题目 要求跨轮维护状态。500 条数据里长链样本占比未在论文里明说,我怀疑长链复杂度是这套管线的软肋。
  3. 反向 query 的分布偏差。answer-first 的一个显然风险是:从工具能跑通的轨迹反推出的 query,会系统性偏向工具容易完成的任务,真实用户想问的很多东西根本就没有对应 API。这是 09-11 那篇 codex-ai-digest 里我已经点过一次的担忧——生成通过率不等于需求覆盖率,用它当训练数据要另外准备一个真实 query 的独立测试集。

小结:一句根本约束 + 一个崩点 + 一个可带走动作

  • 根本约束:验证一条 tool-use 轨迹比搜索一条便宜;answer-first 把这个不对称当作杠杆。
  • 崩点:SELECTOR 换成随机选,工具能跑但语义崩,反向生成的 query 会读起来像精神分裂——这解释了 SELECTOR 为什么必须是那段几百字的详细 prompt。
  • 可带走的动作:如果你在给自己的 tool-use 模型攒 SFT 数据,别照抄 ToolBench 的 query→DFS 老路。先从你的 API 池里让 LLM 跑几条 workflow,再让另一个 LLM 反着写用户 query。前者需要一个 SELECTOR 模块(能读 API 执行结果、能挑最相关的下一步);后者需要一个 PREDICT_WORKFLOW 模块(会把技术调用翻译成人话问题)。这两个模块的参考实现就是 prompt_lib.py 那 220 行,直接读原文比读任何二手总结都快。

通俗总结

把它想象成出练习题:一种老师是「先想好要考什么知识点、然后凑一道题、再自己解一遍验证答案能写出来」,这叫 ToolBench 那套 query-first;另一种老师是「先解一道自己觉得漂亮的题、然后回头给它编个题干」,这叫 ToolGrad 的 answer-first。第二种老师造的题少、每一道都能做对、但可能有点偏——都是他喜欢的类型。ToolGrad 就是这种老师,Google Research 把他派来给 LLM 出练习册,出了 500 题,考出来的学生和市面上最强的对手打成平手。

一句话可复述给同事:「先造答案,再倒着写题目」这套做法,用 500 条样本让开源模型追平闭源顶级模型;关键不是数据多,是每条样本都是干净的成功轨迹。

参考来源

主论文

血脉与共同祖先

  • Yuksekgonul et al. 2024. TextGrad: Automatic “Differentiation” via Text. arXiv:2406.07496(Nature 发表版)
  • Pryzant et al. 2023. Automatic Prompt Optimization with “Gradient Descent” and Beam Search (ProTeGi). arXiv:2305.03495
  • Khattab et al. 2023. DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines. arXiv:2310.03714

四家决策矩阵里的另外三家

  • Qin et al. 2023. ToolLLM: Facilitating Large Language Models to Master 16000+ Real-world APIs. arXiv:2307.16789(ICLR 2024 spotlight)
  • Liu et al. 2024. APIGen: Automated Pipeline for Generating Verifiable and Diverse Function-Calling Datasets. arXiv:2406.18518
  • Liu et al. 2024. ToolACE: Winning the Points of LLM Function Calling. OpenReview: 8EB8k6DdCU(ICLR 2025)

站内相关