news 2026/10/1 3:31:42

从Telemetry到Evaluation:LLM应用回归测试闭环实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从Telemetry到Evaluation:LLM应用回归测试闭环实践

1. 打不通Telemetry和Evaluation,回归测试就是在刻舟求剑

1.1 为什么"跑没跑过"不等于"该测的都测了"

做LLM应用的人应该都有同感:这一类系统的回归测试,是所有测试里最让人心里没底的。传统后端测试好歹有个明确的状态机、数据库字段、接口返回值可以断言,但LLM应用的核心行为是"一段输入得到一段输出",输出本身是概率性的。你今天把v1.2版本的Agent跑一遍测试集,所有case都过了,不代表上线后用户遇到真实场景它还能过。更麻烦的是,很多团队压根没有"真实场景"的测试集,测试用例是产品经理凭感觉写的,或者是开发从用户反馈里挑了几十条手工抄出来的,和线上真实流量之间的gap非常大。

我见过不少团队做LLM应用回归评估的方式:维护一个几百条的Golden Set,每次发版前跑一遍,算个平均分,分没掉就认为安全。听起来合理,但这个Golden Set从哪儿来的?大多数是三个人攒出来的,覆盖的是他们想象中的用户问题,而不是实际发生的用户问题。于是出现一个很魔幻的现象:离线评估分数一路稳中有升,线上用户体感却在下降。原因很简单——评估集和真实分布的偏差越来越大,你在评估一个已经和现实脱节的"模拟考题",考得再好也不代表上路不出事。

这就是标题里"从运行事实到回归证据"这句话想解决的问题。运行事实(Runtime Facts)指的是系统在生产环境里真实发生的调用轨迹、输入输出、异常事件,它们是"已经发生过的事实";回归证据(Regression Evidence)则是用来判断"这次改动是否让系统退步"的证据集。这两者之间如果能打通,回归测试就不再依赖拍脑袋攒数据,而是从线上真实运行中持续提取、沉淀、更新评测样本。

1.2 遥测数据里藏着被浪费的"运行事实"

Telemetry这个词听起来像是运维那边的事——链路追踪、指标采集、日志聚合,和测试团队有什么关系?很多团队的现状是:遥测数据归可观测性平台管,测试数据归质量平台管,两拨人各看各的看板,老死不相往来。

但如果你真去翻一遍生产环境的Trace数据,会发现里面就是一座没开采的金矿。每一次真实的用户请求,都自带完整的输入上下文、模型调用链、工具调用参数、中间结果、最终输出、耗时、Token消耗,甚至用户后续的反馈信号(点赞、点踩、重新生成、复制粘贴)。这些数据比你手工造的任何测试样本都真实、都新鲜、都有代表性。

问题在于,大多数人把这些数据当"日志"看待——出故障了捞出来看看,排查完就归档。很少有人把它当作"可以自动生成评估用例的语料库"来设计。Workrun这个项目最开始也就是个内部工具,目标很朴素:把这两个原本分离的东西接起来,让每一次线上真实运行都能自动沉淀成下一次回归评估的证据。做到后来我们才发现,这件事的价值远不止"省了写用例的时间",它实际上改变了整个团队的发布节奏和评估方法论。

1.3 Workrun的定位与设计前提

先说清楚Workrun到底是什么。它不是一个大而全的可观测性平台,也不是一个通用的LLM评测框架,它更像是一层"翻译层":一边接入生产环境的Telemetry数据,另一边对接你现有的Evaluation流程(无论你是用简单的规则校验,还是用LLM-as-Judge,或者是更复杂的Agent评估沙箱),把两者之间的数据管道和语义映射做得足够可靠。

我们做Workrun之前,团队里的评估系统其实已经跑了两三个月,但一直有个尴尬的处境:评估报告写得再漂亮,研发团队不太当回事。因为大家心里清楚,评测集里那些case的来路不够"硬"。一旦用户线上反馈一个问题,你回溯到对应Trace,发现这个场景离线评估集里根本没有,你就没法证明"这个改动不会让类似的场景变差"。这就是"运行事实"和"回归证据"之间断裂造成的信任塌方。

