RAG(Retrieval-Augmented Generation,检索增强生成)是目前 AI 应用面试中出现频率最高的技术点之一。这篇文章基于 DeepScientist 项目的实际落地经验,整理面试中关于 RAG 的高频问题和回答思路。
RAG 是什么,为什么需要它
大模型有两个核心局限:知识截止日期和上下文窗口限制。
直接把整个知识库塞进 prompt 不现实——成本高、速度慢、超出窗口。RAG 的思路是:先检索相关内容,再把检索结果交给模型生成答案。
1 | 用户提问 |
这样模型只需要处理少量高度相关的内容,既省 token,又能基于真实文档回答,减少幻觉。
RAG 的完整流程
分两个阶段:离线索引和在线检索。
离线阶段(数据准备)
1 | 原始文档(PDF/Word/Markdown) |
在线阶段(回答生成)
1 | 用户提问 |
高频面试题
文档分块策略怎么选,chunk size 怎么定
分块是 RAG 效果的基础,策略选错后面怎么调都没用。
常见策略:
| 策略 | 适用场景 | 优缺点 |
|---|---|---|
| 固定长度(512/1024 token) | 通用场景 | 简单,但可能切断语义 |
| 按段落/标题切分 | 结构化文档(技术文档、手册) | 语义完整,推荐 |
| 滑动窗口(有重叠) | 内容连续性强的文档 | 避免边界信息丢失,但冗余 |
| 递归字符切分 | 混合格式文档 | 灵活,LangChain 默认方案 |
chunk size 怎么定:
没有万能答案,需要实验。我的做法是:
- 从历史问答中整理 50-100 个测试问题,标注每个问题对应的标准文档片段
- 用不同 chunk size(256/512/1024)分别建索引,跑测试集
- 看两个指标:召回率(标准片段是否在 Top-K 里)和精确率(Top-1 是否最相关)
- 选召回率和精确率最优的组合
在 DeepScientist 里,按一级标题切分 + Top-3 召回效果最好。原因是科研文档结构清晰,按标题切分语义完整,不会把一个方法的描述切成两半。
Embedding 模型怎么选
Embedding 模型决定了向量空间的质量,直接影响检索效果。
评估标准: 看 MTEB 榜单,这是业界公认的 embedding 评测基准,覆盖检索、分类、聚类等多个任务。
中文场景推荐:
text-embedding-v4(阿里):MTEB 中文榜前列,国内部署无网络问题bge-m3(智源):开源,支持多语言,可本地部署text-embedding-3-large(OpenAI):英文效果好,中文一般
选型原则:
- 国内生产环境:优先阿里/智源,避免网络依赖
- 需要本地部署:bge 系列
- 英文为主:OpenAI 或 Cohere
向量数据库怎么选
| 数据库 | 特点 | 适用场景 |
|---|---|---|
| Milvus | 专用向量库,高性能,42k star | 生产环境,大规模数据 |
| pgvector | PostgreSQL 插件,SQL 兼容 | 已有 PG 基础设施,数据量中等 |
| Chroma | 轻量,纯 Python | 原型开发,本地测试 |
| Weaviate | 内置 BM25+向量混合检索 | 需要混合检索的场景 |
| Qdrant | Rust 实现,低内存占用 | 资源受限环境 |
实际选型考虑:
- 数据量 < 100 万:pgvector 够用,省去维护独立向量库的成本
- 数据量 > 100 万或高并发:Milvus/Qdrant
- 快速验证:Chroma,5 行代码跑起来
召回效果不好怎么优化
召回效果差通常有几个原因,逐一排查:
1. 文档质量问题(最常见)
文档写得乱、语义分散,是召回差的最大原因。解决方案:清洗文档,规范写法,同一个问题的描述集中在一个段落。
2. 分块策略不合适
chunk 太小:语义不完整,模型拿到片段无法回答。
chunk 太大:相似度被稀释,不相关内容混入。
调整分块策略,重新建索引测试。
3. Embedding 模型不匹配
专业领域(医疗、法律、代码)用通用 embedding 效果差。考虑用领域数据 fine-tune embedding 模型,或换专门的领域模型。
4. 只用向量检索,缺少关键词匹配
向量检索擅长语义相似,但对精确关键词(错误码、API 名称、专有名词)效果差。
解决方案:混合检索(Hybrid Search),向量检索 + BM25 关键词检索,用 RRF(Reciprocal Rank Fusion)融合两路结果:
1 | def hybrid_search(query: str, top_k: int = 10): |
5. 缺少 Reranker
向量检索的 Top-K 结果顺序不一定准确。加一个 Reranker(交叉编码器)对召回结果精排,能显著提升 Top-1 准确率:
1 | from sentence_transformers import CrossEncoder |
相似度阈值怎么设
阈值太低:召回不相关内容,模型被干扰,容易幻觉。
阈值太高:召回为空,模型无法回答。
我的做法:
用测试集跑不同阈值(0.5/0.6/0.7/0.75/0.8),画出召回率-精确率曲线,选拐点。
在 DeepScientist 里设的是 0.75。低于这个值直接返回”知识库中暂无相关信息”,不让模型凭空猜测。
1 | results = vector_db.search(query_vector, top_k=3) |
文档更新了怎么处理,增量索引怎么做
方案:维护文档元数据表
1 | CREATE TABLE doc_index ( |
增量更新流程:
1 | def sync_documents(doc_dir: str): |
整个过程异步执行,不影响在线查询。
RAG 和 Fine-tuning 怎么选
| 维度 | RAG | Fine-tuning |
|---|---|---|
| 知识更新 | 实时,改文档即生效 | 需要重新训练 |
| 成本 | 低(只需向量化) | 高(GPU 训练) |
| 可解释性 | 高(能追溯来源) | 低(黑盒) |
| 适合场景 | 知识频繁更新、需要溯源 | 固定领域、风格/格式要求 |
| 幻觉风险 | 低(基于检索内容) | 高(依赖训练数据) |
结论: 大多数企业知识库场景用 RAG,知识更新频繁且需要溯源。Fine-tuning 适合固定领域的风格迁移(比如让模型学会特定的回复格式)。两者也可以结合:先 fine-tune 让模型理解领域语言,再用 RAG 提供实时知识。
Agentic RAG 和普通 RAG 的区别
普通 RAG:固定流程,每次提问都先检索再生成,检索只发生一次。
Agentic RAG:把检索作为工具,交给 Agent 自主决定什么时候检索、检索什么。
1 | 普通 RAG: |
Agentic RAG 的优势:
- 复杂问题可以多轮检索,每轮 query 根据上一轮结果动态调整
- Agent 可以决定”这个问题不需要检索,直接回答”,避免无效检索
- 可以混合使用多个知识源(内部文档 + 外部搜索)
混合方案(我在 DeepScientist 里用的):
- 对话开始时做一次普通 RAG,召回最相关的背景文档
- ReAct 推理过程中,Agent 可以按需再次调用检索工具
这样结合了普通 RAG 的质量控制(避免每轮都检索的成本)和 Agentic RAG 的灵活性。
如何评估 RAG 系统的效果
离线评估(有标注数据):
1 | # 核心指标 |
在线评估(生产环境):
- 用户反馈(👎 按钮):点击率反映答案质量
- 追问率:用户追问”你说的不对”说明答案有问题
- 会话完成率:用户是否在一次会话内解决了问题
用 LLM 自动评估(RAGAS 框架):
1 | from ragas import evaluate |
一句话总结各个优化点
| 问题 | 解决方案 |
|---|---|
| 召回不到相关内容 | 检查分块策略、换更好的 embedding 模型 |
| 召回到了但排序靠后 | 加 Reranker |
| 关键词/专有名词召回差 | 混合检索(向量 + BM25) |
| 模型答案和文档不符 | 检查 prompt 约束,加相似度阈值过滤 |
| 文档更新不及时 | 增量索引 + 文件 hash 变更检测 |
| 复杂问题一次检索不够 | 升级为 Agentic RAG,多轮检索 |