RAG简介
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read436 words

RAG简介

检索增强生成(Retrieval-Augmented Generation,RAG)是目前最流行的LLM应用架构。

什么是RAG?

RAG通过检索外部知识库,增强LLM的生成能力。

graph LR A[用户问题] --> B[检索] B --> C[向量数据库] C --> D[相关文档] D --> E[拼接Prompt] E --> F[LLM生成] F --> G[答案] style A fill:#e1f5ff style G fill:#c8e6c9 C -.->|索引| H[文档库]

为什么需要RAG?

LLM的局限性

问题 原因 影响
知识过时 训练截止日期 无法回答新事件
幻觉 生成式模型本质 可能编造事实
不透明 黑盒模型 难以追溯信息来源
知识局限 无法容纳所有知识 无法回答专有领域问题

RAG的优势

实时性 - 可访问最新信息 ✅ 准确性 - 减少幻觉,基于事实 ✅ 可控性 - 明确数据来源 ✅ 成本低 - 无需微调模型 ✅ 可更新 - 知识库易于维护 ✅ 隐私安全 - 数据本地化

RAG工作流程

完整流程

sequenceDiagram participant U as 用户 participant A as 应用 participant R as 检索器 participant V as 向量数据库 participant L as LLM U->>A: 提问 A->>R: 检索 R->>V: 查询向量 V-->>R: 相关文档 R-->>A: 检索结果 A->>A: 构建Prompt A->>L: 生成请求 L-->>A: 生成答案 A-->>U: 返回答案

详细步骤

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
# 步骤1: 准备文档
documents = [
"Python是一种高级编程语言,由Guido van Rossum于1991年创建。",
"Python以其简洁清晰的语法而闻名,适合快速开发。",
"Python广泛应用于Web开发、数据科学、人工智能等领域。",
]
# 步骤2: 文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200,
chunk_overlap=50
)
chunks = text_splitter.split_documents(
[{"page_content": doc} for doc in documents]
)
# 步骤3: 创建向量数据库
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings
)
# 步骤4: 定义检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# 步骤5: 构建Prompt
prompt = ChatPromptTemplate.from_template("""
基于以下参考信息回答问题:
参考信息:
{context}
问题:{question}
如果参考信息不足,请明确说明。
""")
# 步骤6: 创建LLM
llm = ChatOpenAI(model="gpt-4o-mini")
# 步骤7: 构建RAG链
def format_docs(docs):
"""格式化文档"""
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
)
# 步骤8: 执行查询
query = "Python是什么时候创建的?"
result = rag_chain.invoke(query)
print(result.content)

核心组件

1. 文档加载器

from langchain_community.document_loaders import (
TextLoader,
PyPDFLoader,
WebBaseLoader,
DirectoryLoader
)
# 加载文本文件
text_loader = TextLoader("document.txt")
docs = text_loader.load()
# 加载PDF
pdf_loader = PyPDFLoader("paper.pdf")
pdf_docs = pdf_loader.load()
# 加载网页
web_loader = WebBaseLoader("https://example.com")
web_docs = web_loader.load()
# 加载整个目录
dir_loader = DirectoryLoader(
"./docs/",
glob="**/*.txt",
loader_cls=TextLoader
)
all_docs = dir_loader.load()

2. 文本分割器

from langchain.text_splitter import (
RecursiveCharacterTextSplitter,
CharacterTextSplitter,
TokenTextSplitter
)
# 递归分割(推荐)
recursive_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", " ", ""]
)
# 字符分割
character_splitter = CharacterTextSplitter(
chunk_size=1000,
chunk_overlap=0,
separator="\n\n"
)
# Token分割
token_splitter = TokenTextSplitter(
chunk_size=500,
chunk_overlap=50,
encoding_name="cl100k_base"  # GPT-4的tokenizer
)
# 使用
chunks = recursive_splitter.split_documents(docs)
print(f"分割后得到 {len(chunks)} 个文档块")

3. 嵌入模型

from langchain_openai import OpenAIEmbeddings
from langchain_community.embeddings import HuggingFaceEmbeddings
# OpenAI嵌入
openai_embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
openai_api_key="your_api_key"
)
# 开源嵌入(本地)
huggingface_embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
model_kwargs={'device': 'cuda'}  # 使用GPU
)
# 使用
text = "这是一个测试句子"
embedding_vector = openai_embeddings.embed_query(text)
print(f"嵌入向量维度: {len(embedding_vector)}")  # 1536 for text-embedding-3-small

4. 向量数据库

from langchain_community.vectorstores import Chroma, FAISS, Pinecone
import os
# Chroma(本地,推荐)
chroma_db = Chroma.from_documents(
documents=chunks,
embedding=openai_embeddings,
persist_directory="./chroma_db"
)
# FAISS(快速,本地)
faiss_db = FAISS.from_documents(
documents=chunks,
embedding=openai_embeddings
)
# Pinecone(云服务,推荐生产环境)
pinecone_db = Pinecone.from_documents(
documents=chunks,
embedding=openai_embeddings,
index_name="my-index",
namespace="test-namespace"
)
# 检索
query = "Python的特点"
results = chroma_db.similarity_search(query, k=3)
for i, doc in enumerate(results, 1):
print(f"结果 {i}: {doc.page_content[:100]}...")

