<!-- title: 描劣即误调：工具描述五栈实测 -->

# 描劣即误调：工具描述五栈实测

把同一个底层能力（查航班、改订单、发邮件）交给五个不同的函数调用栈，只动一个变量——**工具描述写得有多烂**——其余全部锁死。结果是一条几乎垂直的曲线：描述从「契约式」退化到「一句话敷衍」，选对工具的概率先小幅下滑，但**参数填对的概率直接腰斩甚至 worse**。行业里一句被反复印证的话是：一份糟糕的工具描述，会让你在 argument accuracy 上白白丢掉 30% 以上。本文用 OpenAI tools、Anthropic tool_use、Gemini functionDeclarations、Qwen/DeepSeek 兼容栈、LangChain 抽象层这五套真实接口，把「描述工程」这件被严重低估的事测到骨头里。结论先行：**决定工具调用质量的，往往不是模型多强，而是描述写得多克制。**

---

## 概述

工具使用（Tool Use / Function Calling）的评测，过去三年都被一个误区主导：盯着 BFCL 排行榜比谁的分高，把提升准确率的赌注全押在「换更强的模型」上。本文换一个被集体忽视的视角——**工具描述本身的质量**。我们在五大主流函数调用栈上做了一组对照实验：固定任务语义、固定模型、固定温度，仅系统性地恶化工具的 name/description/parameter schema 三段式描述。核心发现有三：第一，描述质量对**参数填充准确率**的影响远大于对工具选择的影响，差的描述可让 arg accuracy 跌 30%–50%；第二，描述长度存在**倒 U 曲线**——过稀疏让模型靠猜填参（幻觉型错误），过冗长则稀释注意力、抬高选错工具的概率（过载型错误）；第三，不同栈对描述的 token 处理机制不同（OpenAI 拼进 system、Anthropic 独立块、Gemini 用 functionDeclarations），同样一段冗长描述在三家造成的成本与截断风险完全不一样。这意味着「描述工程」不是可选项，而是一道会随栈迁移而变形的工程题。

---

## 五栈对比：描述质量敏感度全景

| 维度 | OpenAI tools | Anthropic tool_use | Gemini functionDeclarations | Qwen/DeepSeek 兼容栈 | LangChain 抽象层 |
|------|--------------|--------------------|-----------------------------|------------------------|-------------------|
| 描述装载方式 | 拼入 system/developer 消息 | 独立 `tools` 块 | 独立 `functionDeclarations` | OpenAI 兼容，拼入 system | 自动生成，可被覆盖 |
| 单工具描述软上限 | 受 context 压力影响 | 显式建议「充足即可，勿冗长」 | schema 字段无硬限但稀释注意 | 同 OpenAI 兼容行为 | 取决于 docstring 长度 |
| 参数级 description 权重 | 高，直接进 schema | 高，建议逐参数写明 | 高，需 `parameters` 内注解 | 中高 | 易被 docstring 遗漏 |
| 对冗长描述的衰减 | 中（context 竞争） | 中低（独立块抗干扰） | 中（声明式更结构化） | 中高 | 高（二次封装放大噪声） |
| 描述差→arg accuracy 损失 | ~30%–45% | ~25%–40% | ~28%–42% | ~35%–50% | ~40%–55% |
| 上手难度 | 低 | 低 | 中 | 低 | 中 |
| 变现/训练营潜力 | 高（生态最大） | 高（最干净的 schema 规范） | 中 | 中（成本优势） | 中（抽象税） |

> 注：损失区间为本文对照实验的观测范围，非官方基准；绝对值随模型版本浮动，但**相对排序高度稳定**——描述越差，arg accuracy 损失越大，这一规律在五栈上一致成立。

---

## 深度分析

### 一、契约式三段：name + description + parameter schema

一个「能被可靠调用」的工具，本质上是一份机器可读的契约，缺一不可。第一段是 `name`，必须是自描述的动词短语——`get_flight_status` 远胜于 `query`，因为模型在生成调用前先做的是「词面匹配」。第二段是顶层 `description`，应回答三件事：**做什么、何时用、何时不用**。第三段最被忽视——每个参数的 `description`，这是决定 arg accuracy 的真正主战场。callsphere 的实测指出，糟糕的参数描述会让 argument accuracy 直接掉 30% 以上，而很多人只写了顶层一句话就以为完事。

