1. RAG 是什么及适用边界

RAG(Retrieval-Augmented Generation,检索增强生成)不是单纯的“向量数据库问答”,而是一套在生成回答前检索外部资料,并要求模型基于检索证据回答的系统架构。

一个完整的 RAG 系统通常包含:

数据治理
→ 文档解析与索引
→ 查询理解
→ 检索与排序
→ 上下文构建
→ 模型生成
→ 引用验证
→ 评估与监控

RAG 可以使用不同检索器:

  • BM25 或全文关键词检索;
  • 向量语义检索;
  • SQL 或结构化查询;
  • 知识图谱查询;
  • 多种检索方式组合的混合检索。

因此,RAG 不等于向量检索。向量检索只是 RAG 中可选的一条检索通道。

1.1 适合使用 RAG 的场景

  • 数据规模较大,无法每次全部放入上下文;
  • 数据频繁更新,不能只依赖模型训练知识;
  • 用户表达与文档措辞存在明显差异;
  • 回答需要引用原文并支持审计;
  • 不同用户只能访问不同资料;
  • 需要综合多个来源形成回答;
  • 需要控制上下文 Token、延迟与成本。

1.2 不应默认使用 RAG 的场景

场景优先方案
数据量很小且稳定直接使用长上下文
数据高度结构化SQL、API 或规则查询
已知精确编号或术语关键词或精确匹配
固定、确定性的业务逻辑普通工作流或规则引擎
需要修改模型行为风格Prompt 或微调,而不是 RAG

在决定使用 RAG 前,应先回答:

  1. 数据规模和更新频率是多少?
  2. 用户如何表达问题?
  3. 是否需要严格引用和权限控制?
  4. 长上下文、关键词检索或 SQL 是否已经足够?
  5. 什么指标能够证明 RAG 比基线方案更好?

2. 定义业务目标与 Eval 测试集

RAG 开发不应从选择向量数据库开始,而应从业务问题和评估标准开始。

2.1 明确系统任务

需要先定义:

  • 用户是谁;
  • 查询类型有哪些;
  • 哪些资料是权威来源;
  • 什么情况下应该拒答;
  • 回答是否必须附带引用;
  • 允许的延迟和单次成本;
  • 错误回答会产生什么风险。

例如,法律检索系统可能要求:

输入:自然语言案情、法域、案件日期
输出:相关法条、适用版本、引用原文和教学性解释
拒答:缺少法域、日期或权威依据时停止生成确定性结论

2.2 先建立测试集

每条测试数据至少包含:

{
  "query": "用户问题",
  "required_source_ids": ["DOC-001"],
  "acceptable_source_ids": ["DOC-002"],
  "forbidden_source_ids": ["DOC-OLD-001"],
  "metadata_filters": {
    "jurisdiction": "CN",
    "law_as_of_date": "2026-07-28"
  },
  "should_abstain": false
}

测试集应覆盖:

  • 精确术语查询;
  • 口语化查询;
  • 多文档综合问题;
  • 新旧版本冲突;
  • 权限不足;
  • 无答案或应拒答问题;
  • 容易被语义相似资料干扰的问题。

2.3 建立最小基线

推荐至少建立三组基线:

基线 A:关键词/BM25 检索
基线 B:向量检索
基线 C:BM25 + 向量混合检索

没有固定测试集和基线时,无法判断增加查询改写、Reranker 或 Agent 循环后是否真的提升。

2.4 向量数据库如何选型

向量数据库选型很重要,但重要的不是记住某个产品“性能高”或“使用简单”,而是能否从业务约束和实验结果解释取舍。

选型前至少明确:

维度需要回答的问题
数据规模当前和一年后的 Chunk 数量、向量总量是多少?
查询模式纯向量、关键词、Hybrid、范围过滤分别占多少?
元数据过滤是否需要按租户、权限、时间、法域和版本过滤?
更新模式数据是批量导入、频繁更新还是大量删除?
一致性新增、更新和删除后,何时必须对查询可见?
延迟与吞吐P95 延迟、QPS 和并发目标是什么?
运维能力团队能否维护独立集群、备份、扩缩容和监控?
部署约束云服务、内网私有化、单机还是跨地域?
成本存储、索引、计算、网络和人力成本是多少?
现有技术栈是否已经使用 PostgreSQL 或 Elasticsearch/OpenSearch?

常见选择及适用起点:

方案更适合的情况需要警惕
FAISS/Chroma本地实验、小规模原型权限、持久化、分布式和运维能力有限
PostgreSQL + pgvector已有 PostgreSQL、数据规模中等、事务与业务数据关系紧密大规模混合检索和水平扩展需要额外验证
OpenSearch/Elasticsearch已有搜索栈、BM25与向量混合检索、复杂元数据过滤集群资源和运维成本较高
Qdrant向量检索为主、过滤能力重要、希望独立向量服务关键词搜索和已有数据体系的集成需评估
Milvus/Weaviate等大规模向量、独立检索基础设施系统复杂度和团队维护成本更高
托管向量服务希望快速上线且可接受数据出域和持续费用厂商锁定、价格、网络和隐私约束

选择过程应包含相同数据和查询集上的最小实验:

固定文档与Embedding
→ 导入候选数据库
→ 测试Recall@K与过滤正确性
→ 测试P50/P95延迟和吞吐
→ 测试新增、更新、删除与重建索引
→ 估算资源和运维成本
→ 根据当前约束选择最简单的可满足方案

数据库不会直接提高语义质量。只要使用相同向量和近似搜索参数,不同数据库首先影响的是索引能力、过滤、延迟、扩展性和运维,而不是模型是否“理解”文档。

2.5 Embedding 模型如何选型

Embedding 决定查询和文档如何进入同一个语义空间,对召回质量通常比更换向量数据库更直接。

选型需要评估:

维度说明
语言中文、英文、多语言及混合文本表现
领域通用、法律、医疗、代码等领域适配度
查询类型短查询、长问题、专业术语和口语表达
最大输入长度长条款或长段落是否被截断
向量维度影响索引大小、内存、延迟和迁移成本
检索范式是否区分 Query/Document 前缀或支持非对称检索
部署方式API、本地CPU、本地GPU或内网服务
成本与延迟批量索引成本和在线查询延迟
数据安全文档是否允许发送到第三方API
版本稳定性模型升级后是否能继续使用旧向量

不要仅根据公开榜单选Embedding。公开基准不能完全代表自己的数据、切分策略和查询分布。

推荐实验流程:

准备人工标注的Query-Document集合
→ 固定Chunk和向量数据库
→ 分别生成候选Embedding
→ 比较Recall@5、Recall@10、MRR和nDCG
→ 比较专业术语、口语查询和困难负样本
→ 记录索引体积、查询延迟和成本
→ 再决定模型

至少准备三类困难样本:

  • 关键词不同但语义相同;
  • 关键词高度相似但实际不相关;
  • 新旧版本、否定条件或例外条款只有细微差异。

Embedding 升级不是修改一个模型名。不同模型的向量空间通常不兼容,需要:

  • 记录 embedding_modelembedding_version
  • 创建新索引或新向量字段;
  • 重新向量化全部受影响 Chunk;
  • 使用固定 Eval 对比新旧版本;
  • 完成切换后再下线旧索引;
  • 保留回滚方案。

面试回答可以采用:

候选模型A在公开中文检索基准上较强,但我没有直接采用。
我使用项目中的N条查询进行对比,重点测试专业术语、口语表达和错误版本干扰。
模型B的Recall@5由X提升至Y,P95延迟增加Z毫秒,向量存储增加W%,
在当前数据规模和延迟预算内收益可接受,因此选择B。

如果没有做过对比实验,应明确说这是“基于约束的初始选择”,不能将个人经验包装成已验证结论。


