RAG 检索增强生成入门教程

教程简介

零基础RAG检索增强生成入门教程,涵盖RAG原理架构、文本分块策略、向量嵌入与向量数据库、LangChain实战、混合检索、查询改写、重排序等核心技能,配有企业知识问答系统实战项目,适合AI开发者学习。

RAG 检索增强生成入门教程

零基础掌握RAG(Retrieval-Augmented Generation)技术,从原理到实战,构建企业级知识问答系统。


一、什么是RAG?

1.1 RAG的定义

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

1.2 为什么需要RAG?

大语言模型(如GPT-4、Claude等)虽然强大,但存在以下局限性:

问题 说明 RAG如何解决
知识截止 模型训练数据有时间限制 实时检索最新信息
幻觉问题 模型可能编造不存在的事实 基于真实文档生成
领域知识不足 通用模型缺乏专业领域知识 接入专业知识库
数据隐私 企业数据不能用于外部训练 数据保留在本地知识库

1.3 RAG vs 微调 vs 长上下文

方案 优点 缺点 适用场景
RAG 知识可更新、可溯源、成本低 检索质量影响生成效果 知识问答、客服系统
微调 深度理解特定领域 成本高、知识难更新 特定风格/格式生成
长上下文 实现简单 Token消耗大、有长度限制 少量文档分析

二、RAG核心架构

2.1 整体流程

用户提问
   ↓
┌─────────────────────────────────┐
│         索引阶段 (Indexing)       │
│  文档加载 → 文本分块 → 向量化 → 存储  │
└─────────────────────────────────┘
   ↓
┌─────────────────────────────────┐
│         检索阶段 (Retrieval)      │
│  查询向量化 → 相似度搜索 → 返回Top-K  │
└─────────────────────────────────┘
   ↓
┌─────────────────────────────────┐
│         生成阶段 (Generation)     │
│  拼接Prompt → LLM生成 → 返回答案    │
└─────────────────────────────────┘
   ↓
返回带引用的答案

2.2 核心组件

  1. 文档加载器(Document Loader):读取各种格式的文档
  2. 文本分块器(Text Splitter):将长文档切分为合适大小的块
  3. 嵌入模型(Embedding Model):将文本转换为向量表示
  4. 向量数据库(Vector Store):存储和检索向量
  5. 检索器(Retriever):执行相似度搜索
  6. LLM(大语言模型):基于检索结果生成回答

三、文本分块策略

3.1 为什么需要分块?

  • 大模型上下文窗口有限
  • 检索精度与块大小相关
  • 不同内容需要不同的分块策略

3.2 常见分块方法

固定大小分块

from langchain.text_splitter import CharacterTextSplitter

splitter = CharacterTextSplitter(
    chunk_size=1000,      # 每块最大字符数
    chunk_overlap=200,    # 块之间重叠字符数
    separator="\n"        # 分隔符
)

text = """这里是需要分块的长文本内容..."""
chunks = splitter.split_text(text)
print(f"共分为 {len(chunks)} 个块")

递归字符分块(推荐)

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    separators=["\n\n", "\n", "。", "!", "?", ",", " ", ""]
)

chunks = splitter.split_text(long_text)

语义分块

from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
splitter = SemanticChunker(embeddings)

chunks = splitter.split_text(long_text)

3.3 分块最佳实践

  • 块大小:通常500-1500个字符,根据内容类型调整
  • 重叠:建议10%-20%的重叠,避免上下文断裂
  • 元数据:保留来源、页码等信息
  • 中文处理:注意按句子边界分割,避免截断句子

四、向量嵌入与向量数据库

4.1 什么是向量嵌入?

向量嵌入是将文本转换为高维数值向量的过程。语义相似的文本在向量空间中距离更近。

from sentence_transformers import SentenceTransformer

model = SentenceTransformer('BAAI/bge-base-zh-v1.5')  # 中文嵌入模型

sentences = [
    "什么是机器学习?",
    "机器学习的定义是什么?",
    "今天天气怎么样?"
]

embeddings = model.encode(sentences)
print(f"向量维度: {embeddings.shape}")  # (3, 768)

# 计算相似度
from sklearn.metrics.pairwise import cosine_similarity
sim_matrix = cosine_similarity(embeddings)
print(f"'机器学习' vs '机器学习定义': {sim_matrix[0][1]:.4f}")  # 高相似度
print(f"'机器学习' vs '天气': {sim_matrix[0][2]:.4f}")  # 低相似度

4.2 常用嵌入模型

模型 特点 维度 推荐场景
BAAI/bge-base-zh-v1.5 中文优秀、开源 768 中文场景首选
text-embedding-3-small OpenAI、性价比高 1536 多语言场景
text-embedding-3-large OpenAI、精度最高 3072 高精度需求
m3e-base 中文、轻量 768 资源受限场景

4.3 向量数据库对比

数据库 特点 部署方式 推荐场景
ChromaDB 轻量、易用 嵌入式 快速原型开发
FAISS Facebook开源、高性能 嵌入式 大规模向量搜索
Milvus 分布式、云原生 独立服务 生产环境
Pinecone 全托管SaaS 云服务 无需运维
Weaviate 支持混合搜索 独立服务 复杂检索需求

五、实战:用LangChain构建RAG系统

5.1 环境准备

pip install langchain langchain-openai langchain-community chromadb pypdf

5.2 完整RAG实现

