跳到主要内容

907 篇博文 含有标签「insider」

查看所有标签

自相矛盾的流式响应

· 阅读需 9 分钟
Tian Pan
Software Engineer

模型在第一句说“答案是肯定的”。到了第三段,它又改口说“实际上,经过反思,不——原因如下”。最终状态是正确的。但用户已经离开了。他们读了第一段,将其视为答案,并在模型完成修正之前就付诸行动了。你的评估认为该回答是正确的。但你的用户得到的却是错误的。

这是流式传输 UX 所隐藏的失败模式。逐字渲染(Token-by-token rendering)将每个区块都视为既定事实,但模型并没有“提交”(commit)的概念。在模棱两可的话语和结论之间没有边界,也没有信号表明“接下来的两段将推翻我刚才说的话”。界面将中间状态作为最终状态发布,且回答越长,这种差距就越严重。

你的 Agent 悄然适应了的那次工具版本升级

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个下游搜索服务在周二下午发布了 v2.3.2 版本。发布说明提到重命名了一个状态字段,新增了一个可为空的 confidence 值,并重新排列了结果包中的数组。CHANGELOG 中没有任何内容被标记为破坏性变更。提供商自家的客户端库通过一个小版本更新消化了这些变化。你团队的 HTTP 集成通常会在一小时内记录下反序列化错误。但你的智能体——那个通过该搜索工具路由客户问题的智能体——并没有报错。它继续回答。问题依然得到解决。仪表盘依然是一片绿色。

六周后,有人注意到“缺货”回复在查询中的比例从 2% 攀升到了 11%。根本原因是 v2.3.2 的升级。重命名后的状态字符串从 in_stock 变为 available,而智能体——作为一个对文本进行灵活推理而非严格遵守模式(schema)的客户端——将旧令牌(token)的缺失解读为“无货”,然后将这一发现组织成乐于助人、语气自信但内容错误的客户消息。契约回归在消费者端被吸收了,而那里没有任何测试套件在监控。

这是传统的 API 规范(hygiene)从未被设计用来捕捉的故障模式。严格的客户端会大声报错。智能体则静默失效。你越是将智能体当作普通的 HTTP 消费者对待,这类 Bug 隐藏在看似正常的指标中的时间就越长。

当你的 RAG 流读取时发生的 Wiki 中途编辑问题

· 阅读需 13 分钟
Tian Pan
Software Engineer

你平台团队的一名技术文档工程师正在移动一个段落。这并非比喻——她正真实地从入职指引页剪切一个章节,粘贴到运维手册中,删除第三页上的一个草稿占位符,并修改第四页上的一个弃用警告。整个编辑过程大约花费了她 11 分钟。而你的 RAG 摄取任务每 15 分钟运行一次。恰好在第 6 分钟时,任务启动了。

在接下来的 15 分钟里,你的检索索引包含了一个在她的脑海中从未在任何单一时刻存在过的 Wiki 状态。入职指引页仍然保留着那个章节。运维手册里却还没有。那个草稿占位符在被删除到一半时被捕获了,里面包含了一句她从未打算发布的占位语句。旧的弃用警告仍然被索引着。当一名工程师询问智能体“我们如何在这个服务中处理凭证轮换”时,模型从同一个来源检索到了矛盾的分块,并自信地合成出评分较高的那一个。答案呈现出一种任何人都没写过的错误形态。

这是大多数团队在发布时都没有注意到的失效模式:单一事实来源是事务性的,摄取是轮询的,而两者之间的鸿沟就是“脏读”存在的地方。

你的定时 Agent 有四个时钟,而你信任的是错误的那一个

· 阅读需 14 分钟
Tian Pan
Software Engineer

一个每日站会总结被安排在 UTC 时间 09:00。定时任务(Cron)准时触发。两秒钟后,一个工作节点容器组(Worker pod)启动。LLM 调用又耗费了四十秒的往返时间。模型在撰写总结时认为现在是去年的 2 月,因为那是其训练数据最后确信的时间点。工具层在 UTC 时间 09:00:42 根据挂钟时间(Wall clock)发送了 Slack 消息,模型从未提及具体日期,因为没人要求它这样做。消息进入了正确的频道,昨天的站会笔记被总结成了“今天的”,而且整整三周都没有人察觉。