Workrun的设计前提有三个:

  • 第一,生产环境的Telemetry必须足够结构化,不能只是散落的日志文本;
  • 第二,从Trace到评估用例的转换必须尽量自动化,人工只做审核和抽样确认;
  • 第三,评估结果必须能追溯到原始运行事实,任何时候都能回答"这条评估样本是哪个用户请求演化来的"。

这三个前提确立之后,后面所有的工作都围绕它们展开。

2. 采集层的取舍:Telemetry怎么采才能不变成噪音

2.1 全量采样还是自适应采样

第一个要拍板的事就是采多少。很多人第一反应是全量采集,反正存储便宜。但真正面对LLM应用的生产流量时,全量采集是个灾难。一个Agent请求可能涉及十几轮LLM调用、几十个工具调用,单个Trace的payload轻松上几十KB。用户量一起来,每天几个TB的数据量,传输、存储、检索的成本会让整个项目在第一天就被预算部门掐死。

我们用的是自适应采样策略:默认只对健康流量做10%的采样,对异常流量做100%采样,对慢请求和重试请求做100%采样。这个比例不是拍脑袋定的,而是通过成本估算倒推的——先看单Trace的平均大小,再乘预估日请求量,算出每天最多能扛多少存储增量,然后反推采样率。以我们当时的量级,10%的采样率已经能保证每周攒下足够的有效样本。

注意:采样率不能全局固定。用户体量、流量分布、评估集缺口情况都是在变的。Workrun里我们把采样策略做成了动态配置,每个服务可以单独设置阈值。最核心的一个判断是"当前评估集中该类场景的覆盖度是否足够",覆盖度低的路由自动提升采样率,覆盖度饱和的路由可以降到更低比例。

2.2 事件结构化的三个字段设计原则

遥测数据如果只是按原样塞进ClickHouse或者ES里,后面做评估用例生成的时候会非常痛苦。因为评估需要的是"这一段对话的完整上下文",而不是一串JSON Log。我们在事件结构化的阶段定死了一个规范:不管是什么类型的事件(LLM调用、工具调用、用户消息、系统异常),统一吐成Event对象,至少包含三个字段——trace_id、span_id、parent_span_id,再加上一个event_type。

这三个字段是链路重建的地基。有了它们,任意一条事件都能被还原成一条树状的调用轨迹。第二个原则是:所有高维信息(比如模型返回的完整消息、工具返回的JSON)统一存储为Payload字段,但索引只给低维的元数据(时间戳、模型名、耗时、是否异常、用户反馈标签)。这样可以避免把高大上的Payload丢进倒排索引导致存储膨胀,同时又能保证检索阶段快速过滤。

第三个原则是:事件必须携带"业务语义标签"。比如某个事件是"用户最终采纳了答案"还是"用户反馈不满意",这些标签在原始Trace里通常不会自动出现,需要我们主动从业务系统引入。Workrun的做法是提供了一个轻量级SDK,业务方在关键节点手工打一个semantic_tag,成本极低,但后续做评测样本筛选时几乎是命脉级的字段。

2.3 从分散事件到完整轨迹的链路重建

事件采集进来之后,还有一步脏活:链路重建。分布式系统里一个用户请求会串起多个服务,每个服务都往Trace系统里写自己那一段。如果只是把同一trace_id的数据拼在一起,大概率是乱序、缺段、相互嵌套的。Workrun里维护了一个轻量的轨迹重建器,逻辑不复杂:按照parent_span_id把事件构建成一棵时间树,然后做一次拓扑排序,把同一层级的事件按时间先后排列。

这一步的坑在于,很多服务并没有严格按照OpenTelemetry的规范去传parent_span_id,尤其是老服务或第三方服务。我们实际的解法是:对缺失父节点的子Span做一次"就近匹配"——根据时间窗口和调用链顺序,把孤儿Span挂到最可能的父Span下面,同时打上一个reconstructed: true的标记。这类重建出来的轨迹在生成评测样本时要额外小心,因为它的上下文顺序可能不完整,我们会降低它的优先级,或者只截取其中信息量最大的一小段作为评测片段。

链路重建质量的验收标准很简单:抽样几十条轨迹,人工确认"这棵树能不能讲出一个完整的故事"。如果一段轨迹连"用户问什么、系统经历了什么、最终返回什么"都说不清楚,它就不具备成为评估证据的资格。