3. 离线知识库构建

离线阶段负责把原始资料转换成可检索、可过滤、可追溯的知识索引。

完整流程:

数据收集
→ 来源、授权与权限校验
→ 清洗、去重和格式标准化
→ 结构化解析
→ 文档分块
→ 元数据与版本管理
→ Embedding
→ 关键词索引与向量索引
→ 索引质量检查

3.1 数据来源、授权与权限

每份文档都应记录:

  • 来源和原始 URL;
  • 作者或发布机构;
  • 获取时间;
  • 使用授权;
  • 文档所属租户或权限范围;
  • 是否包含敏感信息;
  • 是否经过人工审核。

生产系统不能先把所有资料交给模型,再通过 Prompt 要求模型“不要泄露”。权限过滤必须在检索前完成。

3.2 数据清洗和去重

随着文档规模增加,重复内容、解析错误、无效模板和冲突版本会占据检索候选位置,并增加索引及生成成本。数据清洗通常是最具性价比的优化之一。

常见清洗内容:

  • HTML 导航栏、页脚和广告;
  • OCR 乱码和异常字符;
  • 空白页和重复页面;
  • 重复标题与模板文本;
  • 无效表格和图片占位符;
  • 已失效或冲突版本;
  • 密钥、个人信息等敏感数据;
  • 文档中的提示注入或指令性文本。

建议使用内容哈希识别完全重复文档,再结合标题、来源和语义相似度识别近似重复文档。

3.3 结构化解析与分块

固定长度切分可以作为基线,但不应默认是最终方案。分块策略必须与文档结构和检索 Eval 对齐。

策略适用场景主要风险建议关注指标
固定长度格式统一的纯文本基线破坏语义边界Recall@K、Token
标题/章节分块结构清晰的文档块大小不均Recall@K、上下文长度
父子分块法律、技术手册索引和回溯复杂召回率、引用完整度
滑动窗口叙事性长文档存储和内容重复去重率、Token
符号分块代码仓库跨符号依赖可能丢失相关符号召回率

对于普通文本,可以从 300~500 Token、50~100 Token 重叠开始实验,但这不是通用最佳参数。

领域数据应优先按照天然结构切分:

法律:法律文件 → 编 → 章 → 节 → 条 → 款 → 项
代码:仓库 → 模块 → 类 → 函数
技术文档:产品 → 版本 → 章节 → 小节

父子分块的基本思路:

小块负责精确检索
→ 找到相关小块
→ 返回包含完整语义的父块给模型

3.4 元数据和版本管理

每个 Chunk 至少应保存:

{
  "chunk_id": "CHUNK-001",
  "document_id": "DOC-001",
  "title": "文档标题",
  "section_path": ["第三章", "第一节"],
  "source_url": "https://example.com",
  "created_at": "2026-01-01",
  "effective_from": "2026-01-01",
  "effective_to": null,
  "status": "effective",
  "tenant_id": "TENANT-001",
  "allowed_roles": ["student"],
  "version_hash": "...",
  "embedding_version": "..."
}

元数据用于权限过滤、时间和版本过滤、增量索引、来源展示与引用回溯。

3.5 关键词索引与向量索引

关键词索引适合人名、机构名、法条编号、代码符号、产品型号、专有术语和错误信息。

向量索引适合用户使用口语化表达、查询与文档措辞不同、需要语义匹配的场景。

二者通常互补,而不是相互替代。

3.6 增量更新与删除

知识库需要处理:

  • 新文档新增;
  • 原文修改;
  • 文档删除;
  • 权限变化;
  • 新旧版本并存;
  • Embedding 模型升级。

可以使用内容哈希判断哪些 Chunk 需要重新解析和向量化。删除文档时必须同步删除关键词索引、向量索引和缓存,避免“幽灵文档”继续被召回。


4. 在线检索与生成

完整在线流程:

用户查询
→ 查询分类与风险检查
→ 权限、法域、时间等元数据约束
→ 判断是否需要检索
→ 查询改写或拆解
→ 多路召回
→ 融合与去重
→ 重排序
→ 上下文构建
→ 结构化生成
→ 引用验证
→ 输出或拒答
→ 保存检索轨迹

4.1 查询理解

查询理解的目标不是直接回答问题,而是生成适合检索的结构化查询。

常见操作包括意图分类、实体提取、Query Rewrite、Multi-Query、Query Decomposition 和 HyDE。

原始查询必须始终保留。查询改写可能引入模型臆测,不能无条件替代用户原意。

例如:

用户问题:偷拿手机后来又还了,还算盗窃吗?

结构化查询:
- 法域:中华人民共和国
- 案由候选:盗窃
- 争议事项:非法占有目的
- 事实变量:取走、归还、主观目的

查询改写、HyDE 和 Multi-Query 都是可选优化。只有基线测试证明存在“表达差异导致召回失败”时才应加入。

4.2 元数据与权限过滤

检索前应尽量缩小候选范围:

用户身份
→ 可访问租户和文档
→ 文档类型
→ 时间和版本
→ 业务域或法域
→ 执行检索

过滤必须发生在检索层,不能只在生成 Prompt 中声明权限。

4.3 多路召回

多路召回优先保证“不要漏掉正确资料”。典型方案:

BM25 召回 Top 20
+ 向量召回 Top 20
→ 合并候选

BM25 擅长精确术语,向量检索擅长语义表达。对于法律、代码和产品文档,混合检索通常比纯向量检索更值得优先评估。

4.4 融合与去重

不同检索器的原始分数通常不在同一尺度上,不能直接比较。

常用融合方法:

  • 归一化后加权;
  • Reciprocal Rank Fusion(RRF);
  • 合并去重后统一交给 Reranker。

MVP 可以从 RRF 开始:

BM25 Top 20
+ Vector Top 20
→ RRF 融合
→ 去重
→ 候选 Top 20

4.5 重排序

召回阶段关注召回率,重排序阶段关注精确率。

Reranker 通常使用 Cross-Encoder 对 [查询, 文档] 对进行更细致的相关性评分,再保留 Top 3~5 个片段进入上下文。

可选方案:

  • 中文或私有部署:BGE 系列 Reranker;
  • 托管服务:Cohere 等 Rerank API;
  • 垂直领域:先建立通用模型基线,积累标注数据后再考虑领域微调。

Reranker 会增加延迟和成本,而且无法补救召回阶段完全漏掉的文档。是否有效必须通过排序指标验证。

4.6 上下文构建

不能将检索结果简单拼接后全部发送给模型。上下文构建需要:

  • 去除重复和近似重复片段;
  • 保留来源、标题和定位信息;
  • 补充必要的父块或相邻条款;
  • 根据相关性和效力排序;
  • 控制总 Token 预算;
  • 将事实资料与不可信指令分离;
  • 对冲突版本进行明确标记。

建议格式:

[SOURCE: DOC-001 / SECTION-03]
原文……

[SOURCE: DOC-002 / SECTION-08]
原文……

4.7 结构化生成与引用验证

Prompt 可以要求模型只根据上下文回答,但 Prompt 是软约束,不能作为可靠性边界。

建议输出结构:

{
  "status": "supported",
  "answer": "回答内容",
  "citations": [
    {
      "source_id": "DOC-001",
      "supporting_quote": "原文引用"
    }
  ],
  "uncertainties": []
}

程序层必须检查:

  • source_id 是否来自本次检索结果;
  • 引文是否真实存在于原文;
  • 文档版本是否适用于当前问题;
  • 用户是否有权访问该来源;
  • 引用是否能够支持对应结论。

4.8 拒答与降级

当资料不足、版本冲突或权限受限时,系统应拒绝生成确定性答案:

{
  "status": "insufficient_context",
  "answer": null,
  "citations": [],
  "missing_information": ["缺少适用日期"]
}

拒答不是失败,而是高风险 RAG 系统的重要能力。


5. RAG Eval

RAG Eval 应在基础链路跑通后立即建立,而不是等到所有优化完成后再补。

5.1 检索层评估

指标含义
Recall@K正确文档是否进入前 K 条结果
Precision@K前 K 条结果中相关文档的比例
MRR第一个正确结果的排名质量
nDCG@K综合考虑不同相关等级和排名
Filter Accuracy权限、时间和版本过滤是否正确
Wrong-Version Rate错误版本被召回的比例

5.2 生成层评估

  • Faithfulness:回答是否被上下文支持;
  • Answer Relevance:回答是否解决用户问题;
  • Citation Correctness:引用是否真实且支持结论;
  • Citation Completeness:关键结论是否都有引用;
  • Abstention Accuracy:无依据时是否正确拒答;
  • Conflict Handling:资料冲突时是否明确呈现不确定性。

LLM-as-Judge 可以用于软质量评分,但必须抽样人工复核。引用存在性、权限、版本和结构化格式等硬约束应由程序判断。

5.3 系统层评估

  • P50/P95 延迟;
  • 单次查询输入和输出 Token;
  • Embedding 与生成成本;
  • 索引更新时间;
  • 缓存命中率;
  • 检索失败率;
  • 超时和重试次数。

5.4 实验原则

  1. 固定测试集和基线;
  2. 每次只修改一个主要变量;
  3. 保存查询、过滤条件、召回结果和最终回答;
  4. 同时记录质量、成本和延迟;
  5. 不用少量人工体验代替批量评估;
  6. 新方案没有稳定提升时不增加生产复杂度。

6. 常见失败与排查

失败类型典型现象优先检查
数据失败文档乱码、重复或版本错误解析、清洗、数据源
分块失败正确知识被切断Chunk 边界、父子块
召回失败正确文档不在 Top-K查询、索引、Embedding
排序失败正确文档已召回但排名低融合、Reranker
过滤失败召回无权限或错误版本文档元数据、过滤顺序
上下文失败正确资料进入 Prompt 但被忽略去重、顺序、Token预算
生成失败上下文正确但回答错误Prompt、模型、Schema
引用失败回答与引用不一致引用绑定、原文校验
拒答失败无资料时仍强行回答置信度和停止条件

推荐排查顺序:

检查原始数据
→ 检查正确文档是否被召回
→ 检查排序位置
→ 检查进入模型的最终上下文
→ 检查模型输出
→ 检查引用验证

不要看到最终答案错误就直接修改 Prompt。很多问题实际发生在数据和检索阶段。


7. 进阶优化

只有基础检索、引用验证和 Eval 稳定后,才评估以下优化。每项优化都应对应一个已经观察到的失败类型。

7.1 Query Rewrite

适用于用户口语与文档术语不一致的情况。必须保留原查询,并评估改写是否改变原意。

7.2 Multi-Query 与 RAG-Fusion

将问题扩展成多个互补查询,分别检索后再融合结果,可以提高复杂问题的召回率。

风险包括查询偏离原问题、重复召回、成本增加和引入错误假设。

7.3 Agentic Retrieval

Agent 可以决定:

  • 是否需要检索;
  • 应查询哪类数据源;
  • 是否拆分问题;
  • 当前证据是否充分;
  • 是否需要继续检索或请求人工帮助。

必须设置最大检索轮数、查询数量、Token与金额预算、查询去重和停止条件。

7.4 领域模型微调

只有积累了稳定的 Query-Document 相关性数据,并证明通用 Embedding 或 Reranker 存在系统性领域误差后,才考虑领域微调。

不应直接用业务 Chunk 盲目微调,而应准备正样本、困难负样本和独立验证集。

7.5 对话记忆