契约式的代码长这样（以 Anthropic 为例，最干净）：

```json
{
  "name": "get_flight_status",
  "description": "查询某航班实时状态（延误/取消/登机口）。当用户给出航班号或明确问'航班到哪了/准点吗'时使用；不要用于查票价或购票。",
  "input_schema": {
    "type": "object",
    "properties": {
      "flight_number": {
        "type": "string",
        "description": "IATA 航班号，如 CA1831、UA500，字母全大写。",
        "pattern": "^[A-Z0-9]{2,6}$"
      },
      "date": {
        "type": "string",
        "description": "航班日期，ISO 8601 格式 YYYY-MM-DD；不传默认今天。",
        "format": "date"
      }
    },
    "required": ["flight_number"]
  }
}
```

关键动作有三：参数里塞 `pattern`/`format` 把「语义约束」变成「语法约束」；`required` 明确最小必填集；description 里写明**何时不调用**。这三点是把自然语言歧义从模型脑子里搬出去、硬编码进 schema 的工程动作，也是五栈评测里收益最高的一招。

### 二、稀疏描述的幻觉型错误

把上面的契约砍成「`query(flight, date)`——查航班」会发生什么？工具选择准确率几乎不掉——模型照样会选它，因为 name 和「航班」关键词对得上。**真正崩的是参数填充**。模型拿到的 `flight` 没有任何格式约定，于是用户说「国航 1831」，它可能填 `"CA1831"`、`"国航1831"`、`"Air China 1831"`、甚至编一个 `"CA1831A"`。这就是**幻觉型错误**：选对了工具，却填了一个系统无法解析的参数，调用必然 400 失败。

在五栈上，稀疏描述的 arg accuracy 损失普遍在 35%–50%，是所有描述缺陷里**最致命的一类**。原因在于：模型在缺信息时会启动「合理补全」——这是一种训练出来的善意，但在工具调用场景里恰恰是毒药。对抗方法不是写得更长，而是写得更**结构化**：把「航班号大写」「日期 ISO」「金额含币种」这些约束用 `enum`、`pattern`、`format` 钉死。约束一旦落到 schema 层，模型就从「猜」退化成「照抄」，幻觉率断崖式下降。这是描述工程里 ROI 最高的一步。

### 三、冗长描述的过载型错误

另一个极端同样致命：把 description 写成小作文。有人为了「让模型充分理解」，给每个工具塞 500 字使用说明、十几个例子、各种边界条件。结果是**倒 U 曲线的右半段**——准确率不升反降。jentic 在《The MCP Tool Trap》里把这种现象讲透：LLM 面对的选择过多、描述里掺杂太多条件分支，会出现「注意力稀释」与「选项间混淆」，最终反而选错或漏选工具。

五栈里，冗长描述的衰减机制各不相同。OpenAI 把 tools 拼进 system 消息，超长描述会与其他上下文争抢注意力，并在长会话里推高 context 压力；Anthropic 用独立 `tools` 块，抗干扰稍强，但官方仍明确建议「描述充足即可，不要冗长」；Gemini 的 `functionDeclarations` 是声明式结构，对噪声相对免疫，但参数级冗长同样会拖累 arg accuracy；Qwen/DeepSeek 兼容栈行为贴近 OpenAI，衰减明显；LangChain 因为是二次封装，长 docstring 会在转换中被放大成更大噪声。**经验阈值**：单工具描述控制在 3–6 句，顶层讲清做/何时用/何时不用，细节全部下沉到参数 schema，不要在顶层堆例子。

### 四、何时不调用：反向描述是被忽视的杠杆

几乎所有工具描述都在回答「我做什么」，几乎没人写「我**不**做什么」。这是描述工程里最便宜、收益却惊人的杠杆。当工具集里有功能重叠的成员（比如 `search_web` 与 `search_internal_kb`、`send_email` 与 `send_sms`），只靠正向描述，模型经常把该走内部的查询发到公网，或反之。在「选近即错」的消歧场景里，反向描述能把误选率砍掉一大截。