3. 转换核心:把运行轨迹加工成回归证据

3.1 切分评测单元的标准

不是每条Trace都能直接变成评测样本。一条用户请求里可能有十几个来回的对话,其中大部分是低价值的中间试探。如果整条Trace直接塞进评测集,模型评估时会被超长上下文带偏,而且最终的得分也没法定位到具体哪个环节出了问题。

我们定义了一个"评测单元"(Evaluation Unit)的概念,它是回归评估的最小数据单位。Workrun切分评测单元的标准有三条:

  • 第一,必须包含一个完整的"用户意图-系统响应"闭环,也就是至少一轮用户输入和对应的最终输出;
  • 第二,上下文长度不能超过评测模型的处理上限,超长的轨迹按轮次截断,保留最核心的意图段;
  • 第三,必须能定位到具体的业务功能模块,这样回归失败时可以直接指认是哪个Agent、哪个Prompt链路的退化。

这三条标准听起来简单,实际执行时最困难的是第一条。因为用户意图不一定在一句话里表达完,经常是"我先问A,再追问B,最后才说出真实目的C"。我们把这类多轮轨迹做了一次"意图聚簇":通过语义相似度把同一话题下的连续轮次合并为一个评测单元,换句话说,我们切分的不只是"每一轮对话",而是一段完整的"话题会话"。这个操作大大提升了后续评估的语义完整性。

3.2 清洗、脱敏与标注的三步走

从生产环境捞出来的原始Trace不能直接进评测集,至少有三道工序是绕不开的。

清洗这步主要处理两类问题。一类是明显异常的输入输出,比如超长乱码、空响应、测试账号的假数据、内部压测产生的流量——这些样本不仅是噪音,还会污染评估集的统计分布。另一类是"脱敏",LLM应用里用户输入经常携带个人隐私信息。Workrun会先跑一轮PII检测,对邮箱、手机号、身份证号、地址做确定性脱敏,同时保留语义占位符。这一步如果没做扎实,评测集本身就有合规风险,千万别省。

标注这步是决定评估集质量的胜负手。我们一开始尝试过纯自动标注——让一个大模型给所有样本打标签,速度快但质量参差不齐。后来改成"弱监督+人工抽查"的方式:先用规则+LLM自动打标签(内容包括业务领域、意图类型、难度等级),然后按5%的比例随机抽样人工复核,复核通过率低于85%的批次自动退回重新标注。测过几次之后,95%以上的样本都能在这种工作流下达到可用的标签质量。

这里有个容易被忽略的细节:脱敏和标注的顺序必须先脱敏再标注。如果先让标注模型看了原始文本,哪怕最后输出的是脱敏后的样本,模型也可能把原始信息泄漏进"系统记忆"里,这在自托管模型上尤其需要注意。

3.3 自动扩写:一个真实交互变出一组评测样本

那些直接把生产Trace原封不动塞进评测集的做法,只能说"能用",但远远不够高效。一个真实用户交互往往只覆盖了一个场景的一个侧面,我们需要的是"同一场景下的多个变体",这样回归评估才不容易被单一输入形态钻空子。

Workrun里做了一个"样本扩写器":给定一条真实的评测单元,模型会基于原样本的意图和上下文,生成3~5条语义等价的变体样本。举例来说,真实用户问的是"帮我总结一下这份合同里的违约责任条款",扩写器会生成"这份合同违约了怎么处理""把违约责任部分提炼给我看""乙方违约要承担什么后果"等不同表述。这些变体在生产上是等价的,但在输入分布上覆盖了不同的措辞模式。

扩写不是无中生有,我们给扩写器设了几个硬约束:不能改变原始意图、不能引入原始样本中不存在的实体信息、生成的变体必须通过一轮双向语义一致性校验——用另一个模型判断"变体能否还原回原样本的意图"。双向一致率达到90%以上才入库。这样既保证了样本的多样性,又防止扩写跑偏成"主题联想"。

4. Evaluation Agent如何嵌入Workrun的评估闭环

4.1 评估智能体解决的问题

