大语言模型(LLM)虽然强大,但存在知识截止日期、幻觉问题和领域知识不足等局限。RAG(Retrieval-Augmented Generation,检索增强生成)技术通过将外部知识库与LLM结合,有效解决了这些问题,成为构建企业级AI应用的核心技术。

📋 目录

TL;DR 核心要点

  • RAG本质:检索相关文档 + 增强LLM上下文 = 更准确的生成结果
  • 核心组件:检索器(Retriever)+ 生成器(Generator)
  • 关键技术:向量嵌入(Embedding)、语义搜索、上下文注入
  • 主要优势:实时知识更新、减少幻觉、可追溯来源、成本更低
  • 适用场景:企业知识库问答、文档智能检索、客服机器人、专业领域助手

想要快速体验AI工具?访问我们的AI工具集合:

👉 AI工具导航

什么是RAG

RAG(Retrieval-Augmented Generation)是一种将信息检索与文本生成相结合的AI技术架构。它的核心思想是:在LLM生成回答之前,先从外部知识库中检索相关信息,将这些信息作为上下文提供给模型,从而生成更准确、更有依据的回答。

RAG解决的核心问题

问题 传统LLM RAG方案
知识截止 训练数据有时效性 实时检索最新信息
幻觉问题 可能编造不存在的事实 基于真实文档生成
领域知识 通用知识,专业性不足 接入专业知识库
可追溯性 无法验证信息来源 提供引用来源
更新成本 需要重新训练模型 仅需更新知识库

RAG的工作原理

graph LR A[用户问题] --> B[查询处理] B --> C[向量化] C --> D[相似度检索] D --> E[知识库] E --> F[相关文档] F --> G[上下文构建] G --> H[LLM生成] H --> I[最终回答] style A fill:#e1f5fe style E fill:#fff3e0 style H fill:#f3e5f5 style I fill:#e8f5e9

RAG核心架构

一个完整的RAG系统由两大核心模块组成:检索器(Retriever)生成器(Generator)

系统架构图

graph TB subgraph "数据准备阶段" D1[原始文档] --> D2[文档分块] D2 --> D3[文本嵌入] D3 --> D4[向量数据库] end subgraph "检索阶段 - Retriever" Q1[用户查询] --> Q2[查询嵌入] Q2 --> Q3[相似度搜索] D4 --> Q3 Q3 --> Q4[Top-K文档] end subgraph "生成阶段 - Generator" Q4 --> G1[上下文构建] Q1 --> G1 G1 --> G2[Prompt模板] G2 --> G3[LLM推理] G3 --> G4[生成回答] end style D4 fill:#fff3e0 style G3 fill:#f3e5f5

检索器(Retriever)

检索器负责从知识库中找到与用户查询最相关的文档片段。

检索方法对比:

方法 原理 优点 缺点
稀疏检索(BM25) 关键词匹配 速度快、可解释 无法理解语义
密集检索(Dense) 向量相似度 语义理解强 需要嵌入模型
混合检索(Hybrid) 结合两者 效果最佳 实现复杂

生成器(Generator)

生成器基于检索到的上下文和用户问题,生成最终回答。

python
prompt_template = """
基于以下参考信息回答用户问题。如果参考信息中没有相关内容,请明确说明。

参考信息:
{context}

用户问题:{question}

回答:
"""

向量数据库详解

向量数据库是RAG系统的核心基础设施,负责存储和检索文档的向量表示。

向量嵌入原理

向量嵌入(Embedding)将文本转换为高维向量空间中的点,语义相似的文本在向量空间中距离更近。

graph LR subgraph "文本到向量" T1["'人工智能'"] --> E1[Embedding Model] T2["'机器学习'"] --> E1 T3["'美食烹饪'"] --> E1 E1 --> V1["0.8, 0.2, 0.9, ..."] E1 --> V2["0.7, 0.3, 0.85, ..."] E1 --> V3["0.1, 0.9, 0.2, ..."] end subgraph "向量空间" V1 -.->|相似| V2 V1 -.->|不相似| V3 end

主流向量数据库对比

数据库 特点 适用场景 开源
Chroma 轻量级、易上手 原型开发、小规模
Pinecone 全托管、高性能 生产环境、大规模
Milvus 功能丰富、可扩展 企业级部署
Weaviate GraphQL支持、模块化 复杂查询场景
Qdrant Rust实现、高性能 高并发场景
FAISS Facebook出品、高效 研究和原型

相似度计算方法

python
import numpy as np

def cosine_similarity(vec1, vec2):
    """余弦相似度:最常用的方法"""
    return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

def euclidean_distance(vec1, vec2):
    """欧氏距离:距离越小越相似"""
    return np.linalg.norm(vec1 - vec2)

def dot_product(vec1, vec2):
    """点积:向量已归一化时等价于余弦相似度"""
    return np.dot(vec1, vec2)

RAG vs 微调对比

RAG和微调(Fine-tuning)是增强LLM能力的两种主要方法,各有优劣。

详细对比

