跳到主要内容

群体提示问题:为什么你的系统提示对80%的用户有效,却悄然让另外20%的用户失望

· 阅读需 11 分钟
Tian Pan
Software Engineer

当你编写系统提示时,脑海中有一个预设的用户形象。也许是一位用简洁英语提出有针对性问题的专业人士,也许是发送简短、范围明确、完全符合提示假设的请求的人。你针对看似具有代表性的示例进行测试,调整直到输出效果令人满意,然后上线。

然后你看到了生产流量。

你的系统提示必须处理的真实查询群体,并非你所设计的中位情形,而是一个分布——有些查询范围狭窄,更多的漫无边际——还有一条长尾,暴露出你指令中每一个隐藏假设。对大多数生产系统而言,15%到30%的真实查询落入提示处理欠佳的类别。令人不安的是:这些失败大多是静默的。系统返回200状态码,用户得到一个看似合理的答案,失败永远不会浮现在你的日志中。

这就是群体提示问题,它是已部署LLM系统中无形质量衰退最常见的根源之一。

想象中的用户 vs. 真实群体

系统提示由对用户有心理模型的人编写。这个心理模型几乎总是比现实更狭窄。你想象的人会用你自己会使用的措辞提问,你隐含地假设使用英语,或某单一语言;假设查询是独立提出的,而非在一段沮丧对话中第七条消息;假设任务被清晰界定,而非一个半成形的想法,期待模型填补空白。

这些假设本身都不无道理,只是不够完整。

在10个用户时,这无关紧要。在10,000个用户时,每一个隐含假设都对应着一批真实用户群体,他们的体验因此受损。一个用葡萄牙语提交查询的用户收到英语回复,因为提示只说"简洁清晰"而没有涉及语言问题。一个粘贴结构化CSV数据的用户得到的是对该数据的叙述性解释,而非他们想要的转换输出,因为提示是针对散文问题调优的。一个在经历五次失败后情绪激动的用户,得到一个完全忽视其情绪语境的轻快回复。

每种失败模式单独来看都很少见,但合在一起,它们决定了你的产品对相当一部分用户来说是感觉可靠,还是隐约有些破损。

为什么静默失败最危险

显而易见的失败——幻觉、拒绝、格式错误——被发现得很快,因为用户会投诉或日志显示异常。静默失败更难察觉,因为它们看起来像成功。

一个为简单查找设计的提示,能正常处理80%的查询。对于一个复杂的多步推理请求,它产生了一个听起来连贯但缺少两个关键步骤的回复。用户不一定知道正确输出应该是什么样子。他们复制了回复,尝试使用它,在下游失败了,却怪罪于自己。你的错误率依然为零,因为HTTP响应是200,没有任何异常。

这种动态在规模化后尤为糟糕。0.1%的失败率听起来微不足道,但当你的系统每天处理100,000个请求,每天就有100个用户收到自信但错误的答案。在0.5%时,那就是每天500个——在后台悄悄侵蚀信任。

绘制你的失败面

第一步是承认你的测试集可能并不代表真实流量。大多数团队针对上线前整理的示例进行评估:20-50个当时看起来具有代表性的案例。这些集合系统性地过度代表开发者当时想到的案例,而那些——按定义——恰恰不是边缘案例。

解决方法是从生产反向推导。如果你有任何日志记录,从过去两周抽取100-200个真实查询并手动分类。不要套用你事先发明的分类体系,冷眼审视这些查询,记录令你惊讶的内容。哪些请求类型出现了,而你的提示并没有为其设计?哪些措辞模式出现在失败中,却不在你的黄金集里?

这个过程几乎总能发现三到五个不同的查询群体,你的提示对它们的处理方式各不相同。常见的有:

  • 短小、模糊的查询 — 用户键入"总结"或"解释这个",几乎没有上下文,期望模型从之前的消息中推断意图
  • 多语言或语码混用查询 — 以非默认语言提交的查询,或在消息中混用语言
  • 结构化数据输入 — 用户粘贴表格、JSON块或CSV,期望特定转换而非散文回复
  • 对抗性或边缘输入 — 不寻常的格式、非常长的输入,或探测任务定义边界的请求
  • 高情绪强度查询 — 传达沮丧、紧迫或困惑的消息,而语气中性的提示无法应对

一旦你有了群体,计算各群体的成功率。不要跨整个分布取平均——那正是隐藏问题的方式。78%的整体成功率可能掩盖了简单查询95%的成功率和复杂多步查询40%的成功率。聚合指标在技术上正确,但在诊断上毫无用处。

应对群体多样性的多路径设计