评估集准备好了,接下来是评什么、怎么评、谁来评。我记得最初团队做评估的方式就是写一堆独立脚本:对每个评测样本调用一次模型,然后把输出丢给GPT-4判断"好还是不好"。很快我们就发现这种做法撑不住规模了。

第一,评估标准散落在各处。有的场景用"回答是否准确",有的场景用"是否遵循系统指令",有的场景看"工具调用参数是否正确",如果每个评估项都写一段独立的评判逻辑,维护成本呈指数上升。

第二,单个评估任务往往需要多步推断。比如判断"Agent是否在用户要求拒绝时仍然强制完成了操作",这不能只看最后一轮输出,要看上下文里的用户明确拒绝信号、工具调用链里是否出现了违规操作。这种多步Evaluator用一次Prompt打分根本做不好。

所以Workrun把评估环节从"一个打分函数"升级成了"Evaluation Agent"——一个有目标、有工具、有记忆的评估智能体。它拿到一条评测样本后,不是直接输出分数,而是先拆解评估维度,决定需要看哪些字段,必要时调用额外的检索工具去查旧版本的历史行为,最后综合出一个带证据链的评估结论。

4.2 方法论注册机制:从Rules到Protocol

这里就是"Evaluation智能体添加方法论"这件事的落点。我们的评估方法论不是写死在代码里的,而是通过一套注册机制来动态添加。每一条方法论本质上是一份评估协议(Protocol),包含四个部分:

  • 适用场景:什么类型的评测单元适用这条方法论;
  • 评估维度:要打分的维度列表,比如事实准确性、指令遵循度、安全性、多轮一致性;
  • 判定流程:明确说明需要哪些上下文、按什么顺序做判断;
  • 输出格式:每个维度需要给出分数、理由、引用的原始证据片段。

最初我们想偷懒,把方法论直接堆进System Prompt里,让Evaluation Agent自己"领悟"。结果效果很不稳定,各场景的评估尺度漂移很大。后来改成了协议注册制——每个场景在添加方法论时,会有一个"协议校验"环节,将这条方法论先在已有人工标注的子集上跑一遍,计算和人工标签的一致率,一致率超过阈值才允许注册生效。这一步相当关键,它保证了新增方法论的靠谱程度。

方法论的添加过程本身很像"教一个实习生学会打分":先给他看规则,再给几个正反样例,最后让他试评一批,你检查结果。Workrun里对应的操作就是注册协议、指定参考样例、进行小规模校准实验。

4.3 评估结果的结构化输出与阈值管理

评估Agent输出的不能只是一个"通过/不通过",否则没法追溯问题。我们规定了评估结果必须输出一份结构化报告,至少包含以下内容:

  • 每个维度的得分与置信度;
  • 判定理由(一段文本);
  • 命中的样本原始片段(Trace中的某一段);
  • 是否存在低置信度的可疑点。

这份报告会随评估结果一起进入数据仓库。回归评估最忌讳的就是输出一个剧场比分——大家只知道"这次总分下滑了2分",但不知道为什么。结构化的评估报告让团队能按图索骥,从分数波动一路钻到具体的某一段运行时轨迹里。

阈值管理上我们经历了几个阶段。最初是人工定每个维度0.8,低于0.8就是失败。但LLM应用没有这么理想的二分边界,很多场景的得分天然围绕0.75上下波动,一个无关紧要的Prompt改动就能让它跳水。后来我们把单阈值改成了"三区制":绿色区(得分高于0.85,视为通过)、黄色区(0.7~0.85,视为需要人工复核)、红色区(低于0.7,视为明确回归)。这个变化让评估结果从"一刀切的红绿"变成了"有弹性的交通信号",研发团队的反感度下降了一个量级。

5. 回归评估上线后的三道坎

5.1 误报刷屏:阈值收敛的真实过程

任何评估系统上线之后都会经历一段"误报刷屏期",Workrun也不例外。刚开始我们把评估结果接入发布流水线,每次发布前自动跑全量评测集,结果前两周几乎每两天就收到一个告警:某个维度的均分跌落了0.05。

一开始团队如临大敌,停了发布去排查,最后发现一半的告警都是"假摔"——具体来说,是评估集里的样本在自动扩写和更新过程中,新加入的样本难度偏高,导致整体均分被拉低。这个锅不在模型,而在评测集本身发生了分布漂移。

