跳到主要内容

763 篇博文 含有标签「ai-engineering」

查看所有标签

停不下来的 Agent:作为运行时故障模式的范围蔓延

· 阅读需 9 分钟
Tian Pan
Software Engineer

你让智能体修复一个不稳定的测试。第三分钟,测试通过了。第四分钟,智能体正在读取相邻文件。第九分钟,它“改进”了一个测试从未触及的辅助函数,为了清晰起见重命名了一个无关的参数,并开始对 fixture 构建器进行重构。最终提交的 diff 涉及 12 个文件和 400 行代码。原始 Bug 修复了,一些原本没坏的代码也顺便被“修复”了。

这不是模型感到困惑,而是模型完全按照指令留下的空间在行事。任务要求“修复 Bug”,但并没说“修复后就停止”。大多数智能体循环都有明确的起点和成功标准,但对第三个问题却含糊其辞:你什么时候结束?在聊天会话中,“结束”是由用户决定的。在自主循环中,“结束”是由停止条件决定的,如果你没写停止条件,那停止条件就是“模型失去了兴趣”。这不属于你可以调试的故障模式,而是一种你必须通过设计来消除的故障模式。

演示成功是因为有人在看:会话长度是你的评测套件遗漏的那个维度

· 阅读需 11 分钟
Tian Pan
Software Engineer

你发布会幻灯片上的可靠性数字,来自一些和用户实际使用的会话完全不像的对话。演示是五轮的:打开、提问、看到一个干净的回答、再细化一次、然后在高音上收尾。而你的核心用户昨天跑的那个会话有三十一轮长,包含两次工具失败(智能体用乐观主义掩盖了过去),最后用户放弃并提交了一张工单。两个会话出自同一个模型。第一个发了新闻稿。第二个被归档为"边缘情况"。

会话长度是评测的一个维度,而演示文化系统性地低估了它。我们衡量单轮准确率,是因为单轮准确率能放进幻灯片里,然后当单会话成功率从一个我们从未在任何图表上画过的悬崖上掉下来时,我们感到惊讶。这个悬崖既不是随机的,也不是尾部事件——它是误差累积、注意力漂移以及那些模型不会重新审视的已承诺假设的可预测后果。每个团队应该问的问题不是"这个模型有多好",而是"在我们已经在第一到第二十七轮说过那些话之后,这个模型在第二十八轮有多好"。

没人接线的紧急开关:因为功能从未失效

· 阅读需 11 分钟
Tian Pan
Software Engineer

发布标志运作完美。你在它后面发布了 AI 摘要生成器,在两周内将其比例从 1% 提高到 10%、50%,最后达到 100%,紧盯仪表盘,一切正常。季度末,平台团队的标志清理机器人发起了一个 PR,删除了这个已经多余的入口。你批准了。该 PR 与其他过期标志清理工作一起合并,代码库精简了 200 行。六周后的凌晨 2 点,供应商滚动更新了一个新的模型快照,你的摘要生成器开始信誓旦旦地在法律文件中编造条款,而你的值班工程师发现没有快速关闭它的手段 —— 只能重新部署。

标志完成了它的工作。但标志是错误的保留产物。发布标志回答的是“这条新代码路径是否应该是可达的?”一旦大家达成共识,删除它就是正确的清理举动。而紧急开关(Kill switch)回答的是“上游模型今天表现正常吗?” —— 这个问题永远不会过期,因为上游模型永远在变化。将它们放在一起清理,就像把烟雾报警器当作建筑许可证一样,是范畴错误:建筑物建成后,许可证会被归档,但报警器的接线必须永远保持连接,因为由于它所监控的情况仍然可能发生。

你删除的代码对你的编程 Agent 是不可见的

· 阅读需 11 分钟
Tian Pan
Software Engineer

你周二下午花时间删除了一个已经废弃的工具模块。你清理了导入,运行了类型检查器,看着 CI 变绿,然后合并了 PR。周三上午,一个新的 Agent 会话查看同样的代码,认定代码库“缺失”了一个小型助手函数,于是又把那个废弃的模块写了回来——名字相同,形状相同,只是风格略有不同。昨天批准删除的评审者现在不得不回想为什么要删掉它,找到当时证明其合理性的对话,并再次解释一遍。Agent 并没有出现故障。它只是完全按照其上下文的要求在行事。

这是编码 Agent 的结构性可靠性问题,没有人通过提示词工程(Prompt Engineering)来解决:Agent 的上下文起始于代码库的当前状态,而不是该状态为何如此的历史。你移除的文件没有留下 Agent 可见的痕迹。你迁移掉的依赖项只是 npm 上的另一个包。你刻意删除的不稳定测试(Flaky test)是一个等待被“修复”的覆盖率缺口。缺席——即你做出的决策留下的负空间——是不可见的。

那个悄然演变成延迟敏感型服务的夜间批处理作业

· 阅读需 11 分钟
Tian Pan
Software Engineer

这一切始于一个 cron 作业。每晚凌晨 2 点,一个脚本会被唤醒,拉取当天的记录,通过模型运行,将结果写入表中,然后继续休眠。这是解决该问题的最简单形态,而且在整整一年的时间里,它确实是最合适的形态。没有人去考虑它,因为没有人需要去考虑。

接着有人问结果能否在早上 8 点而不是中午准备好。然后有人问用户是否可以按需触发单条记录的运行。接着一位产品经理问是否可以让应用内的体验“感觉像是即时的”。每个请求都是合理的。每一次改动都很小。而且从始至终,没有人打开过一份名为“重新架构推理流水线”的文档,因为没有任何一次单一的改动让人觉得像是在重写。

18 个月后,你拥有了一个披着批处理作业外壳的延迟敏感型在线服务。它的 p99 无人衡量,队列无人清理,且存在一种失效模式:由于流水线被构建为重试整个批次,一条错误记录就会导致面向用户的请求停滞。这是 AI 系统中最常见的架构失效之一,而且它几乎从未作为一项决策出现,而是作为对一系列合理请求不断说“是”而产生的缓慢累积。

对于你的 AI 功能,“自研还是购买” 是个错误的问题

· 阅读需 10 分钟
Tian Pan
Software Engineer

每场关于 AI 功能的规划会议最终都会陷入同样的二元对立。一方想“直接套个 API”并在下个冲刺阶段发布。另一方则想“掌握模型”,以便公司掌控自己的命运。这种争论听起来很有战略意义,但实际上是一个分类错误。

“自研还是购买”将你的 AI 功能视为一个不可分割的整体,要么自研,要么购买。但 AI 功能并不是单一的事物。它是一个由至少五个不同层级组成的堆栈,每一层都有其自身的答案。如果团队将决策简化为一次掷硬币,几乎总是会掌握错误的层级并租用错误的层级,因为他们提出的问题无法区分这些层级之间的差异。

更好的问题不是“我们能做出来吗?”大多数东西你都能做出来。真正的问题是:如果竞争对手明天购买了完全相同的东西,哪一层会破坏我们的差异化? 这个问题会为你梳理出堆栈的优先级。

AI 功能规格说明书中无人提及的碳排放项

· 阅读需 11 分钟
Tian Pan
Software Engineer

打开任何一份 AI 功能评论,你都会听到关于这三个数字的辩论:延迟、Token 成本和准确率。有人调出 P95 图表,有人计算单千次请求的成本,还有人争论评估分数 (eval score) 已经好到可以发布了。没人提到能源。没人提到碳排放。正因为没人提及,该功能的环保足迹仍然被决定了——由谁赢得了那场关于金额的争论所含蓄地决定。

这就是 AI 可持续性中沉默的问题。并不是团队故意选择了高碳设计,而是他们根本没有做出选择。碳足迹成了成本决策的副作用,而成本与碳排放之间仅存在松散的关联。在支出仪表盘上看起来大获全胜的路由规则,可能会悄无声息地让排放量翻倍,而会议室里没人会知道,因为那个能告诉他们真相的数字从未出现在仪表盘上。

这篇文章将能源和碳排放视为它们的真实身份:AI 系统的一个可测量、可掌控的属性,与延迟和成本处于同等地位。它不是企业价值的脚注,而是一个明细项。

CFO 在电子表格上看不见的评测预算

· 阅读需 10 分钟
Tian Pan
Software Engineer

打开任何季度计划电子表格,你都能找到团队交付的每一个功能、每一张外包发票、每一项云服务支出。你找不到的是那些从未发生的停机事故、在触达客户前被拦截的幻觉退款,或者是凌晨 2 点被评测(eval)拦截的 Prompt 回归。这些“非事件”没有 SKU。它们不产生工单、没有复盘报告,也没有 Slack 讨论串。因此,当评测预算面临续约时,它在与拥有 Demo 的功能争夺人力配额——而且几乎每次都会输。

