RAG 系统设计:从检索链路到生成可信度¶
本章导读¶
检索增强生成(Retrieval-Augmented Generation,RAG)是大模型应用中出现频率最高的架构之一,但“能跑通”和“可上线”之间隔着解析、切分、召回、重排、评估等一整条链路。
本章按数据流向拆解 RAG 的每个环节,重点讲清楚参数取舍、失败模式与评估方法,而不是罗列组件。
阅读时建议把“检索质量决定上限、生成策略决定下限”作为主线:大多数幻觉与答非所问,根因在检索而非模型。
文中的规模、延迟、成本数字均为量级估算,具体以实际压测和公开资料为准。
核心要点¶
- RAG 解决的是“模型参数里没有的知识”和“需要可追溯来源”的问题,不解决推理能力不足。
- 链路上游的解析与切分质量,往往比换一个更强的 embedding 模型收益更大。
- 切分要区分“检索单元”和“生成单元”,父子块是兼顾两者的常用手段。
- 混合检索(稀疏 + 稠密)加倒数排名融合(Reciprocal Rank Fusion,RRF)是性价比很高的默认方案。
- 重排(rerank)用小模型换大收益,典型做法是召回百级、重排十级、生成取三到五条。
- 评估必须拆成检索指标与生成指标,只看最终答案好坏无法定位问题。
- 上线前要建立按问题类型分层的评测集,并把拒答与引用准确率纳入指标。
1. RAG 的动机与适用边界¶
1.1 为什么需要 RAG¶
大语言模型(Large Language Model,LLM)的知识来自训练语料,存在三个结构性限制:训练截止时间导致知识过期;私有数据从未进入参数;生成过程缺乏事实依据,容易产生幻觉(hallucination)。RAG 的思路是在生成前从外部知识库检索相关片段,把证据放进上下文,让模型“开卷答题”。
它带来的收益包括:知识可热更新,不必重新训练;答案可附引用,便于审计;敏感数据可以留在自有向量库;相比把全部文档塞进上下文,token 成本更可控。
1.2 适用边界¶
RAG 适合:企业知识库问答、客服、文档助手、法规与工单检索、需要引用来源的研究辅助。它不适合:需要复杂多步推理且证据分散的任务(要配合 Agent 或工具)、实时性要求毫秒级的场景、知识库本身质量极差且无法治理的场景、以及主要矛盾是“模型不会推理”而非“模型不知道”的场景。
一个常见误区是把 RAG 当成万能补丁。如果评测显示模型在给定正确上下文时仍答错,那么问题在推理或指令遵循,应该考虑换模型、微调或拆解任务,而不是继续调检索。
1.3 RAG、长上下文、微调、搜索的对比¶
| 维度 | RAG | 长上下文(Long Context) | 微调(Fine-tuning) | 传统搜索(Search) |
|---|---|---|---|---|
| 知识新鲜度 | 高,改库即生效 | 高,但每次都要塞入 | 低,需重新训练 | 高 |
| 私有数据 | 适合 | 适合小规模 | 数据进入参数,需合规评估 | 适合 |
| 单次成本 | 中,检索加有限上下文 | 高,token 随长度线性增长 | 训练成本高,推理成本低 | 低 |
| 延迟 | 中,多一次检索与重排 | 较高,首 token 延迟明显 | 低 | 低 |
| 可追溯性 | 强,可给引用 | 中,取决于是否保留来源 | 弱 | 强 |
| 能力改变 | 只补知识 | 只补知识,受限于注意力稀释 | 可改变风格、格式、领域行为 | 不涉及生成 |
| 典型风险 | 召回失败、噪声 | 中间信息丢失、成本失控 | 灾难性遗忘、过拟合 | 无法直接回答自然语言问题 |
实践中的组合方式通常是:用搜索或 RAG 获取证据,用长上下文承载多篇材料,用微调固化输出格式与领域语气。四者不是互斥选项,而是不同层的工具。
2. 全链路总览¶
RAG 分为离线建库与在线服务两条链路。离线链路追求质量与可重建性,在线链路追求延迟与稳定性。
| 阶段 | 输入 | 关键动作 | 输出 | 主要指标 |
|---|---|---|---|---|
| 文档解析 | PDF、Word、HTML、扫描件 | 版面分析、OCR、表格还原 | 结构化文本 | 字符准确率、表格还原率 |
| 清洗 | 原始文本 | 去页眉页脚、去重、归一化 | 干净语料 | 噪声率、重复率 |
| 切分 | 长文档 | 按结构或语义切块 | 文本块(chunk)集合 | 平均长度、边界完整率 |
| 向量化 | chunk | 调用向量化(embedding)模型 | 向量 | 维度、归一化方式 |
| 索引 | 向量与元数据 | 建立近似最近邻索引 | 可检索库 | 建库耗时、召回率 |
| 查询理解 | 用户问题与对话 | 改写、指代消解、意图识别 | 检索查询(query) | 改写命中率 |
| 召回 | query | 稀疏与稠密多路检索 | 候选集 | Recall@k |
| 重排 | 候选集 | 交叉编码器精排 | Top-N | nDCG@N |
| 上下文组装 | Top-N 文档 | 去重、排序、压缩 | 提示词(prompt)上下文 | 有效 token 占比 |
| 生成 | 上下文与问题 | 受控解码、引用标注 | 答案 | 忠实度、答案相关性 |
| 引用 | 答案与文档 | 对齐句子与来源 | 引用列表 | 引用准确率 |
在线链路的时间预算要做显式分配。以一次问答 3 秒为目标(估算),解析与 embedding 查询约 50 至 150 毫秒,向量检索约 10 至 50 毫秒,重排 20 条约 50 至 200 毫秒,生成占剩余大部分(以上均为量级估算)。任何一环没有超时与降级策略,都会拖垮整体可用性。
3. 文档解析与清洗¶
3.1 PDF 与版面分析¶
PDF 分两类:带文本层的电子版与扫描件。电子版优先直接抽取文本,但必须处理多栏、页眉页脚、脚注、图文混排的阅读顺序。常见做法是先做版面分析(layout analysis),识别标题、正文、表格、图片区域,再按阅读顺序拼接。直接按坐标从上到下抽取,在多栏文档中会把左右栏交错误读。
扫描件需要光学字符识别(Optical Character Recognition,OCR)。流程通常是:图像预处理(去噪、纠偏、二值化)→ 文字检测 → 文字识别 → 后处理(词典纠错、版面回填)。评估 OCR 质量可用字符错误率(Character Error Rate,CER):
其中 \(S\)、\(D\)、\(I\) 分别为替换、删除、插入字符数,\(N\) 为参考字符总数。中文场景下 CER 低于 5% 通常可接受(经验阈值,估算),但专有名词和数字的错误更致命,需要单独抽样检查。
3.2 表格与图片¶
表格是 RAG 的高频失败点。可行策略有三类:把小表转为 Markdown 或 HTML 保留结构;按行切分并为每行重复表头,形成“字段名: 值”的自解释文本;对大表先做摘要,再保留原始表格的定位信息供回查。金额、日期、单位必须在清洗阶段统一格式,否则检索到了也无法正确比较。
图片中的信息应先做图注或 OCR,不应把图片二进制直接交给文本 embedding。若使用多模态模型,可为图片生成描述文本,并与原图建立引用关系。
3.3 清洗规则¶
清洗不是越干净越好,而是去掉会干扰检索、保留会改变语义的内容。常见规则包括:删除重复页眉页脚与页码;合并被硬换行打断的句子;统一全角半角、繁简与单位;去除导航栏、版权声明等模板文本;对近乎重复的文档做指纹去重(如 MinHash、SimHash);对个人身份信息(Personally Identifiable Information,PII)做脱敏或隔离。
清洗后要保留元数据:来源、标题、章节路径、发布时间、权限标签、页码或锚点。这些字段既用于过滤,也用于最终引用。缺少页码锚点,用户点开引用后无法定位原文,体验会明显下降。
4. 切分策略¶
4.1 五种常用策略¶
| 策略 | 做法 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| 固定长度 | 按 token 数硬切,带 overlap | 实现简单、块大小均匀 | 容易切断句子与表格 | 快速基线 |
| 递归切分 | 按段落、句子、字符逐级回退 | 尽量保留自然边界 | 结构复杂时仍会切碎 | 通用默认 |
| 语义切分 | 计算相邻句向量相似度,在低点断开 | 主题完整 | 成本高、阈值难调 | 长论述、报告 |
| 父子块 | 子块检索,返回父块生成 | 检索精准且上下文完整 | 存储与映射复杂 | 问答、法规 |
| 按结构切分 | 依据标题层级、代码块、表格切 | 可解释、保留层级 | 依赖解析质量 | 手册、文档站 |
递归切分是最常用的默认方案:先按标题或段落切,超长再按句子切,仍超长才按字符切。语义切分用相邻句的余弦相似度找“主题断崖”,但相似度阈值对领域敏感,通常需要标注少量数据校准。
4.2 chunk size 与 overlap 的取舍¶
块太小,单块信息不足,召回碎片化,生成时缺少上下文;块太大,向量被多个主题平均,检索精度下降,且浪费上下文预算。经验区间是 256 至 1024 token(估算),问答类偏小,摘要与法规类偏大。overlap 常取块长的 10% 至 20%(估算),用于避免边界信息丢失,但会带来重复召回与存储膨胀。
更合理的做法是“检索用小块、生成用大块”:子块 200 至 400 token 负责被召回,命中后返回其所属父块 800 至 1500 token 用于生成(均为估算)。这样既保持向量语义集中,又不让模型看到断裂的上下文。
4.3 切分伪代码¶
def recursive_split(text, max_tokens=512, overlap=64,
seps=("\n\n", "\n", "。", ";", " ")):
"""按段落 -> 句子 -> 字符逐级回退,超长片段继续递归。"""
if count_tokens(text) <= max_tokens:
return [text]
for i, sep in enumerate(seps):
parts = [p for p in text.split(sep) if p.strip()]
if len(parts) <= 1:
continue # 该层级切不开,换下一级
chunks, buf = [], ""
for part in parts:
if count_tokens(part) > max_tokens: # 单个片段仍超长
if buf:
chunks.append(buf)
buf = ""
chunks.extend(recursive_split(part, max_tokens, 0, seps[i + 1:]))
continue
candidate = f"{buf}{sep}{part}" if buf else part
if count_tokens(candidate) <= max_tokens:
buf = candidate
else:
chunks.append(buf)
buf = part # 新块从当前片段开始
if buf:
chunks.append(buf)
return add_overlap(chunks, overlap) # 相邻块重叠若干 token
return hard_split(text, max_tokens) # 所有分隔符都无效
真实系统还要处理表格不跨块、标题跟随、代码块完整等约束。切分完成后应做抽检:随机抽 30 个块,判断“只看这一块能否回答一个合理问题”,这是比任何自动指标都直接的质检方式。
5. Embedding 与向量索引¶
5.1 Embedding 模型选型¶
选型看五点:语言覆盖、最大输入长度、向量维度、检索任务表现、部署成本。中文场景要确认模型在中文语义匹配上的表现,不能只看英文榜单。多数模型要求查询与文档使用相同的前缀或指令格式,混用会显著掉点。向量通常做 L2 归一化后用余弦相似度或内积检索。
领域术语多、缩写多时,通用 embedding 可能把“同义不同词”判得很远。可以用难负样本做对比学习微调,损失函数为 InfoNCE:
其中 \(d^{+}\) 是正例,其余为负例,\(\tau\) 为温度系数。难负样本应从当前系统真实召回的头部错误中挖,而不是随机采样。
5.2 向量数据库选型¶
| 方案 | 形态 | 优势 | 局限 | 适用规模(估算) |
|---|---|---|---|---|
| FAISS | 嵌入式库 | 性能强、算法全、无服务依赖 | 无服务化与权限管理,持久化需自行封装 | 十万到千万级 |
| Milvus | 分布式服务 | 水平扩展、多索引、生态完整 | 运维重、资源占用高 | 千万到十亿级 |
| pgvector | PostgreSQL 扩展 | 与业务库同事务、SQL 过滤方便 | 超大规模性能有限 | 十万到千万级 |
| Qdrant | 独立服务 | 过滤能力强、部署轻、API 友好 | 超大规模需集群调优 | 百万到亿级 |
选型不要只看 benchmark。若业务数据已在 PostgreSQL,且规模在百万级,pgvector 能省掉一套系统;若需要强过滤与多租户,Qdrant 的 payload 索引更顺手;若追求极致召回与离线实验,FAISS 更灵活。
5.3 HNSW 原理与参数¶
分层可导航小世界图(Hierarchical Navigable Small World,HNSW)通过多层图实现近似最近邻搜索:上层稀疏用于长跳,下层稠密用于精搜。查询从顶层入口点出发,每层贪心走到局部最近,再下沉一层,最终在底层做候选扩展。
关键参数:M 是每个节点的邻居数,越大召回越高、内存越大;efConstruction 是建图时的候选队列长度,影响图质量与建库时间;efSearch 是查询时的候选队列长度,直接 trade-off 召回与延迟。经验上 M 取 16 至 64,efSearch 从 64 起调,按 Recall@10 达到 0.95 左右确定(估算)。
内存量级可粗略估算为 \(N \times (4d + 8M)\) 字节,其中 \(d\) 为维度,\(N\) 为向量数;再乘约 1.1 至 1.3 的图层开销。一百万条 768 维、M=32 的索引大约在 3 至 5 GB 量级(估算),实际以压测为准。
5.4 IVF-PQ 原理与参数¶
倒排文件加乘积量化(Inverted File with Product Quantization,IVF-PQ)先用 k-means 把向量聚成 nlist 个簇,查询时只扫 nprobe 个最近簇;再用乘积量化把高维向量切成 m 段,每段用 256 个码字编码,把存储压到每向量 m 字节。
nlist 越大,单簇越小、每簇样本越少,但训练与查表开销上升;nprobe 越大召回越高、延迟越高;m 越大精度越高、压缩率越低。IVF-PQ 适合内存受限的超大规模场景,但召回通常低于 HNSW,且对分布漂移敏感,需要定期重训练。
带元数据过滤时要注意“先过滤再搜索”还是“先搜索再过滤”。前者召回完整但可能退化为暴力扫描,后者快但过滤条件苛刻时结果不足。生产系统常用分区、租户隔离或可过滤的图索引来规避。
6. 查询理解与改写¶
用户问题往往不适合直接检索:有指代(“它的价格是多少”)、有口语省略、有多跳意图、有时间约束。查询理解的目标是把问题变成“可检索的查询集合”。
| 技术 | 机制 | 收益 | 风险 | 适用 |
|---|---|---|---|---|
| 指代消解 | 用对话历史补全代词与省略 | 多轮场景必备 | 历史过长时误补 | 客服、助手 |
| Multi-Query | 让模型生成 3 至 5 个同义查询并行召回 | 提升召回率 | 延迟与成本上升 | 召回不足 |
| HyDE | 先生成假设答案,再用答案向量检索 | 缓解问题与文档表述差异 | 假设错误会放大偏差 | 专业问答 |
| Step-back | 先抽象出上位问题再检索 | 补充背景知识 | 可能偏离具体诉求 | 原理、政策类 |
| 查询分解 | 把多跳问题拆成子问题依次检索 | 支持多跳 | 依赖分解质量 | 对比、因果 |
改写要设护栏:保留原始 query 作为一路召回,避免改写漂移导致原本能命中的文档丢失;对时间、数字、专有名词做实体锁定;改写结果过长时截断,防止向量被稀释。
7. 检索与融合¶
7.1 BM25 与稠密检索¶
BM25 是稀疏检索的代表,基于词频、逆文档频率与文档长度归一化:
它擅长精确匹配:型号、错误码、人名、法规条款号。缺点是不懂同义改写,中文还需分词。
稠密检索把 query 与文档映射到同一向量空间,用近似最近邻找语义相近的块。它擅长同义表达与跨语言,但对罕见实体、数字、否定词不敏感,且需要训练数据与向量库支撑。
两者互补,混合检索是默认方案。融合可用加权分数归一化,也可用排名融合。RRF 不需要分数可比,稳健且对参数不敏感:
其中 \(R\) 为各召回列表,\(\text{rank}_r(d)\) 是文档在第 \(r\) 路中的名次,\(k\) 常取 60(经验值)。RRF 只使用名次,避免不同检索器分数量纲不一致的问题。
7.2 多路召回与元数据过滤¶
多路召回可以包括:原始 query 的稠密检索、改写 query 的稠密检索、BM25、标题或摘要字段检索、按实体精确匹配、以及图关系扩展。每路取 Top 50 至 100(估算),融合后截断到 20 至 50 条进入重排(估算)。
元数据过滤要先于向量检索生效:租户、权限、时间范围、文档类型、语言。权限过滤尤其不能用“检索后再删”,否则既浪费算力,也可能把无权限内容送进模型上下文,形成越权风险。
7.3 检索指标¶
Recall@k 衡量“该找到的有没有找到”,MRR 关注第一个正确结果的位置,nDCG 兼顾相关度等级与排序位置。问答系统通常先看 Recall@20 是否足够高,再看 nDCG@10 判断排序质量。
8. 重排¶
召回追求高召回,重排(rerank)追求高精度。常见三方案:
- 交叉编码器(cross-encoder):把 query 与文档拼接后过一次模型,输出相关性分数。精度高,但每条候选都要前向一次,延迟随候选数线性增长。
- ColBERT 类延迟交互(late interaction):query 与文档各自编码为 token 向量,用 MaxSim 计算细粒度匹配,可离线建索引,兼顾精度与速度。 $$ S(q,d)=\sum_{i\in q}\max_{j\in d}\mathbf{E}{q_i}\cdot\mathbf{E} $$}^{\top
- LLM 重排:让模型对候选逐条打分或分组排序。灵活、可解释,但成本高、延迟大,适合低 QPS 或高价值场景。
生产常用级联:混合召回 100 条,cross-encoder 重排到 20 条,再用轻量规则或 LLM 选出 3 至 5 条进入上下文(均为量级估算)。重排模型要在业务标注集上评估,公开榜单的排序能力不一定迁移到你的领域。
9. 上下文组装与生成¶
9.1 组装策略¶
组装不是简单拼接。要先去重(同一文档的多个块只保留最相关的一段)、按相关性排序、控制总 token 预算、保留来源标识。研究发现模型对上下文中间位置的信息利用较弱,重要证据应放在开头或结尾,这就是常说的“中间遗忘”(lost in the middle)。
上下文压缩可以用小模型抽取与问题相关的句子,或直接让生成模型忽略无关段落。压缩能降低噪声与成本,但过度压缩会删掉回答所需的限定条件,必须用忠实度评估兜底。
9.2 引用与拒答¶
引用要满足三点:答案中的关键结论能对应到具体文档与位置;引用片段真的支持该结论;没有依据时明确拒答。实现上可要求模型输出结构化引用标记,再在服务端校验标记是否落在给定上下文内,防止编造来源。
拒答策略要分级:检索为空或最高分低于阈值时直接拒答;检索有结果但证据冲突时,说明冲突并给出各自来源;证据不足但可部分回答时,明确标注不确定性。阈值应在评测集上按“误拒率”和“漏拒率”调,而不是拍脑袋。
9.3 冲突处理¶
知识库冲突很常见:旧版制度与新规并存、不同部门口径不一致。处理顺序建议为:按发布时间与生效状态过滤过期文档;按来源权威性排序;在 prompt 中要求模型优先采用最新且权威的来源;若冲突无法消解,在答案中并列呈现并提示用户核实。不要让模型“自行裁决”而不说明。
10. 评估¶
10.1 检索与生成分开评¶
检索评估用带标注的 query-文档对,指标是 Recall@k、MRR、nDCG。生成评估看忠实度、答案相关性、引用准确率。只评最终答案,无法判断是召回没找到,还是找到了但模型没用。
RAGAS 是常用的自动化评估框架,核心指标包括:
其中 \(v_i\) 表示第 \(i\) 个片段是否相关。Faithfulness 低说明模型超出证据自由发挥;Context Recall 低说明召回不全;Context Precision 低说明噪声多;Answer Relevancy 低说明答非所问。
10.2 评测集构造¶
评测集应覆盖:单跳事实、多跳推理、表格数值、时间与版本、否定与排除、无法回答、权限隔离、口语与错别字。每类 30 至 50 题(估算),总量 200 至 500 题可支撑一次迭代。题目来源包括真实日志抽样、业务专家编写、以及从文档反向生成问题。
反向生成要人工校验,否则会得到“文档里有一句话、问题就照抄这句话”的伪题。难负样本要刻意加入:同主题不同条款、旧版本、相似实体。标注内容包括 gold 文档块、参考答案要点、是否可回答、允许的引用范围。
10.3 在线指标¶
离线看质量,在线看效果与成本:答案采纳率、追问率、转人工率、点赞点踩、引用点击率、P95 延迟、单次成本。A/B 实验要控制流量分配与 novelty 效应,指标至少观察一个完整业务周期。
11. 常见失败模式与排查¶
| 现象 | 可能原因 | 诊断方法 | 处理方向 |
|---|---|---|---|
| 召回不到 | 切分过碎、同义词缺失、过滤过严、embedding 不匹配 | 看 gold 文档是否在候选集、逐层放宽过滤 | 改切分、加 BM25、补改写、换模型 |
| 召回噪声多 | 块过大、相似主题干扰、无重排 | 检查 Top20 相关比例、看 nDCG | 缩小块、加重排、加元数据过滤 |
| 忽略上下文 | prompt 过长、证据在中间、指令冲突 | 缩短上下文复测、调换证据位置 | 压缩、重排、把证据前置、强化指令 |
| 幻觉 | 证据不足、模型过度自信、缺少拒答示例 | 对照答案与引用逐句核查 | 拒答阈值、引用校验、few-shot 拒答 |
| 多跳失败 | 单轮检索、子问题未拆解 | 看中间实体是否被召回 | 查询分解、迭代检索、Agent 化 |
| 引用错误 | 引用标记后处理缺失、块定位不准 | 抽查引用片段与结论对应关系 | 结构化引用、服务端校验、保留页码 |
排查顺序建议从数据到模型:先确认 gold 文档在不在库里,再看能否被召回,再看重排后是否还在,最后才怀疑生成模型。这个顺序能避免大量无效的 prompt 调参。
12. 最小检索与重排实现¶
"""
最小 RAG:混合召回 + RRF 融合 + 交叉编码器重排(伪代码,22 行)
"""
def rrf_fuse(rankings, k=60):
scores = {}
for ranking in rankings: # 每一路召回单独计算名次
for rank, doc_id in enumerate(ranking, start=1):
scores[doc_id] = scores.get(doc_id, 0.0) + 1.0 / (k + rank)
return sorted(scores, key=scores.get, reverse=True)
def rag_answer(query, top_k=5):
q = rewrite_query(query) # 指代消解与查询改写
dense = vector_store.search(embed(q), k=50)
sparse = bm25.search(q, k=50)
candidates = rrf_fuse([dense, sparse])[:20]
pairs = [(q, doc_text[d]) for d in candidates]
scores = cross_encoder.predict(pairs) # 逐对打相关性分
ranked = [d for _, d in sorted(zip(scores, candidates), reverse=True)][:top_k]
context = assemble_context(ranked, token_budget=3000) # 去重、排序、压缩
answer = llm.generate(PROMPT.format(context=context, question=query))
return answer, [doc_meta[d] for d in ranked] # 返回引用来源
面试高频问题¶
1. RAG 和长上下文怎么选?¶
参考回答要点:
- 先看知识规模与更新频率:知识库远大于窗口、需要频繁更新时选 RAG;材料少且一次性分析时用长上下文更简单。
- 看可追溯性:需要逐条引用与审计时,RAG 的文档边界更清晰。
- 看成本结构:长上下文的 token 成本随长度线性增长,RAG 多一次检索但上下文更短。
- 实践中常组合:RAG 选材,长上下文承载多篇材料,微调固化输出格式。
2. 为什么切分策略比 embedding 模型更值得先优化?¶
参考回答要点:
- 切分决定了检索单元的信息完整性,块被切断时再强的模型也无法召回完整语义。
- 块过大导致向量主题平均,过小导致上下文缺失,二者都会让召回指标失真。
- 换 embedding 需要重建索引、评估迁移成本,而调整切分可以快速 A/B。
- 经验顺序是先把解析与切分做对,再考虑混合检索与重排,最后才换模型。
3. chunk size 和 overlap 如何确定?¶
参考回答要点:
- 从业务问题出发:事实型问答偏小(256 至 512 token),综述与法规偏大(512 至 1024 token),均为估算。
- overlap 取 10% 至 20%,用于保护边界,但会增加重复召回。
- 用评测集扫参:固定其他环节,比较 Recall@20 与 nDCG@10,而不是只看答案观感。
- 更推荐父子块:小块检索、大块生成,减少“检索精度与上下文完整性”的矛盾。
4. 混合检索为什么有效?RRF 的优缺点是什么?¶
参考回答要点:
- 稀疏检索擅长精确词、型号、条款号;稠密检索擅长同义改写与跨语言,错误相关性低。
- RRF 只用名次不用分数,避免不同检索器分数量纲不一致,几乎不需要调参。
- 缺点是丢失分数强弱信息,且对只有一路召回的文档不够敏感。
- 可先用 RRF 做稳健基线,再在标注集上尝试加权分数融合。
5. HNSW 的参数如何调?¶
参考回答要点:
M控制图连通度,越大召回越高、内存越大,常用 16 至 64(估算)。efConstruction影响建图质量与时间,数据量大时可适当提高。efSearch是查询时召回与延迟的旋钮,从 64 起按目标 Recall 调。- 调参要在真实数据分布上做,并监控内存与 P99 延迟,不能只看离线召回。
6. 召回结果很多但答案仍然错,怎么排查?¶
参考回答要点:
- 先看 gold 文档是否被召回、重排后是否还在,区分召回问题与生成问题。
- 检查上下文是否超长、证据是否落在中间、是否被无关段落稀释。
- 检查 prompt 是否存在指令冲突,模型是否被要求“必须回答”而不敢拒答。
- 做对照实验:只给 gold 片段,若仍答错,问题在生成或推理,不在检索。
7. 如何评估 RAG 系统?¶
参考回答要点:
- 检索与生成分开:Recall@k、MRR、nDCG 评检索;Faithfulness、Answer Relevancy、引用准确率评生成。
- 评测集按问题类型分层,包含不可回答与权限隔离样本。
- 自动指标用大模型作为评审(LLM-as-judge)时要与人工标注校准,注意位置与长度偏差。
- 线上线下都要看采纳率、追问率、转人工率、延迟与成本,避免只优化离线分数。
8. 多跳问题为什么容易失败?如何改进?¶
参考回答要点:
- 单轮检索只能拿到与原始问题表面相似的片段,中间实体往往没有被召回。
- 查询分解把问题拆成子问题,逐步检索并累积证据。
- 迭代检索根据已获证据生成下一轮查询,必要时用 Agent 控制流程。
- 评估时要看中间步骤的召回,而不仅是最终答案。
9. 如何降低 RAG 的幻觉?¶
参考回答要点:
- 提高证据覆盖率:混合召回、重排、父子块,确保正确证据进入上下文。
- 强化 grounding:要求逐句引用,服务端校验引用片段是否真的支持结论。
- 设计拒答:证据不足、分数过低、来源冲突时明确说明,而不是强行作答。
- 降低解码随机性,并在评测集中加入“无法回答”样本做回归。
10. 向量数据库怎么选型?¶
参考回答要点:
- 先看规模与增长预期:百万级可用 pgvector 或 Qdrant,千万级以上考虑 Milvus 或分片方案。
- 看过滤需求:多租户、权限、时间范围要求强过滤时,优先支持 payload 索引的方案。
- 看运维能力:FAISS 灵活但需要自建持久化与服务化,托管服务省事但有成本与锁定。
- 最终以真实数据压测召回、延迟、成本与故障恢复,而不是只看公开 benchmark。
本文档为面试复习资料,指标与产品信息建议结合官方文档复核。