ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

模型输出不确定?AI应用测试实战:从评估集到回归体系

模型输出不确定?AI应用测试实战:从评估集到回归体系 模型输出不确定AI 应用到底怎么测试一份 QA 实践笔记如果你接手过 AI 应用的测试工作大概率经历过这样的场景同一个问题上午跑通了一条链路下午再跑一次模型的回答换了措辞甚至核心结论都变了。你拿着传统软件测试的思维去提 bug开发一脸无奈地说“这是模型行为不是 bug”。你追问那到底怎么才算对开发给你一句“语义上对就行”。那一刻你大概会感觉到过去积累的用例设计、断言方法、回归策略在一夜之间全都不太够用了。这篇笔记不是教科书是我在一家中小型自研公司做 AI 应用 QA 大半年踩坑攒下来的实践总结。内容聚焦一个核心问题当模型输出不确定AI 应用到底应该怎么测。会讲到测试思路的转变、评估集怎么建、评测维度怎么定、工具链怎么选以及一套从零搭起来的可落地方案。适合正在做 AI 应用测试的 QA、刚转岗做 AI 评测的研发以及所有被“模型输出飘忽不定”折磨过的技术人。1. 先想明白AI 应用的测试为什么不能照搬传统 QA1.1 传统测试的确定性假设在模型输出面前全盘失效传统软件测试有一套很成熟的体系需求分析、用例设计、断言验证、回归执行。这套体系的底层逻辑建立在三个确定性假设之上输入可枚举我可以把合法输入、非法输入、边界输入都列举出来。输出可预期给定输入我知道正确输出应该是什么哪怕是一个范围。行为可重复同一条用例无论跑多少遍只要代码没变结果就不变。这三个假设在传统功能测试里天经地义但到了 AI 应用里全部失效。模型输出的不是固定值而是一个概率分布上的采样结果。你问“帮我总结这段合同的风险”第一次它列出三点第二次变成四点第三次可能把第二条换了个说法。你没法拿一个固定的“期望结果”去做字符串比对也没法断言“必须包含某句话”因为模型换个表达方式语义可能完全一致但字面上能差出十万八千里。这不是说 AI 应用没法测而是说测试的对象变了。我们不再测试“这个函数返回什么”而是测试“这个模型提示词参数配置组成的系统在多大比例下能产出可接受的结果”。测试的中心从“验证实现是否正确”变成了“评测质量是否达标”从一次性的通过/不通过变成了概率意义上的质量评估。1.2 从“是否符合预期”到“是否在质量边界内”的思路转换我在团队里推行这套思路的时候反复给大家打的一个比方是传统测试像是在用游标卡尺量螺丝要求每个尺寸精确到小数点后两位超差就是不合格品AI 测试更像是在做食品质检你没法保证每包薯片里的盐粒分布一模一样但你可以定标准——盐度必须在某个区间内不合格率不能超过某个比例消费者吃到的整体体验要稳定。所以AI 应用测试的第一件事不是写用例而是定义质量边界。什么叫可接受什么叫不可接受边界划在哪里拿我们做的智能客服知识库问答系统举例。用户问“我们的年假政策是什么”系统回答时遗漏了“入职满一年才享有年假”这个前提条件这算不算 bug如果按功能测试思路这当然算但你怎么断言一个模型的输出有没有覆盖某个前提这提示了第一条认知变化AI 测试里的“正确”不是一个点而是一个集合一个由语义等价、信息完整、立场安全、格式合规等多个维度共同框定的区域。QA 的工作从“写断言”变成“定义边界建立衡量边界的方法”。这个思路转换不只是在测试人员脑子里发生还得让开发、产品、业务方共同认账。我在项目启动时最常做的一件事就是拉着业务负责人一起对“质量红线”达成书面共识——哪些错误是绝对不能容忍的哪些偏差是可以接受的哪些场景必须 100% 覆盖。这群人是你后续所有测试判断的立法机构没有他们点头你的评测标准就是空中楼阁。2. 测试策略怎么搭评估集、评测维度与回归基线2.1 评估集没有评估集谈 AI 测试就是耍流氓如果说传统测试的根基是“测试用例库”那 AI 测试的根基就是“评估集”。所谓评估集就是一组“输入期望行为描述”的集合用来反复检验模型输出质量的基准数据。评估集不是一次性用的它是 AI 应用测试的锚点每次迭代都要拿同一批问题去跑对比前后质量变化。我在项目里把评估集分成三层来建设每层服务的测试目的不同第一层核心冒烟集50~100 条。覆盖产品最核心的用户路径比如客服问答的“热门问题 Top 30”、文档助手的“高频检索场景”。这一层要保证把主链路跑通每次改动提示词、调整模型参数后先跑它就像传统测试里的冒烟测试。我有一个习惯冒烟集里的问题必须包含一部分“简单直给”的问题它们是为了快速暴露结构性故障用的。第二层回归集300~500 条。按业务场景、问题类型、输入形态分层设计目的是监测模型迭代、提示词调整后有没有引入“回归”。比如客服问答里既有“政策咨询类”也有“投诉处理类”还有“闲聊兜底类”每一类都要有足够的样本。第三层全量评估集1000 条以上。用于发布前的全面质量评估通常还会配上比较完整的期望行为打分标准。全量评估集的建设成本和标注成本都高但它是做模型选型、提示词版本对比时最有力的底牌。这里要特别提醒一个新手容易犯的错评估集不等于网上随便找一些问答对。合格的评估集必须和你的业务深度绑定每条 case 都得能追溯到真实用户场景。我建评估集的第一批数据就是直接从客服聊天记录里捞出来的脱敏真实问题而不是产品经理拍脑袋编的。2.2 评测维度怎么定正确性之外还要看这六件事有了评估集接下来要定义“怎么算好”。AI 应用的质量维度比传统功能测试复杂得多单看“答案对不对”远远不够。我在实践中沉淀出一套六维评估框架每个维度都会在实际评测脚本中单独打分维度说明典型问题示例答案正确性核心事实、结论是否正确完整政策条款引用错误、关键前提缺失指令遵循度是否按提示词要求的形式、长度、语气输出要求 JSON 却输出 Markdown格式合法性结构化输出是否严格符合既定 schemaJSON 字段缺失、枚举值非法安全合规是否包含不当言论、幻觉捏造、越权建议医疗建议编造、侮辱性表达信息完整性用户问题的所有子问题是否都被覆盖多条件问题只回答了其中一个语气与可读性表达是否自然、友好、符合产品调性回答生硬、口语化过度这六个维度的权重不是平均分配的应该由业务风险等级决定。比如医疗问诊类应用安全合规和答案正确性必须拉到最高权重闲聊陪伴类应用可读性和安全合规更重要正确性反而相对宽松。实操上我给每个维度设计了 1~5 分的打分卡。拿“信息完整性”来说5 分代表问题中所有约束条件、隐含的子问题全部覆盖3 分代表主要问题回答了但遗漏次要点1 分代表只抓了表面关键词、漏掉了核心意图。打分卡越具体后面的量化评估越可靠——这一点千万别偷懒模糊的打分标准会直接导致不同的评估员给出完全不同的分数最终数据没法用。2.3 回归策略AI 应用也有“bug 回归”只是方式不同传统软件里开发改了一行代码可能影响十个功能所以需要回归测试。AI 应用里存在同样的风险而且更容易被忽视。你调了一下提示词想让回答更简洁结果发现所有已购商品类的回答都把赠品信息省略了这就是一种经典的提示词回归。AI 应用回归策略要分级不能所有变更都跑全量。我采用的三级回归方案是改提示词跑核心冒烟集必要时加跑受影响场景的回归子集。提示词改动是最高频的变更必须用最短的路径快速验证。改模型参数温度、top_p、max_tokens 等跑完整回归集因为参数对输出的影响是全局性的可能悄悄改变所有场景的回复风格。换模型或升级模型版本跑全量评估集并且要做对比。同一波评估集旧模型全局跑一遍新模型全局跑一遍计算每个维度的分数差异再决定是否切换。这套分级回归执行了一段时间帮我抓到一个特别隐蔽的回归有一次我们只是调整了系统提示词里的“请使用礼貌用语”结果连带所有中文回复都多了一句“如需进一步帮助请随时联系”用户体感很差。如果只跑一条最简单的冒烟用例这个问题根本不会暴露但回归集里包含“如何修改收货地址”这类流程指引型问题很快就把“多话啰嗦”的漂移暴露出来了。3. 工具链怎么选自动化测试框架与 AI 评测的配合3.1 传统自动化测试框架还能不能用先说结论能用而且要大胆用。我们在 AI 应用测试里最常用的自动化工具仍然是 pytest搭配 requests/OpenAI SDK 直接调用模型接口本质上和测试一个 HTTP API 没有区别。你完全可以用 pytest 搭一套 AI 评估的骨架一个测试函数对应一批评估 case通过参数化把评估集里的每一道题喂给模型接口拿到模型返回结果后再把它传给评估函数打分最后生成报表。这个流程里真正需要重新设计的不是测试框架而是“断言”这一步——传统断言是 assert result expectedAI 测试的断言变成了“对模型输出做质量评估然后与阈值比对”。实际工程里我建议这样组织代码结构评估集数据独立存放JSON/CSV测试代码只负责调度和打分评测标准单独抽成一个函数模块。这样数据、逻辑、标准三层分离后续任何一层变更都不用动另外两层是我踩过代码硬耦合的坑之后总结出来的经验。3.2 让大模型当裁判LLM-as-a-judge 的实战用法评估模型输出最常见的两种路子一种是算文本相似度BLEU、ROUGE、语义向量余弦相似度另一种是让一个更强的大模型来当裁判也就是 LLM-as-a-judge。文本相似度对“意思对了但说法不同”这类情况非常不友好。我曾经用 ROUGE 评估两个都算正确的回答一个简洁一个详尽得分差异巨大但人工评定其实都是合格。所以我的建议是不要把文本相似度作为主要评判手段它更适合做粗筛不适合做最终质量裁决。LLM-as-a-judge 是目前更可靠也更好用的方案。做法是写一个评分提示词把用户问题、模型回答、评分标准就是我们前面定的打分卡一起发给裁判模型让它按 1~5 分打分并输出简要理由。核心实践经验有三条裁判模型要比被测模型强否则裁判根本看不出细微错误。我们被测模型用 7B 级别开源模型裁判模型选用更强的商用模型效果差距非常明显。评分标准必须显式写进提示词不能只写“请评价质量”五个字。我的评分提示词里会把每个维度的行为锚点明明白白列出来比如“当回答遗漏了问题里明确包含的时间条件完整性评分不得超过 3 分”。对裁判结果保持怀疑辅以规则校验。裁判模型本身也是模型也可能出错。我通常在裁判打分之外再加一套硬规则兜底比如“回答中出现安全词表则直接判定失败”“JSON 解析失败直接判定格式维度 0 分”。这样模型的主观判断和规则的客观校验结合结果才可信。3.3 确定性校验不该变的地方必须锁死AI 应用很玄学但不是处处玄学。应用里其实有很多确定性部分这些地方必须用传统测试的严格断言来锁死不能惯着。以我们的客服问答系统为例整条链路分三段检索召回、上下文组装、模型生成。第三段是概率性的但前两段完全可以做成确定性校验——召回是否命中正确的知识库文档、组装后的上下文是否包含用户问题的必要限定条件这些都是可以硬断言的。另外一个确定性大阵地是结构化输出。现在很多 AI 应用要求模型输出 JSON让下游系统解析。JSON 的合法性、字段完整性、枚举值范围这些完全可以用 JSON Schema 做严格校验不需要模糊打分。我始终强调一句话AI 应用测试的最高境界是明确知道哪些地方要“放过模型一马”哪些地方要“跟模型死磕到底”。把确定性命门锁死把概率性空间管住测试的稳定性和可信度都上来了。4. 从零搭一套 AI 应用 QA 体系的实操记录4.1 先定需求与红线把“质量”翻译成可执行指标这里用我实际做的项目当例子一个企业内部知识库问答助手员工可以问休假政策、报销流程、组织架构等模型基于向量检索到的文档片段生成回答。项目启动第一周我没急着写测试代码而是拉着业务方和研发把质量要求聊透最后落到一张纸上红线场景任一触发即判测试失败涉及“医疗建议”“法律结论”“贬损他人”“绝对化承诺”的回答引用不存在的文档或政策条款输出内容偏离问题主题知识库范围。质量指标核心场景通过率核心冒烟集 50 条测试要求回答完整率不低于 90%格式合法率 100%安全合规 100% 无违例。可接受的表现波动同一问题多次回答核心信息点覆盖率允许 20% 以内的浮动但关键限定条件如时间、资格、金额缺失率不得超过 5%。这些数字不是拍脑袋定的而是先跑了 200 条真实问题的人工评测后以人工合格率为参考倒推出来的。没有基线数据就定指标后面一定会被不现实的指标反复折磨。4.2 评估集建设从真实日志里捞分三批落地第一批评分量最大的还是真实数据。我从客服聊天记录里筛了 300 条脱敏问题覆盖高频问题、长尾问题、误导性提问、多条件复合问题四类。为保证场景均衡我按“高频问题 40%边缘情况 30%困难问题 30%”的比例人工调平。第二批评分针对已知短板补齐边界。比如我发现系统对“报销时限是多久”这类直接问政策的问题表现不错但对“我上个月底提交的报销为什么还没到账”这种混合了流程状态的问题经常答非所问。所以专门补充了一批“复合意图”问题进回归集。第三批是通过线上日志持续回流。系统上线后生产环境里的真实提问会成为评估集的新鲜血液。我每个双周从日志里抽 20 条未覆盖类型的问题人工 demo 确认后补入回归集让评估集保持对真实环境的敏感度。4.3 评测脚本与 CI 接入让回归每天自动跑工具链我选了 pytest 一套自研的评估 runner。核心代码如下所示逻辑不复杂读评估集、调模型、并发评分开写、汇总出报告。import pytest import json from concurrent.futures import ThreadPoolExecutor # 评估集文件结构: [{ id: case001, question: ..., expect: ..., tags: [policy] }] TEST_SET json.load(open(eval_sets/core_smoke.json)) PASS_RATE_THRESHOLD 0.9 # 核心场景通过率红线 def call_model(question): # 调用被测应用的统一接口拼接 prompt、请求模型、返回文本 return client.chat(question) def judge(question, answer): # 分两条线硬规则校验 LLM 裁判打分 rule_result run_hard_rules(answer) llm_score run_llm_judge(question, answer) return rule_result and llm_score 4 pytest.mark.parametrize(case, TEST_SET, idslambda c: c[id]) def test_core_case(case): answer call_model(case[question]) assert judge(case[question], answer), fcase {case[id]} failedCI 接入做的是一套双阶段流水线每次代码合并前跑核心冒烟集 50 条速度控制在 5 分钟内每天凌晨全量跑回归集 400 条自动生成质量报告并推送群里。这里有个教训一开始我把全量回归挂在了每次合并前结果一次模型接口抖动导致所有提交都红灯大家怨声载道。后来改成“核心集卡合并回归集跑定时”节奏才理顺。4.4 线上监控补位LLM 输出不能被放养测试环境做得再充分也无法完全模拟生产环境的输入分布。所以我额外加了一层线上监控核心就两件事一是抽检。按 5% 比例采样生产环境的问答记录先用规则过滤明显异常超时、拒答、空回复、格式乱码再抽取一部分送去做人工抽检打分。抽检结果每两周汇总一次进入质量周报。二是用户反馈闭环。产品里加了“回答是否满意”的点赞点踩按钮点踩的数据自动进入待评审队列。我每周处理一次点踩较高的回答当作新的评估集候选防止线上持续产生同类问题而我们毫不知情。这套体系跑下来真实效果很直接上线首月人工抽检的核心场景通过率稳定在 95% 左右提示词调整引发的回归被 CI 抓到 3 次线下的严重事实性错误从每周 4~5 个下降到 1 个以内。5. 常见问题与排查技巧实录5.1 高频问题速查表问题现象可能原因排查方法解决建议同一用例跑两次一次过一次挂模型温度过高 / 上下文随机扰动 / 裁判打分波动固定随机种子或降低温度同一 case 跑 3 次取多数结果关键判断场景温度下调到 0.2 以下核心集全过线上却出同类问题评估集与真实分布脱节对比线上日志提问风格与评估集差异定期从真实日志回流新 case 进评估集改了个小提示词大批用例变差提示词改动影响了全局指令遵循对比改动前后的回归集逐 case 分维度差异用分级回归先跑受影响场景子集LLM 裁判给分忽高忽低评分标准模糊 / 裁判模型太弱看裁判输出理由检查打分锚点是否含糊细化打分卡换更强的裁判模型JSON 输出时而合法时不合法模型对复杂 schema 遵循能力不足检查失败 case 的错误字段分布加解析失败自动重试配合 few-shot 示例全量回归一次要跑两小时评估集太大且串行执行分析耗时分布看模型调用占多少并行化改造按场景分配执行5.2 独家避坑经验三个容易犯的严重错误最后一个大坑我从自己团队和同行交流里提炼了三点希望能帮大家少交点学费。第一不要用模型自带的 logprobs 来充当置信度。我一开始以为拿到模型每个 token 的概率就能断言“这回答是不是瞎编的”实际测下来效果很一般。模型给出低概率 token 并不等于错误很多创造性表达本来就在概率尾端反过来高概率输出也可能是训练数据里的陈词滥调。置信度判断只适合做信息熵统计不适合当正确性判断。第二不要迷信 BLEU 和 ROUGE 这类文本重合指标。它们适合做机器翻译、摘要这类对原文强依赖的任务但开放问答里同样的语义可以有无数种表达重合度低不代表错。我见过一个团队用 ROUGE 做门禁导致开发为了刷分不停把模型输出改得和参考答案越来越像最后可读性差到用户投诉。第三评估集不是只增不改的“死库”。数据分布漂移是常态某个政策半年后更新了、某个热门话题不再热了评估集里的“正确答案”过时了如果不主动清理和更新评估集本身就会变成测试质量的污染源。我每个月固定做一次评估集体检标记过时 case、修正期望行为、淘汰无效题目让评估集和业务一起“活着”。我个人做完这套体系最深的体会是AI 应用测试本质上不是在“测一个产品”而是在“测一个不断变化的系统”——模型在变、提示词在变、数据分布在变所以测试方法和评估数据也得跟着变。与其追求一套一劳永逸的完美方案不如把一个能持续演进的 QA 闭环搭起来然后让它和产品一起迭代。这也是这份实践笔记最想传递的东西。
返回列表