跳到主要内容

148 篇博文 含有标签「prompt-engineering」

查看所有标签

增长速度快于评估套件的系统提示词

· 阅读需 11 分钟
Tian Pan
Software Engineer

你发布 Agent 的那天,系统提示词(System Prompt)仅包含三条规则和一个语气指令。评估测试集(Eval suite)为每条规则覆盖了十个案例,CI 徽章是绿色的,团队理所当然地感到自豪。十八个月后,同样的提示词变成了四十条规则、六个工具描述、四个 Few-shot 示例、两个安全前导语,以及一个在每次事故后都会增加一项的拒绝分类法。相比之下,评估测试集可能只增加了二十个案例——每个事故增加一个,且都是在压力下编写的,从未针对通过日常提示词 PR 悄无声息引入的几十条规则进行补测。

当 PR 发布时,团队仍然会说“评估通过了”。他们实际的意思是“我们十八个月前编写的评估,在针对那些评估已无法完全描述的提示词时依然通过了。”置信区间的分母在默默扩大,而分子几乎固定不变。下一次触及三十七条未测试规则之一的提示词修改,将被一个对其毫无判断力的测试集评定为安全。

悄然渗入你提示词中的评估集

· 阅读需 10 分钟
Tian Pan
Software Engineer

基准测试指标连续四个季度上升。用户满意度却没有。团队中没有人能解释这种差距,直到有人对提示词模板进行了 diff,并注意到 Few-shot 示例正从评估器读取的同一个 CSV 文件中获取。评估集已悄然变成了上下文示例。这个指标不再衡量泛化能力。它衡量的是模型在刚被告知答案的情况下,复制与之最接近问题的能力。

这就是我想命名的失效模式:评估集到提示词的泄露 (eval-to-prompt leakage)。它在结构上与传统机器学习中的测试集污染 (test-set contamination) 完全一致,但它是通过团队刻意构建的后端通道发生的。Few-shot 检索是一个合理的工程举措。评估库是一个合理的工程产物。当两者在没有人划定界限的情况下汇集到同一个存储层时,污染就产生了。

那个让你的故障面成倍增加的供应商故障转移方案

· 阅读需 12 分钟
Tian Pan
Software Engineer

当你的服务商故障转移(failover)第一次在生产环境中真正触发时,你会发现你真正构建的是什么。网关在几秒钟内完成了流量切换 —— 这一部分运行正常。接着,一种不同类型的事故开始了:12% 的响应中出现了格式错误的 JSON,之前从未被拒绝过的提示词开始遭到拒绝,延迟破坏了你的下游超时设置,面向客户的输出读起来就像是另一个产品。主服务商在 90 分钟后恢复了。而这次“成功”的故障转移留下了一个耗时 48 小时的事故复盘。

这是架构演示稿中最便宜的那一行所产生的账单:“备用服务商以实现韧性”。演示稿中从未提到,备用服务商需要专门的提示词、专门的评估套件(evals)、经过压力测试的容量,以及独立的值班手册。演示稿只说你不会宕机。在这点上它是对的,但在其他所有方面都错了。

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

· 阅读需 10 分钟
Tian Pan
Software Engineer

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

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

当评审在 A 与 B 之间始终偏袒自己

· 阅读需 10 分钟
Tian Pan
Software Engineer

你对两个 prompt 变体跑了一次 A/B 实验。你的 LLM 评审——因为图省事,默认就用了和候选模型同一家厂商的模型——一致地偏好变体 A,差距大到足以被称为统计显著。你上线了 A。一周后,满意度指标下降了,退款队列上升了,没人能解释原因。终于有人用另一个模型家族的评审重新跑了一遍评测,偏好翻转了。

评审根本不是在衡量质量,评审只是在衡量候选模型听起来有多像评审自己。

团队内部的 AI 素养鸿沟,才是你路线图上最大的交付风险

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的招聘页上写着「需要 AI 经验」。发布会的通稿里点名提到了那些 AI 功能。本季度路线图上又新承诺了两个。而真正要把这些东西交付、维护下去的团队里,只有一个工程师真懂怎么调试一次 eval 失败,两个人能自信地编辑 prompt,剩下十二个把 LLM 调用当成一个黑盒——一旦它出问题,就甩出去给别人接。

这种分布就是领导团队从没点名说出来的交付风险:团队对外宣称的 AI 能力——也就是出现在汇报幻灯片上那一个数字——是任何单个成员技能的最大值;而团队真实的交付速度,是中位数。幻灯片上写的是一个数,生产环境跑的是另一个数。

长出胳膊和腿的缓存提示词前缀

· 阅读需 11 分钟
Tian Pan
Software Engineer

