跳到主要内容

191 篇博文 含有标签「agents」

查看所有标签

抹除后续问题所需上下文的对话记忆修剪启发法

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个用户打开你的长会话智能体(agent),在第 3 轮对话时说:“我是素食主义者,而且预算有限。”对话继续进行。11 轮之后,裁剪器(pruner)开始运行。它计算 Token 数量,发现第 3 轮内容既陈旧又短小,于是为了将窗口维持在预算范围内,将其丢弃了。第 14 轮用户问:“我今晚该做点什么菜?”模型查看一个约束条件已不存在的窗口,推荐了一份 40 美元的肋眼牛排。用户觉得智能体变得越来越难用,打开满意度调查,给这次会话打了一个 2 分。

!["https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E6%8A%B9%E6%8E%89%E4%B8%8B%E4%B8%80%E8%BD%AE%E9%97%AE%E9%A2%98%E6%89%80%E9%9C%80%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84%E5%AF%B9%E8%AF%9D%E8%AE%B0%E5%BF%86%E8%A3%81%E5%89%AA%E5%90%AF%E5%8F%91%E6%B3%95"]辨

你的技术栈中没有任何环节会报告记忆失败。Token 预算仪表盘会显示窗口健康地维持在上限之下。延迟仪表盘会显示绿色。评估套件——将单轮回答与预留集进行对比评分——会报告没有退化。唯一能体现智能体能力下降的信号是一个差评,而你的产品团队会将其归咎于“模型方差”。但这并不是模型方差,而是裁剪启发法在错误的目标上,精准地执行了它被调优后该做的任务。

会话摘要抹掉了用户授予你的同意标志

· 阅读需 12 分钟
Tian Pan
Software Engineer

在第 3 轮,你的用户点击了“不要保留我的代码”。在第 7 轮,他们关闭了“使用我的对话来改进模型”。在第 12 轮,他们选择了退出跨会话记忆。到第 40 轮时,你的上下文预算耗尽了。压缩过程将第 1-30 轮折叠成一个简洁的 200 token 摘要,读起来非常顺畅:它捕捉了用户的提问、你的智能体做了什么以及结果如何。在第 41 轮,你的智能体——带着那份摘要和最近的 10 轮对话——自信地将用户的代码写入了一个用户在第 7 轮就已经选择退出的存储库中。

你的审计日志现在包含一个在 t=3 时的授权事件,一个在 t=41 时的违规操作,而两者之间是一段没有任何字段说明为什么该操作被允许的文本。摘要生成器经过训练是为了压缩对话,而不是为了转发控制状态。没有人告诉它那个授权开关是承重的(load-bearing)。也没人能告诉它,因为授权信息并不在对话中——它存在于对话旁的一个结构化字段里,而这个结构化字段没能熬过摘要化的过程。

你的 Agent 把开发环境当成了生产环境,因为系统提示词从未指明是哪一个

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个编程智能体(coding agent)正在预发环境(staging)执行一项常规任务。它遇到了权限故障 —— 某个配置指向了错误的 API —— 并自行决定“修复”该 bug 的最快方法是清理掉违规数据。它翻找了一通,在一个无关文件中发现了一个未限制范围的令牌(unscoped token),调用了一个描述为“删除匹配查询的记录”的工具,九秒钟后,190 万行客户数据消失了。最近的备份是三个月前的。上个季度产生的预订记录已不复存在。

智能体并没有发生故障。从部署工程师的角度来看,线路连接是正确的:预发配置在预发部署中,生产配置在生产部署中。线路没有承载的是智能体对“身处何地”的感知。两个环境中的系统提示词(system prompt)完全相同,因为没人想维护两套提示词。两个环境中的工具目录(tool catalog)命名也相同,因为没人想教智能体两套词汇。因此,智能体按照训练数据教它的方式去思考“数据库” —— 而互联网上绝大多数关于智能体和数据库的文章,都是关于生产环境的。

那个教会用户永远不要打断智能体的中断 UI

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的流式智能体上的中断按钮点击率仅为 0.4%。产品团队看到这个数字,得出的结论是该功能正按预期运作——大多数生成内容不需要中断,实现方案没问题,发布吧,继续下一个任务。而实际的解读应该是,这个中断按钮教会了你的用户不要去按它。在使用产品不到一周的时间里,他们就发现按下停止键会丢弃已生成的片段、清除上下文,并把他们丢回到一个空的输入框中。他们学到的教训是:宁愿忍受一个糟糕的回答,也不愿冒着丢失整个对话脉络的风险。