后来我们搞了一个"基线锁定机制":每次回归评估必须同时跑"对照子集"和"增量子集"。对照子集是从上一次通过的样本里固定抽出的500条,用于排除评测集变化导致的分数波动;增量子集是从最新Telemetry里新增的样本。只有当增量子集的得分显著低于对照子集时,才认定为真实回归。这套机制上线之后,误报率直接从40%降到了个位数。

5.2 评测集污染:同一批样本反复用会钝化

和单元测试一样的道理,评测集本身也会过时。生产流量永远是动态的,用户的问法会变,产品在迭代,新的工具在接入。如果你几个月都不更新评测集,它在数学上仍然是"运行事实",但在语义上已经退化成"旧世界的化石"了。

我们吃过这个亏:有一段时间评估集连续三周没更新,结果模型的一次重大改动在评估集上完好无损,上线后却被用户投诉"连基本问题都答不好"。回溯后发现,新增的用户问题类型在评估集里的覆盖几乎为零——评估集已经钝化到对现实失明。

现在Workrun规定评测集必须每周增量更新,更新节奏是"70%保留、20%替换、10%新增"。保留的是历史关键回归场景,替换的是语义相似度过高的冗余样本,新增的是这周Telemetry里覆盖度缺口最大的场景。同时我们有一个"相似度去重器",对入库的每个样本做一次向量相似度检查,和已有样本相似度超过0.92的直接丢弃,避免评测集被某一种问法刷屏。

5.3 跨团队信任:如何让研发认账

做一个内部评估平台,最难的往往不是技术,而是让研发团队相信你的评估结论。开学时我们经常收到研发的质疑:"这个case我本地跑过没问题,为什么线上评估说不行?" ——后来发现一半的情况是"评测样本本身有问题",另一半是"评测标准有歧义"。

解决方案其实不复杂:我们强制做到了两点。第一,任何评估失败结论必须附带证据链接,一键跳转到原始Trace,研发可以直接看到当时的样子,而不是只看到一个冷冰冰的评分数字。第二,评估标准必须对研发可见——他们可以随时查看某个维度的方法论协议,甚至对协议提出修改建议。一旦研发发现评估标准本身不合理,可以通过"协议变更提案"流程提交修改,走校准实验验证后更新。这样一来,评估体系不再是测试团队单方面制定的"法律",而是一个大家一起维护的共识机制。

信任这个东西,只能靠透明换回来。把评估逻辑做成黑箱,它再准也没人买账;做成白盒,即使偶尔出点小问题,大家也愿意陪你一起调。

6. 一些可以带走的具体配置

6.1 自适应采样策略示例

最后分享几个可以直接抄作业的配置。Telemetry的自适应采样,我们在Workrun里用的是类似下面这样的规则,不同团队按自己的量级调整阈值即可:

  • 健康请求:默认采样率10%,如果该场景在评测集覆盖度低于20%,提升到50%;
  • 异常请求(返回错误、超时、重试):采样率100%,不参与覆盖度判断;
  • 慢请求(耗时超过P95):采样率100%,优先保留;
  • 评估集覆盖度达标的场景:采样率降至5%,只保留每日随机一部分用于漂移监测。

这套配置的核心思路是:Telemetry的采集成本要花在"未来可能变成评估证据"的数据上。健康流量的价值密度低,不值得全留;异常和慢请求往往能暴露边界行为,价值密度高,值得全留。

6.2 评估集增量更新的节奏

评估集更新的具体节奏,我们的经验是做"周级别滚动",不要搞成每天。每天更新意味着每个工作日都要重新校准一遍分数基线,团队会被评估系统本身拖着走。

每周一执行一次增量更新流程:

  • 从过去7天的Telemetry中筛选候选评估单元;
  • 跑一轮自动去重、脱敏、标注;
  • 人工抽样审核新批次(311比例,通过率达标才入库);
  • 计算新旧评估集的分布差异,输出一份"评测集变化报告";
  • 更新基线锁定子集,重新校准阈值。