维度 RAG 微调(Fine-tuning)
知识更新 实时更新,仅需修改知识库 需要重新训练模型
成本 较低,主要是存储和检索成本 较高,需要GPU训练资源
准确性 基于真实文档,可追溯 知识内化,可能产生幻觉
延迟 略高(需要检索步骤) 较低(直接生成)
适用场景 知识密集型、需要引用来源 风格适配、特定任务优化
数据需求 文档即可,无需标注 需要高质量标注数据
可解释性 高,可展示引用来源 低,黑盒生成

选择建议

graph TD A[需要增强LLM能力] --> B{知识是否频繁更新?} B -->|是| C[选择RAG] B -->|否| D{是否需要引用来源?} D -->|是| C D -->|否| E{是否有大量标注数据?} E -->|是| F{是否需要特定风格?} E -->|否| C F -->|是| G[选择微调] F -->|否| H{预算是否充足?} H -->|是| I["RAG + 微调结合"] H -->|否| C style C fill:#e8f5e9 style G fill:#fff3e0 style I fill:#f3e5f5

RAG实现步骤

步骤1:文档准备与分块

文档分块是RAG的关键步骤,分块策略直接影响检索效果。

python
from langchain.text_splitter import RecursiveCharacterTextSplitter

def split_documents(documents, chunk_size=500, chunk_overlap=50):
    """
    文档分块策略
    - chunk_size: 每块大小,建议300-1000字符
    - chunk_overlap: 重叠部分,保持上下文连贯
    """
    splitter = RecursiveCharacterTextSplitter(
        chunk_size=chunk_size,
        chunk_overlap=chunk_overlap,
        separators=["\n\n", "\n", "。", "!", "?", ";", " "]
    )
    return splitter.split_documents(documents)

分块策略建议:

文档类型 推荐chunk_size 推荐overlap
技术文档 500-800 50-100
新闻文章 300-500 30-50
学术论文 800-1200 100-150
对话记录 200-400 20-40

步骤2:向量嵌入

python
from langchain.embeddings import OpenAIEmbeddings, HuggingFaceEmbeddings

openai_embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

local_embeddings = HuggingFaceEmbeddings(
    model_name="BAAI/bge-base-zh-v1.5",
    model_kwargs={'device': 'cuda'}
)

步骤3:向量存储

python
from langchain.vectorstores import Chroma

vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db"
)

步骤4:检索与生成

python
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=vectorstore.as_retriever(search_kwargs={"k": 5}),
    return_source_documents=True
)

result = qa_chain.invoke({"query": "什么是RAG技术?"})
print(result["result"])

Python代码实战

完整RAG系统实现

python
import os
from typing import List, Dict, Any
from langchain.document_loaders import DirectoryLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import RetrievalQA

class RAGSystem:
    """完整的RAG系统实现"""
    
    def __init__(
        self,
        embedding_model: str = "text-embedding-3-small",
        llm_model: str = "gpt-4-turbo",
        persist_directory: str = "./rag_db"
    ):
        self.embeddings = OpenAIEmbeddings(model=embedding_model)
        self.llm = ChatOpenAI(model=llm_model, temperature=0)
        self.persist_directory = persist_directory
        self.vectorstore = None
        self.qa_chain = None
        
    def load_documents(self, directory: str, glob: str = "**/*.txt") -> List:
        """加载文档"""
        loader = DirectoryLoader(
            directory,
            glob=glob,
            loader_cls=TextLoader,
            loader_kwargs={'encoding': 'utf-8'}
        )
        return loader.load()
    
    def process_documents(
        self,
        documents: List,
        chunk_size: int = 500,
        chunk_overlap: int = 50
    ) -> List:
        """文档分块处理"""
        splitter = RecursiveCharacterTextSplitter(
            chunk_size=chunk_size,
            chunk_overlap=chunk_overlap,
            separators=["\n\n", "\n", "。", "!", "?", " "]
        )
        return splitter.split_documents(documents)
    
    def build_vectorstore(self, chunks: List) -> None:
        """构建向量数据库"""
        self.vectorstore = Chroma.from_documents(
            documents=chunks,
            embedding=self.embeddings,
            persist_directory=self.persist_directory
        )
        
    def setup_qa_chain(self, k: int = 5) -> None:
        """设置问答链"""
        prompt_template = """你是一个专业的AI助手。请基于以下参考信息回答用户问题。
        
如果参考信息中没有相关内容,请明确说明"根据现有资料无法回答该问题"。
回答时请尽量引用具体来源。

参考信息:
{context}

用户问题:{question}

回答:"""
        
        prompt = PromptTemplate(
            template=prompt_template,
            input_variables=["context", "question"]
        )
        
        self.qa_chain = RetrievalQA.from_chain_type(
            llm=self.llm,
            chain_type="stuff",
            retriever=self.vectorstore.as_retriever(
                search_kwargs={"k": k}
            ),
            return_source_documents=True,
            chain_type_kwargs={"prompt": prompt}
        )
    
    def query(self, question: str) -> Dict[str, Any]:
        """执行查询"""
        if not self.qa_chain:
            raise ValueError("请先调用setup_qa_chain()初始化问答链")
        
        result = self.qa_chain.invoke({"query": question})
        return {
            "answer": result["result"],
            "sources": [
                {
                    "content": doc.page_content[:200] + "...",
                    "metadata": doc.metadata
                }
                for doc in result["source_documents"]
            ]
        }

