工具输出压缩:决定上下文质量的注入策略
你的智能体调用了一个数据库工具。查询返回了8000个Token的原始JSON——嵌套对象、null字段、分页元数据,以及每一行都带有时间戳。智能体只需要其中三个字段。你刚刚为7900个噪音Token付了费,并把它们全部注入上下文,让它们与真正的任务争夺注意力。
这就是工具输出注入问题,也是智能体设计中最被低估的架构决策。大多数团队都是在付出代价后才意识到这一点:演示运行顺畅,生产逐渐退化,却没人能解释为什么模型开始对之前能自信回答的问题开始含糊其辞。
你的智能体调用了一个数据库工具。查询返回了8000个Token的原始JSON——嵌套对象、null字段、分页元数据,以及每一行都带有时间戳。智能体只需要其中三个字段。你刚刚为7900个噪音Token付了费,并把它们全部注入上下文,让它们与真正的任务争夺注意力。
这就是工具输出注入问题,也是智能体设计中最被低估的架构决策。大多数团队都是在付出代价后才意识到这一点:演示运行顺畅,生产逐渐退化,却没人能解释为什么模型开始对之前能自信回答的问题开始含糊其辞。
智能体调用文件写入工具,工具因权限错误而失败。智能体记录此事,转而采用其他方案。任务运行足够长时间后,运行时触发上下文压缩,生成摘要:"智能体一直在尝试写入输出文件。"被丢弃的内容:权限错误曾经发生过,以及为什么最初的方案被放弃。三百个 token 之后,智能体再次尝试同样的写入操作。
这种模式——姑且称之为压缩陷阱——是生产智能体系统中最顽固的可靠性故障之一。这不是模型 bug,而是压缩机制的工作方式与智能体在长时会话中保持连贯性所需之间的架构失配。
当一个用户的 80 轮支持对话突然开始与其 60 轮前的建议相矛盾时,团队最初将其归咎于 Bug。其实并没有 Bug,只是模型“迷失”了。在所有主流的前沿模型中,多轮对话在相同任务上的表现平均比单轮交互下降了 39%。大多数团队从未衡量过这一点。他们假设上下文窗口的效力大致等同于其 Token 限制所暗示的程度,并据此构建产品。
这种假设在无声无息中出现了错误。长会话不仅仅是变得更慢或更昂贵 —— 它们变得不可靠,而这种不可靠性在用户感到沮丧之前几乎无法被察觉。
这是一个静默发生的失败模式:你要求编程智能体更新身份验证服务的令牌刷新端点。智能体生成了看起来很干净的代码——自信、注释详尽且类型安全。然而,它调用了一个三层目录之上的共享库中,在三个月前就被重命名的函数签名。由于 Mock 仍然使用旧的签名,该端点的测试通过了。直到代码进入预发布环境并拉取真实的库时,错误才浮出水面。
这在抽象意义上并不是“幻觉”。模型知道那个方法——它存在于训练数据中的某个地方,或曾在上下文中简短出现过。问题在于架构:智能体从未获得过它所调用的接口的当前版本。
你的智能体完成了十二步工作流中的第三步,并自信地报告目标 API 返回了 200 状态。实际上并没有 —— 这个结果来自第一步,仍然停留在上下文窗口中。到第九步时,智能体已经基于一个从未真实存在过的事实进行了四次下游调用。工作流“成功”结束。没有记录任何错误。
这就是上下文污染(context poisoning):它不是一种安全攻击,而是一种可靠性故障模式,即智能体自身积累的上下文变成了错误信息的来源。随着智能体运行时间变长、交互工具增多、管理状态增加,这种故障的发生概率会急剧上升。而且,与崩溃或异常不同,上下文污染对标准监控来说是不可见的。
在AI工程领域,有一种持久的信念:一个平庸的LLM应用和一个优秀的LLM应用之间的差距,归结于提示词的精心打磨。团队雇佣"提示工程师",对措辞进行数十次A/B测试,花好几周纠结"你必须"是否比"请确保"表现更好。与此同时,检索管道输入的是垃圾上下文,没有输出验证,错误处理策略是"希望模型能搞定"。
数据讲述了一个不同的故事。典型LLM应用的前五小时提示词工作带来大约35%的提升。接下来的二十小时带来5%。再接下来的四十小时?大约1%。那些早期认识到这条曲线并将精力重新导向系统设计的团队,始终优于那些持续打磨提示词的团队。