技术速递|如何在投入生产环境前评估 LLM
作者:Mariko Wakabayashi & Zixiao Chen
排版:Alan Wang
以下是我们在真实的密钥扫描场景中评估 LLM 时总结出的经验。
语言模型在干净的基准测试上表现良好,并不意味着它在生产环境中真正重要的场景下也能表现出色。
在对基于 LLM 的系统进行原型设计时,基准测试和精心整理的数据集非常有用。它们可以帮助团队比较模型、测试初始提示词,并判断一个想法在技术上是否可行。
但随着系统逐渐接近生产环境,评估问题也会发生变化。
真实输入往往存在歧义。标签可能不一致。重要上下文可能缺失或被截断。评估集可能无法反映生产环境中的数据分布。在基准测试中很少出现的边缘案例,可能会成为生产环境中常见的失败来源。即使离线指标有所提升,这些结果也未必能顺利转化为生产环境中的实际表现。
在评估一个旨在减少 GitHub Secret Scanning 误报的基于 LLM 的系统时,我们遇到了这些挑战。
Secret Scanning 用于识别可能已提交到代码仓库中的令牌、密钥等凭据。由于某些候选字符串看起来像机密信息,但实际上并不代表真实凭据,开发者可能会花费时间调查那些并不需要采取补救措施的告警。
我们需要解决的并不是判断 LLM 是否能够正确分类一个字符串,而是要了解该系统能否在保持足够召回率、确保安全工作流可靠性的同时,减少噪声告警。
在本文中,我们将分享帮助我们从表现有希望的原型结果走向生产环境的一些实践。这些经验同样适用于代码分析、开发者工具、安全、数据分析以及其他生产工作流中的 LLM 驱动系统。