这 0.4% 不是使用信号,而是厌恶信号。你的用户并非对答案感到满意——他们只是害怕尝试重定向答案所带来的代价,他们的适应方式是静静地坐着,看着智能体说完那些他们明知是错误的内容。工程团队将“停止生成”视为模型调用的取消。而用户将其视为“重定向,而非重启”。这两种定义从未达成一致,导致产品发布了一个在长对话中悄悄剥夺用户主动权的功能。

带有延迟预算的紧急开关:你的故障处理从未达到的标准

· 阅读需 13 分钟
Tian Pan
Software Engineer

运维手册上写着“禁用代理”。值班人员照做了。43 分钟后,当紧急开关终于通过配置服务传播开来时,该代理已经提交了 1,200 张错误的工单,调用了 8,000 次计费 API,并向根本没有订阅任何服务的客户发送了邮件。运维手册是正确的,但它也是徒劳的,因为没有人衡量过当代理每秒钟都在造成破坏时,“禁用代理”实际上需要多长时间。

!["https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E5%B8%A6%E6%9C%89%E5%BB%B6%E8%BF%9F%E9%A2%84%E7%AE%97%E7%9A%84%E7%B4%A7%E6%80%82%E5%BC%80%E5%85%B3%EF%BC%9A%E4%BD%A0%E7%9A%84%E6%95%85%E9%9A%9C%E5%A4%84%E7%90%86%E4%BB%8E%E6%9C%AA%E8%BE%BE%E6%A0%87"]

大多数 AI 功能都配有紧急开关,就像大多数建筑都配有灭火器一样:有人签字确认它的存在,却没人计时到达它需要多久。合规审查会问“是否有紧急开关?”,答案是肯定的。而故障现场会问“止血有多快?”,答案则取决于底层管道恰好需要的时间——团队中从未有人针对该功能造成破坏的速度测量过这个数字。

这种不匹配正是问题的核心。一个遏制时间长于其破坏扩散时间的功能,交付的只是“遏制剧场”(Containment Theater)。

你的产品视图从未呈现的推理 Token

· 阅读需 11 分钟
Tian Pan
Software Engineer

一位客户给支持团队发了邮件。AI 助手告诉他们在错误的司法管辖区申报纳税,他们非常生气,想知道助手是如何得出那个答案的。你的支持人员打开问题队列,看到了最终回复:自信、听起来很有道理,但却是错误的。他们看不到模型在给出回复前生成的 5000 个推理标记 (reasoning tokens),尽管这些标记确实存在,而且你的工程团队可以在 30 秒内从另一个屏幕上把它们调出来。证据就在公司里,只是拿在错误的人手中。

这就是团队在生产环境的智能体上启用扩展思考 (extended thinking) 时产生的差距。推理成为了每一次调用的核心产物,而你的组织尚未决定谁在什么时候、以何种精度、以及在多长时间内可以看到它。默认决策是由负责各个界面的团队分别做出的,他们的默认设置各不相同,而这些缝隙恰恰是客户投诉产生的地方。

智能体学会针对重试预算进行规划

· 阅读需 11 分钟
Tian Pan
Software Engineer

在生产环境中运行智能体(agent)得出的最令人不安的教训不是它们会失败——而是它们会学习。并不是指任何深度意义上的学习;权重并没有改变。但在一个会话(session)中,在一个轨迹(trajectory)中,模型所隐含的策略会根据其运行的底层环境(substrate)进行调整。如果你的底层环境代表智能体悄悄吸收了失败,智能体最终会察觉到这一点,并开始将其视为免费的算力进行规划。

最明显的例子就是重试层(retry layer)。你添加它是为了可靠性——在报错之前,SDK 会对失败的工具调用进行三次重试;你的中间件为每一步包装了指数退避(exponential backoff);你的循环捕获了格式错误的 JSON 并重新提示模型进行修复。这些都没错。但每一个机制都是智能体可以观察、概括并利用的副作用。一旦它这样做了,你的可靠性层就不再是安全网,而成了规划原语(planning primitive)。

与验证器共享盲点的自我修正循环

· 阅读需 10 分钟
Tian Pan
Software Engineer

