RAG 基础架构
问题
RAG 的基础架构是什么?Naive RAG 的完整流程是怎样的?
答案
一、Naive RAG 流程
最基础的 RAG 系统包含两个阶段:离线索引和在线检索生成。
二、核心组件
1. 文档加载与解析
from langchain_community.document_loaders import PyPDFLoader
# 加载 PDF 文档
loader = PyPDFLoader("knowledge_base.pdf")
documents = loader.load()
# 每页作为一个 Document 对象,包含 page_content 和 metadata
2. 文本分块
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=512, # 每块最大字符数
chunk_overlap=50, # 相邻块重叠字符数,保持上下文连贯
separators=["\n\n", "\n", "。", ",", " "]
)
chunks = splitter.split_documents(documents)
3. Embedding + 存储
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = FAISS.from_documents(chunks, embeddings)
4. 检索 + 生成
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
llm = ChatOpenAI(model="gpt-4o-mini")
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=vectorstore.as_retriever(search_kwargs={"k": 5}),
return_source_documents=True, # 返回引用来源
)
result = qa_chain.invoke({"query": "什么是 Transformer?"})
print(result["result"])
三、RAG 演进
| 阶段 | 特点 | 典型问题 |
|---|---|---|
| Naive RAG | 简单的检索→拼接→生成 | 检索不准、上下文不足 |
| Advanced RAG | Query 改写、混合检索、重排序 | 工程复杂度上升 |
| Modular RAG | 可插拔模块、自适应路由 | 需要精细调优 |
| Agentic RAG | Agent 驱动,多步推理+检索 | 延迟高、成本高 |
四、Naive RAG 的问题
| 问题 | 原因 | 解决方向 |
|---|---|---|
| 检索不相关 | 语义不匹配 | Query 改写、HyDE |
| 遗漏关键信息 | Top-K 不够或分块粗糙 | 提高 K、优化分块 |
| 冗余/矛盾 | 多个块内容重复 | 重排序、去重 |
| 无法多跳推理 | 单次检索信息不足 | 多步检索、Agent |
| 幻觉 | LLM 忽略检索内容 | 强制引用、Prompt 优化 |
常见面试问题
Q1: RAG 的检索阶段如何确定 Top-K 的值?
答案:
- 小 K(3-5):上下文窗口有限时使用,减少噪声,但可能遗漏关键信息
- 大 K(10-20):配合 Reranker 使用——先检索 20 条,Reranker 精排后取 Top-5 送入 LLM
- 经验法则:先设 K=10,通过评估指标(Recall@K)调整
Q2: RAG 和直接把文档放进 Context Window 有什么区别?
答案:
| 维度 | RAG | 长上下文 |
|---|---|---|
| 文档量 | 无限(存向量库) | 受窗口限制(128K-1M Token) |
| 成本 | 只传入相关片段 | 全量文档每次都传 |
| 精度 | 精确到段落级 | 大量文档时 Lost in the Middle |
| 适用 | 大规模知识库 | 少量文档深度分析 |