·21 分钟
RAG 全解析:让大模型拥有外部知识
RAG向量数据库检索增强知识库AI
什么是 RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合检索和生成的技术,让大模型能够访问外部知识库,从而提供更准确、更及时的回答。
核心思想
code
传统大模型: 用户提问 → 模型生成答案(基于训练数据)
RAG: 用户提问 → 检索相关文档 → 结合文档生成答案
为什么需要 RAG?
1. 知识时效性问题
code
问题: "2026年诺贝尔物理学奖得主是谁?"
传统大模型: "抱歉,我的知识截止到2024年..."
RAG: [检索最新新闻] → "2026年诺贝尔物理学奖授予了..."
2. 私有知识问题
code
问题: "我们公司的请假流程是什么?"
传统大模型: "一般公司的请假流程是..."
RAG: [检索公司制度文档] → "根据《员工手册》第3章..."
3. 减少幻觉
code
问题: "量子计算机目前的量子比特数是多少?"
传统大模型: 可能编造一个数字
RAG: [检索最新论文] → "根据IBM 2026年发布的报告..."
RAG 系统架构
code
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 用户提问 │ ──→ │ 检索系统 │ ──→ │ 大模型 │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
↓ ↓
┌─────────────┐ ┌─────────────┐
│ 向量数据库 │ │ 生成答案 │
└─────────────┘ └─────────────┘
核心组件详解
1. 文档处理与切分
将文档切分成小块(chunks),便于检索:
python
# 文档切分策略
def split_document(text, chunk_size=500, overlap=50):
"""
将文档切分成固定大小的块
- chunk_size: 每块的字符数
- overlap: 块之间的重叠字符数
"""
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunk = text[start:end]
chunks.append(chunk)
start = end - overlap
return chunks
切分策略对比:
| 策略 | 优点 | 缺点 |
|---|---|---|
| 固定长度 | 简单高效 | 可能切断语义 |
| 按句子 | 语义完整 | 块大小不一致 |
| 按段落 | 保留上下文 | 可能过长 |
| 语义切分 | 语义最完整 | 计算成本高 |
2. 向量嵌入(Embedding)
将文本转换为向量表示:
python
from openai import OpenAI
client = OpenAI()
def get_embedding(text):
"""获取文本的向量嵌入"""
response = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
# 示例
text = "RAG 是一种检索增强生成技术"
vector = get_embedding(text)
print(f"向量维度: {len(vector)}") # 通常是 1536 维
3. 向量数据库
存储和检索向量:
python
import chromadb
# 创建向量数据库
client = chromadb.Client()
collection = client.create_collection("my_docs")
# 添加文档
collection.add(
documents=["RAG 是检索增强生成技术", "向量数据库存储嵌入向量"],
ids=["doc1", "doc2"]
)
# 检索相似文档
results = collection.query(
query_texts=["什么是 RAG?"],
n_results=3
)
常见向量数据库:
- ChromaDB: 轻量级,适合开发测试
- Pinecone: 云托管,适合生产环境
- Weaviate: 开源,支持多种搜索
- Milvus: 高性能,适合大规模数据
4. 检索策略
python
# 1. 相似度检索
def similarity_search(query, top_k=5):
query_vector = get_embedding(query)
results = collection.query(
query_embeddings=[query_vector],
n_results=top_k
)
return results
# 2. 混合检索(结合关键词和语义)
def hybrid_search(query, top_k=5):
# 语义检索
semantic_results = similarity_search(query, top_k)
# 关键词检索
keyword_results = keyword_search(query, top_k)
# 合并结果
return merge_results(semantic_results, keyword_results)
完整 RAG 实现
python
from openai import OpenAI
import chromadb
class RAGSystem:
def __init__(self):
self.client = OpenAI()
self.db_client = chromadb.Client()
self.collection = self.db_client.create_collection("knowledge_base")
def add_documents(self, documents):
"""添加文档到知识库"""
for i, doc in enumerate(documents):
# 获取嵌入向量
embedding = self.get_embedding(doc)
# 存储到向量数据库
self.collection.add(
documents=[doc],
embeddings=[embedding],
ids=[f"doc_{i}"]
)
def get_embedding(self, text):
"""获取文本嵌入"""
response = self.client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
def retrieve(self, query, top_k=3):
"""检索相关文档"""
query_embedding = self.get_embedding(query)
results = self.collection.query(
query_embeddings=[query_embedding],
n_results=top_k
)
return results['documents'][0]
def generate(self, query):
"""生成答案"""
# 1. 检索相关文档
relevant_docs = self.retrieve(query)
# 2. 构建提示词
context = "\n".join(relevant_docs)
prompt = f"""基于以下参考信息回答问题。如果参考信息中没有相关内容,请说明。
参考信息:
{context}
问题: {query}
答案:"""
# 3. 生成答案
response = self.client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
# 使用示例
rag = RAGSystem()
# 添加知识
rag.add_documents([
"RAG 是检索增强生成技术,结合了检索和生成两种方法",
"向量数据库用于存储和检索文本的向量表示",
"嵌入模型将文本转换为高维向量"
])
# 提问
answer = rag.generate("什么是 RAG?")
print(answer)
高级优化技巧
1. 查询改写(Query Rewriting)
优化用户查询,提高检索质量:
python
def rewrite_query(original_query):
"""改写查询以提高检索效果"""
prompt = f"""请将以下查询改写为更适合搜索的形式。
保持原意,但使用更通用的关键词。
原查询: {original_query}
改写后:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
2. 重排序(Re-ranking)
对检索结果进行二次排序:
python
from sentence_transformers import CrossEncoder
def rerank(query, documents, top_k=3):
"""使用交叉编码器重排序"""
model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
# 构建查询-文档对
pairs = [(query, doc) for doc in documents]
# 计算相关性分数
scores = model.predict(pairs)
# 按分数排序
scored_docs = list(zip(documents, scores))
scored_docs.sort(key=lambda x: x[1], reverse=True)
return [doc for doc, score in scored_docs[:top_k]]
3. 上下文压缩
减少输入长度,降低成本:
python
def compress_context(query, documents):
"""压缩上下文,只保留相关信息"""
prompt = f"""从以下文档中提取与问题相关的关键信息。
只保留直接相关的内容,删除无关信息。
问题: {query}
文档:
{chr(10).join(documents)}
压缩后的内容:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
实际应用场景
1. 企业知识库
code
场景: 员工询问公司政策
数据源: 员工手册、制度文档、FAQ
优势: 准确引用官方文档,减少误解
2. 客户支持
code
场景: 客户询问产品问题
数据源: 产品文档、历史工单、知识库
优势: 快速准确回答,减少人工客服压力
3. 学术研究
code
场景: 研究者询问领域问题
数据源: 论文、教科书、研究资料
优势: 引用最新研究,提供准确信息
4. 法律咨询
code
场景: 询问法律条文解释
数据源: 法律法规、判例、司法解释
优势: 准确引用法条,减少错误
常见问题与解决方案
Q1: 检索结果不相关
解决方案:
- 优化文档切分策略
- 使用更好的嵌入模型
- 实现查询改写
- 添加重排序步骤
Q2: 答案不准确
解决方案:
- 增加检索的文档数量
- 优化提示词模板
- 添加事实验证步骤
- 使用引用追踪
Q3: 响应速度慢
解决方案:
- 使用更快的向量数据库
- 实现缓存机制
- 优化文档索引
- 使用流式输出
总结
RAG 技术通过结合检索和生成,解决了大模型的多个痛点:
- 知识时效性: 访问最新信息
- 私有知识: 集成企业内部数据
- 减少幻觉: 基于事实生成答案
- 可追溯性: 提供信息来源
构建 RAG 系统的关键步骤:
- 文档处理与切分
- 向量嵌入与存储
- 检索策略设计
- 答案生成与优化
随着技术的发展,RAG 正在成为企业级 AI 应用的标准架构。
延伸阅读: