Chenyj Space
返回博客
·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 技术通过结合检索和生成,解决了大模型的多个痛点:

  1. 知识时效性: 访问最新信息
  2. 私有知识: 集成企业内部数据
  3. 减少幻觉: 基于事实生成答案
  4. 可追溯性: 提供信息来源

构建 RAG 系统的关键步骤:

  1. 文档处理与切分
  2. 向量嵌入与存储
  3. 检索策略设计
  4. 答案生成与优化

随着技术的发展,RAG 正在成为企业级 AI 应用的标准架构。


延伸阅读