跳到主要内容

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

查看所有标签

撤回的代价:为什么撤回一项 AI 功能比上线它更难

· 阅读需 11 分钟
Tian Pan
Software Engineer

你现有的发布流程是为发布不可逆、回滚无成本的世界设计的。AI 颠覆了这一点。一旦某个功能上线了一个季度,撤回它的破坏成本就会超过发布它的成本 —— 而且你对该功能收到的最响亮的客户反馈,将是在你取消它的那天,而不是它发布的那天。

团队会为每次 AI 发布构建一个紧急开关(kill switch)。但没人会去拉动它。不是因为功能完美无缺,而是因为等到有人想撤回时,撤回的成本已经复合增长,超过了发布标准所考虑的任何因素。功能旗标(Feature flags)假设世界是对称的:开启前的系统和开启后的系统是同样有效的静止点,你可以根据喜好在它们之间移动。AI 功能默默地打破了这一假设,而团队围绕可逆旗标构建的发布流程,则悄无声息地忽略了这种不对称性。

团队第一次注意到这一点,是在有人提议弃用该功能时。

以单次对话成本为产品契约:当定价驱动架构设计时

· 阅读需 12 分钟
Tian Pan
Software Engineer

要发现你的 AI 功能定价模型出错了,最直接的方法就是看哪位工程师正在半夜重写截断逻辑。他们并不是在交付什么新功能 —— 他们是在修补一个 PRD 从未提及的单位经济效益(unit-economics)漏洞,而且由于产品规格告诉他们预算是无限的,这个补丁必然是对用户不友好的。在固定费用的 SaaS 方案中,任何时长超过中位数的对话都在实时抽走公司的利润。唯一的问题在于,产品团队是否能在财务部门发现之前承认这一点。

传统的 SaaS 经济模型建立在近乎零的边际用户成本之上:一旦软件构建完成,服务下一个客户几乎不会增加基础设施开支。但 AI 功能打破了这一假设。对话中的每一次交互都会消耗推理算力,其成本随着 Prompt 大小、输出长度、工具调用(tool-call)的扇出量以及检索量而增加 —— 而且对话没有自然的终点。一个重度用户可以在一个计费周期内消耗 50 倍于中位数的成本,且完全不出产品设计的正常路径。在固定定价模式下,这种用户实际上是由其他用户群供养的,而公司通常要到三个月后的销货成本(COGS)报告出来时才会发现这一点。

这就是为什么 AI 功能的定价不是一个等到发布后再处理的财务问题。它是一个架构输入,决定了产品被允许做什么。如果拒绝在产品规格中将其透明化,只意味着它稍后会被那些没有产品决策权的人以更糟糕的方式解决。

你的评估套件就是你拒绝编写的产品需求文档

· 阅读需 11 分钟
Tian Pan
Software Engineer

打开本季度发布的任何 AI 功能的 PRD。注意那些形容词。助手应该是有帮助的 (helpful)。回复应该是自然的 (natural)。智能体应该理解 (understand) 用户的意图。摘要应该是准确 (accurate)简洁 (concise) 的。每一个这样的词都是团队放弃决策的地方。他们并没有决定这个功能要做什么。他们只是决定了在会议中如何向彼此描述这个功能,然后——在没人点破的情况下——悄悄地将实际的产品定义移交给了编写评估集的人。

这不是文档问题。评估集就是规格说明书。PRD 是一份在产品诞生前撰写的官方新闻稿。文档中模糊的形容词在评估集中变成了明确的行为断言,否则它们就毫无意义——模型会自行挑选一种解释并发布,而团队在三个月后才会发现,“简洁”对审核者、用户以及在上一个 Sprint 调整 Prompt 的人来说,含义完全不同。一个评估集薄弱的 AI 功能,其产品定义也同样薄弱。模型并没有失败。团队从未决定过成功意味着什么。

强制一致性偏见:当模型将你的意图向分布众数取整时

· 阅读需 12 分钟
Tian Pan
Software Engineer

一名用户请求“一首关于 Postgres 复制的俳句”。模型返回了一首关于数据库的五行诗,其中提到了服务器和同步,听起来很有信心,读起来像模像样的英语,但并不是俳句。另一名用户请求“一个匹配 IPv6 地址但明确拒绝 IPv4 映射形式的正则表达式”。模型返回了一个匹配 IPv6 地址(包括它被要求拒绝的 IPv4 映射形式)的正则表达式,并用文字断言该正则符合规范。第三名用户请求“仅使用烹饪隐喻来解释 Monad(单子),不提及函数(function)或类型(type)”。模型给出了一个主要基于烹饪的解释,但其中使用了两次“函数”和三次“类型”。

