引用约束生成实战:让模型句句有据,把幻觉率再压一个量级 个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 大模型开发从0到1 其他栏目: iOS项目总结大全 其他栏目: 我想学python了 其他栏目: iOS UI 文章目录引用约束生成实战让模型句句有据把幻觉率再压一个量级一、为什么基于资料回答这句话约束不住模型二、第一层约束格式义务——逐句标注三、第二层约束无据即拒答——拒答率平衡术3.1 三档响应策略3.2 档 3 的工程价值拒答要拒得有用3.3 拒答率监控这个指标必须单列四、第三层约束生成后逐句核对4.1 引用有效性轻量全量跑4.2 支撑关系核对重量抽样跑五、faithfulness 度量怎么量化有据程度六、和检索质量的联动约束生成的输入端七、落地检查清单八、小结引用约束生成实战让模型句句有据把幻觉率再压一个量级上一篇解决了答案能不能点回原文这一篇解决更狠的问题怎么让答案里的每句话都有出处没出处的宁可不说。基础 RAG 的生成 prompt“基于以下资料回答问题”约束非常软——资料不全时模型会热心地用训练知识补全语气自信事实全错。引用约束生成constrained generation就是给模型套上笼头逐句标注来源、无据即拒答、生成后逐句核对。这篇文章讲三层约束的设计、拒答率的平衡艺术、以及 faithfulness 的度量。一、为什么基于资料回答这句话约束不住模型先看一个实验。给模型一段不完整的资料问资料里没有的问题【资料】 [1] 违约金比例合同总额的 5%。 [2] 争议解决地上海仲裁委员会。 【问题】 违约金的支付期限是多久 【弱约束 prompt常见写法】 请基于以上资料回答用户问题。 → 模型输出违约金应在违约行为发生后 30 日内支付。资料里根本没有 这是编的但用户以为有据LLM 的本质是续写最合理的文本不是核查事实的数据库查询器。资料不全时它默认该用合理知识补全——礼貌、流畅、错误。弱约束 prompt 改变不了这个行为模式。强约束要做的是三件事让引用变成格式义务每句话必须挂来源、让无据变成合法输出明说没资料不丢人、让核对变成生成后的程序不信模型自评。二、第一层约束格式义务——逐句标注约束 prompt 的严格版【回答格式必须严格遵守】 1. 你的回答只能由论断句 [来源编号]组成 2. 每个论断句末尾必须紧跟来源编号如违约金比例为合同总额的 5%[1] 3. 一句话只能引用一段资料综合多段的论断拆成多句分别标注 4. 找不到资料支持的论断禁止输出该句 5. 允许输出根据现有资料无法确定违约金的支付期限。 【资料】 [1] 违约金比例合同总额的 5%。 [2] 争议解决地上海仲裁委员会。关键在第 1、3、4 条只能由论断句编号组成是格式宪法——不允许模型自由发挥寒暄、总结、延伸。第 3 条防止一句话挂三个引用的模糊归属[1][2][3] 都对到底是哪句支持哪个论断。第 4 条是废话删除条款没有支撑的句子输出本身就是违规。结构化输出兜底用 JSON mode / function calling 把格式钉死比自然语言约束可靠一个量级frompydanticimportBaseModelclassCitedAnswer(BaseModel):sentences:list[Sentence]# 每句强制带 cite_idsclassSentence(BaseModel):text:strcite_ids:list[int]# 至少 1 个且 ≤ 编号总数confidence:float# 可选模型自评支撑强度JSON schema 强制cite_ids非空——格式层面消灭无引用句子比 prompt 里求它管用。三、第二层约束无据即拒答——拒答率平衡术强约束的副作用模型变胆小能答的也说不知道。护数据纯洁性和用户体验之间的平衡是这套系统的真实调优点。3.1 三档响应策略检索结果质量 → 响应档位 档 1 强支撑Top chunk 相关度 0.8 且覆盖问题要点 → 正常生成逐句引用 档 2 弱支撑Top chunk 相关度 0.5或要点部分覆盖 → 生成资料表明……但以下方面资料未覆盖X、Y → 允许基于资料的部分回答 明确缺口声明 档 3 无支撑Top chunk 相关度 0.3 → 直接拒答现有知识库中未找到相关信息建议联系 XX / 换个问法 → 拒答时给出建议换个什么问法从 query 理解层拿线索3.2 档 3 的工程价值拒答要拒得有用纯我不知道是负体验。好的拒答 道歉 归因 出路知识库里没有关于离职证明开具流程的文档检索最相关的 是《入职指南》相关度仅 0.2。 你可以 1. 换个说法试试比如离职手续怎么办 2. 联系 HR 咨询 3. 查看知识库中没有的相关分类入职 / 考勤 / 薪酬第三条从检索日志的同类已解决问题里捞建议问法——拒答变成导航不是死胡同。3.3 拒答率监控这个指标必须单列拒答率 拒答次数 / 总查询。两条红线拒答率飙升比如从 5% 到 30%要么检索侧出了问题索引挂了/过滤过度要么 prompt 约束太紧把能答的也拒了——先查检索质量再看 prompt拒答率归零模型在不懂装懂约束失效——查 prompt 有没有被改坏或模型换了不遵守格式的版本。健康的拒答率在 10%~25%视业务而定客服库可以更低合规库必须更高把它做成仪表盘和告警项和准确率同级监控。四、第三层约束生成后逐句核对模型自评的引用不可全信程序化核对是最后一关。核对两个层次4.1 引用有效性轻量全量跑上一篇讲的每个 cite_id 在 context 里存在、每句至少一个引用。轻到可以每次生成都跑正则 集合运算的事。4.2 支撑关系核对重量抽样跑“这句话的内容真的出自被引的那段吗”——需要语义比对。两种实现规则版便宜论断句的实体/数字/关键词必须在被引 chunk 里出现。问违约金 5%[1]“chunk 里必须同时有违约金”“5%”。数字和专有名词的规则匹配准确率其实很高defcheck_support(sentence,cited_chunk):numsset(re.findall(r\d\.?\d*%?,sentence.text))ifnumsandnotnumsset(re.findall(r\d\.?\d*%?,cited_chunk)):returnFalse# 论断里的数字被引段没有 疑似编造# 实体词/专名粗查用 jieba 分词或预训练 NERtermsextract_key_terms(sentence.text)hitsum(tincited_chunkfortinterms)/len(terms)returnhit0.6模型版准但贵小模型当裁判输入论断 被引 chunk输出支持/不支持/部分支持。离线批处理跑不占实时链路。处理策略核对不通过的句子从答案里剔除并在答案末尾声明部分内容因无法核实来源已隐去——宁可答案短不可答案假。五、faithfulness 度量怎么量化有据程度约束生成的效果要靠 faithful 指标度量公式faithfulness 被资料支持的句子数 / 答案总句数计算方式离线评估集上人工或裁判模型对每句标注资料支持/资料无关/资料矛盾汇总成三个比例指标含义目标faithfulness有据句占比 0.9contradiction_rate和资料矛盾的句占比 0.02answer_relevance答案实际回应了问题 0.85防过度保守三个指标必须一起看只追 faithfulness 会把模型逼成复读机答案全是资料原句拼贴faithfulness 100% 但没用只追 relevance 回到老路上啥都敢答。faithfulness × relevance 双高才是约束生成的成功。RAGAS 框架里有标准实现faithfulness answer relevance context precision/recall 四件套评估集从真实查询日志构造 人工标注一千条是初期投入之后增量维护。六、和检索质量的联动约束生成的输入端约束生成改的是输出端但幻觉的一大概率根源在输入端——检索回来的东西本来就是错的生成端再约束也是垃圾进垃圾出。联动监控检索层context precision召回的 chunk 里多少真相关低 → 先生成端拿不到好料faithfulness 上不去组合指标算端到端 faithfulness和检索层 precision两条曲线定位瓶颈在哪一层经验分布约束生成能把检索精度的上限提高 15~20%但检索精度低于 60% 时生成端也救不回来——那时候该修索引而不是修 prompt。七、落地检查清单强约束 prompt 三段式格式宪法论断句引用、无据拒答条款、资料边界声明JSON mode / function calling 强制 cite_ids 非空三档响应策略强支撑/弱支撑缺口声明/拒答建议问法拒答率单列监控红线双向告警飙升 检索坏 or 过紧归零 约束失效生成后两层核对引用有效性全量、支撑关系抽样 高风险场景全量不通过句子剔除 声明宁可短不可假faithfulness / contradiction / relevance 三指标评估集 RAGAS 对接端到端指标和检索 precision 分层看瓶颈定位到层。八、小结引用约束生成的四句话LLM 默认补全而非核查基于资料回答是弱约束改变不了行为模式——必须格式义务、拒答合法化、程序化核对三管齐下格式是宪法不是建议JSON schema 强制每句带 cite_ids比 prompt 请求管用一个量级拒答率是平衡艺术纯我不知道是负体验好的拒答 道歉 归因 建议问法 相关分类导航拒答率要和准确率同级监控双向红线faithfulness 三指标一起考核有据率 × 相关率双高才算成只追一个指标都会被模型钻空子——复读机和瞎编是两个极端都要防。下一篇讲多轮 RAG 的上下文处理对话历史怎么进检索、指代消解怎么做、以及防止多轮累积的上下文腐烂。