1. 从用户问题到可执行任务
用户的一句话往往同时包含事实查找、条件判断、计算和表达要求. 系统先把它拆成可验证的子任务: 哪些命题必须由外部材料支持, 哪些值来自数据库计算, 哪些动作需要工具执行, 哪些部分只是组织语言. 分解结果决定后续是否检索以及检索什么.
任务契约可写成 . 是输入与上下文, 是允许来源及权限, 是新鲜度和时间语义, 是输出与失败动作. 契约规定验收口径, 不承担实现配置的职责. 同一个实现可以服务多个契约, 但一次评测只能针对一个明确契约.
1.1. 证据需求
可核验命题需要标出证据粒度. 产品价格可能要求精确到当前地区和日期; 政策解释可能需要条款与生效时间; 技术综述可以接受多篇来源的综合. 粒度决定文档解析、索引字段和引用位置.
证据需求同时规定“什么算支持”和“什么仍然缺失”. 只含主题相近词的片段不是支持; 缺少数字单位、适用条件或否定范围的片段也可能不充分.
1.2. 时间与权限
时间不能只作为文档排序特征. 有效时间、抓取时间和索引时间含义不同. 回答“当时的政策”需要按有效时间回溯, 回答“现在的政策”需要排除已经失效的版本.
权限过滤应在召回前执行, 并贯穿缓存和日志. 先检索全部文档再从结果中删除越权项会泄露标题、分数或缓存命中信息. 权限是候选集合的定义域, 不是排序后的装饰.
可以把一次请求的可见语料写成 . 这里的 不只表示用户 ID, 还包括租户、角色、项目成员关系和请求用途. 检索器实际计算的是 , 而不是先算 再删掉若干结果. 两种写法在结果列表上偶尔相同, 在近似近邻索引、top-k 截断和缓存上却有本质差异. 如果十个高分位置都被越权文档占据, 事后过滤会返回空列表, 尽管授权子集中存在足够证据.
时间同样进入集合定义. 设文档版本 的有效区间为 , 查询时间为 , 当前问题只允许 的版本参与检索. 一个简单例子是某制度在 4 月 1 日从报销上限 500 元改为 800 元. 用户问“3 月 20 日的上限”时, 最新版本排序会给出错误答案; 用户问“现在的上限”时, 同时返回两个版本又会制造冲突. 时间过滤先决定版本集合, 相关性排序再在集合内部工作.
2. RAG 与相邻系统的分工
2.1. 搜索、数据库与工具
搜索擅长从非结构化材料中找到相关文本. 数据库擅长精确过滤、聚合与联接. 工具调用擅长执行受控动作. RAG 可以编排这些能力, 但生成模型不应替代它们的确定性语义.
例如“列出上季度退款最多的三个产品并解释原因”包含 SQL 聚合和文档检索. 产品名单及数值由数据库产生, 原因解释从工单或复盘文档取得证据. 将全部数据转成文本再向量搜索会损失计算口径.
分流可以依据输出语义判断. 如果答案要求精确聚合、唯一约束、余额或库存, 需要数据库提供确定性结果. 如果答案要求变更状态, 工具调用必须承担鉴权、幂等和审计. 如果答案要求从非结构化材料中找依据并解释, 才进入检索链. 模型可以编排三条路径, 但每条路径的返回值要保留类型: 数据库返回结构化记录, 工具返回动作结果, 检索返回带位置的证据.
混合问题的关键是不要让语言模型重算已经由确定性系统给出的值. 假设数据库返回产品 A、B、C 的退款数分别是 42、37、31, 检索只为三者找原因材料. 提示中把数值标为受保护字段, 生成后再做一致性校验. 如果回答把 42 改写成“约 40”或把排序调换, 即使解释流畅也判失败. 这类检查不依赖另一个大模型, 直接比较结构化字段即可.
2.2. 参数记忆与外部记忆
参数记忆适合稳定、广泛的语言和常识模式. 外部记忆适合频繁更新、需要撤回、来源受限或组织私有的信息. 两者共同影响回答, 因而基线需要无检索对照, 观察模型是否绕过证据使用参数记忆.
外部证据也不能自动覆盖参数中的先验. 当文档与模型记忆冲突时, 提示、训练和验证共同决定行为. 系统必须保留冲突状态, 而非悄悄选择更流畅的一方.
Lewis et al. (2020) 将生成概率写成对检索文档这一潜变量的边缘化. RAG-Sequence 在整段输出中共享文档, 可写为 ; RAG-Token 则允许每个输出 token 重新组合文档分布. 这个原始定义揭示两件事: 检索器给文档分配概率质量, 生成器仍然可能在给定文档时输出其他内容; 文档进入 top-k 也不等于它对最终答案产生了可识别贡献.
现代工程流水线常使用不可微搜索、重排和固定上下文, 不再严格求上述边缘概率, 但潜变量视角仍有用. 它提醒我们分别观察 所代表的候选质量和 所代表的证据使用. 当正确证据排在第一而答案仍错, 继续训练检索器不会直接修复生成器; 当答案靠参数记忆偶然正确而引用无关, 端到端准确率会掩盖证据链失败.
3. 失败状态与响应协议
3.1. 无答案和证据不足
无答案样本表示授权语料中不存在足够证据. 它不同于召回失败: 前者的正确动作是拒答, 后者应改进系统. 数据集若不区分二者, 召回器会被要求寻找不存在的内容, 生成器也会因拒答受到错误惩罚.
拒答信息应指出缺少的证据类型, 但不能暴露用户无权访问的材料. “没有找到当前版本的生效条款”比泛化的“我不知道”更可操作, 同时仍需避免暗示受限文档存在.
可回答性可以拆为覆盖和充分两个判断. 覆盖判断目标主题是否进入候选, 充分判断候选能否支持任务要求的全部命题. 问题“药物 X 是否适用于 12 岁以下儿童, 剂量多少”若只检索到成人剂量, 主题覆盖成立而证据不充分. 系统若把高相似度当作可回答概率, 很容易补写一个儿童剂量.
为拒答阈值做手算时, 可以准备 100 个问题, 其中 40 个在授权语料中有充分答案, 60 个没有. 某阈值下系统回答 35 个有答案问题和 15 个无答案问题. 对“回答”这一动作, precision 为 , recall 为 . 若高风险任务中误答代价是误拒的十倍, 0.70 的 precision 明显不够. 阈值选择依赖代价矩阵, 不能只追求总体准确率.
3.2. 冲突、过期与越权
冲突证据应保留来源、版本与日期, 让生成器描述差异. 过期证据可以用于历史问题, 却不能支持当前结论. 越权材料不得进入模型上下文, 因为生成后的内容过滤无法可靠消除泄露.
失败动作是任务输出的一部分, 不是系统异常的统一兜底. 只有把状态分开, 才能分别测量拒答校准、版本选择和权限正确性.
冲突检测至少比较实体、属性、取值、时间和适用范围. 两段材料分别写“标准保修期为一年”和“企业增强方案保修期为三年”, 表面取值冲突, 加上客户类型后可以同时成立. 若系统在切分时丢掉“企业增强方案”这一限定, 下游验证器会把真实的条件差异误判为来源冲突. 这说明冲突处理依赖结构完整的证据, 无法只在生成末端补救.
越权状态与无答案状态在用户界面上可以采用相同保守文案, 在内部标签上必须分开. 否则评测人员可能为了提高回答率, 把越权文档加入召回. 生产日志也不应记录“命中了文档 X 但用户无权查看”这类对普通操作员可见的信息; 只保存受控的策略结果和审计标识, 详细材料进入权限更高的安全日志.
4. 契约如何进入测试
4.1. 样本字段
一个可复现样本至少包含问题、用户权限、查询时间、允许来源、参考证据位置、可接受答案要点和预期失败状态. 多跳问题还要标出证据组合关系. 只保存问答文本无法判断系统使用了哪份文档.
样本应同时覆盖正常命中、近似干扰、旧版本、越权文档、证据冲突和确实无答案. 这些边界样本比大量同分布简单问题更能暴露设计缺口.
证据标注使用文档版本和字符区间或结构路径, 并允许一个问题有多组充分证据. 例如问题可由“定义段 + 例外条款”支持, 也可由后续汇总表的一行独立支持. 若评测只承认第一组, 检索到汇总表会被错误计为漏召回. 标注结构可以写成证据组集合 , 只要某个 被完整覆盖, 证据召回即成功.
多跳样本还需标出依赖顺序. 问题“发明技术 A 的研究者后来创办了哪家公司”需要先从证据一确定研究者, 再从证据二确定公司. 两篇文档都进入 top-k 只能说明集合覆盖; 如果第二次查询使用了错误同名人物, 推理链仍然失败. 因此样本除了最终答案, 还应保存中间实体和连接关系.
4.2. 验收条件
验收先检查硬约束: 无越权命中, 删除可传播, 引用可解析. 随后检查召回、排序、忠实性和任务正确性. 硬约束不能被平均分抵消.
任务契约稳定后, 切分、embedding、重排器或生成模型都可以独立替换. 每次实验记录变化的组件和固定的其余条件, 结果才具有比较意义.
一个实用的验收表按硬门槛、质量目标和资源预算分层. 硬门槛包括零越权证据、删除测试通过、引用可解析; 质量目标包括关键问题簇的 recall@k、命题支持率和拒答 precision; 资源预算包括 P95 延迟、单请求 token 和外部调用次数. 硬门槛失败直接阻止发布, 质量与资源则在预定范围内比较方案.
边界条件也写进契约. 若来源连接器延迟超过 24 小时, 系统对时效问题降级或拒答; 若重排器超时, 使用召回顺序但缩小回答范围; 若证据之间存在未消解冲突, 回答列出差异而不合并成单一结论. 这些规则使故障行为能够预演, 而不是等线上异常时由模型临场决定.
证据支持与任务决策继续展开命题支持、加权损失、澄清动作与制度问答手算.