从自然语言到可执行的 API 调用
假设你正在开发一个自动化运维工具,需要根据用户的一句话“列出所有运行中的 EC2 实例”生成对应的 AWS API 调用。直接让大语言模型(LLM)写这段代码,它很可能给出一个看起来合理但实际不存在的参数,或者把 describe_instances 拼成 list_instances。这种幻觉在 API 调用场景中尤其致命,因为错误的调用要么直接报错,要么在无人值守的流水线里静默失败。
传统的解决思路是让模型记住 API 文档,但 API 数量庞大且频繁更新,模型参数化记忆很难跟上。Gorilla 提出了一种不同的做法:在训练时把检索到的 API 文档拼接到用户查询之后,让模型学会阅读文档并据此生成调用。这样,模型不再依赖记忆,而是依赖推理时提供的文档,从而在 API 变更时无需重新训练。
基线方法:提示工程与 Toolformer 的局限
在 Gorilla 之前,让 LLM 调用 API 主要有两条路线。一是直接提示,例如在 prompt 中附上少量示例,希望模型模仿。这种方法在 API 数量少、结构简单时可行,但面对成千上万的 API 时,模型容易混淆相似接口,且无法处理超出训练数据的参数。
另一条路线是 Toolformer,它采用自监督方式训练模型自己决定何时调用哪个 API。Toolformer 让模型在文本中插入 API 调用标记,然后通过困惑度过滤筛选出对预测有帮助的调用,再用这些数据微调模型。这种方法不需要人工标注,但存在两个问题:一是模型可能学会调用错误的 API,因为过滤只关注困惑度下降,不保证调用正确;二是它对 API 文档的利用很弱,模型主要依靠自身记忆,无法适应文档变化。
Gorilla 的出发点正是这两点:用文档增强微调,让模型在生成时参考文档,而不是凭记忆。
核心机制:检索感知训练(RAT)
Gorilla 基于 LLaMA-7B 微调,采用检索感知训练(Retriever-Aware Training, RAT)。训练时,每个样本由用户查询和对应的 API 文档组成,格式为“使用此 API 文档作为参考:<retrieved_API_doc_JSON>”。模型被训练成根据文档内容生成正确的 API 调用。
这种训练方式教会模型两件事:一是阅读文档,提取关键信息,如函数名、参数类型和默认值;二是信任文档而非参数化记忆。当推理时文档发生变化,模型会依据新文档生成调用,从而实现测试时的自适应。
数据流与决策过程
输入是自然语言查询,例如“加载一个在 ImageNet 上预训练的图像分类模型”。系统首先通过检索器从 API 文档库中获取相关文档,然后将查询和文档拼接,送入 Gorilla。模型输出 API 调用,例如 torch.hub.load('pytorch/vision', 'resnet50', pretrained=True)。整个过程如下:
flowchart TD
A[用户自然语言查询] --> B[检索器从文档库获取相关API文档]
B --> C[拼接查询与文档]
C --> D[Gorilla模型生成API调用]
D --> E{是否验证调用?}
E -->|是| F[执行验证器检查语法与参数]
E -->|否| G[直接使用调用]
F --> H{验证通过?}
H -->|是| G
H -->|否| I[返回错误或重新生成]
检索是可选的。在零样本模式下,Gorilla 直接根据查询生成调用,不依赖外部文档;在检索模式下,文档被注入提示,模型据此生成。检索模式对 API 变更更鲁棒,但检索质量直接影响生成准确性。
评估数据集与指标:APIBench 与 AST 子树匹配
为了评估 API 调用能力,Gorilla 团队构建了 APIBench 数据集,涵盖 HuggingFace(925 个 API)、TorchHub(95 个)和 TensorFlow Hub(696 个)。每个 API 通过 self-instruct 生成 10 个合成查询,共约 1.6 万个指令。
评估指标采用 AST 子树匹配,即把生成的 API 调用解析成抽象语法树,检查其功能正确性,而不仅仅是字符串相似。例如,如果模型输出 model = torch.hub.load('pytorch/vision', 'resnet50'),而正确调用应包含 pretrained=True,则 AST 匹配会识别出缺少参数,视为错误。
AST 匹配比 BLEU 等文本相似度指标更严格,也更贴近实际执行。但需要注意,APIBench 的查询是合成生成的,与训练分布相似,可能高估模型在真实模糊查询上的表现。
与 Toolformer 的对比:监督微调 vs 自监督学习
Toolformer 和 Gorilla 都旨在让 LLM 使用工具,但方法不同。Toolformer 通过自监督方式让模型自己决定调用哪些 API,训练数据由模型自身生成,并用困惑度过滤。Gorilla 则使用人工标注的(查询,文档,调用)三元组进行监督微调。
在效果上,Gorilla 在 APIBench 上的准确率显著高于 Toolformer,尤其是在 API 数量多的场景。Toolformer 的优势在于无需大量标注数据,但它的调用准确性受限于模型自身的判断,容易产生幻觉。Gorilla 的监督信号更直接,但依赖高质量的训练数据。
下表对比了两者的关键差异:
| 维度 | Gorilla | Toolformer |
|---|---|---|
| 训练方式 | 监督微调(文档增强) | 自监督学习(困惑度过滤) |
| 文档利用 | 训练时注入检索文档,推理时可选 | 不显式利用文档 |
| 幻觉率 | 较低(5%~11%) | 较高(未报告具体数字) |
| 适应 API 变更 | 通过检索文档实现测试时适应 | 需要重新训练 |
| 数据要求 | 需要(查询,文档,调用)三元组 | 仅需少量示例 |
| 适用场景 | API 数量大、更新频繁 | API 数量少、结构简单 |
检索增强的集成:提升准确率与适应性的双刃剑
Gorilla 的检索模式在推理时从文档库中检索相关 API 文档,并注入提示。当检索到正确的文档时,模型生成准确率显著提升。例如,在 oracle 检索(检索到地面真值文档)下,准确率可达 67%~94%。
但真实检索器并不完美。论文报告,从 oracle 切换到 GPT-Index 时准确率下降 29.20%,切换到 BM25 时下降 52.27%。这意味着检索质量是系统性能的关键瓶颈。如果检索器返回不相关或过时的文档,模型可能被误导,生成错误的调用。
因此,在生产环境中,检索器的选择至关重要。BM25 这类传统检索器在 API 文档这种专业领域效果有限,可能需要使用语义检索或微调检索器。但即使检索质量不高,Gorilla 的零样本模式仍能提供一定准确性,可以作为降级方案。
幻觉的缓解与残余风险
Gorilla 的核心贡献之一是显著降低幻觉。在 APIBench 上,Gorilla 的幻觉率在 TorchHub 上为 6.98%,HuggingFace 上为 10.95%,TensorFlow Hub 上为 5.40%,而 GPT-4 的幻觉率在 36.55% 到 78.65% 之间。
幻觉的降低主要归功于文档感知训练:模型学会了依赖文档而非记忆,从而减少了编造不存在的 API 或参数。但幻觉并未完全消除,尤其在检索文档不完整或模糊时,模型仍可能生成错误调用。
此外,APIBench 的评估范围有限,主要针对机器学习库 API,这些 API 结构相对规则。对于更复杂的 REST API,如云服务,涉及认证、速率限制、多步工作流,Gorilla 的效果尚未充分验证。因此,在实际应用中,仍需结合执行时验证器,如 AST 检查或沙箱执行,来捕获残余错误。
工程实践:部署边界与可观测性
将 Gorilla 集成到生产系统时,需要考虑以下工程问题:
- 检索器选择:根据文档库规模和查询分布选择检索器。如果文档库较小,BM25 可能足够;如果较大,需要语义检索。建议评估检索质量对最终准确率的影响。
- 缓存与版本管理:API 文档会更新,需要定期重新索引。缓存检索结果时,要注意文档版本,避免使用过时文档。
- 错误处理:生成的调用可能不完整或错误,需要设置验证层。例如,使用 AST 解析检查函数名和参数类型,或在实际环境中试运行。
- 可观测性:记录检索到的文档、生成的调用、验证结果,以便分析失败模式。监控指标包括检索命中率、生成准确率、幻觉率。
Gorilla 的部署边界在于:它擅长单步 API 调用,对于多步工具链或需要状态管理的场景,需要结合其他机制,如 ToolLLM 或函数调用框架。
尚未解决的问题与未来方向
Gorilla 展示了文档感知微调的有效性,但仍存在未解决的问题。一是检索质量对性能影响巨大,如何构建更鲁棒的检索器是开放问题。二是训练数据依赖人工标注,扩展新领域成本高。三是评估基准的局限性,APIBench 主要覆盖 ML 库,需要更多真实场景的基准。
后续工作如 ToolLLM 扩展了 16,000 多个真实 REST API,伯克利函数调用排行榜(BFCL)则持续跟踪前沿模型的函数调用能力。这些进展表明,API 调用是 LLM 应用的重要方向,而 Gorilla 的文档感知训练为这一方向奠定了基础。