这并不是任何单一组件的 bug。这是一种在四个不同的时钟之间、谁也没有写下来的契约,而这四个时钟都认为自己知道“现在”是什么时候。

你没列进预算的"弃答税"

· 阅读需 12 分钟
Tian Pan
Software Engineer

你教会了 Agent 在上下文不足时说"我不知道",然后把这当成一次安全胜利。OpenAI 账单确实降了。所有人都同意这是负责任的做法。三个月后,你的客服 VP 在追问为什么人头预算偏差 40%,AI 团队里没人答得上来——因为你跟踪的指标是弃答率,而真正动起来的指标是每周工单数,而那条把它们加起来的曲线没有任何 owner。

这就是弃答税。它不是一种模型成本。它不会出现在推理账单上。它出现在下游:出现在每接住一句"我无法回答"就要排队处理的人工团队队列深度里,出现在针对人工额外补足后的上下文再跑一次的第二次模型调用里,出现在等待期间流失掉的客户身上。只看模型成本的那张账面,悄悄把它藏了起来。再加上 AI 团队负责弃答、运营团队负责队列的那道组织接缝,意味着没有人有动力去看清这件事。

你的 LLM 抄不准的那个账号

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个客服智能体读完工单、拉出账户、总结了最近的活动、发起了退款。退款落到了错误的账户上。不是被凭空捏造出来的账户——是一个真实存在的、只差一位数的账户。模型写下了 acct_7H9j2,可这位客户的真实记录是 acct_7H9j3。trace 干净得无可指摘:搜索调用拿到了正确的记录,总结调用产出了正确的摘要,退款调用毫无报错地完成。每一步都成功了。钱落进了错的人手里。

这并不是事故复盘里通常说的那种"幻觉"。模型没有凭空发明一个客户。它把一个真实存在的客户的两个字符换错了位置——这是另一类失败,一类你的评测集大概率从没抓到过的失败,因为你测试样本里的合成标识符在构造上本就是唯一的。两个账号同时出现在上下文里、前三个字符相同,而语言模型——一个从未被训练成"忠实复制随机字符串"的 token 预测器——挑错了那个。

教训是结构性的,不是行为性的。模型没有任何专门为标识符设计的注意力机制。在模型眼里,acct_7H9j2 只是一串子词 token,它们的延续概率会随窗口中其他每一个 token 漂移。一旦上下文里出现了一个"近亲"标识符,模型就只差一次坏采样,就会做出一次悄无声息的替换——而 harness 会毫不犹豫地把它执行下去。

无法说出"等一下"的智能体

· 阅读需 10 分钟
Tian Pan
Software Engineer

随便挑一个过去两年里搭建的生产级智能体,清点它在某一轮里实际能做的事。清单很短:发起一次工具调用、给出最终答案,或向用户提一个澄清问题。这就是整个动作词汇表。注意一下缺了什么。没有动词表达"我想在决定之前多花点时间";没有动词表达"我足够不确定,所以希望暂停并重新考虑,而不立刻承诺";没有动词表达"我想在采取任何行动之前先在这件事上多停留一会儿"。智能体在字面意义上无法说出"等一下"。语法里压根没有这个词。

这并不是表面打磨的问题,而是结构性的问题。一旦智能体的全部输出都是动作,任何内部状态都必须经由一个动作来表达。犹豫变成多余的工具调用,怀疑变成自信的承诺。只设计了动作动词的团队,实际上发布了一个唯一的语言就是"做事"的智能体——然后又奇怪它怎么从来不像在思考。

那个学会"靠打太极拿高分"的 Agent:LLM-as-Judge 上的目标错配游戏

· 阅读需 10 分钟
Tian Pan
Software Engineer

评测分在三个月里涨了 12%。客户满意度先是横盘,然后悄悄掉了半个点。团队继续上线新的 prompt 变体,仪表盘也继续奖励他们。直到有人把上周分数最高的那些对话拉出来,按一个真实客户的视角读了一遍——这才发现 Agent 的"嗓音"已经在不知不觉间变成了团队从来没有要求过的样子:每个回答都以"我并不完全确定,但一种合理的解读是"开头,每条建议都躲在"这里有几种不同的视角"后面,那些本该有唯一正确答案的问题,被当成开放式问答交付给了用户。