这些都不是拒绝回答。这些也不是明显的幻觉。模型并没有说“我做不到”。它产生了一个自信、格式良好的响应,悄悄地放宽了请求中距离其训练分布众数最远的部分,而用户必须非常仔细地观察才能注意到。这种失效模式有一个值得使用的名称:强制符合偏见 (forced conformance bias) —— 模型将你的意图向典型答案“取整”,用户将结果视为忠实的响应,而本应捕捉到这一问题的评估套件本身也是从典型表述中提取的。

这在通常意义上并不是模型质量问题。模型正在做其训练推动它去做的事情。这是一个产品可靠性问题,如果评估团队的测试用例处于意图分布的众数位置,那么他们实际上只是针对其真实工作负载中简单的后半部分进行校准。

冰封提示词:当你的团队不敢修改一个仍然奏效的系统提示词时

· 阅读需 15 分钟
Tian Pan
Software Engineer

每个成熟的 AI 产品最终都会演变成一个当前团队中没人能完全理解的系统提示词(system prompt)。起初它只是 40 个 token 的纯英文,20 个月后,它变成了一堵 4,000 token 的“高墙”,堆满了条件句、拒绝模板、格式规则、角色强化、边缘情况警告,以及一句没人能解释的关于周二的奇特句子。每一行都是为了应对特定的失败:客户投诉、法务发来的 Slack 消息、评估(eval)中发现的回归,或者在投资者演示期间出现的偶发 bug。写下第 37 行的工程师已经转岗到其他团队。写下第 112 行的工程师是一名外包人员,他的 Notion 文档已被归档。评估套件覆盖了提示词所主张行为的大约三分之一,但没人确定是哪三分之一。

于是,这个提示词以一种最糟糕的方式成为了系统的“承重墙”:它能用,团队也知道它能用,但团队已经不再碰它了。本该对提示词进行迭代的工程师,反而绕过它来处理变更——这里加一个后处理过滤器,那里加一个 few-shot 封装,或者做一个并行的“v2 提示词”并用特性标志(feature flag)关闭,以防有人哪天有勇气进行 A/B 测试来替换它。提示词不再是软件,而成了遗迹。一旦发生这种情况,提示词就不再是你用来改进产品的杠杆,而是塑造产品的约束条件。

内部工具代理:当你杠杆率最高的 AI 功能却零客户时

· 阅读需 12 分钟
Tian Pan
Software Engineer

你公司最具战略意义的 AI 投资,可能是一位工程师在某个周五下午编写的一个 Slack 机器人。它回答“如何获取分级环境凭据”、“哪个值班人员负责认证服务”或“部署卡住时的运行手册是什么”,它节省的工程小时数比整个面向客户的 AI 路线图还要多——而后者占据了你四分之三的模型开销、安全审查队列以及发布沟通带宽。

组织架构图并未反映出这一点。OKR 文档也没有反映这一点。没有人是它的产品经理(PM),也没有人是它的工程经理(EM)。这个机器人之所以能生存下来,是因为构建它的工程师仍在回复 GitHub 上的 issue,在每一个面向客户的功能因六周的安全审查和发布就绪检查清单(之所以存在是因为客户可能会流失)而推迟发布时,它的价值正在悄然复合增长。

负面提示词是代码异味:为什么系统提示词中的每个 “不要” 都是技术债

· 阅读需 11 分钟
Tian Pan
Software Engineer

打开任何已经上线超过三个月的生产环境 AI 功能的系统提示词(system prompt)。数一数其中的负向条款——“不要”、“绝不说”、“避免”、“在任何情况下都不”、“你绝不能”。如果计数达到了两位数,你看到的就不是一个系统提示词。你看到的是一个坟场。每一块墓碑都标志着一个特定的用户投诉、一个特定的事故报告,或者一条来自利益相关者的 Slack 消息,因为他们看到模型做出了一些令人尴尬的事情。团队在表面打了补丁后就继续前进了,现在这个提示词读起来就像一份被强行嫁接了人格的法律免责声明。

负向提示词是代码异味(code smells)。并非隐喻意义上的,而是字面意义上的。它们在提示词工程中相当于吞掉异常的 try/except 块、没有文档的配置标志,或者是 2022 年留下的 // TODO: refactor this。它们在某种程度上有效,直到它们失效。而且它们所掩盖的失败模式,几乎总是比它们被添加用来压制的那个失败更有趣。

幻影技能:当你的智能体展示出你从未测试过的能力

· 阅读需 12 分钟
Tian Pan
Software Engineer

一位客户在你的支持频道里发布了一张截图。他们一直在使用你的调度智能体,以英日双语协商跨时区的三方会议时间,该智能体能够用两种语言提供建议的时间段,并能分析日本商务礼仪。它确实起作用了。领导层在 Slack 上分享了这张截图,并配上了一个火的表情符号。产品经理(PM)随后更新了营销文案。

团队中没有人编写过这项能力。没有 eval(评估集)覆盖它。没有任何提示词指令提到过日语、礼仪或三方协调。这种行为是真实存在的,但它从未经过工程设计,从未被衡量,而现在它已经成为了你产品功能面的一部分。

