前言欢迎回到《2026 DjangoLlama 4 AI应用实战》在上一讲中我们为应用构筑了安全护栏防止恶意输入和输出。但还有一种更隐蔽的危机常常在夜深人静时摧毁你的 AI 应用——模型退化。当你微调了 Prompt、更换了 RAG 切片策略甚至只是 Ollama 默认更新了 Llama 4 的权重版本原本能完美回答的“退货政策”突然开始胡编乱造原本输出的标准 JSON 突然多了一个逗号。传统软件有单元测试但大模型的输出具有非确定性传统的assert output xxx完全失效。如果没有自动化的评估手段每一次 AI 迭代都像是在拆盲盒。今天这一讲我们将引入大模型领域的“单元测试”概念集成轻量级 Eval 框架DeepEval在 Django 中构建一条自动化回归测试流水线让你的 AI 在持续迭代中始终保持卓越。准备好了吗我们开始环境准备我们将使用 DeepEval 作为评估框架它提供了丰富的开箱即用的指标如答案相关性、幻觉检测等并且原生支持调用本地模型作为评判员。在虚拟环境中执行pipinstalldeepeval1.2.5分步实现评估的核心逻辑是测试集 - 运行被测 AI (Django Service) - 裁判员模型打分 - 记录结果。我们将分 6 步完成这条流水线。第 1 步配置 DeepEval 使用本地 Llama 4 作为裁判默认情况下DeepEval 使用 OpenAI 的 GPT-4 作为裁判模型。为了保证架构一致性和省钱我们需要让它使用本地 Ollama 的 Llama 4。修改settings.py增加配置# llama4_chat/settings.py# ... 之前的配置 ...importos# DeepEval 配置使用本地 Ollama 作为评判模型os.environ[DEEPEVAL_TELEMETRY_OPT_OUT]YES# 关闭遥测DEEPEVAL_MODEL_CONFIG{model_name:llama4,api_base:http://localhost:11434/v1,api_key:ollama}第 2 步设计测试集数据模型我们需要一个表来存储“黄金标准”的问答对作为回归测试的基准。在chat/models.py中新增# chat/models.pyfromdjango.dbimportmodelsclassEvalTestCase(models.Model):AI 评估测试用例categorymodels.CharField(max_length50,verbose_name用例分类(如:退货政策,JSON输出))input_querymodels.TextField(verbose_name用户输入)expected_outputmodels.TextField(verbose_name期望的黄金回答)contextmodels.TextField(blankTrue,nullTrue,verbose_nameRAG参考上下文(可选))is_activemodels.BooleanField(defaultTrue,verbose_name是否启用)created_atmodels.DateTimeField(auto_now_addTrue)def__str__(self):returnf[{self.category}]{self.input_query[:20]}...classEvalRunResult(models.Model):评估执行结果test_casemodels.ForeignKey(EvalTestCase,on_deletemodels.CASCADE)actual_outputmodels.TextField(verbose_nameAI实际输出)scoremodels.FloatField(verbose_name得分 (0-1))reasonmodels.TextField(verbose_name裁判模型给出的评分理由)passedmodels.BooleanField(defaultFalse,verbose_name是否通过 (如 score 0.7))run_atmodels.DateTimeField(auto_now_addTrue)def__str__(self):returnf{self.test_case}- 得分{self.score}-{通过ifself.passedelse不通过}执行数据库迁移python manage.py makemigrations chat python manage.py migrate关键说明EvalTestCase中的context字段用于模拟 RAG 场景可留空。EvalRunResult记录每次评估的详细结果便于历史追溯和分析。auto_now_addTrue自动记录评估执行时间。第 3 步编写评估逻辑服务在chat/目录下新建eval_service.py。我们将使用 DeepEval 的AnswerRelevancyMetric答案相关性和HallucinationMetric幻觉指标。# chat/eval_service.pyimportloggingfromdeepeval.metricsimportAnswerRelevancyMetric,HallucinationMetricfromdeepeval.test_caseimportLLMTestCasefromdjango.confimportsettingsfromopenaiimportOpenAIfrom.modelsimportEvalTestCase,EvalRunResult loggerlogging.getLogger(__name__)classEvalService:def__init__(self):model_configsettings.DEEPEVAL_MODEL_CONFIG# 初始化指标传入本地模型配置self.relevancy_metricAnswerRelevancyMetric(modelmodel_config[model_name],api_basemodel_config[api_base],api_keymodel_config[api_key],threshold0.7# 得分大于 0.7 算通过)self.hallucination_metricHallucinationMetric(modelmodel_config[model_name],api_basemodel_config[api_base],api_keymodel_config[api_key],threshold0.5# 幻觉得分小于 0.5 算通过该指标越低越好)defrun_regression(self):执行全量回归测试test_casesEvalTestCase.objects.filter(is_activeTrue)totaltest_cases.count()iftotal0:logger.warning(没有启用的测试用例跳过评估)return100.0passed_count0logger.info(f开始回归测试共{total}个用例...)fori,caseinenumerate(test_cases,1):logger.info(f({i}/{total}) 执行:{case.input_query[:50]}...)# 1. 调用被测系统获取实际输出actual_outputself._get_actual_output(case.input_query,case.context)# 2. 构造 DeepEval 测试用例test_caseLLMTestCase(inputcase.input_query,actual_outputactual_output,expected_outputcase.expected_output,context[case.context]ifcase.contextelseNone)# 3. 执行评估相关性self.relevancy_metric.measure(test_case)relevancy_scoreself.relevancy_metric.score relevancy_reasonself.relevancy_metric.reason# 4. 幻觉评估需要 contexthallucination_score0.0hallucination_reason无上下文跳过幻觉评估ifcase.context:self.hallucination_metric.measure(test_case)hallucination_scoreself.hallucination_metric.score hallucination_reasonself.hallucination_metric.reason# 综合判定相关性 0.7 且 幻觉 0.5is_passed(relevancy_score0.7)and(hallucination_score0.5)ifis_passed:passed_count1# 5. 保存结果到数据库EvalRunResult.objects.create(test_casecase,actual_outputactual_output,scorerelevancy_score,reasonf相关性:{relevancy_reason}| 幻觉:{hallucination_reason},passedis_passed)pass_rate(passed_count/total*100)iftotal0else0logger.info(f回归测试完成通过率:{pass_rate:.1f}% ({passed_count}/{total}))returnpass_ratedef_get_actual_output(self,query:str,context:strNone)-str:封装对 LLM 的调用确保与生产逻辑一致# 模拟简单的 RAG 拼装可根据实际业务扩展ifcontext:promptf请基于以下参考资料回答问题\n{context}\n\n问题{query}else:promptquery clientOpenAI(base_urlsettings.LLAMA4_API_BASE,api_keysettings.LLAMA4_API_KEY)responseclient.chat.completions.create(modelsettings.LLAMA4_MODEL_NAME,messages[{role:user,content:prompt}],temperature0.0,# 测试时保持输出稳定max_tokens1024)returnresponse.choices[0].message.content eval_serviceEvalService()关键说明使用temperature0.0确保同一输入每次都产生一致输出便于回归对比。评估指标threshold定义了“通过”的门槛可根据业务敏感度调整。通过数据库保存每次评估的详细输出和理由便于后续审计和分析。第 4 步创建 Django 管理命令触发测试我们不需要通过 HTTP 请求来触发耗时的回归测试而是通过 Django 的自定义命令方便在 CI/CD 流水线中执行。创建目录结构chat/management/commands/如果不存在则创建并在其中新建run_ai_eval.py# chat/management/commands/run_ai_eval.pyfromdjango.core.management.baseimportBaseCommandfromchat.eval_serviceimporteval_serviceclassCommand(BaseCommand):help运行 AI 模型回归评估测试defhandle(self,*args,**options):self.stdout.write(self.style.WARNING(开始执行 AI 评估...))pass_rateeval_service.run_regression()ifpass_rate80.0:self.stdout.write(self.style.SUCCESS(f评估通过通过率:{pass_rate:.1f}%))else:self.stdout.write(self.style.ERROR(f评估未达标通过率:{pass_rate:.1f}%))# 在 CI/CD 中可以在这里抛出异常以中断流水线# raise SystemExit(1)说明该命令可在部署前手动执行或集成到 GitHub Actions、GitLab CI 中作为自动化门禁。第 5 步在 Admin 中管理测试用例与结果修改chat/admin.py让运营和算法同学可以方便地维护测试集和查看报告# chat/admin.pyfromdjango.contribimportadminfrom.modelsimportEvalTestCase,EvalRunResultadmin.register(EvalTestCase)classEvalTestCaseAdmin(admin.ModelAdmin):list_display(category,input_query_short,is_active,created_at)list_filter(category,is_active)search_fields(input_query,expected_output)definput_query_short(self,obj):returnobj.input_query[:30]...input_query_short.short_description输入问题admin.register(EvalRunResult)classEvalRunResultAdmin(admin.ModelAdmin):list_display(test_case,score,passed,run_at)list_filter(passed,test_case__category)readonly_fields(test_case,actual_output,score,reason,passed,run_at)defhas_add_permission(self,request):returnFalsedefhas_change_permission(self,request,objNone):returnFalse说明评估结果通常为只读历史记录禁止手动修改保证数据可信。第 6 步准备黄金数据集与测试验证1. 在 Admin 中添加测试用例登录 Django Admin向EvalTestCase中添加至少 3 个用例分类输入期望输出上下文可选退货政策你们的退货流程是什么收到商品7天内可以无理由退款。公司政策规定所有商品在未拆封且不影响二次销售的情况下7天内支持无理由退换货。JSON输出提取我的名字和年龄我叫张三今年25岁。{name: 张三, age: 25}留空闲聊你好你好有什么我可以帮忙的吗留空2. 执行回归测试命令在终端运行python manage.py run_ai_evalDeepEval 会调用本地的 Llama 4 分别作为“被测模型”和“裁判模型”进行推理。这可能需要几分钟取决于用例数量和模型速度。3. 查看结果执行完毕后刷新 Admin 的EvalRunResult页面你将看到每次运行的得分、是否通过以及裁判模型给出的详细评分理由。测试效果模拟一次“退化”危机现在我们人为制造一次退化。假设我们在chat/services.py中的系统提示词里加入一句捣乱的指令def_get_react_system_prompt(self)-str:return 你是一个遵循 ReAct 范式的智能助手。 ... 新增捣乱指令在回答用户问题时请务必在开头加上本回答由外星人赞助。 再次运行python manage.py run_ai_eval。这一次由于 AI 的输出变成了“本回答由外星人赞助收到商品7天内…”与黄金标准严重偏离。查看 Admin 结果测试用例将赫然显示Passed: FalseScore 骤降至 0.2裁判理由写道“实际输出包含了不相关的赞助信息且格式与期望不符”。这就是自动化 Eval 的威力在你将破坏性的 Prompt 部署到生产环境之前测试流水线已经替你踩住了刹车3 个常见坑在构建 AI 回归测试时以下三个坑是摧毁你信任体系的元凶。坑 1裁判模型“偏袒”自己Self-Bias现象使用 Llama 4 作为裁判评估 Llama 4发现分数总是虚高即使回答有明显瑕疵也常常给 0.8 分以上。原因大模型存在“自我偏好”现象倾向于认为自己的输出是合理的。解决如果条件允许裁判模型应比被测模型更强大如用 GPT-4 评估 Llama 4。如果必须用同源模型可以在裁判的 Prompt 中增加极度严苛的约束例如“请严格挑剔地评分只有当回答与期望完全匹配时才给高分”。引入启发式规则辅助对于 JSON 输出、特定关键词提取等任务不要依赖大模型裁判直接在 Python 代码中用json.loads()或正则表达式硬性校验这部分得分占权重的一半。坑 2测试集漂移现象公司的退货政策从 7 天改成了 15 天但 Eval 测试集中的黄金回答还是 7 天。导致每次正确的 AI 回答都被判定为 Fail。原因业务逻辑在演进但测试集没有同步更新变成了“僵尸测试”。解决Eval 绝不是一劳永逸的。需要建立机制当业务规则更新时第一时间更新EvalTestCase。可以在 Admin 中增加一个“定期复审”的标记提醒运营人员过时用例需要清理。也可以编写脚本自动同步业务规则数据库中的最新条款到测试集。坑 3评估指标的“刻板印象”现象期望输出是“你好”AI 输出是“您好请问有什么可以帮您”语义完全正确但因为字面差异大AnswerRelevancy 给出了低分。原因基于字面匹配或弱语义的指标无法理解表达的多样性。解决对于开放域对话不要死板地使用AnswerRelevancy而应改用SemanticSimilarityMetric语义相似度或者只评估幻觉不评估字面匹配。在构造测试集时期望输出应尽量描述“核心要点”而非固定的句式。也可以接受多个正确答案通过正则表达式或模糊匹配进行校验。专栏目录与订阅本文是《2026 DjangoLlama 4 AI应用实战》专栏的第十九讲完整专栏持续更新中你可以在以下地址查看所有文章和后续章节专栏主页https://blog.csdn.net/zsh_1314520/category_13175252.html本专栏将从零带你搭建生产级可上线的 AI 全栈项目涵盖大模型 API 集成、RAG 检索增强、智能对话系统、AI 内容生成等核心场景详解 Django 后端架构优化、大模型调用封装、流式响应实现等工业级实战内容。全部代码基于真实项目提炼可直接用于你自己的业务系统。建议你收藏专栏主页方便第一时间获取更新。下一篇预告至此我们已经完成了从基础对话、RAG、Agent、网关、安全到质量评估的所有核心模块建设。在最后一讲中我们将跳出代码细节站在架构师的高度复盘整个系统的设计并探讨从开发环境走向千万级并发生产环境的最后一公里K8s 部署、网关统筹与未来展望。在第 20 讲《终局之战Django AI 中台架构复盘与千万级并发生产部署指南》中我们将为这个系列画上一个完美的句号。敬请期待本专栏持续更新中点击专栏主页或关注我获取完整教程。