如果某周有重大版本发布(比如更换了主模型或Agent框架),可以在发布前额外触发一次"定向补集":专门从最近异常反馈中快速构建一小批回归用例,跑一个只针对改动的快速评估。这个流程跑得多了,团队就会形成条件反射——改大结构前先补评估集,再改代码。

6.3 回归评估的指标看板

最后是看板指标。我们的主看板不放大而全的"综合分",因为综合分不具备可操作性。放的是"回归证据覆盖率"和"回归失败定位耗时"这两个指标。

回归证据覆盖率衡量的是:当前评测集中的场景数,占最近30天Telemetry中识别出的有效场景数的比例。这个指标直接告诉你"评估盲区有多大"。回归失败定位耗时衡量的是:从评估告警出发,到定位到具体是哪个模块、哪个Prompt、哪个工具调用导致的退化,需要多长时间。在结构化评估报告和Trace追溯链路跑通之后,这个耗时从最初的平均半天压缩到了20分钟以内。

顺便提一嘴,如果你也在做类似的事情,建议团队里至少有一个既懂一点可观测性、又理解评估体系的人来牵头。很多人觉得这是两个领域、两套体系,但实际上它们缝合起来的那一层才是真正的价值所在。我见过好多团队在采集端做得极其漂亮,评估集却还在手工维护;也见过评估方法论研究得很深,但输入数据全靠瞎编。Workrun这段实践给我的最大感受是:Telemetry和Evaluation不是两个平行的子系统,它们本质上是一条价值链的两端——运行事实只有被转化成回归证据,才真正产生了闭环价值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 3:31:41

msxml6.dll丢失修复全攻略:官方方案+连带问题一次解决

你刚把某个软件装上,或者双击一个老项目生成的报表程序,屏幕上直接弹出一个红框:“无法启动此程序,因为计算机中丢失msxml6.dll。”我一看到这种提示就知道,又是系统组件缺失引发的连锁故障。msxml6.dll 是微软的 XML …

作者头像 李华
网站建设 2026/10/1 3:30:17

Spring Boot用户CRUD实战:三层架构落地与代码详解

搞懂Spring Boot用户增删查改,三层设计模式到底怎么落地?这是很多初学后端的朋友最纠结的一道坎。网上讲CRUD的教程一抓一大把,但要么只贴代码不讲为什么,要么绕来绕去把简单事情复杂化。我这个项目很简单,就是一个基于…

作者头像 李华
网站建设 2026/10/1 3:30:17

Kafka与Elasticsearch集成实战:从部署到数据管道的高频问题排查

1. 内容整体设计与思路拆解先说个我自己的例子。前阵子帮朋友做网约车订单数据的实时分析展示,一上来就是日均百万级订单事件,字段几十个,还要求延迟在秒级以内,前端大屏要能实时刷新“当前时刻完成订单数”“热门路线Top10”这类…

作者头像 李华
网站建设 2026/10/1 3:29:59

SSM+Maven+MySQL企业人事管理系统实战:从建表到部署完整指南

做JavaWeb课设或者毕设的同学,SSMMavenMySQL这套组合应该是接触频率最高的搭配了。基于javaweb和mysql的ssmmaven企业人事管理系统,我用SSM框架完整实现了一个可运行、可部署、可扩展的企业人事管理系统,覆盖员工信息管理、部门维护、考勤记录…

作者头像 李华
网站建设 2026/10/1 3:29:44

Redis缓存店铺查询:读多写少场景下的设计与实践

店铺项目做到第二天,终于轮到性能优化里最经典也最实用的一环:把店铺查询信息加进Redis缓存。“黑马店铺”这个项目本身就是读多写少的典型——用户进首页看店铺列表、点店铺详情、搜索店铺,几乎全是查询操作。如果每次查询都直接打到MySQL&a…

作者头像 李华
网站建设 2026/10/1 3:29:26

RuoYi-Vue二次开发第一步:Git克隆与分支切换

1. 前言:RuoYi-Vue 二次开发的第一脚,从拉代码开始后台管理系统做久了,你会发现市面上能直接拿来改的开源项目就那么几个,RuoYi-Vue 绝对算得上绕不开的一个。它是基于 Spring Boot Vue 的经典前后端分离脚手架,权限、…

作者头像 李华