import os
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.document_loaders import PyPDFLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

# ========== 第一步:加载文档 ==========
def load_documents(file_paths):
    """加载多个文档"""
    documents = []
    for path in file_paths:
        if path.endswith('.pdf'):
            loader = PyPDFLoader(path)
        elif path.endswith('.txt'):
            loader = TextLoader(path, encoding='utf-8')
        else:
            continue
        documents.extend(loader.load())
    print(f"共加载 {len(documents)} 页文档")
    return documents

# ========== 第二步:文本分块 ==========
def split_documents(documents):
    """将文档分块"""
    splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200,
        separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""]
    )
    chunks = splitter.split_documents(documents)
    print(f"共分为 {len(chunks)} 个文本块")
    return chunks

# ========== 第三步:创建向量数据库 ==========
def create_vectorstore(chunks, persist_dir="./chroma_db"):
    """创建并持久化向量数据库"""
    embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
    vectorstore = Chroma.from_documents(
        documents=chunks,
        embedding=embeddings,
        persist_directory=persist_dir
    )
    print(f"向量数据库已创建,保存至 {persist_dir}")
    return vectorstore

# ========== 第四步:构建RAG链 ==========
def create_rag_chain(vectorstore):
    """创建RAG问答链"""
    llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

    prompt_template = """基于以下上下文信息回答用户的问题。
如果上下文中没有相关信息,请说明你无法根据已有信息回答。

上下文:
{context}

问题:{question}

回答:"""

    prompt = PromptTemplate(
        template=prompt_template,
        input_variables=["context", "question"]
    )

    qa_chain = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=vectorstore.as_retriever(
            search_type="similarity",
            search_kwargs={"k": 4}
        ),
        chain_type_kwargs={"prompt": prompt},
        return_source_documents=True
    )
    return qa_chain

# ========== 主程序 ==========
if __name__ == "__main__":
    # 1. 加载文档
    files = ["./docs/company_intro.pdf", "./docs/product_manual.txt"]
    documents = load_documents(files)

    # 2. 分块
    chunks = split_documents(documents)

    # 3. 创建向量数据库
    vectorstore = create_vectorstore(chunks)

    # 4. 创建RAG链
    qa_chain = create_rag_chain(vectorstore)

    # 5. 提问
    while True:
        question = input("\n请输入问题(输入q退出):")
        if question.lower() == 'q':
            break

        result = qa_chain.invoke({"query": question})
        print(f"\n回答:{result['result']}")
        print(f"\n参考来源:")
        for doc in result['source_documents']:
            print(f"  - {doc.metadata.get('source', '未知')}")

5.3 运行效果示例

请输入问题:公司的核心产品有哪些?

回答:根据公司介绍文档,公司目前有三大核心产品:
1. 智能客服系统 - 基于大模型的7x24小时客服解决方案
2. 知识管理平台 - 企业级RAG知识库系统
3. AI写作助手 - 面向内容创作者的AI辅助工具

参考来源:
  - ./docs/company_intro.pdf (第3页)
  - ./docs/product_manual.txt (第1页)

六、进阶优化技巧

6.1 混合检索

结合关键词检索和语义检索,提高召回率:

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever

# BM25关键词检索器
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 4

# 向量检索器
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# 混合检索
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.4, 0.6]  # BM25权重0.4,向量权重0.6
)

6.2 查询改写

优化用户查询,提高检索质量:

from langchain.prompts import ChatPromptTemplate

rewrite_prompt = ChatPromptTemplate.from_template(
    "请将以下用户问题改写为更适合搜索的形式,"
    "保持原意但使用更准确的关键词:\n\n"
    "原始问题:{question}\n"
    "改写后的搜索查询:"
)

6.3 重排序

对检索结果进行重排序,将最相关的内容排在前面:

from sentence_transformers import CrossEncoder

reranker = CrossEncoder('BAAI/bge-reranker-base')

def rerank(query, documents, top_k=3):
    pairs = [(query, doc.page_content) for doc in documents]
    scores = reranker.predict(pairs)
    ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True)
    return [doc for doc, score in ranked[:top_k]]

七、常见问题与解决方案

Q1:检索结果不相关怎么办?

  • 检查分块策略是否合理
  • 尝试不同的嵌入模型
  • 使用混合检索
  • 添加查询改写

Q2:回答质量不高如何优化?

  • 增加检索的文档数量(k值)
  • 优化Prompt模板
  • 使用重排序
  • 确保上下文信息完整

Q3:如何处理多轮对话?

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True
)

八、总结

RAG技术是当前企业落地大模型应用的最重要技术之一。通过本文的学习,你应该掌握了:

  1. ✅ RAG的核心概念和工作原理
  2. ✅ 文本分块的各种策略
  3. ✅ 向量嵌入和向量数据库的使用
  4. ✅ 使用LangChain构建完整RAG系统
  5. ✅ 混合检索、查询改写、重排序等优化技巧

下一步学习建议

  • 尝试用你自己的文档构建RAG系统
  • 探索多模态RAG(图片、表格)
  • 学习RAG评估指标(如Faithfulness、Relevancy)
  • 了解Agentic RAG(带Agent的RAG系统)

本教程内容基于公开技术文档和开源项目整理,仅供学习参考。

内容声明

本文内容为AI技术学习教程,仅供学习参考。如涉及技术问题,欢迎通过 xurj005@163.com 与我们交流。

目录