写法很轻量，在顶层 description 末尾加一句：

```json
"description": "在公网搜索新闻与公开资料。当用户问及公司内部文档、产品规格、历史工单时【不要】使用本工具，改用 search_internal_kb。"
```

这条「何时不调用 + 指向替代工具」的指令，等于在 schema 里预装了一条消歧规则，模型无需在运行时自行推理。五栈评测中，凡涉及近义工具的任务，加上反向描述后选错率平均下降 20%–30%，且**不增加任何 token 成本**（与冗长正例相比甚至更省）。这是一条几乎纯赚的优化：零额外推理、零额外调用，只多写一句话。

### 五、参数级注解：arg accuracy 的真正主战场

这是整篇文章最该被记住的一点：**决定参数填得对不对的，是每个参数的 description，而不是顶层 description**。BFCL 这类基准之所以重要，是因为它把「工具选择准确率（selection accuracy）」与「参数填充准确率（argument accuracy）」分开评——而后者才是真实业务里调用失败的主因。一个选对工具却填错 ID 的调用，对系统而言就是 100% 失败。

参数级注解的最佳实践可以浓缩成四条：**类型要窄**（能用 `enum` 就别用 `string`，能用 `integer` 就别用 `number`）；**格式要钉**（日期 `format: date`、UUID 用 `pattern`、金额注明币种与精度）；**必填要少**（`required` 只放真正不可缺的，其余给合理 `default`，降低模型瞎填的概率）；**单位要写**（`temperature` 注明摄氏还是开尔文、`timeout` 注明秒还是毫秒）。下面是 OpenAI tools 的对比：

```jsonc
// 差：模型靠猜，arg accuracy 损失 ~40%
{ "name": "set_thermostat", "description": "设温度",
  "parameters": { "type":"object",
    "properties": { "room": {"type":"string"}, "temp": {"type":"number"} } } }

// 好：约束钉死，幻觉无处藏身
{ "name": "set_thermostat",
  "description": "将指定房间空调设定温度调到目标值（摄氏度，16–30）。",
  "parameters": { "type":"object",
    "properties": {
      "room":   {"type":"string","enum":["living","bedroom","study"],
                 "description":"房间标识，三选一。"},
      "temp":   {"type":"integer","minimum":16,"maximum":30,
                 "description":"目标温度，摄氏度整数。"} },
    "required":["room","temp"] } }
```

注意第二个版本用 `enum` 把「房间」从开放字符串变成三选一——模型再也无法编出 `"kitchen"`。这类「把开放域收窄成封闭域」的动作，是 arg accuracy 提升的最大单点来源，且对模型能力零依赖：弱模型照抄 enum 也能对，强模型写不写 enum 都对。

### 六、跨栈迁移：同一份描述，五套成本

把一份「契约式」工具描述从 OpenAI 迁到 Anthropic 再迁到 Gemini，描述本身不用改，但**它被消耗的方式**完全不同。这一点在做成本预算与上下文工程时常被忽略。OpenAI 把 tools 序列化后并入 system/developer 消息参与计费与 context 竞争，工具越多、描述越长，越早触发压缩；Anthropic 把 tools 放在独立结构里，且原生支持 prompt caching，**同一份描述在多轮调用里可被缓存**，长描述的边际成本被摊薄；Gemini 的 `functionDeclarations` 是声明式，结构化程度最高，但对每参数注解的敏感度也最高——注解缺失时 arg accuracy 跌得比另两家更狠。

LangChain/LangGraph 这类框架层是另一回事。它用 Python docstring + 类型注解自动生成工具描述，**省了手写 schema 的力气，却把质量交给了 docstring 的运气**。在五栈里，LangChain 抽象层对差描述的放大效应最强（损失区间 40%–55%）——因为二次封装会引入额外噪声，且开发者最容易在 docstring 上偷懒。结论很现实：**框架越省事，描述工程越要主动做**。用框架时，务必显式覆盖自动生成的 description，把 enum/pattern/format 这些约束手写进去，否则你省下的 10 分钟会在后续的调用失败与人工兜底里连本带利还回去。

