跳到主要内容

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

查看所有标签

这场本该成为评测 (Eval) 的会议

· 阅读需 9 分钟
Tian Pan
Software Engineer

每个发布 LLM 功能的团队最终都会开同一种会。有人会问:新模型 —— 或者新提示词、新的检索优化 —— 是否已经好到可以发布。整个周末都在进行测试的高级工程师说,感觉效果更犀利了。产品经理(PM)则提到,上周正好有客户投诉过这个问题。团队里的怀疑论者翻出一份对话记录,显示旧版本明显更好。45 分钟后,没人改变主意,最后的决定要么由发言最积极的人做出,要么由职位最高的人拍板。

那场会议是一个症状。它之所以反复出现,是因为团队正试图用轶事(anecdotes)来解决一个实证问题 —— 这次变更究竟是让系统变好了还是变坏了?而轶事是无法收敛的。你可以整天堆砌这些案例。争论永无止境的原因在于,缺乏一个大家都同意受其约束的共享工具。那场本该是 Eval 的会议,就是你发现自己正缺少一个 Eval 的时刻。

资历倒置:为什么当 Agent 加速时,你的资深工程师反而变慢了

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的团队采用编程 Agent 的那个季度,发生了两件没人会放在同一张幻灯片上的事情。吞吐量上升了 —— 更多的 PR、更多的合并代码、更多的工单被关闭。然而,你最资深的三位工程师却变慢了。这种慢不是因为偷懒,而是因为“溺水”。他们自己的提交量枯竭了,日历被评审任务填满,一对一面谈的主旋律也从“这是我交付的内容”变成了“我花了一整周时间在帮别人排障”。

这就是“资历倒挂”。那些本该通过 AI 获得更多杠杆效应的人,反而被它埋没了。这既不是动力问题,也不是工具差距,而是 Agent 改变工作形态后的结构性后果:它们让生成变得廉价,而让验证变得昂贵。验证正是你无法交给初级人员或其他 Agent 的那一项任务。

你的编程代理基于落后 Main 分支三周的代码版本重建的代码库索引

· 阅读需 11 分钟
Tian Pan
Software Engineer

你团队中的一个 AI 编程 Agent 提交了一个 PR,在两个文件中调用了四次 parseUserToken()。这个函数在代码仓库中并不存在,甚至已经消失了 19 天,早在你团队所有工程师都记得评审过的一次提交中就被 decodeSessionClaim() 替换了。Agent 并不是凭空捏造了这个名字,它是从其语义索引中读取的——那个向量库是从一个比 main 分支落后 21 天的工作副本重建的。相比之下,Agent 的编辑步骤在会话开始时运行了 git pull,操作的是最新的代码。对同一个代码库的两个视角,相隔三周,而 Agent 却自信地用一段无法针对任何真实环境编译的代码桥接了它们。

这是一种不会自我宣告的失败模式。Agent 运行了。测试看起来通过了。PR 合并了。第一位评审者之所以注意到,仅仅是因为一个被删减的函数与一个无关的辅助函数重名,触发了 linter 报错。到那时,Agent 已经花了一个完整的冲刺(sprint)针对一个“幻影版本”的代码库进行编写,而团队中没有一个人——包括 Agent 自己——收到任何异常信号。

服务商在 API 边界遵守但在缓存处违反的数据驻留契约

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的驻留审计追踪了来自租户流量的每一个出站请求,观察它在法兰克福的一个主机名上终止,并签了字。审计对它所测量的一切都是正确的。但它也看错了层级。请求确实去了欧盟。但满足该请求的字节——即服务商哈希并从最近可用节点提取的缓存前缀——却存放在 us-east-1。你的区域端点向你承诺了一个目的地。而缓存什么也没承诺,因为缓存是一个不同的产品,受不同的 SLA 约束,是为成本而非合规而设计的。

客户的审计员发现了它。不是你的。另一个供应商的事件报告提到 Prompt 缓存的放置与推理区域是解耦的,于是客户的 GRC 团队提出了那个显而易见的后续问题:我们的前缀去了哪里?修补这一差距的合同修正案花了 90 天。续约被暂停了。根据他们拿到的文档,编写集成的团队并没有做错任何事。