if __name__ == "__main__":
    rag = RAGSystem()
    
    docs = rag.load_documents("./knowledge_base")
    chunks = rag.process_documents(docs)
    rag.build_vectorstore(chunks)
    rag.setup_qa_chain()
    
    result = rag.query("RAG技术的主要优势是什么?")
    print(f"回答:{result['answer']}")
    print(f"\n引用来源:")
    for i, source in enumerate(result['sources'], 1):
        print(f"{i}. {source['content']}")

高级检索策略实现

python
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

class AdvancedRAGSystem(RAGSystem):
    """高级RAG系统:支持多种检索策略"""
    
    def setup_hybrid_retriever(self, k: int = 5):
        """混合检索:结合语义搜索和关键词搜索"""
        from langchain.retrievers import BM25Retriever, EnsembleRetriever
        
        bm25_retriever = BM25Retriever.from_documents(self.chunks)
        bm25_retriever.k = k
        
        dense_retriever = self.vectorstore.as_retriever(
            search_kwargs={"k": k}
        )
        
        self.retriever = EnsembleRetriever(
            retrievers=[bm25_retriever, dense_retriever],
            weights=[0.3, 0.7]
        )
    
    def setup_reranking(self, k: int = 5):
        """重排序:使用LLM对检索结果进行重新排序"""
        base_retriever = self.vectorstore.as_retriever(
            search_kwargs={"k": k * 2}
        )
        
        compressor = LLMChainExtractor.from_llm(self.llm)
        
        self.retriever = ContextualCompressionRetriever(
            base_compressor=compressor,
            base_retriever=base_retriever
        )
    
    def setup_multi_query(self):
        """多查询检索:生成多个查询变体提高召回率"""
        from langchain.retrievers.multi_query import MultiQueryRetriever
        
        self.retriever = MultiQueryRetriever.from_llm(
            retriever=self.vectorstore.as_retriever(),
            llm=self.llm
        )

RAG最佳实践

1. 文档预处理优化

  • 清洗数据:去除噪声、格式化文本
  • 元数据增强:添加来源、时间、类别等信息
  • 结构化处理:保留标题、段落等结构信息

2. 检索策略优化

策略 描述 适用场景
混合检索 结合BM25和向量检索 通用场景
重排序 使用交叉编码器重排 高精度需求
多查询 生成查询变体 提高召回率
父文档检索 检索小块,返回大块 需要完整上下文

3. 提示工程优化

python
optimized_prompt = """
你是{domain}领域的专家助手。

## 任务
基于提供的参考资料回答用户问题。

## 规则
1. 仅使用参考资料中的信息
2. 如果资料不足,明确说明
3. 引用具体来源增加可信度
4. 使用清晰、专业的语言

## 参考资料
{context}

## 用户问题
{question}

## 回答
"""

4. 评估与监控

关键指标:

  • 检索准确率:Top-K文档的相关性
  • 回答质量:准确性、完整性、流畅性
  • 延迟:端到端响应时间
  • 成本:API调用和存储成本

常见问题

RAG和传统搜索引擎有什么区别?

传统搜索引擎返回文档列表,用户需要自己阅读和总结;RAG系统则直接生成综合性回答,并可以进行推理和总结。RAG结合了检索的精确性和LLM的生成能力。

如何处理RAG中的幻觉问题?

  1. 使用明确的提示词要求模型只基于检索内容回答
  2. 实现答案验证机制,检查生成内容与源文档的一致性
  3. 要求模型在不确定时明确表示
  4. 提供引用来源,方便用户验证

RAG系统的检索效果不好怎么办?

  1. 优化文档分块策略,调整chunk_size
  2. 尝试不同的嵌入模型
  3. 使用混合检索策略
  4. 添加重排序步骤
  5. 优化查询预处理

RAG适合处理多语言内容吗?

是的,但需要注意:

  1. 使用支持多语言的嵌入模型
  2. 考虑跨语言检索需求
  3. 可能需要语言检测和翻译模块

如何降低RAG系统的成本?

  1. 使用本地嵌入模型(如BGE、M3E)
  2. 实现缓存机制,避免重复计算
  3. 优化检索数量,减少上下文长度
  4. 使用更经济的LLM模型处理简单查询

总结

RAG技术是构建智能AI应用的关键技术,它有效解决了LLM的知识局限性问题,让AI系统能够基于最新、最准确的信息生成回答。

关键要点回顾

✅ RAG = 检索(Retrieval)+ 增强(Augmented)+ 生成(Generation)
✅ 核心组件:向量数据库 + 嵌入模型 + LLM
✅ 相比微调:更新成本低、可追溯、无需标注数据
✅ 关键优化:分块策略、检索策略、提示工程
✅ 适用场景:知识库问答、文档检索、智能客服

相关资源

延伸阅读


💡 开始实践:访问我们的 AI工具导航 探索更多AI开发工具和资源!