1.RAG概述
RAG概述
依赖安装:
pip install langchain langchain‑community chromadb sentence‑transformers
一、RAG基础概念
RAG(检索增强生成),解决大模型幻觉、知识过时、私有知识无法使用问题,分为索引阶段(离线)和查询阶段(在线)。
1. 索引阶段(离线:构建知识库,类比制作书本目录)
流程:数据源加载 → 文本切分(切块) → Embedding嵌入 → 向量数据库存储(向量+原始文本块)
- 数据源:PDF、Word、Markdown、网页、TXT;PDF处理最麻烦,尤其带表格、图片的PDF。
- 文本切分:大文档切为多个文本块(chunk),避免块太大难以存储、检索。
- Embedding(嵌入):把文本转为带语义信息的向量,索引阶段和查询阶段必须使用同一个Embedding模型,否则向量空间不一致检索失效。
- 向量数据库存储:同时存两件东西:①文本块的语义向量(做索引检索);②原始文本块(最终给大模型用)。向量仅用于相似度匹配,真正回答需要原始文本。
2. 查询阶段(在线:用户提问得到答案)
流程:用户Query输入 → Query做Embedding → 向量库相似度检索(余弦相似度/欧式距离)→ 获取top‑N相关文本块 → 将文本块塞入Prompt做上下文增强 → 大模型结合上下文+用户问题生成回答返回用户
余弦相似度:更常用,衡量向量语义相近;分数越接近1语义越接近。
代码示例:朴素RAG Demo
点击查看代码
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
# ====================== 【索引阶段 离线构建知识库】======================
# 输入:私有知识原始文本
raw_text = """RAG全称检索增强生成,用来缓解大模型幻觉问题。
RAG分为索引阶段和查询阶段。索引阶段离线处理文档,做加载、切分、嵌入、入库。
查询阶段接收用户问题,检索知识库,把检索到的知识放进提示词交给大模型生成答案。
Embedding模型在索引和查询阶段必须保持完全一致。"""
# 操作1:文本切分,递归切分+滑动窗口重叠
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=150, # 块最大token长度
chunk_overlap=30, # 块之间重叠,防止语义被切断
separators=["\n\n", "\n", "。", ","]
)
chunks = text_splitter.split_text(raw_text)
# 输出:chunks,是切分完成的多个文本块列表
# 操作2:初始化embedding模型,索引、查询共用同一个
embedding_model = HuggingFaceEmbeddings(model_name="all‑MiniLM‑L6‑v2")
# 操作3:存入向量数据库,同时保存向量和原始文本块
vector_db = Chroma.from_texts(texts=chunks, embedding=embedding_model, persist_directory="./chroma_db")
# ======================【查询阶段 用户提问】======================
# 输入:用户的问题
user_query = "RAG分为哪两个阶段?"
# 操作:1.用户query自动走同一个embedding模型;2.余弦相似度检索,取top2最相关块
retriever = vector_db.as_retriever(search_kwargs={"k": 2})
retrieved_docs = retriever.invoke(user_query)
# 输出:retrieved_docs,检索召回出来的2个相关的文本块对象
# 把召回的上下文拼接成prompt上下文
context = "\n".join([doc.page_content for doc in retrieved_docs])
prompt = f"""基于下面的参考上下文回答用户问题,只使用参考里的内容:
【参考上下文】
{context}
【用户问题】
{user_query}
你的回答:"""
print("===构造好的Prompt===")
print(prompt)
print("\n===检索得到的原始上下文块===")
for idx, doc in enumerate(retrieved_docs):
print(f"块{idx+1}:{doc.page_content}")
代码输入、操作、输出解释
- 索引阶段
- 输入:
raw_text私有原始长文本 - 操作:递归切分得到小块;调用embedding模型将每块转为语义向量;向量+原始文本存入Chroma向量数据库。
- 输出:磁盘
chroma_db知识库;内存中切分好的chunks文本列表。
- 查询阶段
- 输入:用户问题字符串
user_query - 操作:Retriever会自动对query执行Embedding,和库内向量做余弦相似度计算,召回top‑k相似度最高的文本块;拼接检索结果构造Prompt。
- 输出:召回的文档对象
retrieved_docs;组装完成的prompt字符串,接下来就可以喂给大模型生成最终答案。
朴素RAG缺点:只做简单切块+向量检索,容易出现语义召回错误(例如查询苹果手机召回水果苹果),所以需要高级RAG做优化。
二、高级RAG(Advanced‑RAG)优化
高级RAG = 朴素RAG + 检索前优化 + 检索后优化
1. 检索前优化(查询进入向量库之前做处理)
| 优化手段 | 核心说明 |
|---|---|
| 分块策略 | 1.固定长度切块:简单,容易切断语义;2.递归+滑动窗口(工业最常用):按段落/句子分隔符切分,块之间设置overlap重叠,保留上下文;3.大模型语义切块:效果最好,成本极高。中文经验:chunk_size=400‑600,overlap=50‑100。 |
| 元数据索引 | 存储块对应的页码、标题、来源,支持按来源/页码过滤检索。 |
| 结构化分层索引 | 对文档分组聚类,生成分组摘要、全局摘要;检索时先匹配摘要快速定位分组,减少向量计算量。维护成本高,适合稳定不变的知识库。 |
| 查询重写 | ①改写用户模糊问题为标准无歧义问题;②指代消解,多轮对话把代词(它、其)替换为实体。收益很高,工业必做。 |
| 查询扩展(多查询) | 大模型生成同一个问题的多种表达方式,多个query分别检索,结果汇总去重。 |
| HyDE假设文档检索 | 问题先交给大模型生成一份无依据的假设答案,拿假设答案做向量检索,解决【问题和答案文本差异巨大,向量匹配不到】的语义鸿沟。注意:只用来检索,不用假设文档作为回答。 |
| 查询路由 | 多知识库场景,判断当前问题应该查向量库/知识图谱/业务数据库,可以规则路由、也可以大模型agent路由。 |
| 混合检索 | 向量语义检索 + 关键词检索(BM25),两套检索拿到结果后后续统一重排。 |
2. 检索后优化(拿到向量库返回结果之后,再处理)
- 重排序Rerank(最重要)
- 向量余弦相似度只是粗召回,embedding低维空间不能完全表达深层语义,会出现误召回。
- Rerank模型(如BGE‑Reranker)专门输入【query+候选文本块】,做深层次语义相关性打分,做精排,过滤不相关块。
- 流程:向量库粗召回top‑10 → Rerank精排筛选top‑3送入prompt。
- RRF融合:多来源检索结果融合算法,不依赖模型,合并多查询、多路检索的结果。
- 上下文压缩:对召回块做摘要提炼,减少token消耗,过滤噪声;缺点:多调用大模型,链路变长、速度变慢。
三、GraphRAG & Agentic‑RAG
- GraphRAG(图RAG)
- 原理:文档提取实体、实体关系存入图数据库,搭配分层摘要索引。微软开源GraphRAG框架。
- 优点:擅长实体、关系、复杂推理类问题;前提:知识图谱质量要高。
- 缺点:自动抽取实体关系容易出错;构建图谱人力成本高。没有高质量图谱不建议使用。
- Agentic‑RAG(智能体RAG)
- 引入Agent智能体大模型作为大脑:自动拆解复杂问题、自主选择检索策略、路由不同知识库、反思复盘。
- 缺点:现在落地成熟度低;大模型调用次数多,延迟高、成本高;效果高度依赖提示词设计。属于未来趋势,企业落地少。
四、RAG效果评估
RAG评估分为三大维度:检索上下文质量、生成答案真实性、生成答案相关性。
核心指标
- 检索层面
- 精确率Precision:召回出来的块里面真正相关块占比;追求高精确容易丢失正确答案。
- 召回率Recall:所有真正相关块里面,有多少被成功召回;高召回尽量不漏掉正确文档。
精确率和召回率需要综合权衡,不能单独看一个。
- 生成层面
- 答案真实性(忠实度):回答是否被检索上下文支撑,是否幻觉。
- 答案相关性:回答是否贴合用户提问,不跑题。
评估工具:Ragas
开源工具,输入:用户query、检索到的上下文、模型输出回答;自动计算各类RAG指标,适合项目验收。
五、RAG vs 模型微调对比
| 维度 | RAG | 模型微调 |
|---|---|---|
| 知识更新 | 更新知识库即可,不用改动模型,简单快速 | 需要重新微调模型,耗时耗算力,成本高 |
| 可解释性 | 回答可以溯源到参考文档 | 黑盒,无法溯源依据 |
| 幻觉抑制 | 有效降低幻觉(仍存在) | 依赖训练数据质量,幻觉风险高 |
| 推理性能 | 链路长,响应慢,token开销大 | 推理速度快,毫秒级 |
| 适用场景 | 私有知识库问答,企业知识库(优先选RAG) | 模型本身能力、风格、输出格式改造;小场景任务 |
落地经验:项目优先RAG;RAG效果不足,再考虑微调Embedding模型或者生成大模型;极少直接只用微调做知识库问答。
六、面试高频问题速记
- 索引阶段和查询阶段Embedding模型为什么必须一样?
只有同一个模型,文本才会映射到同一个向量空间,向量相似度对比才有意义。
- 为什么有向量相似度还要Rerank重排序?
Embedding向量是低维表征,只能粗粒度语义匹配;Rerank模型专门做query‑文本对的深度语义判断,做精排,解决误召回。
- HyDE解决什么问题?
解决问题文本和答案文本语义差距很大,直接用query向量召回不到正确文档的语义鸿沟。先用大模型生成假设文档,拿假设文档向量检索知识库。
- RAG效果不好怎么排查?
按链路排查:①索引阶段:切分策略是否合理、embedding模型选型;②检索前:是否做查询重写;③检索:召回的top‑k块是否包含正确信息;④检索后:是否做Rerank过滤噪声;⑤Prompt提示词设计。

浙公网安备 33010602011771号