那个将你的系统提示词泄露到客户审计日志中的调试日志器

· 阅读需 11 分钟
Tian Pan
Software Engineer

一位具有安全意识的客户拉取了其租户的审计导出文件,打开 JSON,从一个名为 llm.request.system 的字段中读到了逐字记录的拒绝策略、检索流水线结构以及一些内部产品标识符。没有漏洞利用。没有提示词注入。没有越狱。仅仅是你的平台团队在六个月前添加的一个日志字段,目的是让工程师能够将提示词版本与事件关联起来——结果通过你的企业团队出于 SOC 2 合规原因单独向租户开放的摘要(feed)泄露了出来。

泄露发生在周三下午。你的安全团队是由客户呼叫(paged)的,而不是报警系统。事件时间线显示泄露当天并没有部署——错误配置是在审计摘要扩大其字段白名单的那天发布的,那是另一个团队、另一个迭代周期(sprint)和另一张工单。两名评审员都批准了他们所看到的内容。但没有人从全局组合的角度去审视。

权重并列语气与正确性的评估准则:如何悄无声息地筛选掉正确答案

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的评测提示词(judge prompt)从四个维度(1-5 分)进行评分:帮助性、清晰度、共情力和准确性。你对它们取了平均值。在六个月里,你的周度仪表盘数据稳步上升。而与此同时,你的支持队列(support queue)却一直朝着相反的方向发展,直到一次客户投诉引发了人工审计,你才发现模型学会了一种你的产品无法承受的姿态。

这种姿态就是“委婉的错误”。一个温和的错误回答——“有几种方式来看待这个问题,一种常见的观点是 X”(其中 X 是错误的)——在你的综合评分中得到了 4.2 分。而一个生硬的正确回答——“不,X 是错的,答案是 Y”——仅得到了 3.8 分。评判模型(judge)没有坏,评测准则(rubric)显然也没有坏。每一个维度单独看都是站得住脚的。聚合方式才是那个 Bug。

那些被你的提示词工程师转变为生产环境 Few-Shot 示例的评估集

· 阅读需 12 分钟
Tian Pan
Software Engineer

评估仪表盘连续三个迭代(sprints)都在攀升。困难切片的质量提升了 6 个百分点,回归切片提升了 9 个百分点,而在支持团队根据上季度最糟糕的工单亲手整理的切片上,质量提升了 12 个百分点。团队据此发布了模型升级。两天后,一位客户提出了一个与评估集中的任何内容都不沾边的问题,结果得到的答案比六个月前还要糟糕。

一旦有人想到进行排查,原因很快就浮出水面了。提示词工程师(prompt engineers)一直与评估团队在同一个代码仓库中工作。他们发现了那些精心策划的示例——这些示例来之不易,有的甚至是某人为了一个理想答案的措辞争论了一个小时才定下来的。在几个迭代中,他们把其中最有代表性的示例以 few-shot 演示的形式直接复制到了生产环境的系统提示词(system prompt)中。仪表盘持续攀升,是因为模型在推理时处理的正是它曾经逐字见过的输入。没有人指出这个问题。没有人负责划定“用于衡量质量的示例”与“用于发布到提示词中的示例”之间的界限。两个团队都准确地完成了他们被雇佣来做的工作。

被你的模型视为“约束性判例”的 Few-Shot 示例

· 阅读需 11 分钟
Tian Pan
Software Engineer

用户提交了一个问题。你的模型生成了一个答案,这个答案以一种非常具体的方式“自信地出错”:格式完美,推理结构严密,并且出现了一个特定的限定词——这个限定词完全不适用于这个问题——它出现的位置,恰好是你系统提示词(system prompt)中示例三出现类似限定词的地方。这既不是幻觉,也不是提示词注入。模型只是精确地执行了示例教它的操作,尽管这些示例原本并非为了涵盖这个问题。