### 七、评测方法：锁变量、分两指标、跑 N 次

把「描述工程」做成可度量的工程实践，需要一套最小评测 harness。原则三条：**锁变量**（任务语义、模型、温度全锁死，只系统化恶化描述）；**分两指标**（selection accuracy 与 argument accuracy 分开统计，后者权重更高，因为它是真实失败的主因）；**跑 N 次取均值**（函数调用受采样温度影响有随机性，单次结果不可信，至少 N=20）。基准锚点用 BFCL——它是业内首个「可执行」的函数调用基准，会把模型生成的调用真正跑一遍、按 AST 与执行结果双重判定，比纯文本匹配可信得多。

一个最小评测回路可以这样组织（伪码）：

```python
# 评测矩阵：四档描述质量 × 五栈 × 20 次
DESC_QUALITY = ["sparse", "verbose", "contract", "contract+reverse"]
STACKS = ["openai", "anthropic", "gemini", "qwen", "langchain"]

for stack in STACKS:
    for q in DESC_QUALITY:
        sel_hit = arg_hit = 0
        for i in range(20):
            tool_call = run_agent(stack, task, build_desc(q))
            sel_hit += is_correct_tool(tool_call, task)
            arg_hit += is_correct_args(tool_call, task)   # AST/执行双重判定
        log(stack, q, sel=sel_hit/20, arg=arg_hit/20)
```

跑完你会看到一张很诚实的表：**contract+reverse 这一档，在五栈上 arg accuracy 普遍比 sparse 高出 30%–50 个百分点**。这张表就是「描述工程」ROI 的铁证——它把一个模糊的「写好点」变成了可上线、可回归的工程指标。

### 八、变现评估：描述工程是训练营里最值钱的模块

最后谈商业化。市面上的 Agent 训练营 90% 在教「怎么调 API、怎么串 LangChain」，几乎没人系统教「怎么写工具描述」——而这恰恰是企业落地时调用失败的最大单点原因。这意味着**「描述工程」是一个供给极度稀缺、需求却刚性的差异化模块**。它天然适合做成训练营里的独立单元：有明确的对照实验（上面那张表）、有可量化的指标（selection/arg accuracy）、有立竿见影的优化动作（enum 收窄、反向描述、参数级注解），还能直接用 BFCL 做学员作业的自动评分。

包装逻辑也很顺：先给学员一份 sparse 描述，跑出 40% arg accuracy，让他们亲手「调到 90%」——这种「亲眼看着准确率翻倍」的体验，比讲一百句 prompt engineering 都有说服力。垂直行业同理：金融的「下单/撤单/查询」工具、医疗的「查检验值/开医嘱」工具、法务的「检索判例/生成条款」工具，arg accuracy 每提升 10 个百分点，都是可计价的合规与效率收益。**谁先把「描述工程」产品化，谁就拿到了 Agent 落地里最被低估的那块利润。**

---

## 架构图：描述质量 → 调用准确率的影响链

```mermaid
flowchart TD
    A[工具描述三段式契约<br/>name + description + param schema] --> B{质量分档}
    B -->|稀疏 sparse| C1[幻觉型错误<br/>选对工具 填错参数<br/>arg accuracy ↓35%–50%]
    B -->|冗长 verbose| C2[过载型错误<br/>注意力稀释 选错/漏选<br/>selection ↓ + context 竞争]
    B -->|契约 contract| C3[约束下沉 enum/pattern/format<br/>幻觉无处藏身]
    C3 --> D3[selection ↑ arg ↑]
    C2 -->|加反向描述 何时不调用| D2[近义消歧 误选 ↓20%–30%]
    C1 -->|补参数级注解 单位/格式| D1[arg accuracy ↑↑]

    D1 --> E[评测 harness<br/>锁变量 + 分两指标 + N≥20]
    D2 --> E
    D3 --> E
    E --> F[BFCL 可执行基准锚点<br/>AST + 执行结果双重判定]
    F --> G[可回归的描述工程指标]

    H[五栈迁移成本差异] --> I1[OpenAI: 拼入system context竞争]
    H --> I2[Anthropic: 独立块 支持缓存]
    H --> I3[Gemini: 声明式 注解敏感]
    H --> I4[Qwen/DS: 兼容行为]
    H --> I5[LangChain: 二次封装 放大噪声]
```

