LangChain 构建 RAG 应用学习笔记

最近在学习和实践 LangChain 构建 RAG 应用,整理了一份学习笔记,内容包括 RAG 核心概念、LangChain 组件体系、实战项目以及一些经验总结。

一、RAG 技术概述

1.1 什么是 RAG

RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合检索系统与生成模型的技术架构。其核心流程是:用户提问 → 检索相关文档 → 将文档与问题组合 → LLM 生成答案。

1.2 RAG 的优势

RAG 技术具有以下显著优势:

  • 知识时效性:可接入最新文档数据,解决 LLM 知识截止问题
  • 可解释性:答案来源于检索文档,便于追溯和验证
  • 成本效益:更新知识无需重新训练模型,降低维护成本
  • 减少幻觉:基于检索内容生成,降低 LLM 胡编乱造的风险

1.3 RAG 流程图

用户提问 → 向量检索 → 上下文组装 → LLM 生成 → 最终回答

二、LangChain 核心组件详解

LangChain 将 RAG 流程拆解为多个独立模块,主要包括以下组件:

2.1 文档加载器(Document Loader)

LangChain 支持多种文档格式的加载:

from langchain_community.document_loaders import TextLoader, PyPDFLoader, WebBaseLoader

# 文本文件加载
loader = TextLoader("document.txt")
docs = loader.load()

# PDF 文件加载
loader = PyPDFLoader("document.pdf")
docs = loader.load()

# 网页内容加载
loader = WebBaseLoader("https://example.com/article")
docs = loader.load()

提示:文件较多时,可使用 DirectoryLoader 一次性处理整个目录。

2.2 文本分割器(Text Splitter)

长文档需要切割成小块以适应向量检索和 LLM 上下文限制:

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,      # 每段字符数
    chunk_overlap=50,    # 相邻段重叠字符数
    length_function=len
)

chunks = splitter.split_documents(docs)

参数设置建议

  • chunk_size:推荐 500-1000 字符,过大会降低检索精度,过小会丢失上下文
  • chunk_overlap:建议设为 chunk_size 的 10-20%,保证语义连贯

2.3 嵌入模型(Embedding)

文本向量化是计算语义相似度的基础:

from langchain_community.embeddings import OpenAIEmbeddings, HuggingFaceEmbeddings

# OpenAI 方案
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

# 本地方案
embeddings = HuggingFaceEmbeddings(
    model_name="sentence-transformers/all-MiniLM-L6-v2"
)

选型建议

  • 正式项目推荐使用 OpenAI Embedding,效果更好
  • 数据敏感场景可使用 HuggingFace 本地模型

2.4 向量数据库(Vector Store)

存储向量并支持高效相似度检索:

from langchain_community.vectorstores import Chroma, FAISS

# Chroma:轻量级,适合原型开发
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db"
)

# FAISS:高性能,适合大规模数据
vectorstore = FAISS.from_documents(
    documents=chunks,
    embedding=embeddings
)
vectorstore.save_local("./faiss_index")

向量数据库对比

数据库 特点 适用场景
Chroma 轻量、易用 原型开发、小规模数据
FAISS 高性能、多索引 大规模数据、实时检索
Milvus 分布式、可扩展 企业级应用
Pinecone 云原生、托管服务 不想管理基础设施

2.5 检索器(Retriever)

从向量库中检索相关文档:

# 基础相似度检索
retriever = vectorstore.as_retriever(
    search_kwargs={"k": 3}  # 返回最相关的3个文档
)

# MMR 策略:增加结果多样性
retriever = vectorstore.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 3, "fetch_k": 10}
)

MMR(最大边际相关性):先从数据库取出多个候选,再选择多样性结果,避免返回内容过于相似。

2.6 问答链(Chain)

组装各组件形成完整 RAG 流程:

from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

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

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",  # 将文档拼接到 prompt
    retriever=retriever,
    return_source_documents=True  # 返回源文档
)

result = qa_chain({"query": "RAG 是什么?"})

chain_type 类型说明

  • stuff:将所有文档拼接到一起,简单高效,文档多时可能超出上下文
  • refine:迭代优化答案,适合处理长文档
  • map_reduce:分别处理后合并,适合大量检索结果

三、实战项目:构建完整 RAG 应用

3.1 项目结构

rag_app/
├── main.py              # 主程序
├── requirements.txt     # 依赖
└── docs/                # 知识库文档
    ├── intro.txt
    └── guide.txt

3.2 完整代码实现

import os
from langchain_community.document_loaders import TextLoader
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

class RAGApp:
    def __init__(self, docs_path):
        self.docs_path = docs_path
        self.embeddings = OpenAIEmbeddings()

        # 加载并处理文档
        docs = self._load_docs()
        chunks = self._split_docs(docs)

        # 构建向量索引
        self.vectorstore = Chroma.from_documents(
            documents=chunks,
            embedding=self.embeddings,
            persist_directory="./chroma_db"
        )

        # 初始化 LLM 和检索链
        self.llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
        self.qa_chain = RetrievalQA.from_chain_type(
            llm=self.llm,
            chain_type="stuff",
            retriever=self.vectorstore.as_retriever(search_kwargs={"k": 3}),
            return_source_documents=True
        )

    def _load_docs(self):
        docs = []
        for fname in os.listdir(self.docs_path):
            if fname.endswith('.txt'):
                path = os.path.join(self.docs_path, fname)
                loader = TextLoader(path)
                docs.extend(loader.load())
        return docs

    def _split_docs(self, docs):
        splitter = RecursiveCharacterTextSplitter(
            chunk_size=500,
            chunk_overlap=50
        )
        return splitter.split_documents(docs)

    def ask(self, question):
        result = self.qa_chain({"query": question})
        return {
            "answer": result["result"],
            "sources": [doc.page_content for doc in result["source_documents"]]
        }