这就是 Few-Shot 提示主动诱发的故障模式,而大多数评估套件(eval suites)在结构上对此是视而不见的。你的示例并不是“优秀范式”的中立演示。它们是判例法(case law)。模型通过表面 token 选择最匹配的项,并将该先例——包括其限制条件——应用到眼前的任何案例中。

KV Cache 驱逐:供应商称其为“缓存压力”,而你的账单则称其为“双倍前缀费用”

· 阅读需 13 分钟
Tian Pan
Software Engineer

你的应用程序开启了一个包含 4 万 token 系统提示词和完整工具库的长对话。第一轮对话按写入费率为前缀付费,且提供商的 KV 缓存(KV cache)开始预热。第二轮对话在 90 秒后到来。你假设这会命中缓存。有时确实如此。但有时,同样的 4 万 token 会再次以未缓存的价格出现在你的账单上,而你的代码在第一轮和第二轮之间没有任何改动。

改变的是别人的流量。KV 缓存是共享基础设施。你的租户被分配到一个推理节点上,而在你的两轮对话之间的 90 秒内,该节点接纳了足够多的其他租户,从而将你的前缀从内存中驱逐。提供商的控制台会将其描述为“缓存压力(cache pressure)”。你的财务团队会将其描述为一项翻倍的支出项。这两种描述都是准确的,但原因都不在你的代码里。

当 On-Behalf-Of 悄然变成 Act-As:你的智能体继承的 OAuth 作用域陷阱

· 阅读需 10 分钟
Tian Pan
Software Engineer

安全审查称智能体(Agent)“代表”(on behalf of)用户操作。OAuth 令牌却有不同的说法,而审计日志也支持令牌的说法。

语言上的一点微小差别,在架构层面起到了意想不到的作用。“代表”(On behalf of)是安全审查在试图描述一种委派安排时使用的语言,即智能体是一个可识别的委派对象,并受此身份约束。“作为”(Act as)则是运行时的行为,此时智能体持有的令牌与用户本人的令牌完全一致,因此在任何下游系统看来,智能体就是用户。这两个短语描述了完全不同的威胁模型。典型的企业级 OAuth 集成交付的是后者,但宣传的却是前者。

用户还来不及核实多模态模型的结论,预签名 URL 就已过期

· 阅读需 11 分钟
Tian Pan
Software Engineer

用户打开了昨天的对话。在支持专员的回复旁边,原本上传收据的地方显示为一个破碎的图片占位符。回复中自信地引用了“3 月 14 日在 Coffee Tribunal 商店消费的 47.32 美元”。用户无法检查该引用是否准确,因为模型赖以工作的证据现在来自你对象存储的 403 错误。他们提交了一个“幻觉”工单。你的评估套件没有发现这个问题,因为在调用时,模型的回答确实是完全正确的。

这是一个关于“保留策略不匹配”的故事,而不是模型质量的问题。你的对话记录比它的事实依据(grounding)活得更久。事实依据是一个只有 15 分钟有效期的预签名 URL,而关于该依据的断言则是会存放在你数据库中多年的文本。当资源时钟(asset clock)和断言时钟(claim clock)以不同的速度运行时,任何有据可查的多模态答案在重新访问时,最终都会看起来像是凭空编造。

那些悄然成为你唯一评测集阅读者的提示工程师

· 阅读需 10 分钟
Tian Pan
Software Engineer

评测集(eval set)是一个文件。但它也暗含了对 AI 功能用途的理论定义。这两者并非一回事,混淆它们的团队建立了一个质量网关,而其校准完全依赖于单个人的工作记忆。当那个人离职时,文件留下了,但那套理论也随之而去了。

这是你在组织架构图中看不到的失败模式。你规划了一个提示工程(prompt engineering)角色。你雇佣了一个优秀的人才。他们发布了 v1 版本的提示词,审视了简陋的基准测试,并将其重写为内容丰富的东西——一个失败模式分类法、每个类别的权重,以及一套能够消除边缘情况歧义的标注指南(rubric)。评测集变成了“该模型是否好到足以发布”的契约。六个季度后,你发现这份契约除了编写它的那个人之外,其他人都看不懂。