从产品决策开始,而不是从模型开始
当一个 LLM 系统的表现没有达到预期时,人们的第一反应往往是调整它的技术组件。
团队可能会重写提示词、增加上下文、引入额外的推理步骤、调整周边流程,或者更换模型。在进行任何这些修改之前,团队都应该先明确评估需要支持的决策。
在我们的 Secret Scanning 工作中,我们提出了这样的问题:
系统能否在保持足够召回率、确保生产环境安全工作流可靠性的同时,减少误报?
要回答这个问题,团队必须确定哪些错误是可以接受的、哪些指标应该驱动产品决策,以及哪些护栏必须保持在既定阈值之内。
在 Secret Scanning 中,错误地抑制一个真实凭据的告警,其后果可能比要求开发者额外检查一个告警更加严重。因此,我们并没有将精确率和召回率视为可以相互等价替换的指标。
我们的首要目标是减少误报并提高精确率。召回率则作为安全约束:只有当召回率的下降仍处于预先定义的可接受范围内时,一项实验才能继续推进。这为我们评估权衡提供了清晰的方式。我们选择了在满足召回率要求并符合运营护栏的前提下,实现最强误报减少效果的配置。
我们将评估标准分为三个层级:
主要结果
用于衡量我们希望改善的用户收益:
-
误报减少率
-
精确率
安全约束
用于防止表面上的改进引入不可接受的安全风险:
- 召回率
运营护栏
用于判断结果是否具有实际部署价值:
-
延迟
-
成本
-
可靠性
-
生产环境兼容性
这种区分避免了我们将所有指标视为可以相互替换的指标。一项能够减少误报、但同时显著降低召回率的修改,并不能自动被视为改进。同样,一项虽然提升了质量,却让系统变得过慢、成本过高或难以集成的修改,也不能算作改进。
考虑两个假设性的实验结果:
如果单独看精确率,实验 A 可能显得更强。实验 B 则与产品目标更加一致,因为它在没有违反召回率护栏的情况下改善了开发者体验。
在评估 LLM 系统之前,应先确定对用户而言成功意味着什么,以及系统必须遵守哪些护栏。我们希望生成能够支持产品决策的证据。
将离线评估视为集成测试
LLM 系统在首次成功评估之后仍会持续变化,因此评估不应该是一次性的工作。团队会修改提示词、采用新的模型、改变输入和上下文的构建方式,并不断完善周边的业务逻辑。
这些变化中的任何一项都可能改善系统、引入回归问题,或者以意料之外的方式改变系统行为。
因此,我们将离线评估视为类似端到端集成测试的过程。每当我们对提示词、模型、输入构建方式或更广泛的系统逻辑进行有意义的修改时,都会重新运行评估。
评估还需要具备足够的可重复性,使每一个新结果都能够与已知基线进行比较。对于每次运行,我们都会记录提示词、模型、数据集版本以及系统配置。
这样一来,我们就能够回答诸如以下问题:
-
新提示词是否在没有降低召回率的情况下提高了精确率?
-
模型升级是在整个数据集范围内带来了帮助,还是只在某些类别中有效?
-
对输入或上下文的修改是否修复了一种错误模式,却引入了另一种错误?
-
对周边逻辑的修改是否持续稳定地改善了结果,还是只是改变了错误出现的位置?
如果缺乏这种规范,团队很容易比较在不同条件下产生的结果,并将改进错误地归因于某项修改。
一次只改变一个主要变量
仅仅具备可重复性还不够。实验还需要经过合理设计,以便能够明确结果产生的原因。
我们一次只改变一个主要变量,并将每次运行与已知基线进行比较。例如,我们会分别评估提示词修改和模型升级,然后再测试两者结合的效果。
这一点很重要,因为即使是很小的提示词变化,也可能改变模型行为,而模型升级则可能影响质量、成本、延迟或输出一致性。如果在同一个实验中同时改变两者,我们就无法知道究竟是哪一项导致了改进或回归。
我们将提示词和评估配置视为代码来管理。我们对它们进行版本控制,记录发生了什么变化,确保之前的配置可以复现,并支持回滚。
上方评估运行跟踪表中的数值均为假设值,仅用于说明如何跟踪和比较评估运行。
定期测试模型升级
当 LLM 系统表现不佳时,开发者通常会通过向提示词中添加更多指令来应对。有时这确实有效,但并非总是如此。例如,提示词中的复杂性可能实际上来自模型本身。
相比旧模型经过大量调优后的表现,更强的模型可能只需要更简单的提示词就能取得更好的效果。更简单的提示词也更容易理解、测试和维护。
模型升级仍然需要经过仔细评估。新模型可能会提升某个类别中的表现,同时在其他地方引入回归问题。它还可能影响成本、延迟、输出格式,或与现有流程的兼容性。
评估过程应该足够廉价且可重复,使测试新模型成为一种常规工作。在进入生产环境之前,任何对提示词、模型或流程的有意义修改,都应该经过离线评估。
让离线评估贴近生产环境
只有当离线评估与系统在生产环境中实际执行的任务相似时,它才有价值。
在 Secret Scanning 工作流中,模型很少只是评估一个干净、孤立的值。它可能需要结合周围代码以及其他相关信息来评估一个特定候选值,而这些信息可能是不完整的,也可能会分散模型的注意力。信息呈现方式上的差异可能会实质性地影响结果。
因此,我们的离线评估需要保留生产任务的重要特征,包括:
-
正在评估的候选值
-
提供给模型的周围上下文
-
相关的辅助信息
-
输入的格式以及约束方式
-
模型周围更广泛的系统逻辑
即使是很小的差异也可能使结果产生偏差。一个更加干净的数据集可能会排除存在歧义的案例、提供更加完整的上下文,或者移除附近可能分散模型注意力的值。
考虑一个简化的例子:
example_token = "sample_value_for_documentation"
production_api_key = get_secret_from_environment()
candidate_value = "flagged_value"
假设 candidate_value 是系统需要评估的值。模型可能反而关注 example_token,因为它的变量名称看起来与安全性更加相关,从而针对错误的值给出一个看似合理的解释。
当评估示例中只有一个明显的候选值时,这类失败很容易被忽略。它之所以能够暴露出来,是因为离线评估保留了真实 Secret Scanning 工作流中的部分歧义和干扰因素。
离线流程越接近生产流程,评估就越有用。当两者存在差异时,一个较高的离线分数可能仅仅意味着评估的是一个比实际部署问题更加容易的问题。
将生产环境标签视为信号,而不是不可质疑的真相
生产数据可以让评估更具代表性,但其中的标签往往反映的是工作流结果,而不是可靠的真实标签。例如,一个被忽略或已解决的 Secret Scanning 告警,并不一定代表误报。
开发者可能会解决一个告警,因为:
-
凭据已经轮换
-
风险已经被接受
-
为了解除工作流阻塞,需要清除告警
-
告警被错误分类
这些结果在产品数据中可能看起来相似,但实际上代表着不同的真实状态。
在使用生产环境标签之前,应先问:
-
标签是如何产生的?
-
它是否与评估试图回答的问题一致?
-
不同的工作流结果是否被归入了同一个类别?
对于重要或存在歧义的子集,可能需要进行人工审核。你的目标并不是消除每一个不完美的标签,而是确保评估数据足够准确,能够支持当前正在做出的决策。
使用合成数据集和开放数据集填补覆盖范围缺口
具有代表性的生产数据可能受到限制、包含敏感信息,或者在开发早期根本无法获得。合成示例、学术基准和开放数据集可以帮助开发者快速建立评估体系并扩大覆盖范围,但这些示例应该作为生产环境数据的补充,而不是替代品。
考虑到这一点,合成示例可以很好地帮助填补测试中的空白,用于测试那些罕见或难以收集的案例,例如存在歧义的输入、缺失的上下文、不常见的格式,以及代表性不足的失败模式。例如,一组凭据字符串可以用于测试模型是否能够识别常见格式,但它无法全面评估模型如何在真实代码中结合上下文对候选值进行推理。
我们调整了外部示例,使其与我们的任务相匹配,并对与产品定义不一致的标签进行了审核。我们还利用真实的失败模式创建了有针对性的合成案例,其中包括附近存在类似凭据的值、测试代码、占位符、间接引用以及缺失上下文。
通过错误分析发现聚合指标所隐藏的问题
聚合指标可以告诉你一个系统整体上是否有所改进。错误分析则告诉你下一步应该改变什么。
更高的精确率得分并不能揭示剩余错误究竟来自有歧义的输入、不佳的提示词设计、缺失的上下文、噪声标签,还是过于狭窄的数据集。
要理解这些问题,就需要检查失败案例。
我们对误报和漏报样本进行了审核,并根据它们可能的来源进行分类:模型、提示词、输入、流程、数据集或标签。其中反复出现的问题包括前文已经讨论过的一些情况,例如针对错误的候选值进行推理、缺失上下文,以及与评估定义不匹配的标签。
每个类别都指向了不同的应对方式。针对错误值进行推理意味着需要调整提示词或输入的呈现方式,缺少证据则意味着需要改进上下文构建,而错误标签则需要进行数据清理。反复出现的领域特定歧义可能意味着需要制定更清晰的产品策略,或者增加专门的评估类别。
手动审核几十甚至数百个示例需要花费时间,但这通常能够带来更快的进展。一旦明确了反复出现的失败模式,团队就可以进行有针对性的修改,并衡量它是否解决了问题。
针对每个错误,一个有用的问题是:这次失败来自模型、提示词、输入、流程、数据集,还是标签?
这种分类可以将一个模糊的质量问题转化为具体的工程任务。
使用 LLM-as-judge 聚焦人工审核
手动审核每一个评估示例可能无法扩展。LLM-as-judge 可以通过对明确案例进行分类、识别可能存在错误标签的示例,以及将存在歧义的案例优先交由人工审核,从而减轻这一负担。由于评判模型本身也可能犯错,或者出于错误的原因与另一个模型达成一致,因此其输出应该被视为另一项预测,而不是真实标签。
一种更安全的模式是将评判模型用于分流:
-
自动处理明确且低风险的案例。
-
将低置信度、存在冲突或影响较大的案例交由人工审核。
-
定期抽样检查高置信度案例,以发现系统性错误。
-
跟踪评判模型、被评估系统和人工审核人员之间的分歧。
-
像管理其他模型组件一样,对评判模型的提示词进行版本控制和评估。
通过这种方式使用评判模型,可以将人工注意力集中到最有可能通过审核改变最终结果的案例上。

