本节摘要:LLM 生成的内容进到用户眼前之前,可以用 Jev 装一道(或一组)质检闸门——这是第 2.3 节"Jev 管门、LLM 管活"架构的输出侧。经典三闸门:忠实性(每个事实断言都能在资料中找到依据)、完整性(回应了问题的全部子问题)、无捏造(不存在资料里没有的人名/数字/链接)——三道 Noul 一次请求并行返回,任一不过即触发重生成或降级。两条设计铁律:验证标准由你写死在代码里(与生成 prompt 利益分离,不能"顺手"带上);验证判据保持在语义层(是否忠实、是否夸大),可计算的部分(加总、计数、格式)留给代码断言。RAG 场景是此模式的最大受益者。
阅读完本节,你应当能够:
QUESTIONS = { "faithful": { "type": "noul", "instructions": "答案中的每个事实性断言都能在提供的资料中找到依据" }, "complete": { "type": "noul", "instructions": "答案回应了问题的全部子问题" }, "no_halluci": { "type": "noul", "instructions": "答案中不存在资料里没有的人名、数字、链接" }, } # state = {"question": ..., "sources": ..., "answer": ...} # 三问并行,一次返回
设计要点:state 把问题、资料、答案三样都放进去——验证是三方对照,缺了问题判不了完整性,缺了资料判不了忠实性。每道闸门的判据是单一的:不要写"忠实且完整且无捏造"一道闸——分开才能定位失败原因、独立调阈值(第 3.4 节"闸门优先"法则)。
按业务换闸门:
| 业务 | 闸门组 |
|---|---|
| RAG 问答 | 忠实 / 完整 / 无捏造 |
| 营销文案 | 合规(无夸大疗效等)/ 风格符合品牌 / 无竞品提及 |
| 代码生成(配合静态检查) | 符合团队规范 / 与需求描述一致 |
| 结构化抽取 | 字段值忠实原文 / 无多余推断(配合 schema 校验代码) |
def answer_with_guardrails(q: str, sources: list[str]) -> str: for attempt in range(3): draft = llm_generate(q, sources) # 系统二:生成 verdict = jev_noul({"question": q, "sources": sources, "answer": draft}, QUESTIONS) # 系统一:验证 gates = {k: v["noul"] for k, v in verdict.items()} if gates["faithful"] > 0.8 and gates["no_halluci"] > 0.8 and gates["complete"] > 0.6: return draft # 全过 → 放行 # 定向重生成:哪道闸没过,就把哪条要求写进重生成提示 feedback = [name for name, p in gates.items() if p < 0.6] q = f"{q}\n(注意修正:{feedback})" return fallback_answer(q, sources) # 三次不过 → 降级
三个工程细节:
铁律一:验证标准写死在代码里(利益分离)。 判据是 QUESTIONS 常量、随代码走版本控制、有回归集守护(第 9.1 节)——而不是生成 prompt 里的一句"请确保忠实"。后者的本质是让同一个模型既当运动员又当裁判;前者的裁判标准由你(以及你的回归集)持有。
铁律二:语义归 Jev,可计算归代码。 "数字加总是否正确""字数是否超限""格式是否合法"用断言/解析器检查——免费且精确;Jev 只判机器算不了的语义面(是否忠实、是否夸大、语气是否合规)。混着来既浪费又不可靠(Jev 不做数学,第 10.1 节)。
💡 RAG 是最大受益者:检索相关性(第 7.1 节排名)+ 生成后验证(本节闸门)两道 Jev 关卡,正好卡住 RAG 质量问题的两端——检索端"选错料"、生成端"说错话"。
验证模式上线后的核心指标(都是闸门日志的简单聚合):
输出侧的闸门装好了,最后一道门开在动作侧——Agent 要执行命令、调工具之前,风险最高的一道关:护栏。