你有没有遇到过这种场面?给 Agent 接上了 50 个工具:查天气、订日历、发邮件、搜数据库……结果你让它“看看明天天气怎么样”,它居然调用了日历工具,给你创建了一个事件。工具没错,但全错了。

我最早以为是工具描述写得不清楚。后来把描述改得又短又直白,还是错。直到我去查了注意力机制的原理,才意识到——问题不在工具,而在模型的注意力被稀释了。
注意力不是自来水,它是有限的
你给模型一段包含 N 个 token 的上下文,它每生成一个 token 之前,都要让上下文里所有 token 互相对视一眼,计算彼此的相关度。这个过程叫注意力计算。关键限制是:一个 token 对其他 token 的注意力权重加起来是 1(归一化)。也就是说,注意力预算固定,分给谁多了,分给别人的就少了。
这就像你面前有 100 个人同时说话,你只有一对耳朵。10 个人时还能勉强分辨,100 个人时每个声音都模糊。工具描述就是那些“声音”,超过 50 个之后,模型的“耳朵”就开始抓瞎。
“中间位置”是注意力的盲区
这不是我的猜测。研究者在 2023 年发表过一篇论文,名字很直白:Lost in the Middle: How Language Models Use Long Contexts。他们发现,当关键信息位于长上下文的中间位置时,模型对它的召回率会显著下降;信息在开头或结尾时表现最好。
模型并没有真正“读”全部上下文,它只是重点读了头尾,中间部分一旦变长就只能“随缘”。
这对 Agent 开发意味着什么?工具列表恰恰是那种“中间区域”:前面是系统指令,后面是用户对话,工具描述夹在中间。它们就像一堆没有剧情联系的说明书,模型很难给每个工具持续分配足够的注意力。
为什么偏偏是 50 个工具?
这不是一个严格的阈值,而是很多实践者共同感受到的一个“悬崖”。50 个工具,每个描述平均 50 个 token,整体就是 2500 个 token。这个长度还不至于触及窗口上限,但已经超过了许多模型的“黄金区间”——也就是模型还能保持稳定理解的上下文长度。
一些实验表明,即使标称上下文窗口是 128k,模型的有效关注范围也远小于这个值。所以“50 个工具”本质是“工具描述占用 token 太多”的替代表达。你塞 30 个很长描述的工具,效果可能比 80 个简短描述更差。
一个把模型“逼疯”的实际例子
我曾经构建过一个带三个工具的 Agent,注意只有三个,但已经出现诡异调用。工具列表是:
- get_weather(city) —— 查询指定城市当前天气
- add_calendar_event(title, time) —— 在日历中添加事件
- send_email(to, subject, body) —— 发送邮件
用户说:“明天上午提醒我带上伞,因为天气预报说可能下雨。”理想情况下,模型应该先调用 get_weather 确认会不会下雨,再考虑要不要创建提醒。但它直接调用了 add_calendar_event,把“带伞”当成事件写进日历。
为什么?因为“提醒”和“明天上午”这两个词触发了日历工具的关联,而“天气预报”这种间接需求在几十行工具描述中变得不那么显眼。这不是智力问题,而是注意力分配问题——如果工具描述只有这一个,它当然不会混淆;当描述多了,匹配概率就会被摊薄。
怎么把注意力“抢”回来
我在项目里试过四种思路,按见效速度排序:
- 精简工具数量。把功能相近的工具合并成一个,用参数区分。比如 get_weather 和 get_forecast 合并成 get_weather_forecast。
- 给工具描述“做减法”。只保留“做什么”和“什么时候用”,删掉形容词和定冠词。一个描述超过 30 个词,就开始抢别人的注意力了。
- 加一个路由器。先用一个小模型判断用户意图属于哪个领域,再把该领域的 5~10 个工具描述注入上下文。Anthropic 的官方文档就专门讨论过处理大量工具的这种策略。
- 用向量检索动态选择。把所有工具描述预嵌入,用户提问后按相似度取 top 10,只把这 10 个描述塞给 LLM。这相当于给模型开卷考试,但只给它看得分最高的几页书。
一张表看透四种方案
| 方案 | 核心思路 | 优点 | 缺点 |
|---|---|---|---|
| 精简工具 | 减少工具数量 | 最直接,几乎不引入额外错误 | 工具多后合并成本高 |
| 描述做减法 | 降低每个工具的 token 占比 | 见效快,容易实施 | 信息不足会导致模型误解 |
| 路由器 | 先分类,再加载子集 | 大幅度缩短上下文,准确率高 | 多一跳延迟,路由也可能误判 |
| 向量检索 | 动态选择 top k | 适合大规模工具集 | 依赖嵌入质量,系统复杂度高 |
从更长远的角度看,这个问题最终要靠模型架构的改进来解决。比如稀疏注意力,让模型只跟自己相关度最高的 token 打交道,而不是跟所有 token 乱打招呼;比如外部记忆,把工具描述存在向量库里按需读取。这些都是针对注意力稀释的正统解法。
三个常见误区
把工具描述写得更详细,模型会更准吗?
不一定。详细的描述确实消除歧义,但同时也占用更多 token,稀释别的工具。更好的做法是抓重点:功能是什么,什么时候用,什么时候绝对不要用。多余的解释,删。
上下文窗口那么大,多塞点没问题吧?
窗口大小只是模型“读得下”的上限,不是“读得好”的上限。就像一间屋子能站 100 个人,但想认出其中某个人的面孔,20 个人时远比 100 个人容易。
路由方案能彻底解决注意力稀释吗?
不能。路由只是把“从 50 个里选”变成“从 5 个里选”,注意力分配压力小了,但稀释仍然存在。任何依赖注意力的方法,都有天花板。
想通这件事之后,我不再纠结“为什么 50 个工具会犯迷糊”。注意力稀释不是 bug,而是 Transformer 架构的物理规律。要让 Agent 处理更多工具,唯一可靠的办法不是把所有描述硬塞进上下文,而是主动做取舍。
如果你现在还在给一个 Agent 手动配置上百个工具的系统提示词,我建议你停下来,先做一次注意力审计:数一数你的工具描述总共有多少 token,哪些工具其实很少被调用,哪些描述可以压缩。你省下的每个 token,都是在给模型的注意力腾位置。
下一次,当你的 Agent 在五十个工具面前选错工具时,别再怪它了。它并不笨,只是注意力被稀释了。而你作为开发者,要做的不是给它更大的上下文窗口,而是帮它决定——此刻,该注意谁。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/413.html