多轮问答时,应先将历史对话改写成独立查询,再进行检索。不要直接把全部聊天历史拼入检索查询或生成上下文。


8. 生产化:权限、监控、成本和更新

8.1 权限安全

  • 在检索前过滤用户无权访问的文档;
  • 不依赖模型自觉保密;
  • 文档内容视为不可信输入;
  • 对敏感操作保留审计日志;
  • 多租户数据必须隔离。

8.2 可观测性

每次请求应保存:

原始查询
改写查询
元数据过滤条件
各检索通道结果与分数
融合和重排结果
最终上下文
模型输出
引用校验结果
Token、成本、延迟和错误

8.3 成本控制

  • 缓存稳定查询和 Embedding;
  • 使用内容哈希避免重复向量化;
  • 控制召回候选和 Reranker 数量;
  • 去重后再进入模型;
  • 设置上下文 Token 预算;
  • 简单查询优先使用关键词或结构化查询;
  • 复杂查询才启用查询扩展和多步检索。

8.4 数据与索引更新

需要设计定时同步、失败重试、新旧版本切换、索引重建、Embedding版本迁移、回滚策略和删除资料后的索引清理。


9. 场景选择:长上下文、关键词、RAG 与 LLM Wiki

这些方案不是互斥关系,而是处于不同层级。

方案主要作用适合场景主要风险
长上下文直接读取完整资料数据少、单文档分析成本、延迟、注意力衰减
关键词检索精确查找术语法条、代码、产品型号口语表达召回不足
向量检索语义匹配自然语言与文档措辞不同语义相似但业务不适用
Hybrid RAG精确与语义结合专业知识问答系统复杂度增加
LLM Wiki整理知识和导航中等规模团队知识二次整理可能失真

9.1 选择顺序

数据很少且稳定 → 长上下文
查询和数据高度结构化 → SQL/API
查询包含精确术语 → 关键词/BM25
用户表达口语化 → 向量检索
精确术语和语义都重要 → Hybrid RAG
知识需要持续整理和人工维护 → LLM Wiki + 原始资料链接
任务需要主动、多步取证 → Agentic Retrieval

9.2 LLM Wiki 与 RAG 的组合

LLM Wiki 可以作为知识导航和解释层,但不能替代原始事实来源:

原始资料层:权威原文
→ Wiki层:主题摘要、目录和关系链接
→ 检索层:关键词、向量或混合检索
→ 生成层:带引用回答

高风险场景中的最终结论必须回到原始资料,不能只引用 Wiki 的二次总结。


10. 推荐实施路线

第1步:准备小规模数据和固定测试集
第2步:建立BM25基线
第3步:在固定数据库上对比Embedding模型
第4步:根据规模、过滤、延迟和运维约束选择检索后端
第5步:增加向量检索并与BM25对比
第6步:实现混合检索与去重
第7步:实现结构化生成和引用验证
第8步:建立检索、生成和系统Eval
第9步:根据失败类型增加Reranker或查询改写
第10步:确有多步检索需求时再增加Agent

学习和工程优先级:

数据质量
> Eval测试集
> 关键词和混合检索
> 引用验证
> 上下文工程
> 权限与版本管理
> Agentic Retrieval
> 更换向量数据库

RAG 的真正能力不在于接入了哪个向量数据库,而在于能否回答:

  • 为什么使用这种分块策略?
  • 为什么选择这个向量数据库,它解决了哪些明确约束?
  • 对比过哪些Embedding,使用了什么数据集和指标?
  • 正确资料是否进入 Top-K?
  • 为什么选择关键词、向量或混合检索?
  • Reranker 带来了多少提升和延迟?
  • 旧版本和无权限文档如何过滤?
  • 回答中的引用是否真实支持结论?
  • 检索不足时系统能否正确拒答?
  • 每次优化是否通过固定测试集得到验证?

只有这些问题可观测、可评估、可复现时,RAG 系统才从演示进入工程阶段。