六个月前,你的提示词前缀是 4,000 tokens。它稳定、缓存预热,几乎可以摊销到不计成本——系统指令的每次调用附加费,相比每次响应的成本,只是一个舍入误差。今天那个前缀变成了 11,000 tokens,你的缓存命中率从 92% 滑到了 31%,你的推理账单上升了 4 倍。团队里没有人能指出是哪个 PR 干的。没有一条 commit message 写着"将提示词增加 7,000 tokens"。每一次修改都很小,每一次修改都有理有据,每一次修改都干干净净地合入了。

提示词前缀长出胳膊和腿,就像地下室积攒纸箱一样。一个团队需要注入用户的订阅等级,这样 agent 才能解释套餐限制。另一个团队需要用户时区的今天日期,这样"明天提醒我"才能工作。第三个团队把当前 A/B 变体名硬塞进去,这样 eval traces 才能切片。市场团队加进了当前促销 banner,这样 agent 才能适时提及它。合规团队加进了功能标志清单,这样模型才能拒绝那些不在灰度名单里的用户访问 beta 功能。每一条都是一行的添加。每一条单独看都站得住脚。但加起来摧毁了你的缓存。

提示词 Diff 隐藏了自身的爆炸半径

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个 PR(合并请求)进入了你的评审队列。Diff 显示系统提示词(system prompt)中修改了三个词:Output strictly valid JSON 变成了 Always respond using clean, parseable JSON。这看起来就像是一次文案润色。你快速浏览了一下,CI 检查勾标是绿色的,于是你点击了批准。总耗时:90 秒。

六个小时后,下游解析器开始拒绝带有尾随逗号和缺失字段的响应。结构化输出的错误率从接近零飙升至两位数,一个创收工作流陷入停滞。Diff 中没有任何迹象预示到这一点。Diff 中也不 可能 预示到这一点,因为 Diff 衡量的是错误的东西。

这就是评审提示词变更的核心问题:提示词 Diff 的大小完全无法说明其影响范围的大小。三五个词的修改与三段话的重写都只是文本,而文本 Diff 以相同的视觉权重呈现它们,就像对待任何其他编辑一样。但提示词并不是 描述 行为的文本 —— 它是 导致 行为的文本,而一次编辑所产生的因果爆炸半径在你评审的产物中是不可见的。

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

· 阅读需 9 分钟
Tian Pan
Software Engineer

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

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

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

· 阅读需 10 分钟
Tian Pan
Software Engineer

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

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

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

模型已到生命周期终点,并带走了你的提示词

· 阅读需 12 分钟
Tian Pan
Software Engineer

弃用通知看起来人畜无害。它以更新日志或邮件中一段平静的文字形式出现:该模型快照将在几个月后的某个日期从 API 中移除,这里是推荐的替代方案,感谢你与我们一起构建。其中暗含的工作量似乎只是一行代码的改动 —— 换掉模型字符串,重新部署,搞定。

这种设想是错误的,而且错得很昂贵。模型字符串是你损失的最小的东西。真正随着旧模型一起消失的,是你花了六个月调优的提示词(prompt) —— 每一个针对边缘案例的补丁、每一个重新排序的指令、每一个你因为那个特定模型会有特定烦人行为而添加的“仅以有效的 JSON 响应,不要用 Markdown 包装”。这些都不是可移植的。从统计学意义上讲,它是针对一个模型的行为进行拟合的。替代模型并不是“缺陷对缺陷”兼容的,因此这种拟合不再成立。

模型生命周期的结束是一个迁移项目。如果把它仅仅视为一次配置更改,你就会在生产环境中、在新模型上通过真实流量发现其中的差异。

每次事故后你的系统提示词都会增长 —— 而且没人会删掉任何一行

· 阅读需 10 分钟
Tian Pan
Software Engineer

打开任何一个已经在生产环境中运行了一年的智能体的系统提示词(system prompt)。滚动到底部。你会发现一层读起来像道歉一样的句子沉积层:“绝对不要伪造订单号。”“不要承诺无法确认的退款。”“如果用户在德国,不要提及旧版方案。”每一句都是一块化石。每一句都标志着生产环境中出现问题的确切时刻 —— 有人被传呼了,而当时能找到的最快修复方法就是增加一句话。

没人删除这些句子。不是因为它们还在发挥作用,而是因为删除一句话意味着需要证明一个否定命题 —— 证明模型不会在一个可能已经在三个模型版本前修复的 Bug 上发生回退。没人能证明这一点,所以那行字留了下来。系统提示词变成了一个关于过去事故的“只增不减”(append-only)日志,它让你在每一次调用中都永远支付着 token 费用。

这是 AI 系统中最隐蔽的一种技术债,因为它看起来不像债。它看起来像是在尽职尽责。