这不是勇气的问题。这是一个衡量标准的问题。评测投资同时兼具安全网和测试套件的属性:它悄无声息地产生复利,在规避灾难中体现价值,而其全部价值都建立在“反事实(counterfactual)”之上。财务部门在结构上对反事实视而不见。如果你领导一支 AI 团队,你的工作不是去争论评测是否重要——这一点每个人都会点头同意。你的任务是让那些只相信电子表格的人,能够看懂这种具有复利效应且无形的投资回报。

为尚未建立职业阶梯的 AI 岗位招聘人才

· 阅读需 10 分钟
Tian Pan
Software Engineer

你开启了一个“评测工程师 (eval engineer)”的招聘需求。一周后,你的招聘人员问了一个显而易见的问题:这个岗位的职级是什么,一份优秀的简历长什么样?你给不出答案。两年前,这个头衔还不存在。没有职级评定标准,没有标准的面试流程,LinkedIn 上也没有现成的“评测工程师”人才库。你在为一个行业尚未达成共识是否存在的职位进行招聘。

这是交付 AI 系统过程中一个隐形的瓶颈。模型是现成的,基础设施是可租用的。你无法从市面上直接买到的是这样一种人:他们的实际工作是确保基于 Prompt 的系统保持“诚实”——而你那套为拥有数十年先例的岗位而构建的招聘机制,并没有给他们留位置。

直觉是等待。等待头衔标准化,等待培训班批量产出候选人,等待别人写出你可以照搬的职级指南。这种直觉是错误的。无论头衔是否存在,工作就摆在那里,而现在就开始组建团队的人,会在竞争对手还没开启招聘需求之前,就摸索出什么是真正的“优秀”。

故障复盘:根本原因竟是一个无人负责的提示词

· 阅读需 10 分钟
Tian Pan
Software Engineer

故障复盘进行得非常顺利,直到遇到了一个没人能回答的问题。下午 2:14,结构化输出错误激增,某个收入工作流停滞了 90 分钟。时间线还原得很清晰:三周前,有人修改了系统提示词(system prompt),多加了几个关于“对话语气”的词,这在特定输入下悄悄导致模型偏离了 JSON 契约。修复方法很简单,只需一行代码回滚。但接下来的部分很难:有人问是谁做的改动,谁审核的,以及未来哪个团队负责维护这个提示词。房间里陷入了沉默。没有 Pull Request,没有审核人。改动是某个人在晚上 11 点通过厂商控制面板操作的,而那个人已经不记得这回事了。

那种沉默才是真正的事故。JSON 契约的失效只是症状。根因在于,系统中杠杆率最高的一处行为逻辑,竟然没有负责人,没有变更历史,也没有走任何管理其他生产环境变更的流程。模型没有出错。模型完全按照指令行事。失败之处在于,“指令”本身完全脱离了变更管理。

这是目前最常见的生产环境 AI 事故之一,而且几乎从未被正确命名。复盘报告在根因栏写下“提示词退化(prompt regression)”然后就此揭过。但“提示词退化”描述的是代码表现。真正的根因是组织架构图上的一个漏洞。

Token 预算是产品决策,而非配置值

· 阅读需 12 分钟
Tian Pan
Software Engineer

在你的代码库某处,有一行代码看起来像 retriever.search(query, top_k=8)。某位工程师在某个下午写下了那个 8。它从未被团队以外的任何人评审过,从未出现在规范文档中,也从未被重新审视。这一个整数决定了你的上下文窗口中有多少配额分配给了检索到的文档而非对话历史,决定了每次请求的成本,决定了响应速度的感官体验,并且——由于语言模型在长文本下的实际表现——还决定了答案的准确性。

这是一个产品决策。它却被硬编码在一个 f-string 里。

你的语音智能体将每一个转录错误都视为事实

· 阅读需 11 分钟
Tian Pan
Software Engineer

一名用户拨打你的保险语音代理,询问关于其免赔额(deductible)的问题。语音识别器听到了 "the duck tibble"。你的语言模型接收到了字符串 "the duck tibble",发现它逻辑不通,于是要么提出了一个令人生疑的后续问题,要么——更糟糕的是——胡编乱造了一个关于并不存在的产品答案。用户挂断了电话。你的日志显示了一次成功的交互:音频输入,生成转录,产生回应,没有抛出错误。

这就是几乎每个生产环境中的语音代理都存在的隐蔽失败。语音转文本系统完成了它的工作——它产生了一个最优的猜测。语言模型完成了它的工作——它对收到的文本进行了推理。而 Bug 就存在于它们之间的鸿沟中,存在于一个将概率猜测重新标记为事实的交接过程中。