如何构建单元测试集并保证覆盖常见边界条件?
解读
在大模型应用开发中,单元测试不仅要覆盖传统代码分支,还必须把模型行为不确定性、提示模板动态性、知识外挂召回链路、推理加速前后数值一致性等纳入测试范围。面试官真正关心的是:你能否用可重复、可度量、可自动化的手段,把“黑盒”大模型变成“灰盒”,让每一次微调、Prompt 迭代、RAG 数据更新都能被单元级断言守护,同时在中国特有的合规、算力、数据安全约束下落地。
知识点
- 四层测试对象:纯函数单元、提示模板单元、模型推理单元、服务化端点单元。
- 边界条件三维矩阵:输入长度(Token 截断、中文多字节)、语义边界(歧义、敏感、OOD)、系统边界(并发、超时、显存占满)。
- 测试数据生成策略:基于规则变异+模型对抗采样+真实日志回灌,并用中文敏感词库+监管合规样本做负例。
- 断言设计:除精确相等外,引入语义相似度阈值、拒绝率上限、幻觉事实一致性打分、加速前后 KL 散度上限。
- LLMOps 集成:单元测试必须跑在CI 的 GPU 容器里,每次 Merge Request 触发零样本、Few-shot、微调模型三路回归,失败即阻断。
- 覆盖率新定义:代码行覆盖≥90% 同时要求Prompt 分支覆盖≥95%、RAG 段落召回覆盖≥98%、安全拒答覆盖100%。
答案
我采用“三层五阶”单元测试框架,已在现团队落地,供参考:
-
分层对象
a. 纯逻辑层:把 Prompt 模板、后处理正则、JSON 解析写成纯函数,用 pytest+parameterized 千级用例秒级跑完。
b. 模型推理层:把模型封装成“语义函数”,输入输出统一为张量+Token ID,用 HuggingFacepipeline的trust_remote_code=False模式,确保权重不变。
c. 服务层:基于 FastAPI 的/v1/chat/completions接口,用 TestClient + asyncio 压测,重点测并发 200 路时显存不 OOM。 -
边界条件用例设计
- Token 截断:构造 128k 上下文,用中文古籍无标点文本,断言首段与末段知识都能召回,且截断提示必须返回
length_limit字段。 - 敏感拒答:引入国家网信办 2024 版敏感词库 1.2 万条,采用动态混淆(拼音、emoji、间隔号),断言模型必须 100% 拒绝,并返回
safe_block标志。 - OOD 输入:用冷门方言语音转写错误文本,断言模型不得输出“无法回答”以外的幻觉,幻觉事实一致性<0.15。
- 知识外挂空召回:把 RAG top-k 设为 0,断言模型 fallback 到通用知识,且答案与黄金答案 ROUGE-L≥0.6。
- 数值一致性:对同一输入跑原始 fp16 模型与INT8 量化+KVCache 优化模型,输出分布 KL 散度<0.01,首 Token 延迟下降≥40%。
- Token 截断:构造 128k 上下文,用中文古籍无标点文本,断言首段与末段知识都能召回,且截断提示必须返回
-
测试数据流水线
每周从线上拉取脱敏日志→用规则+大模型自举生成变异用例→人工审核合规性→入库。用例库版本化,Git LFS 存储,可回滚。 -
CI 集成
GitLab CI 采用华为昇腾 910B 容器,阶段化执行:- CPU 阶段:纯逻辑层≤2 分钟。
- 单卡阶段:模型推理层≤10 分钟,失败发企业微信。
- 双卡阶段:服务压测≤15 分钟,显存监控用NPU-smi采集,超限即视为失败。
Merge Request 必须三级门禁全绿,才能进入模型灰度。
-
覆盖率看板
内部平台实时展示Prompt 分支热力图,红色为未覆盖路径;点击可自动反推出缺失用例模板,平均补全时间<30 分钟。
通过以上手段,我们在 6 个月内把线上“幻觉投诉”从 3.2% 降到 0.4%,单元测试用例数 1.8 万条,回归耗时稳定 12 分钟,完全满足国内金融客户对可控、可追溯、可审计的合规要求。
拓展思考
- 多模态边界:当输入出现图片+文字时,如何定义单元?我的做法是把图像编码也视为确定性函数,用 base64+哈希做输入键,断言图文交叉注意力热力图与人工标注的关键区域 IoU≥0.8。
- 持续微调场景:如果每周增量微调 1% 数据,单元测试必须跑**“新旧模型差分”,用对抗探针检测能力漂移,出现安全拒答率下降>0.1%** 即回滚。
- 国产化适配:在昇腾、寒武纪、海光等芯片上,同一单元测试要跑多后端(PyTorch→MindSpore→ONNX),断言数值误差<1e-3,否则视为国产芯片适配失败。