用文档元数据过滤提升 RAG 检索准确度:字段设计、入库抽取与查询解析
元数据过滤的思路很简单:先用“这份文档属于哪个产品、哪个版本、什么类型、谁能看”这些结构化信息把候选范围收窄,再在剩下的文档里做语义检索。 真正的难点不在检索那一步,而在三件事:字段设计得是否合理、入库时元数据是否准确、用户的问题能否被正确解析成过滤条件。
常见的过滤模式(按产品线、时间、权限、文档类型)可以参考 RAG 元数据过滤模式清单,本文按落地顺序讲实现。
第一步:从“检索错在哪”反推字段
不要一开始就设计几十个字段。先收集一批检索结果不理想的问题,逐条看错在哪:
- 返回了旧版本文档 → 需要
version或effective_date; - 问 A 产品却返回 B 产品 → 需要
product; - 想找操作步骤却返回了会议纪要 → 需要
doc_type; - 返回了用户无权查看的内容 → 需要
access_group,而且必须强制过滤。
字段宁少勿多,每个字段都要对应一类真实存在的检索错误。 字段的取值也要提前定好枚举,例如产品名统一用规范名称,避免同一产品有三种写法。
第二步:入库时抽取元数据
元数据的来源按可靠程度排序:
- 系统自带:文件路径、所属空间、创建和修改时间、权限组,直接读取;
- 规则提取:文件名或目录中的版本号、文档模板中的固定字段;
- AI 抽取:对没有结构的文档,用模型读取开头部分判断类型和所属产品。
AI 抽取时要限制取值范围,并允许“无法判断”:
请阅读下面文档的开头部分,判断它的元数据,只输出 JSON:
- "product":只能从 【产品A、产品B、产品C、通用】 中选择;无法判断时输出 "unknown";
- "doc_type":只能从 【操作手册、FAQ、发布说明、会议纪要、政策制度】 中选择;无法判断时输出 "unknown";
- "version":文档中明确写出的版本号字符串;没有写出时输出 null,不要推测。
文档开头:
【粘贴前 1–2 页内容】
抽取结果为 unknown 的文档单独列出,由人工补标或抽样检查,不要直接丢弃。权限类字段不建议交给 AI 判断,应来自系统真实的权限设置。
第三步:从问题中解析过滤条件
用户很少会说“请过滤 product=产品A”。常见做法是让模型先从问题里解析条件,再执行检索:
请从用户问题中识别检索过滤条件,只输出 JSON:
- "product":问题中明确提到的产品,取值同上;没有提到输出 null;
- "doc_type":如果问题明显是在问操作步骤,输出 "操作手册";否则输出 null;
- "version":问题中明确提到的版本号,没有提到输出 null。
不要根据猜测填写,宁可输出 null。
用户问题:【问题】
解析结果为 null 的字段不参与过滤。权限过滤则不依赖解析,每次检索都按当前用户的身份强制加上。
第四步:过滤过严时的兜底
过滤最大的风险是把正确答案挡在门外。可以这样设计:
- 过滤后结果太少或相关度都很低时,放宽非强制条件重试(权限条件永远不放宽);
- 默认偏向最新版本,而不是只保留最新版本,用户明确问旧版本时仍能找到;
- 在回答中说明使用了哪些过滤条件,例如“以下内容基于产品A的操作手册”,方便用户发现解析错误。
第五步:评估
准备一组带标准答案来源的问题,分别比较“只做向量检索”和“加元数据过滤”两种方式下,正确文档是否出现在前几条结果中,并单独统计因过滤导致漏召回的问题。没有你自己的数据验证,不要假设过滤一定带来提升。
小结
元数据过滤 = 合理的字段 + 准确的入库标注 + 谨慎的查询解析 + 放宽兜底。它和 混合检索、查询改写等手段可以叠加使用。想看研究场景下如何用 AI 快速筛选资料,可以参考 科研人员用 AI 快速读懂论文和报告。