本能的解决方案是让系统提示更长——为你发现的每种情形添加指令。这种方法通常会使事情变得更糟。长提示更难让模型一致遵循,为边缘情形添加的指令经常干扰之前有效的基线行为。一个为解决长尾查询失败而增加了500个词的提示,往往以微妙的方式降低了中位情形的质量,同时也只是部分修复了边缘情形。

有更好的方法。

查询类别路由在查询到达LLM之前对其分类,然后根据分类应用不同的系统提示路径。一个简单的分类器——通常是另一个更轻量的LLM调用——判断查询是简单查找、复杂推理任务、结构化数据转换还是其他类型。每个类别都有专门为其校准的指令。路由逻辑是明确且可审计的;当某个类别开始失败时,你确切地知道要调查哪个提示路径。

嵌入提示中的条件指令是一种更轻量的替代方案,不需要单独的路由步骤。不是写单一指令如"清晰地回应",而是编写自适应指令:"如果用户的问题模糊,在回应前提一个澄清问题。如果输入包含结构化数据,以相同格式返回结果。"这以一定的提示复杂度换取更广的覆盖率,而无需维护多个分群提示文件的开销。

分群覆盖仅在你有一个特征足够一致、值得专用变体的充分理解的群体时才适用。一个同时被运行结构化工作流的企业客户和提出自由提问的消费者使用的产品,可能合理地维护两套不同的系统提示,由路由层决定调用哪个。当群体需求确实彼此不兼容时,这种复杂性是合理的。

选择哪种方法取决于你有多少个不同的群体,以及它们的需求差异有多大。一两个差异细微的边缘群体:使用条件指令。三个或更多需求根本不同的群体:使用路由。只有当路由加条件指令确实无法弥合差距时,才转向分群覆盖。

使这一切可行的测量纪律

没有一个能给你诚实数字的测量系统,这一切都不会奏效。关键的转变是从单一聚合分数转向各群体的覆盖率指标,在从生产失败而非上线前想象构建的黄金集上进行评估。

从查询分类练习中构建你的黄金集。纳入你识别出的每个群体的示例,特别强调容易失败的群体。50个精心挑选的生产示例,比一千个合成示例能发现更多回归,因为它们代表了你的提示将面临的实际问题分布。

针对完整黄金集评估每次提示变更,按群体分解。当你为改善复杂推理群体的性能而修改提示时,检查简单查找群体是否退步。它经常会。如果某个提示更新将一个群体的成功率从55%提升到75%,同时将另一个群体从95%降到85%,而那第二个群体的流量是前者的三倍,那就是净损失。

报告不确定性,而非仅仅平均值。在50个示例的评估中,5-8个百分点的差异在噪声范围内。在得出一个提示优于另一个的结论之前,量化置信区间。小型测试集有一种方式产生自信但错误的结论,这些结论会以生产回归的形式出现。

将提示变更视为生产部署

大多数团队对系统提示的框架——一个你编辑并重新部署的配置文件——低估了变更的风险。在实践中,提示更新以与基础设施变更大致相同的频率引发生产事故,但没有应用于基础设施的部署纪律。

小小的改写以无法从检查中预测的方式产生巨大的行为变化。将"始终以有效JSON回应"改为"以清晰、可解析的JSON回应",在重要的边缘情形中产生不同的JSON格式行为。添加一条改善语气的指令,以在违规内容溜过之前不可见的方式削弱安全执行。这些不是理论风险——它们定期出现在事故复盘中。

操作含义很直接:对待提示变更的方式就像对待代码变更一样。版本控制,配有有意义的提交消息,解释为何做出此变更。合并前进行评估。以5-10%的流量进行金丝雀部署,监测输出长度分布、格式错误率和下游业务指标中的异常。提前定义回滚标准。

这不需要复杂的MLOps设置。一个带版本控制的提示注册表、CI中的黄金集评估,以及输出异常告警,覆盖了90%的失败面。相对于它所预防的事故,这个投资是很小的。

做对时的样子

一个认真对待群体提示问题的团队,不会只有一个由最后需要修改它的人维护的系统提示。他们有提示版本控制系统、各群体评估集,以及一个在所有群体的测量覆盖率——而非仅仅在便利样本上的平均表现——上设定变更门槛的部署流程。

他们还有关于哪些群体存在、其特征是什么,以及每个群体当前覆盖率的明确文档。当有人想为特定用户类型改善产品时,他们有一套测量装置告诉他们变更是否有效,且没有破坏其他任何东西。

输出是一个随着流量演变而优雅降级的系统,失败会在仪表板中浮现,而非用户投诉。达到这一目标所需的工作大多是分析性的——工程工作次于提出正确问题的纪律:你的真实用户是谁,你的真实失败模式是什么样的。

你的系统提示是为你脑海中的用户编写的。问题是:你是否已经遇见了那些你还未曾想到的用户。

References:Let's stay in touch and Follow me for more thoughts and updates