引言
大语言模型(LLM)虽然强大,但存在几个关键局限:
- 知识截止 - 训练数据有截止日期,无法获取最新信息
- 幻觉问题 - 可能生成看似合理但实际错误的内容
- 领域局限 - 对特定领域知识掌握不足
- 无法溯源 - 无法说明信息来源
RAG(Retrieval-Augmented Generation,检索增强生成) 正是为解决这些问题而生的技术架构。
什么是RAG?
核心定义
RAG是一种将信息检索与文本生成相结合的技术架构。它在生成回答之前,先从外部知识库中检索相关信息,然后将检索结果作为上下文输入给大语言模型,从而生成更准确、更可靠的回答。
简单类比
想象RAG就像一个开卷考试的学生:
- 传统LLM = 闭卷考试,只能依赖记忆
- RAG = 开卷考试,可以查阅资料后再作答
工作流程
┌─────────────────────────────────────────────────────────┐
│ RAG 工作流程 │
├─────────────────────────────────────────────────────────┤
│ │
│ 用户提问 │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 查询理解 │ │
│ │ Query Understanding │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 向量检索 │◄────│ 向量数据库 │ │
│ │ Retrieval │ │ Vector DB │ │
│ └──────┬──────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 重排序 │ │
│ │ Reranking │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 上下文构建 │────►│ LLM │ │
│ │ Prompt │ │ 生成 │ │
│ │ Building │ │ Generation │ │
│ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ▼ │
│ 最终回答 │
│ │
└─────────────────────────────────────────────────────────┘
RAG的核心组件
1. 文档处理(Document Processing)
# 文档处理流程示例
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 加载文档
loader = PyPDFLoader("document.pdf")
docs = loader.load()
# 文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", " "]
)
chunks = text_splitter.split_documents(docs)
关键概念:
- Chunk Size - 每个文本块的大小(通常 200-1000 tokens)
- Overlap - 相邻块的重叠部分,保持上下文连贯
- 分割策略 - 按段落、句子或语义分割
2. 嵌入模型(Embedding Model)
from langchain_openai import OpenAIEmbeddings
# 初始化嵌入模型
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
dimensions=1536
)
# 生成向量
chunk_texts = [chunk.page_content for chunk in chunks]
vectors = embeddings.embed_documents(chunk_texts)
主流嵌入模型对比:
| 模型 | 维度 | 语言支持 | 特点 |
|---|---|---|---|
| text-embedding-3-small | 1536 | 多语言 | 性价比高 |
| text-embedding-3-large | 3072 | 多语言 | 精度更高 |
| bge-large-zh | 1024 | 中文优化 | 中文场景首选 |
| m3e-base | 768 | 中文 | 开源可商用 |
3. 向量数据库(Vector Database)
from langchain.vectorstores import Chroma
# 创建向量数据库
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
# 相似度检索
results = vectorstore.similarity_search(
query="什么是RAG?",
k=5 # 返回前5个结果
)
主流向量数据库对比:
| 数据库 | 特点 | 适用场景 |
|---|---|---|
| Chroma | 轻量、易用 | 本地开发、小型项目 |
| Pinecone | 托管服务、高性能 | 生产环境、大规模 |
| Milvus | 开源、分布式 | 企业级、海量数据 |
| Weaviate | 语义搜索强 | 复杂查询场景 |
| pgvector | PostgreSQL扩展 | 已有PG基础设施 |
4. 检索与重排序
# 基础检索
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 10}
)
# 重排序(Reranking)
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=retriever
)
检索策略:
- 相似度检索 - 基于向量相似度
- 混合检索 - 结合关键词和向量
- 多路召回 - 多种检索方式融合
5. 提示工程(Prompt Engineering)
from langchain.prompts import ChatPromptTemplate
template = """基于以下上下文回答问题。如果上下文中没有相关信息,请明确说明。
上下文:
{context}
问题:{question}
请提供准确、简洁的回答,并注明信息来源。
"""
prompt = ChatPromptTemplate.from_template(template)
RAG vs 其他方案
RAG vs 微调(Fine-tuning)
| 对比维度 | RAG | 微调 |
|---|---|---|
| 知识更新 | 实时更新 | 需要重新训练 |
| 成本 | 低(检索成本) | 高(训练成本) |
| 灵活性 | 高 | 低 |
| 适用场景 | 频繁变化的知识 | 固定领域知识 |
| 实现难度 | 中等 | 较高 |
RAG vs 长上下文
| 对比维度 | RAG | 长上下文 |
|---|---|---|
| 成本 | 低 | 高(按token计费) |
| 精度 | 高(精准检索) | 可能遗漏信息 |
| 速度 | 快 | 慢 |
| 适用文档 | 海量文档 | 少量长文档 |
RAG的应用场景
1. 企业知识库问答
- 内部文档查询
- 产品手册问答
- 规章制度检索
2. 客服机器人
- 基于产品文档回答
- 减少幻觉回答
- 提供可溯源答案
3. 代码助手
- 基于代码库检索
- API文档查询
- 最佳实践推荐
4. 法律/医疗咨询
- 法规条文检索
- 病例知识查询
- 专业文献参考
RAG的挑战与优化
常见挑战
-
检索质量
- 问题:检索不到相关内容
- 解决:查询改写、混合检索
-
上下文长度
- 问题:检索结果超出上下文限制
- 解决:重排序、上下文压缩
-
多跳推理
- 问题:需要多个文档综合回答
- 解决:Agent RAG、图检索
-
幻觉问题
- 问题:模型编造答案
- 解决:严格提示、引用溯源
优化策略
# 查询改写
from langchain.chains import HypotheticalDocumentEmbedder
hyde_embeddings = HypotheticalDocumentEmbedder.from_llm(
llm=llm,
base_embeddings=embeddings,
prompt_key="web_search"
)
# 混合检索
from langchain.retrievers import BM25Retriever, EnsembleRetriever
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 2
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.5, 0.5]
)
实战:搭建简单RAG系统
# 完整RAG系统示例
from langchain import hub
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
# 1. 加载向量数据库
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings
)
# 2. 创建检索器
retriever = vectorstore.as_retriever(
search_type="mmr", # 最大边际相关性
search_kwargs={"k": 5, "fetch_k": 10}
)
# 3. 初始化LLM
llm = ChatOpenAI(model="gpt-4", temperature=0)
# 4. 创建RAG链
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
chain_type_kwargs={"prompt": prompt}
)
# 5. 执行查询
result = qa_chain.invoke({"query": "什么是RAG?"})
print(result["result"])
print("\n来源文档:")
for doc in result["source_documents"]:
print(f"- {doc.metadata.get('source', 'Unknown')}")
RAG的未来趋势
- Agentic RAG - 结合Agent实现多跳推理
- 多模态RAG - 支持图片、音频、视频检索
- Graph RAG - 结合知识图谱进行推理
- 自适应RAG - 动态调整检索策略
- RAG评估 - 建立标准化评估体系
总结
RAG是解决大语言模型局限性的关键技术,通过将外部知识检索与文本生成相结合,实现了:
✅ 知识实时更新 - 无需重新训练模型
✅ 减少幻觉 - 基于检索内容生成回答
✅ 可溯源 - 明确信息来源
✅ 成本可控 - 比微调更经济
下一步学习建议:
本文最后更新于 2024-01-20,如有问题欢迎在社区讨论。