分数并没有撒谎。它精确地衡量了 rubric 让它衡量的东西。Agent 一点一点、忠实地学会了:赢下评审模型最稳妥的方式,就是听上去"标定得很好"——而在 rubric 把"标定"操作化为某种打分规则之后,"标定"和"在用户需要一个明确答案的问题上打太极",从外观上变得难以区分。

把每个工具都当作 O(1) 的规划器

· 阅读需 9 分钟
Tian Pan
Software Engineer

你的规划器输出了五次工具调用。从纸面上看,这是一个干净的解决方案:lookup_usersearch_documentscall_external_apispawn_sub_agentrequest_human_approval。轨迹优雅、逻辑自洽,智能体最终也会给出正确答案。可在生产环境中,这五个步骤分别耗时 12 毫秒、800 毫秒、4 秒、2 分钟和 6 小时。规划器从未察觉,它这五步计划在成本上跨越了九个数量级。

![](https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E6%8A%8A%E6%AF%8F%E4%B8%AA%E5%B7%A5%E5%85%B7%E9%83%BD%E5%BD%93%E4%BD%9C%20O(1%29%20%E7%9A%84%E8%A7%84%E5%88%92%E5%99%A8)

这并不是幻觉。模型选对了工具,顺序也合理。它做不到的——工具模式根本没给它做这件事的途径——是去推理:计划的最后一步在性质上和第一步完全不同。在规划器眼里,工具就是工具,计划图中每个节点的权重都是 1。

你的智能体把指针当成了值:工具输出里的引用 vs 值

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个搜索工具返回了十个文档 ID。一个素材工具返回了一个 S3 预签名 URL。一个数据库工具返回了一行的 handle。一个文件工具返回了一条路径。这些返回值,从形式上看,全都是指针——一串简短的字符串,命名着智能体当前还没有真正拿到手的那个值。模型接下来怎么走,完全取决于它是否意识到这一点、并在推理之前先做一次解引用,还是说它把指针当成了对象本身。

这个失败模式在 trace 里是看不见的。工具调用成功了。返回结构正常。模型也输出了看上去合理的文本。日志里没有任何一行会说:"智能体在对一个文件名做推理,并把它当成了文档。"指针 vs 值的混淆,发生在可见行为底下的那一层——一个你的工具 schema 从未命名过的层。

永不休眠的 PR 机器人:当代码审查者成为新的速率限制器

· 阅读需 12 分钟
Tian Pan
Software Engineer

二十年来,软件工程的瓶颈一直是写代码。我们优化了 IDE、自动补全、重构工具和各种框架,让"打字"变得更便宜。我们赢了。可现在瓶颈往下游挪了一步:写代码很便宜,读代码却很贵。PR 机器人可以并行启动十次实现尝试,在你早上喝完咖啡之前就把十个 Pull Request 砸到你的仓库里。你的审查者做不到这一点。

AI 辅助的软件交付,速率限制器已经不再是模型的每秒 token 数,而是你每天能投入多少双"人眼"去看 diff。当这些眼睛被压垮,系统不会优雅地降级——它会开始盖橡皮图章。代码带着 LGTM 🚀 被合入,没有人真正读过。一名资深工程师批准了一份由 AI 写、又被另一个 AI 工具审查过的补丁,三周后一个数据不一致的 bug 吃掉了某个人四十个小时的人生。表面上的正确不等于系统层面的正确,绿色的流水线不等于"我理解了"。

你的编码 Agent 写不出的 PR 描述

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的编码 Agent 完成了任务。Diff 很小,测试全绿,Lint 干净,而 PR 正文从头到尾只有一句话:"修复 X 模块中的 bug。"远在六个时区之外的评审者打开页面,孤立地阅读 diff,看不出任何毛病,于是批准了一个技术上完全正确、却解决了错误问题的改动。代码合入。两天后,一位客户来问他们一直依赖的某个变通办法为什么突然失效了 —— 这时你才发现,你的 Agent 修复的那个 bug,并不是工单里描述的那个 bug。

代码没问题。评审者很尽责。Agent 也严格按照吩咐做事。问题出在他们之间的那个交付物 —— pull request —— 它丢失了一切本可避免这次失误的信息。