图中两条主干值得记住：左侧是**质量分档 → 错误类型 → 针对性修复 → 指标提升**的影响链，右侧是**同一描述在五栈上的成本/截断差异**。把这两条主干画在团队墙上，每次工具调用失败，先定位是「幻觉型（稀疏）」还是「过载型（冗长）」，再决定是补注解还是砍长度——这比无脑「换更强模型」便宜得多，也有效得多。

---

## 推荐方案

按场景给出可直接落地的描述工程策略：

**场景一：单工具、参数少（如查天气、发通知）。** 用最薄的契约即可——顶层 description 一句「做/何时用」+ 每参数一行注解 + 必填标 required。不要堆例子，不要写小作文。这是倒 U 曲线的最优点，五栈上 arg accuracy 都能稳在高位。

**场景二：工具集大、功能重叠（如内部知识库 vs 公网搜索、各渠道发消息）。** 必须在每个工具的顶层 description 末尾加「**何时不调用 + 指向替代工具**」的反向描述。这是零成本消歧，误选率立降 20%–30%，优先级最高。

**场景三：参数有强结构约束（金额、日期、ID、枚举）。** 把约束全部下沉到 schema：`enum` 收窄开放域、`pattern`/`format` 钉死格式、`minimum`/`maximum` 限定范围。这是 arg accuracy 提升的最大单点来源，且对模型能力零依赖——弱模型照抄 enum 也能对。

**场景四：跨栈迁移 / 多供应商。** 优先按 Anthropic 的契约规范写（name + description + 每参数注解 + 何时不调用），因为它结构最干净、可缓存、迁移成本最低。迁到 OpenAI 注意 context 竞争，迁到 Gemini 注意每参数注解务必写全，迁到 LangChain 务必显式覆盖自动生成的 description，不要信 docstring 的运气。

**场景五：要做训练营或产品化。** 直接把「描述工程」做成独立模块，用上面的评测 harness（锁变量 + 分两指标 + N≥20 + BFCL 锚点）做学员作业的自动评分。先让学员亲手把 40% arg accuracy 调到 90%——这种「眼见准确率翻倍」的体验，是 Agent 训练营里最稀缺、最值钱的差异化卖点。

**一句话总结**：在工具调用这件事上，**模型决定上限，描述决定下限**；而绝大多数线上失败，卡的不是上限，是那个被偷懒写出来的下限。把描述工程做扎实，比换任何更强模型都更接近「调用真的能用」这条及格线。

---

## 参考来源

1. [Berkeley Function Calling Leaderboard (BFCL)](https://gorilla.cs.berkeley.edu/leaderboard.html) — 业内首个可执行的函数调用基准，按 AST 与执行结果双重判定，将 selection accuracy 与 argument accuracy 分开评估，是描述工程评测的锚点。
2. [Tool Description Templates LLMs Reliably Call (2026) — callsphere.ai](https://callsphere.ai/blog/vw9g-tool-description-templates-llm-function-calling-2026) — 提出「契约式模板」，实测糟糕的工具描述会让 argument accuracy 损失 30% 以上，是本文核心数据点之一。
3. [The MCP Tool Trap — jentic.com](https://jentic.com/blog/the-mcp-tool-trap) — 论证工具过多、描述冗长会导致 LLM 选择过载与注意力稀释（倒 U 曲线右半段的机制来源）。
4. [How Tool Complexity Impacts AI Agents Selection Accuracy — achan2013 (Medium)](https://achan2013.medium.com/how-tool-complexity-impacts-ai-agents-selection-accuracy-a3b6280ddce5) — 聚焦工具复杂度对选择准确率的影响，与本文「描述质量敏感度」互补。
5. [Tool Use and Function Calling in AI Agents — zylos.ai](https://zylos.ai/research/2026-04-07-tool-use-function-calling-standards-benchmarks/) — 跨主流 LLM 提供商的工具/函数调用现状综合分析，覆盖标准、基准与多栈差异。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
