RAG 从零到一:让大模型读懂你的文档
目录
- 什么是 RAG
- RAG 的核心流程
- 环境搭建与依赖安装
- 完整代码实现
- 代码逐行解析
- 运行测试
- 优化建议
- 总结
一、什么是 RAG
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合信息检索和文本生成的技术。
核心思想:让大模型在回答问题前,先从你的文档中检索相关信息,然后基于这些信息生成答案。
解决的核心问题:
问题 说明 RAG 的解决方案
知识陈旧 大模型训练数据有截止日期 实时检索最新文档
幻觉问题 模型会编造不存在的信息 强制基于检索内容回答
私有数据 模型不知道你的内部文档 让模型读取你的文档
通俗理解:
· 普通大模型 = 闭卷考试(凭记忆回答)
· RAG = 开卷考试(允许查阅资料)
二、RAG 的核心流程
┌─────────────────────────────────────────────────────────────────┐
│ RAG 完整流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 阶段一:索引(预处理) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 加载文档 │ -> │ 文本分割 │ -> │ 向量化 │ -> │ 存储 │ │
│ │ PDF/TXT │ │ Chunk │ │ Embed │ │ Chroma │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 阶段二:检索(查询时) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 用户问题 │ -> │ 向量化 │ -> │ 相似度 │ │
│ │ "什么是 │ │ Embed │ │ 检索 │ │
│ │ RAG?" │ │ │ │ Top-K │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │
│ ▼ │
│ 阶段三:生成(回答) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 问题+ │ -> │ 大模型 │ -> │ 最终 │ │
│ │ 检索结果 │ │ LLM │ │ 答案 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
三、环境搭建与依赖安装
3.1 依赖库清单
text
langchain
langchain-openai
langchain-community
langchain-chroma
langchain-huggingface
chromadb
sentence-transformers
pypdf
python-dotenv
3.2 一键安装
bash
pip install langchain langchain-openai langchain-community langchain-chroma langchain-huggingface chromadb sentence-transformers pypdf python-dotenv -i https://pypi.tuna.tsinghua.edu.cn/simple
3.3 配置 API Key
创建 .env 文件:
bash
DASHSCOPE_API_KEY="你的阿里云百炼API Key"
DASHSCOPE_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
3.4 准备测试文档
创建 sample.txt:
text
人工智能(AI)是计算机科学的一个分支,致力于创建能够执行通常需要人类智能的任务的系统。
这些任务包括视觉感知、语音识别、决策制定和语言翻译等。
机器学习是人工智能的一个子集,它使系统能够从数据中学习并改进,而无需明确编程。
深度学习是机器学习的一个子集,使用多层神经网络来处理复杂的数据模式。
大语言模型(LLM)如GPT、通义千问等,是基于深度学习技术的模型,能够理解和生成人类语言。
LangChain 是一个用于开发由大语言模型驱动的应用程序的框架。
检索增强生成(RAG)是一种结合信息检索和文本生成的技术,可以让大模型基于外部知识库回答问题,
有效解决大模型知识陈旧和幻觉问题。
四、完整代码实现
python
# rag_demo.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_chroma import Chroma
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
# 加载环境变量
load_dotenv()
# 初始化大模型
llm = ChatOpenAI(
model="qwen3-max",
temperature=0.7,
openai_api_key=os.getenv("DASHSCOPE_API_KEY"),
openai_api_base=os.getenv("DASHSCOPE_BASE_URL"),
)
print("=" * 60)
print("RAG 从零到一:让大模型读懂你的文档")
print("=" * 60)
# ========== 步骤1:加载文档 ==========
print("\n📄 步骤1:加载文档...")
loader = TextLoader("sample.txt", encoding="utf-8")
documents = loader.load()
print(f"✅ 已加载 {len(documents)} 个文档")
# ========== 步骤2:分割文档 ==========
print("\n✂️ 步骤2:分割文档...")
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300, # 每块最大字符数
chunk_overlap=50, # 块之间的重叠字符数
)
chunks = text_splitter.split_documents(documents)
print(f"✅ 文档已分割成 {len(chunks)} 个文本块")
# 显示前3个块
print("\n📝 文本块示例:")
for i, chunk in enumerate(chunks[:3]):
print(f" 块{i+1}: {chunk.page_content[:60]}...")
# ========== 步骤3:向量化 ==========
print("\n🔢 步骤3:向量化(将文本转换为向量)...")
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
print("✅ Embedding 模型已加载")
# ========== 步骤4:存储向量 ==========
print("\n🗄️ 步骤4:创建向量数据库...")
vectorstore = Chroma.from_documents(chunks, embeddings)
print("✅ 向量数据库已创建")
# ========== 步骤5:创建检索器 ==========
print("\n🔍 步骤5:创建检索器...")
retriever = vectorstore.as_retriever(
search_kwargs={"k": 3} # 每次检索返回3个最相关的文本块
)
print("✅ 检索器已创建")
# ========== 步骤6:创建 RAG 链 ==========
print("\n🔗 步骤6:创建 RAG 链...")
# 定义提示词模板
system_prompt = """
你是一个基于文档的问答助手。请根据以下检索到的文档内容回答问题。
检索到的相关内容:
{context}
问题:{input}
规则:
1. 只根据提供的文档内容回答
2. 如果文档中没有相关信息,明确说"根据现有文档无法回答"
3. 回答要准确、简洁
"""
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "{input}")
])
# 创建文档组合链
document_chain = create_stuff_documents_chain(llm, prompt)
# 创建检索链
rag_chain = create_retrieval_chain(retriever, document_chain)
print("✅ RAG 链已创建")
# ========== 步骤7:测试问答 ==========
print("\n" + "=" * 60)
print("💬 开始测试问答")
print("=" * 60)
test_questions = [
"什么是人工智能?",
"什么是RAG?",
"LangChain 是什么?",
"今天天气怎么样?", # 文档外的问题
]
for question in test_questions:
print(f"\n🤔 问题: {question}")
response = rag_chain.invoke({"input": question})
print(f"📖 回答: {response['answer']}")
print("\n" + "=" * 60)
print("✅ RAG 演示完成!")
print("=" * 60)
五、代码逐行解析
5.1 文档加载
python
from langchain_community.document_loaders import TextLoader
loader = TextLoader("sample.txt", encoding="utf-8")
documents = loader.load()
参数 说明
TextLoader 加载 txt 文件,支持 PDF 可改用 PyPDFLoader
encoding="utf-8" 指定编码,避免中文乱码
load() 返回 Document 对象列表
5.2 文本分割
python
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=50,
)
chunks = text_splitter.split_documents(documents)
参数 说明 建议值
chunk_size 每个块的最大字符数 300-1000
chunk_overlap 块之间的重叠字符数 chunk_size 的 10-20%
为什么需要重叠? 防止重要信息被切断在块边界。
5.3 向量化
python
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
模型 特点 大小
paraphrase-multilingual-MiniLM-L12-v2 支持中文,速度快 ~500MB
shibing624/text2vec-base-chinese 轻量中文 ~120MB
5.4 向量存储
python
from langchain_chroma import Chroma
vectorstore = Chroma.from_documents(chunks, embeddings)
from_documents 会自动:
- 遍历每个文本块
- 调用 Embedding 模型转换为向量
- 存储到 Chroma 数据库
5.5 检索器
python
retriever = vectorstore.as_retriever(
search_kwargs={"k": 3}
)
参数 说明
k 返回最相关的 Top-K 个文本块
5.6 RAG 链
python
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
document_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, document_chain)
组件 作用
create_stuff_documents_chain 将检索到的文档"填充"到提示词中
create_retrieval_chain 组合检索器和生成链
六、运行测试
6.1 执行脚本
bash
python rag_demo.py
6.2 预期输出
============================================================
RAG 从零到一:让大模型读懂你的文档
============================================================
📄 步骤1:加载文档...
✅ 已加载 1 个文档
✂️ 步骤2:分割文档...
✅ 文档已分割成 8 个文本块
📝 文本块示例:
块1: 人工智能(AI)是计算机科学的一个分支...
块2: 机器学习是人工智能的一个子集...
块3: 深度学习是机器学习的一个子集...
🔢 步骤3:向量化...
✅ Embedding 模型已加载
🗄️ 步骤4:创建向量数据库...
✅ 向量数据库已创建
🔍 步骤5:创建检索器...
✅ 检索器已创建
🔗 步骤6:创建 RAG 链...
✅ RAG 链已创建
============================================================
💬 开始测试问答
============================================================
🤔 问题: 什么是人工智能?
📖 回答: 人工智能(AI)是计算机科学的一个分支,致力于创建能够执行通常需要人类智能的任务的系统。
🤔 问题: 什么是RAG?
📖 回答: 检索增强生成(RAG)是一种结合信息检索和文本生成的技术,可以让大模型基于外部知识库回答问题,有效解决大模型知识陈旧和幻觉问题。
🤔 问题: LangChain 是什么?
📖 回答: LangChain 是一个用于开发由大语言模型驱动的应用程序的框架。
🤔 问题: 今天天气怎么样?
📖 回答: 根据现有文档无法回答
============================================================
✅ RAG 演示完成!
============================================================
七、优化建议
7.1 分块策略优化
python
# 针对不同文档类型调整
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 增大块大小,保留更多上下文
chunk_overlap=100, # 增加重叠,避免信息丢失
separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""]
)
7.2 检索优化
python
# 提高检索数量
retriever = vectorstore.as_retriever(
search_kwargs={"k": 5} # 返回更多相关块
)
# 设置相似度阈值
retriever = vectorstore.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={"score_threshold": 0.7, "k": 3}
)
7.3 提示词优化
python
system_prompt = """
你是公司内部文档助手,回答要专业、准确。
参考文档:
{context}
用户问题:{input}
要求:
1. 优先使用文档原文
2. 引用来源
3. 不确定时说不确定
"""
7.4 持久化存储
python
# 保存向量数据库,避免重复处理
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db" # 指定保存目录
)
# 下次直接加载
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings
)
八、常见问题
Q1:首次运行很慢?
首次运行需要下载 Embedding 模型(约 500MB),之后会缓存到本地。
Q2:中文乱码?
确保文档使用 UTF-8 编码,加载时指定 encoding="utf-8"。
Q3:回答不准确?
· 调整 chunk_size 和 chunk_overlap
· 增加 k 值,检索更多相关块
· 优化提示词模板
Q4:内存不足?
· 减小 chunk_size
· 使用更轻量的 Embedding 模型
· 分批处理文档
九、总结
本文完整实现了 RAG 的核心流程:
步骤 功能 代码实现
1 加载文档 TextLoader
2 分割文档 RecursiveCharacterTextSplitter
3 向量化 HuggingFaceEmbeddings
4 存储向量 Chroma.from_documents
5 创建检索器 vectorstore.as_retriever
6 创建 RAG 链 create_retrieval_chain
7 问答测试 rag_chain.invoke
核心代码(极简版):
python
# 5 行代码实现 RAG
loader = TextLoader("sample.txt")
chunks = RecursiveCharacterTextSplitter().split_documents(loader.load())
vectorstore = Chroma.from_documents(chunks, HuggingFaceEmbeddings())
retriever = vectorstore.as_retriever()
rag_chain = create_retrieval_chain(retriever, create_stuff_documents_chain(llm, prompt))