if __name__ == "__main__":
    app = RAGApp("./docs")

    while True:
        q = input("\n请输入问题(quit 退出): ").strip()
        if q.lower() == 'quit':
            break
        if not q:
            continue

        res = app.ask(q)
        print("\n回答:", res["answer"])
        print("\n参考来源:")
        for i, src in enumerate(res["sources"], 1):
            print(f"  {i}. {src[:150]}...")

3.3 依赖配置

# requirements.txt
langchain
langchain-community
langchain-openai
chromadb
openai

安装依赖:pip install -r requirements.txt

四、高级技巧与最佳实践

4.1 检索策略优化

问题:单独使用向量检索对专有名词、缩写等识别不准确。

解决方案:使用 Ensemble Retriever 结合多种检索方法。

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

# 向量检索 + BM25 关键词检索
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
bm25_retriever = BM25Retriever.from_documents(chunks)

ensemble = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.5, 0.5]
)

4.2 自定义提示词模板

根据实际需求调整提示词:

from langchain.prompts import PromptTemplate

template = """基于以下参考资料回答问题。如果找不到相关信息,请如实说明。

参考内容:
{context}

问题: {question}

回答:"""

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

4.3 常见问题排查

问题 原因 解决方案
答案重复 chunk_overlap 太小 增大 chunk_overlap
答非所问 chunk_size 太小或 k 值不合适 调整参数或增加检索数量
检索不准确 Embedding 模型不匹配 更换或微调 Embedding

4.4 调试方法

  1. 设置 return_source_documents=True 查看实际检索到的文档
  2. 检查文档是否正确加载
  3. 验证切分方式是否符合预期

五、生产环境部署注意事项

5.1 性能优化

  • 选择高效的向量索引类型(如 FAISS 的 IndexIVFFlat)
  • 对 Embedding 结果进行缓存,避免重复计算
  • 考虑使用异步处理提升并发能力

5.2 安全考虑

  • API Key 通过环境变量管理,禁止硬编码
  • 对用户输入进行校验,防止注入攻击
  • 控制输入长度,避免资源耗尽

5.3 监控与日志

建议记录以下信息:

  • 查询内容和响应时间
  • 检索到的文档信息
  • 异常情况和错误日志

六、总结

本文系统介绍了使用 LangChain 构建 RAG 应用的核心知识点:

  1. RAG 原理:检索增强生成的基本流程和优势
  2. 组件体系:文档加载、分割、嵌入、存储、检索、生成的完整链路
  3. 实战项目:从零构建完整的 RAG 应用
  4. 优化技巧:检索策略、提示词调整、问题排查
  5. 生产部署:性能、安全、监控要点

后续学习方向

  • 向量数据库索引算法优化
  • RAG 系统性能评估方法
  • 多模态 RAG(支持图片、音频等)
  • Agent 与 RAG 的结合应用

如果有问题或建议,欢迎在评论区交流。

4.1 检索策略优化

问题:单独使用向量检索对专有名词、缩写等识别不准确。

解决方案:使用 Ensemble Retriever 结合多种检索方法。

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

# 向量检索 + BM25 关键词检索
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
bm25_retriever = BM25Retriever.from_documents(chunks)

ensemble = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.5, 0.5]
)

4.2 自定义提示词模板

根据实际需求调整提示词:

from langchain.prompts import PromptTemplate

template = """基于以下参考资料回答问题。如果找不到相关信息,请如实说明。

参考内容:
{context}

问题: {question}

回答:"""

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

4.3 常见问题排查

问题 原因 解决方案
答案重复 chunk_overlap 太小 增大 chunk_overlap
答非所问 chunk_size 太小或 k 值不合适 调整参数或增加检索数量
检索不准确 Embedding 模型不匹配 更换或微调 Embedding

4.4 调试方法

  1. 设置 return_source_documents=True 查看实际检索到的文档
  2. 检查文档是否正确加载
  3. 验证切分方式是否符合预期

五、生产环境部署注意事项

5.1 性能优化

  • 选择高效的向量索引类型(如 FAISS 的 IndexIVFFlat)
  • 对 Embedding 结果进行缓存,避免重复计算
  • 考虑使用异步处理提升并发能力

5.2 安全考虑

  • API Key 通过环境变量管理,禁止硬编码
  • 对用户输入进行校验,防止注入攻击
  • 控制输入长度,避免资源耗尽

5.3 监控与日志

建议记录以下信息:

  • 查询内容和响应时间
  • 检索到的文档信息
  • 异常情况和错误日志

六、总结

本文系统介绍了使用 LangChain 构建 RAG 应用的核心知识点:

  1. RAG 原理:检索增强生成的基本流程和优势
  2. 组件体系:文档加载、分割、嵌入、存储、检索、生成的完整链路
  3. 实战项目:从零构建完整的 RAG 应用
  4. 优化技巧:检索策略、提示词调整、问题排查
  5. 生产部署:性能、安全、监控要点

后续学习方向

  • 向量数据库索引算法优化
  • RAG 系统性能评估方法
  • 多模态 RAG(支持图片、音频等)
  • Agent 与 RAG 的结合应用

如果有问题或建议,欢迎在评论区交流。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