5. 检索策略

# 相似度搜索
results = vectorstore.similarity_search(query, k=3)
# 带分数的相似度搜索
results_with_scores = vectorstore.similarity_search_with_score(query, k=3)
for doc, score in results_with_scores:
print(f"分数: {score:.4f} | 内容: {doc.page_content[:50]}...")
# 最大边界相关性搜索(MMR)
from langchain_community.vectorstores.utils import DistanceStrategy
mmr_results = vectorstore.max_marginal_relevance_search(
query,
k=3,
fetch_k=10  # 先获取10个候选,再选3个
)

RAG架构类型

1. Naive RAG(基础RAG)

最简单的架构,直接检索后生成。

graph LR A[查询] --> B[检索] B --> C[LLM] C --> D[输出]

2. Advanced RAG(高级RAG)

包含预处理、检索优化、后处理。

graph TB A[查询] --> B[查询重写] B --> C[检索] C --> D[重排序] D --> E[LLM] E --> F[输出] G[文档] --> H[预处理] H --> C E --> I[后处理] I --> F

3. Modular RAG(模块化RAG)

灵活组合不同模块。

graph TB subgraph "输入模块" A[查询] --> B[路由] end subgraph "检索模块" C[检索器1] D[检索器2] E[混合检索] end subgraph "生成模块" F[LLM1] G[LLM2] end B --> C B --> D B --> E C --> F D --> F E --> G

实践案例

案例1: 企业知识库问答

class EnterpriseKnowledgeBase:
"""企业知识库RAG系统"""
def __init__(self, docs_path: str):
self.docs_path = docs_path
self.embeddings = OpenAIEmbeddings()
self.vectorstore = None
self.llm = ChatOpenAI(model="gpt-4o")
def build_index(self):
"""构建索引"""
# 加载文档
loader = DirectoryLoader(self.docs_path, glob="**/*.md")
docs = loader.load()
# 分割
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
chunks = splitter.split_documents(docs)
# 创建向量数据库
self.vectorstore = Chroma.from_documents(
documents=chunks,
embedding=self.embeddings,
persist_directory="./chroma_kb"
)
print(f"✅ 索引构建完成,共 {len(chunks)} 个文档块")
def query(self, question: str) -> str:
"""查询"""
if not self.vectorstore:
return "请先构建索引"
# 检索
retriever = self.vectorstore.as_retriever(search_kwargs={"k": 3})
docs = retriever.invoke(question)
# 构建Prompt
context = "\n\n".join(doc.page_content for doc in docs)
prompt = f"""
你是一个企业知识库助手。基于以下文档回答用户问题。
参考文档:
{context}
用户问题:{question}
请提供准确、有用的回答。如果文档中没有相关信息,请明确说明。
"""
# 生成
response = self.llm.invoke(prompt)
return response.content
# 使用
kb = EnterpriseKnowledgeBase("./company_docs/")
kb.build_index()
answer = kb.query("公司的请假政策是什么?")
print(answer)

案例2: 代码文档查询

class CodeDocSearcher:
"""代码文档查询系统"""
def __init__(self, repo_path: str):
self.repo_path = repo_path
self.embeddings = OpenAIEmbeddings()
self.vectorstore = None
def load_code(self):
"""加载代码文件"""
from langchain_community.document_loaders import TextLoader
code_files = []
for root, _, files in os.walk(self.repo_path):
for file in files:
if file.endswith(('.py', '.js', '.ts')):
filepath = os.path.join(root, file)
loader = TextLoader(filepath)
docs = loader.load()
code_files.extend(docs)
return code_files
def build_index(self):
"""构建代码索引"""
docs = self.load_code()
# 代码特定的分割
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\ndef ", "\nclass ", "\n# ", "\n"]
)
chunks = splitter.split_documents(docs)
self.vectorstore = Chroma.from_documents(
documents=chunks,
embedding=self.embeddings
)
print(f"✅ 代码索引构建完成,共 {len(chunks)} 个代码块")
def search_code(self, query: str):
"""搜索代码"""
if not self.vectorstore:
return []
results = self.vectorstore.similarity_search(query, k=5)
return results
# 使用
code_searcher = CodeDocSearcher("./my_project/")
code_searcher.build_index()
results = code_searcher.search_code("如何连接数据库")
for doc in results:
print(f"文件: {doc.metadata.get('source', 'unknown')}")
print(f"代码:\n{doc.page_content}\n")

学习要点

✅ RAG通过检索外部知识增强LLM ✅ 核心组件:文档加载、分割、嵌入、向量数据库、LLM ✅ 三种架构:Naive RAG、Advanced RAG、Modular RAG ✅ 可以用于企业知识库、代码查询等多种场景 ✅ 相比微调,RAG更灵活、成本更低


下一步: 学习 构建完整RAG系统 🏗️