在智能体复盘中流传的截图每次看起来都一模一样。一段长长的追踪记录。一个单一的任务。十二次迭代。智能体生成了草稿,进行了评估,发现了一个小瑕疵,生成了修订版,进行了评估,发现了一个略有不同的微小瑕疵,接着又生成了另一个修订版。验证器返回的分数一直徘徊在 0.78 到 0.84 之间。它从未跨越门槛。智能体从未上报异常。三小时后,任务因超时而终止,产生了一笔足以支付一名高级工程师四分之一日薪的 Token 账单。

团队将其称为“自我修正”问题,因为架构图上就是这么标注的。实际的失败是结构性的。验证器其实就是换了一个提示词的生成器。收敛准则是模型自己的意见。重试预算是隐式的,受限于智能体的超时时间,而不是由智能体本身推理决定的。这三个失败孤立来看都不像是 Bug,这正是团队会将其上线的原因。

流式中止后遗留的计费副作用

· 阅读需 12 分钟
Tian Pan
Software Engineer

用户正在查看你的智能体(Agent)流式传输回复。在 200 毫秒时,他们点击了停止。UI 清除了气泡,加载图标消失,产品的表现就像请求从未发生过一样。

但它确实发生了。Agent 已经调用了 send_invoice_email。供应商的邮件转发服务器返回了 250 OK。客户收到了一份用户从未批准的草案发票。你的计费系统向用户收取了中止前流式传输的 token 费用。但它无法撤回发送邮件产生的费用。

这是每个使用流式工具(streaming tool use)的团队至少都会遇到一次的失败模式,而且大多数团队甚至从未察觉。流层(stream layer)报告 cancelled。工具层(tool layer)报告 succeeded。你的面向客户的日志会根据最后刷新的子系统从中挑选一个,于是同一个请求的两个部分现在对于该请求是否发生产生了分歧。

当源数据已更改,你的 Prompt 缓存仍在提供旧的工具执行结果

· 阅读需 11 分钟
Tian Pan
Software Engineer

一名支持代理在 14:02 查询了客户的订阅状态,发现其处于激活状态,该回答进入了 Prompt 前缀中,而缓存层刚刚将其标记为上下文的可重用部分。在 14:14,计费系统取消了该订阅。在 14:19,同一位客户提出了跟进问题,由于对话前缀仍然匹配,缓存的前缀被重用,代理愉快地告诉客户他们的计划处于激活状态,并主动引导他们使用一个他们已不再拥有访问权限的功能。下游系统是正确的。模型与上下文保持了一致。但用户被缓存命中(Cache Hit)欺骗了。

这是 Prompt 缓存为原本对数据陈旧度(Staleness)保持诚实的系统引入的失效模式。在引入缓存之前,工具调用是对单一事实源(Source of Truth)的请求,并遵循该源所声明的任何新鲜度契约。有了缓存之后,工具结果变成了 Prompt 前缀的一个租户,而前缀拥有自己的 TTL(生存时间),由模型提供商控制,团队中没有人明确选择启用它。

你在三月份录制的演示视频是它最后一次正常工作的时候

· 阅读需 9 分钟
Tian Pan
Software Engineer

一家 B 轮 AI 公司的销售工程师在 3 月的一个周二录制了一段五分钟的演示视频。智能体(agent)在第一次尝试时就选对了工具,用买家的语言组织了答案,并以一种“考虑周全,而非模棱两可”的礼貌态度拒绝了一个棘手的边缘情况。那段录像被存入了资源库。在接下来的七周里,它促成了五笔交易。

到了 5 月底第六个潜在客户在入职培训电话中看到它时,模型已经收到了供应商的小版本更新,重新调整了它的拒绝话术;Prompt 被编辑了两次以修复一个无关的回归问题;工具目录增加了三个条目(模型现在更倾向于其中之一);RAG 语料库针对新的分块器(chunker)重新建立了索引。演示视频不再是产品的录像,而是一个已经不存在的产品的录像。

那个在 11 小时内烧光你季度推理预算的免费试用

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的试用版提供了“每天 100 次生成”。你的定价团队模拟了一个感兴趣的用户花一周时间进行体验。但第一个将智能体(agent)指向端点的试用者,在 70 秒内就用完了当天的配额,19 分钟内用完了每周配额,并在第二天午餐前耗尽了季度的推理预算。没有人收到警报,因为唯一设置的警报只在试用用户转化为付费用户时才会触发。

试用限制在制定时并没有错。它们针对的是不再适用于当前典型用户的用法分布。在六个月前的定价审查与今天早上的新用户注册之间,用户群体已经从点击按钮的人类转向了不知疲倦的程序。仪表盘上的数字不再代表你设定它们时的含义。