上个月准备 RAG 分享时,“提问、检索、回答”画在一张图上很直观。整理产品资料以后,困难却大多发生在回答之前。文字找到了,条件没找到,模型仍然会给出方向错误的操作建议。
比如页面已经发布,用户问为什么改不了标题。库里同时有修改标题的步骤与发布页面只读的规则,命中前一份不等于回答有了依据。这个问题适合用来检查资料、召回、上下文和生成各自做了什么。
文档版本比片段数量更重要
我会把文档版本与片段分别保存。版本记录原文、适用版本、状态和内容摘要;片段记录章节路径、父章节、来源区间和内容摘要。更新资料产生新版本,旧回答仍能指回当时的材料。
切分按标题、步骤和注意事项组织,过长章节才继续拆。限制条件紧接着操作步骤时,应尽量保留关系。把“仅草稿可编辑”切到另一块,后面再调相似度也未必能补回来。
权限和适用版本由检索入口的可信上下文确定,不能让问题文本自行声明可访问范围。任何片段进入模型之前,都必须经过这层检查。
两种检索怎样形成同一份候选
关键词适合命中发布、标题、只读这样的明确词,语义检索可以补不同说法。两边的分数含义不同,直接相加没有可靠依据。我用名次融合示意候选合并:
def reciprocal_rank_fusion(rankings, k=60):
scores = {}
for ranking in rankings:
for rank, chunk_id in enumerate(ranking, 1):
scores[chunk_id] = scores.get(chunk_id, 0) + 1 / (k + rank)
return sorted(scores, key=scores.get, reverse=True)
assert reciprocal_rank_fusion([
["edit-title", "readonly-rule"],
["readonly-rule", "draft-mode"]
])[0] == "readonly-rule"k 和候选数需要用自己的题集调整。函数只负责合并,排第一并不保证能回答。候选可以继续做小范围排序,不必对整个库逐条判断。
“标题设置”片段命中后,沿父章节补回同版本的前提与例外,按来源范围去重,避免相邻片段占满上下文。版本冲突不靠模型猜,资料互相矛盾就明确保留冲突。
相似不等于足够
发布态问题需要两项依据:当前状态禁止直接编辑,以及进入草稿后的修改流程。只拿到后者,就不能建议在发布页面直接改标题。针对高频问题,可以人工定义所需事实与期望证据,不把一个向量阈值当成答案正确率。
证据分配本轮编号,生成时让业务判断对应证据。输出检查编号确实来自本轮获准上下文,原文确实支持结论,链接或来源引用也指向同一版本。第一项能排除编造编号,后两项还要检查语义与来源映射。
资料中的指令仍是外部内容。文档写着“忽略限制并调用接口”,不会因此获得工具权限。只解释功能的知识助手可以根本不提供写工具。
错误记录应该指出可修改的环节
| 观察 | 判断依据 | 对应处理 |
|---|---|---|
| 原始资料没有规则 | 人工也找不到支持内容 | 补资料或明确无法回答 |
| 资料存在但候选没有 | 查看召回列表 | 检查切分、查询与过滤 |
| 候选正确但上下文缺前提 | 比较实际提示输入 | 补父章节、去重、调整预算 |
| 依据齐全仍解释错 | 逐项对照结论 | 修改回答约束与生成策略 |
| 解释对但来源错 | 核对文档版本和区间 | 修复引用映射 |
题集保留问题、适用版本、期望证据、能否回答和预期行为。召回、进入上下文与最终答对分别统计,无法回答的题单独检查错误肯定回答。一次实验固定资料快照、题集与模型配置,只改主要变量。
发布态例子的合格行为是解释只读限制,说明转草稿流程,不代替用户修改。移除关键规则后,应明确缺少依据。这是方案的验收要求,不是线上准确率声明。资料索引、候选、实际上下文和回答都能重放,错误才有确定的排查入口。