RAG 细节与优化理解
本文是 RAG 系列第二篇。第一篇已经介绍了文档处理、分块、Query、召回和重排的完整流程,本文不再重复基础概念,重点理解 Bi-Encoder、Cross-Encoder 的工作方式,以及如何定位和优化 RAG 检索效果。
一、RAG 优化的基本思路
RAG 的效果不是由某一个模型单独决定的,而是由多个环节共同影响:
数据质量 → Chunk 质量 → Query 质量 → 召回质量 → 排序质量 → 生成质量第一篇已经分别介绍了这些环节的基本方法。本文重点关注其中最容易混淆、也最影响检索效果的两个模型架构:
Bi-Encoder → 负责快速召回候选 Cross-Encoder → 负责对候选进行精细排序优化时不要一开始就更换大模型,而应先根据问题表现判断故障环节:是相关内容没有被召回,还是已经召回但排序靠后,或者上下文已经正确但模型没有正确利用。
二、Bi-Encoder 与 Cross-Encoder:从召回到重排
2.1 Bi-Encoder:结构、速度与优缺点
2.1.1 Bi-Encoder 的基本结构
Bi-Encoder(双编码器)将 Query 和 Document 分别编码成向量,然后通过余弦相似度或点积计算相关性:
Query → Query Encoder → Query Vector Document → Document Encoder → Document Vector Similarity(Query Vector, Document Vector) ↓ Top-K 候选Query 和 Document 在编码阶段互相独立,模型不会对两段文本进行逐 Token 的交互。文档向量可以在离线阶段提前计算,并建立 HNSW、IVF 等 ANN 索引;在线阶段只需要计算 Query 向量并搜索相近向量。
2.1.2 Bi-Encoder 为什么速度快
假设知识库中有 100 万个 Chunk:
离线阶段:100 万个 Document → Embedding → 100 万个文档向量 在线阶段: 1 个 Query → 1 个 Query 向量 Query 向量 → ANN 索引 → Top-K 候选文档向量不需要在每次查询时重新计算,因此 Bi-Encoder 能够支持大规模检索。向量数据库的作用,就是保存这些向量并通过 ANN 索引高效完成近似最近邻搜索。
2.1.3 Bi-Encoder 的优势与局限
| 优势 | 原因 |
|---|---|
| 检索速度快 | Query 和 Document 分开编码,文档向量可以离线计算 |
| 支持大规模数据 | 可以使用 HNSW、IVF、PQ 等 ANN 索引 |
| 易于扩展 | 支持批量计算、分布式向量检索和多路召回 |
| 语义泛化能力较好 | 能够匹配不同表达方式的相似语义 |
| 局限 | 具体表现 |
|---|---|
| 整体向量可能淹没局部证据 | 文档大部分内容无关时,少量关键句可能被稀释 |
| 容易受到近义干扰 | 主题相近但不能回答问题的文档可能得分较高 |
| 对细粒度条件不够敏感 | 年份、版本号、否定词和数字差异可能被弱化 |
| 依赖 Chunk 质量 | Chunk 过大或语义混杂会影响向量表示 |
例如,Query 要求“2025 年版本的国标”,2020 年版本的文档可能与 Query 具有很高的语义相似度,但并不满足时间条件。这类问题通常需要 BM25、元数据过滤或 Cross-Encoder 进一步处理。
2.1.4 Embedding 与 Bi-Encoder 的关系
Embedding 和 Bi-Encoder 经常被混用,但它们描述的不是同一个层面:
| 概念 | 本质 | 关注点 |
|---|---|---|
| Embedding | 文本经过模型编码后得到的向量表示,也可以指向量化过程 | 输出是什么向量 |
| Bi-Encoder | 分别编码 Query 和 Document 的模型架构 | 向量如何生成 |
简单来说,Embedding 是结果或过程,Bi-Encoder 是生成结果的模型架构。在 RAG 中,BGE、E5、GTE、Qwen3-Embedding 等语义 Embedding 模型通常采用 Bi-Encoder 思路:Query 和 Document 分别经过编码器得到向量,再通过相似度进行检索。文档向量可以离线计算,Query 向量则在用户查询时实时计算。
Bi-Encoder:生成 Query 向量和 Document 向量的模型架构 Embedding:模型输出的向量表示,或生成向量的过程 向量数据库:保存向量并执行相似度检索需要注意,Embedding 不一定都用于 RAG,也可以用于文本分类、聚类、相似度计算和推荐系统;Bi-Encoder 也不等于某一个具体模型名称,而是一类独立编码 Query 和 Document 的架构。
2.2 Cross-Encoder:为什么适合精细排序
2.2.1 Cross-Encoder 的基本结构
Cross-Encoder 将 Query 和 Document 拼接后一起输入模型,让两者在 Transformer 的注意力层中进行 Token 级交互,并直接输出相关性分数:
[Query, Document 1] → Cross-Encoder → Score 1 [Query, Document 2] → Cross-Encoder → Score 2 [Query, Document 3] → Cross-Encoder → Score 3 ↓ 重新排序它判断的不是“Query 和 Document 整体像不像”,而是“Document 中是否存在真正回答 Query 的证据”。因此,它更擅长处理局部证据、实体、年份、版本、数字和限定条件。
2.2.2 Cross-Encoder 为什么更准确但更慢
Bi-Encoder 可以提前计算所有文档向量,而 Cross-Encoder 必须对每一个 Query-Document 组合单独推理:
Bi-Encoder: Query → 1 个向量 → 与索引中的文档向量进行相似度搜索 Cross-Encoder: Query + Doc1 → 推理一次 Query + Doc2 → 推理一次 Query + Doc3 → 推理一次因此,Cross-Encoder 不适合直接扫描百万级知识库。典型做法是:先通过 BM25、向量检索或混合召回得到 Top 50~1000,再使用 Cross-Encoder 处理这批候选,最后选出 Top 5~20 进入 Prompt。
2.2.3 常见重排模型
常见的 Cross-Encoder / Reranker 包括:
- BGE Reranker:中文和多语言 RAG 中常用,可选择不同规模;
- Jina Reranker:适合多语言和较长文本场景;
- Mixedbread Reranker:提供不同规模模型,便于在效果和速度之间取舍;
- Cross-Encoder MS MARCO:Sentence-Transformers 生态中常用的英文基线模型;
- Cohere Rerank:云端 Rerank API,适合快速接入。
模型选择需要结合语言、候选数量、上下文长度、显存、延迟和部署方式进行评测,不能只根据模型名称判断效果。
2.3 Bi-Encoder、Cross-Encoder 与 RAG 检索链路
2.3.1 标准检索链路
用户 Query ↓ Query 理解 / 改写 ↓ BM25、Dense 或 Hybrid Recall ↓ 候选集 Top 50~1000 ↓ Cross-Encoder Rerank ↓ Top 5~20 高质量 Chunk ↓ Prompt → LLM两种模型的职责可以概括为:
Bi-Encoder:从海量文档中“找得到” Cross-Encoder:从候选文档中“排得准”2.3.2 召回、粗排、精排与业务重排
严格的搜索系统可能区分召回、粗排、精排和业务重排:
- 召回:从全量文档中快速找出候选,强调覆盖率;
- 粗排:对较大候选集进行低成本筛选,很多 RAG 系统将它并入召回;
- 精排:使用 Cross-Encoder 等模型,对候选进行更准确的语义打分;
- 业务重排:根据时间、权限、来源可信度、热度和业务优先级调整结果。
在很多 RAG 项目中,“Rerank”通常泛指模型精排,但严格来说,Cross-Encoder 精排和业务规则重排并不是同一件事。
三、关键参数与实验优化
3.1 Chunk Size 与 Overlap
Chunk Size 会同时影响向量表示、召回粒度、上下文完整性和 Token 成本:
| 参数过小 | 参数过大 |
|---|---|
| 检索粒度更细 | 上下文更完整 |
| 可能丢失上下文 | 噪声和 Token 成本增加 |
| Chunk 数量更多 | 相关信息可能被无关内容稀释 |
Chunk Size 不存在通用最优值。可以选择 256、512、1024 等候选范围,使用覆盖业务场景的问题集进行对比,观察 Recall@K、Context Precision、Context Recall 和最终答案质量。Overlap 用于缓解边界截断,但过大可能造成索引膨胀和重复上下文。
3.2 召回与重排参数
常见需要实验的参数包括:
- BM25 与向量召回的权重;
- 各召回通道的 Top-K;
- RRF 的
k值和融合方式; - 送入 Reranker 的候选数量;
- 最终送入 Prompt 的 Chunk 数量;
- 元数据过滤和权限过滤条件;
- 是否启用 Query Rewrite、Multi-Query 或 HyDE。
参数调整不应只观察最终答案,要分别记录“正确 Chunk 是否被召回”“正确 Chunk 是否排在前面”“答案是否忠实于上下文”。
3.3 常见问题与定位方式
| 问题表现 | 更可能的原因 | 优化方向 |
|---|---|---|
| 找不到相关内容 | Query 表达差异大、关键词缺失、召回范围过小 | Query Rewrite、Multi-Query、Hybrid Search、提高 Top-K |
| 结果相关但不完整 | Chunk 太小、跨块关系丢失、召回覆盖不足 | Parent-Child、增大 Chunk、补充标题和表头 |
| 结果很多但噪声大 | Chunk 太大、过滤不足、召回范围过宽 | 元数据过滤、降低 Top-K、增加 Rerank |
| 相关 Chunk 已召回但排在后面 | 向量相似度无法识别细粒度条件 | Cross-Encoder、BM25、字段加权 |
| 答案没有依据 | 上下文不足、Prompt 约束弱或模型自由发挥 | 保留来源、要求引用、设置无答案策略 |
| 多轮对话答非所问 | 指代未消解、历史上下文过长或缺失 | Context Completion、会话摘要、Query Rewrite |
| 响应速度慢 | 召回候选过多、Reranker 过大或链路过长 | 减少候选、使用小模型、缓存、分层检索 |
3.4 评测驱动的优化闭环
RAG 优化不应依赖主观感受,而应建立固定测试集,记录每次调整前后的指标:
准备业务问题集和参考答案 ↓ 分别评估召回、重排和生成 ↓ 定位最先出现问题的环节 ↓ 只调整一个或一组相关参数 ↓ 重新评测并保留实验记录例如:
- Recall@K 低:优先检查 Query、Chunk、Embedding 和召回策略;
- Context Precision 低:优先检查召回噪声、RRF 和 Reranker;
- Faithfulness 低:优先检查上下文组织、Prompt 约束和生成模型;
- Answer Relevancy 低:优先检查 Query 理解、问题改写和回答格式。
四、小结
第二篇的核心结论是:
Bi-Encoder 负责高效召回 Cross-Encoder 负责精细判断 RAG 优化需要通过实验和评测定位问题分块、Query 和召回策略决定候选集质量,Bi-Encoder 与 Cross-Encoder 决定检索和排序效率,最终还需要结合评测指标持续迭代。
个人声明:本文内容是个人在学习、实践和工程探索过程中的整理与理解,文中涉及的模型、参数和优化建议仅供参考。RAG 的实际效果会受到数据类型、业务目标、模型版本、部署环境和评测数据集影响,具体方案应以真实实验和项目结果为准。本文会持续更新,后续将补充更多工程落地经验,包括参数选择、延迟与成本权衡、召回和重排问题排查,以及真实项目中的优化案例。