1 一个最小可用的 RAG 系统由哪些部分组成
P0 · rag
🏷 标签:rag, retrieval, vector-database, llm
1️⃣ 考察意图
面试官想确认你能否从“最小可用”出发,拆解RAG系统的核心骨架,而不是堆砌生产级组件。这是典型的“系统设计+概念验证”题,刁钻点在于:很多人会漏掉“索引”阶段的文档解析和分块策略,或者把rerank、query改写等非必需组件强行塞入。答好了能展示你对RAG pipeline的底层理解(检索召回 vs. 生成质量),以及区分MVP与生产系统的工程判断力。
2️⃣ 标准答
一个最小可用的RAG系统,核心是“索引-检索-生成”三阶段,缺一不可。下面按顺序拆解,每个阶段只保留最精简的组件。
1. 索引阶段:把外部知识变成可检索的向量
- 文档解析:输入是PDF、HTML或Markdown,必须用解析器(如PyMuPDF、BeautifulSoup)提取纯文本。坑:PDF表格或多栏布局容易乱序,解法是用layout-aware解析(如Unstructured库)或OCR(Tesseract)兜底。
- 文本分块(Chunking):将长文本切成固定大小(如512 tokens)的块,重叠(overlap)设为10-20%避免上下文断裂。为什么这么做?块太大导致检索噪声(一个块含多个主题),块太小丢失语义连贯性。trade-off:固定大小分块简单但可能切碎实体,语义分块(如按段落或句子边界)更好但计算成本高。最小可用选固定大小+overlap即可。
- 向量化:用embedding模型(如text-embedding-ada-002或BGE-small)将每个块转为向量。注意:query和文档必须用同一模型,否则向量空间不对齐。
- 向量存储:用FAISS(本地)或Pinecone(云端)建索引,支持近似最近邻搜索(ANN)。最小可用选FAISS的IVF(倒排文件)索引,参数nlist=100,召回率约90%但速度够快。
2. 检索阶段:从向量库中召回相关块
- query编码:用户输入query,经相同embedding模型编码为向量。
- ANN搜索:在向量库中执行top-k搜索(k通常取3-5)。为什么k=3-5?太少可能漏答案,太多会引入噪声并撑爆LLM上下文窗口。实际落地的坑:向量搜索对query的语义变化敏感,比如“苹果公司”和“苹果水果”可能混淆。解法:在检索前加query改写(如用LLM扩展同义词),但最小可用阶段跳过,直接依赖embedding的语义理解。
- 返回结果:输出top-k块的文本内容及其元数据(如来源文档名)。
3. 生成阶段:用LLM合成答案
- Prompt拼接:将检索到的块按相关性排序,与原始query拼接成结构化prompt。格式示例:
- LLM生成:用GPT-4或开源模型(如Llama 3-8B)生成答案。为什么加“无法回答”指令?防止LLM幻觉,强行约束其只依赖检索内容。trade-off:指令越严格,回答越准确但可能过于保守;最小可用选保守策略,生产级再调温度或加rerank。
- 后处理(可选):最小可用可省略rerank,直接输出LLM结果。如果检索质量差(如top-1不相关),可加简单过滤:计算query与块之间的余弦相似度,低于阈值(如0.5)则丢弃。
总结:最小可用RAG = 文档解析 + 固定大小分块 + embedding模型 + FAISS索引 + top-3检索 + 带约束的LLM生成。生产级会加rerank、query改写、多路召回等,但MVP只需这三阶段。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从索引、检索、生成三个层面回答。索引阶段包括文档解析、固定大小分块(512 tokens + 10% overlap)、用text-embedding-ada-002向量化、存入FAISS;检索阶段用相同模型编码query,执行top-3 ANN搜索;生成阶段将检索块与query拼接成prompt,用GPT-4生成答案,并加‘无法回答’指令防幻觉。总结一句:最小可用RAG就是‘分块→向量化→搜索→生成’的完整流程,缺一不可。”
4️⃣ 高频追问 & 应对
追问 1:为什么不用BM25做检索,而用向量搜索?
BM25是基于词频的稀疏检索,适合关键词匹配(如“苹果公司财报”),但对语义相似(如“库克最近说了什么”)效果差。向量搜索用embedding捕获语义,能处理同义词和上下文。trade-off:BM25速度快、可解释性强,但召回率低;向量搜索召回率高但需要GPU推理。最小可用选向量搜索,因为RAG核心是语义理解;如果数据是短文本或专有名词多,可以加BM25做混合检索(如Reciprocal Rank Fusion融合结果)。
追问 2:分块大小怎么选?为什么是512 tokens?
512 tokens是经验值,基于LLM上下文窗口(如GPT-4的8K)和检索效率的平衡。块太小(如128 tokens)导致每个块信息量不足,检索时可能漏掉关键细节;块太大(如1024 tokens)增加检索噪声,且一个块可能包含多个主题。实际落地:先用固定大小512 tokens + 20% overlap做基线,然后按文档类型调优——技术文档用256 tokens(术语密集),新闻用512 tokens(段落完整)。评估指标用Recall@k,调参到90%以上。
追问 3:如果检索结果全是噪声,怎么处理?
这是常见坑。解法分两步:第一,在检索阶段加相似度阈值过滤(如余弦相似度<0.5的块丢弃),避免低质量结果进入生成;第二,在生成阶段用prompt指令约束,比如“如果上下文不相关,回答‘未找到相关信息’”。如果噪声仍多,说明embedding模型或分块策略有问题,需要换模型(如从ada-002换到BGE-large)或调分块大小。生产级还会加rerank(如Cohere rerank)二次排序,但最小可用用阈值+指令即可。
5️⃣ 避坑 · 常见错误答法
- ❌ 把rerank、query改写、多路召回等生产级组件塞入最小可用系统 → ✅ 明确区分MVP和生产级,只说“索引-检索-生成”三阶段,其他作为“可选扩展”提及。
- ❌ 忽略文档解析,直接说“把文本丢进向量库” → ✅ 强调文档解析(如PDF解析)是前置步骤,并点出表格/多栏的坑。
- ❌ 说“用LLM直接生成答案,不需要检索” → ✅ 强调RAG的核心是“检索增强”,生成必须基于检索结果,否则就是纯LLM问答。
6️⃣ 简历呼应
- 如果你有RAG项目:从“我在XX项目中用LangChain搭建了最小可用RAG,分块用512 tokens + 10% overlap,检索用FAISS的IVF索引,生成用GPT-4并加‘无法回答’指令,最终Recall@k达92%”切入,展示工程落地细节。
- 如果你只做过传统NLP:用“传统检索(如BM25)和向量检索的对比”类比,说明RAG如何融合两者优势,并强调分块策略与文本分类中的特征工程类似。
- 如果你是校招无项目:聚焦“我复现了论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》中的最小系统,用Wikipedia子集做demo,评估了不同分块大小对Recall的影响”,展示动手能力和论文理解。
- 《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》(Lewis et al., 2020)
- FAISS官方文档:IndexIVFFlat参数调优指南
- LangChain RAG快速入门教程(官方文档)
- 《Dense Passage Retrieval for Open-Domain Question Answering》(Karpukhin et al., 2020)
- Pinecone博客:Chunking Strategies for RAG