Toolformer:Language Models Can Teach Themselves to Use Tools
(NeurIPS 2023 oral)
早期调用工具的大模型。
方法
核心概念与符号定义
为了让语言模型 $M$ 能够无缝地调用工具,作者将每个 API 调用表示为一个元组 $c = (a_c, i_c)$,其中 $a_c$ 是 API 的名称,$i_c$ 是输入参数 。
在文本中,API 调用被线性化表示为特殊的字符串序列:
- 无结果的 API 调用:$e(c) = \langle API \rangle a_c(i_c) \langle /API \rangle$
- 包含结果的 API 调用:$e(c, r) = \langle API \rangle a_c(i_c) \to r \langle /API \rangle$
这里的 $\langle API \rangle$、$\langle /API \rangle$ 和 $\to$ 是模型用来识别工具调用的特殊标记 。
方法详解:自监督的 API 数据集生成
Toolformer 的核心思路是:给定一个普通的纯文本数据集 $\mathcal{C}$,利用语言模型自身的上下文学习(In-context learning)能力,自动生成一个包含有效 API 调用的增强数据集 $\mathcal{C}^*$,然后再用这个增强数据集对模型自身进行微调 。
这一过程分为四个关键步骤:
1. 采样 API 调用 (Sampling API Calls)
首先,对于每种工具,作者编写了一个提示(Prompt)$P(x)$,通过少量示例鼓励语言模型为给定的文本序列 $x = x_1, …, x_n$ 标注潜在的 API 调用 。
在文本的每个位置 $i \in {1, …, n}$,计算模型生成 API 开始标记 $\langle API \rangle$ 的概率 $p_i$:
$$p_i = p_M(\langle API \rangle | P(x), x_{1:i-1})$$
如果该概率大于设定的采样阈值 $\tau_s$,即 $p_i > \tau_s$,则保留该位置作为潜在的调用点 。对于这些候选位置,模型会基于前缀生成最多 $m$ 个具体的 API 调用候选 $c_i^1, …, c_i^m$ 。
2. 执行 API 调用 (Executing API Calls)
接下来,模型会真实地执行上一步生成的所有 API 调用候选,从而获取外部工具返回的文本结果 $r_i$ 。例如,如果调用是计算器 [Calculator(400/1400)],执行后获得的结果 $r_i$ 就是 0.29 。
3. 过滤 API 调用 (Filtering API Calls) —— 最核心步骤
这一步决定了哪些 API 调用是“真正有用的”。作者设计了一个基于困惑度(交叉熵损失)的过滤机制。
给定模型 $M$ 在前缀为 $z$ 时,对后续标记(tokens)$x_i, …, x_n$ 的加权交叉熵损失函数为:
$$L_i(z) = -\sum_{j=i}^n w_{j-i} \cdot \log p_M(x_j | z, x_{1:j-1})$$
(注:$w_{j-i}$ 是权重,用于让模型更关注紧随 API 调用之后的 token 的预测 。)
为了评估 API 的有用性,作者对比了两种损失:
$L_i^+$ (提供 API 及其结果的损失):
$$L_i^+ = L_i(e(c_i, r_i))$$
这代表模型在已知工具调用及正确结果的情况下,预测后续文本的难度 。
$L_i^-$ (不提供有用信息的损失):
$$L_i^- = \min(L_i(\varepsilon), L_i(e(c_i, \varepsilon)))$$
这里 $\varepsilon$ 代表空序列。$L_i^-$ 取以下两种情况的最小值:(1) 完全不进行 API 调用;(2) 进行了 API 调用但没有提供结果 。
过滤标准:如果提供 API 的结果能够显著降低模型预测未来 token 的难度,那么这个 API 就是有用的 。因此,只有当满足以下条件时,该 API 调用才会被保留:
$$L_i^- - L_i^+ \ge \tau_f$$
(即:加入 API 及其结果后,模型的损失至少减少了过滤阈值 $\tau_f$ 。)
无结果调用 是训练准备阶段的一把尺子。它用来测试:“如果我只问问题但不给答案,模型是不是照样能猜出后续文本?” 如果是,说明这个工具调用是多余的,直接删掉 。
4. 模型微调 (Model Finetuning)
经过过滤后,保留下来的高质量 API 调用会与其对应的文本合并,形成新的增强序列 $x^$ 。对整个语料库执行此操作后,得到增强数据集 $\mathcal{C}^$ 。最后,使用标准的语言建模目标,在这个增强数据集上对语言模型 $M$ 进行微调 。
因为插入 API 调用的位置恰好是工具能帮助模型预测的地方,微调过程让模型内化了何时、何地以及如何使用这些工具的决策能力 。
推理阶段
在实际应用(推理)阶段,微调后的 Toolformer 像常规模型一样逐字生成文本 。
- 当它生成特殊标记 $\to$ 时,表示它需要外部工具的帮助 。
- 此时,解码过程会暂停,系统会调用相应的 API 并获取结果 。
- 将结果和关闭标记 $\langle /API \rangle$ 插入到文本序列中后,模型恢复解码过程,继续生成后续文本 。
与agent区别
单次插入 vs. 多轮交互与链式调用
Toolformer:它是一个“单向”的流水线。一旦决定调用工具,它就暂停,拿到结果,插入文本,然后继续往后写 。论文明确指出,它的主要局限性之一是无法将工具链式调用(即把一个工具的输出作为另一个工具的输入),也无法交互式地使用工具(比如搜索结果不好时主动修改搜索词重新搜) 。
现代 Agent:具备强大的纠错和多步规划能力。如果第一次搜索没找到答案,Agent 可以根据返回的报错信息或无关结果,自主调整参数进行第二次查询,甚至串联多个工具(先搜今天日期,再把日期传给天气 API查询天气)。
现代 Tool-Calling Agent 是如何训练出来的?
1. 高质量的监督微调(SFT, Supervised Fine-Tuning)
这是最核心的一步。研究人员会构造大量“人类 - 助手”的对话数据,这些数据专门展示了如何正确使用工具。不同于 Toolformer 试图避免大量人工标注 ,现代 Agent 往往依赖极高质量的标注数据:
数据包含什么:用户的原始请求、系统提供的可用工具列表(JSON 描述)、模型“思考”的过程、模型输出的函数调用指令,以及工具返回结果后模型的最终回答。
获取方式:早期的工作确实依赖大量人工标注 。现在则多采用“蒸馏”或“合成数据”的方法,即用最强的模型(如 GPT-4)去自动生成这种多轮工具交互的高质量对话,再拿去微调小模型。
2. 基于人类反馈的强化学习(RLHF / DPO)
有了基础的工具调用能力后,模型还需要学会“常识”和“规矩”。
- 比如,当用户问“天空为什么是蓝色的”,模型其实不需要调用搜索引擎就能回答。
- 研究人员会通过 RLHF(强化学习)来惩罚模型的“滥用工具”、“幻觉调用(编造不存在的参数)”或“死循环”,并奖励那些“高效、准确解决了用户问题”的调用轨迹。
3. 提示词工程驱动(无需微调的 Agent)
很多时候,我们现在用的 Agent(比如基于 LangChain 搭建的代理),其底层大模型根本没有专门针对你手头的工具进行过微调。
- 它们之所以能工作,是因为底层模型(如 GPT-4)经过了海量的 SFT 和 RLHF 训练,拥有了极强的**指令遵循(Instruction Following)**和**逻辑推理**能力。
- 你只需要在 System Prompt 中告诉它:“你是一个助手,你有以下三个工具(计算器、搜索、日历),当你需要时,请按照固定的 JSON 格式输出你想调用的工具”。模型就能利用其强大的零样本(Zero-shot)泛化能力直接扮演一个 Agent。