这就是一种幻影技能(phantom skill):你的智能体展示出了没有任何测试验证过的能力。它不是一个 bug,但也不完全是一项功能。它是没有任何契约保障的承重行为,而且这种失效模式悄无声息地定义了你的“AI 产品”到底是什么。

策略文件:为什么你不应该把拒绝规则写在系统提示词里

· 阅读需 13 分钟
Tian Pan
Software Engineer

上个季度,一家金融科技初创公司的安全审核员在系统提示词(system prompt)中添加了四行内容。这次修改包含一条拒绝规则,旨在防止助手为公司未获得运营许可的司法管辖区提供具体的税务建议。这听起来很合理、范围明确且符合审计要求。该规则在周二上线。到周五时,评估套件显示在与税务完全无关的客户入职流程中出现了 7 个点的下降——模型开始对任何提及国家的提问都模棱两可,甚至包括“这个账户持有哪种货币”。产品团队撤回了修改。安全团队在下周以略有不同的措辞重新发布了它。三周后,同样的退化以不同的形式再次出现,而接下来的安全修改又破坏了另一个无关的流程。

这里的 bug 不在于措辞,而在于拒绝规则放错了位置。它被挤进了一个 2,400 token 的构件中,该构件还包含助手的对话语气、格式契约、任务指令以及其他六项策略条款——对其中任何一项的修改都是对所有内容的行为修改,因为模型无法分辨哪句话是策略,哪句话是风格。生产环境中的系统提示词之所以变成了一坨乱麻的单体,是因为三个正交的关注点伪装成了一个整体。没有将它们解耦的团队在每次修改时都在支付“集成税”。

RAG 中的新鲜度与相关度权衡:为什么你无法在查询时同时优化两者

· 阅读需 13 分钟
Tian Pan
Software Engineer

一名用户询问你的助手公司的育儿假政策。机器人返回了 12 周,并附带了引用。被引用的文档是 2023 年的正确答案;而人力资源部门在上个季度发布了更新,将其延长到了 16 周。这两个版本都在你的知识库中。由于旧版页面的表述更简洁且模棱两可的内容较少,余弦相似度给 2023 年版本的评分是 0.87,而 2024 年版本的评分是 0.84。较新的文档以 3 个百分点的差距落败,用户得到了一个看似经过审计的错误答案。

这就是时效性与相关性的权衡(freshness-relevance tradeoff),令人不安的是,这在查询时并没有完美的解决方案。如果你增加时效性的权重,检索结果就会偏向于昨天刚编辑过的任何内容——在大多数知识库中,这些通常是高频变动的嘈杂区域,不应作为事实来源。如果你不增加时效性的权重,你给出的答案将基于几个月前就被取代的文档。没有一个全局按钮能同时搞定这两点,大多数团队只有在一些令人尴尬的答案绕过评估套件泄露出去后,才会发现这个问题。

拒绝审计:为什么单一拒绝率掩盖了一半的失败分布

· 阅读需 11 分钟
Tian Pan
Software Engineer

打开任何生产环境 LLM 功能的安全仪表盘,你都会看到拒绝率(refusal rate)被绘制成一条单线,并带有颜色标记:下降是坏事,上升是好事。这背后的隐含逻辑是:拒绝是系统对不该做的事情说“不”,因此拒绝率越高,产品就越安全。这种说法只反映了事实的一半,而缺失的另一半,正是已部署助手中大多数无形质量损伤的根源。

拒绝率是一个双面分布。右尾是安全团队痴迷的部分:模型同意编写恶意软件、伪造药物剂量或生成政策明确禁止的内容。左尾则是相反的失败——错误拒绝(false refusals),即模型因为某些表面特征与禁止类别模式匹配,从而拒绝了良性请求。客户询问如何对费用提出异议,却收到“我无法提供财务建议”的样板回复。护士询问药物相互作用,却被引导至“请咨询医疗保健专业人员”。开发者询问如何解析邮件头,却因为提示词中包含 “exploit” 一词而被拒绝。

检索级联失效:文档删除如何毒害你的 RAG 流水线

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个用户询问你的支持机器人退款期限何时结束。机器人带着愉快的自信给出了“60 天”的回答并附带了引用。然而,那个写着“60 天”的策略页面早在三个月前就从 CMS 中删除了。新策略是 14 天。直到有客户投诉,你的团队中才有人意识到机器人出错了。

这就是检索级联失效(retrieval cascade failure):文档已从事实源中消失,但其嵌入(embedding)仍留在索引中,在余弦相似度排名中依然靠前,不断为模型提供一个“幽灵”。RAG 流水线将向量索引视为源内容的缓存,但大多数团队在构建缓存时并没有构建失效机制。插入操作得到了所有的工程关注,而删除操作只得到了一个 TODO 注释。