Secret Scanning 教会我们的经验
我们的目标是在一个对安全敏感的工作流中减少误报,同时保持召回率。离线评估为我们提供了一种受控的方式,可以在开始在线实验之前,对提示词、模型、输入和流程的修改进行比较。
通过反复评估和有针对性的错误分析,我们在评估的离线数据集上实现了 95% 的误报减少,同时将召回率保持在我们定义的安全护栏范围内。更重要的是,我们了解了这一结果是如何产生的:评估更加贴近生产任务,修改都是基于可复现的基线进行衡量,剩余的失败模式也得到了记录。
离线评估并不能证明系统在每一种生产场景下都会如何表现。它提供了足够的结构化证据,让我们能够在充分理解风险和安全护栏的情况下,进入在线实验阶段。
清单:将 LLM 系统推向生产环境之前
使用这份清单来评估你的评估工作是否提供了足够的证据,可以让系统继续向前推进。逐项检查每个部分,确认目标、数据、实验以及剩余的生产风险都得到了清晰理解。
产品目标
-
产品决策和主要成功指标是否明确?
-
是否定义了安全护栏和运营护栏?
数据与标签
-
评估数据是否与生产工作流相似,并包含困难案例?
-
我们是否了解标签是如何创建的,以及哪些地方需要人工审核?
评估严谨性
-
是否记录了提示词、模型、数据集和流程的版本?
-
是否将主要修改单独隔离,并与已知基线进行比较?
错误分析与生产就绪度
-
是否按照类别审核了误报和漏报?
-
我们能否重新运行评估,并解释离线结果可能在哪些方面与生产环境存在差异?
在信任之前先进行评估
随着基于 LLM 的系统进入生产环境,评估应该成为日常工程工作流的一部分。一次强有力的离线评估可以展示:在具有代表性的条件下,产品目标是否已经实现、不确定性仍然存在于哪些地方,以及系统是否已经准备好进行受控的生产环境部署。
生产环境中的不确定性无法避免。评估可以让这些不确定性变得可见、可衡量且可管理。
更多推荐



所有评论(0)