基于 LangChain 的 RAG(检索增强生成)

第一部分:导入模块

复制代码
from langchain_community.document_loaders import PyMuPDFLoader
from langchain_community.vectorstores import Chroma
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain.indexes import VectorstoreIndexCreator

解析:

模块 作用
PyMuPDFLoader 用于加载 PDF 文件(基于 PyMuPDF,即 fitz 库)
Chroma 向量数据库,存储文本向量
OllamaEmbeddings 用于生成文本嵌入(embedding)的模型(如 qwen3-embedding)
ChatOllama 用于生成自然语言回答的大模型(如 qwen3:8b)
VectorstoreIndexCreator 自动化工具,简化"加载 → 分块 → 嵌入 → 存储"流程

第二部分:加载 PDF 并构建索引(方式1)

复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter

llm = ChatOllama(model="qwen3:8b")
pdf_loader = PyMuPDFLoader("docker_info.pdf")
pdf_pages = pdf_loader.load()

embed = OllamaEmbeddings(model="qwen3-embedding:0.6b")
text_splitter = RecursiveCharacterTextSplitter(
    separators=["\n\n", "\n", ". ", "? ", "! ", "; ", " ", '"'],
    chunk_size=50,
    chunk_overlap=10,
    length_function=len
)

inter_creator = VectorstoreIndexCreator(
    vectorstore_cls=Chroma,
    embedding=embed,
    text_splitter=text_splitter,
    vectorstore_kwargs={"persist_directory": "./test_db1"}
)

index = inter_creator.from_documents(pdf_pages)
res1 = index.query("Docker引擎主要有那两个版本", llm)
print(res1)

解析:

  1. 加载 PDF

    • PyMuPDFLoader("docker_info.pdf"):读取 PDF 内容。
    • load() 返回的是 Document 对象列表(每个页或段落是一个 Document)。
  2. 设置文本分块器

    • RecursiveCharacterTextSplitter:递归按字符分割文本。
    • 参数说明:
      • chunk_size=50:每块约 50 字符(中文),适合短句。
      • chunk_overlap=10:相邻块之间重叠 10 字符,避免断句。
      • separators:优先按换行、句号等切分。
  3. 创建向量化索引

    • VectorstoreIndexCreator 是一个自动化工具,整合了:
      • 分块
      • 嵌入
      • 存入 Chroma
    • persist_directory="./test_db1":持久化保存数据到本地磁盘,程序重启后仍可使用。
  4. 查询

    • index.query(...):调用 LLM + 检索,自动完成"检索 + 生成"。
    • 输出是 LLM 生成的回答。

注意:这种方式是 一键式流程,适合快速原型开发。


第三部分:手动构建 RAG 流程(方式2,推荐用于生产)

复制代码
from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain_community.document_loaders import PyMuPDFLoader
from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 初始化模型
llm = ChatOllama(model="qwen3:8b")
embedding = OllamaEmbeddings(model="qwen3-embedding:0.6b")

# 加载 PDF
pdf_loader = PyMuPDFLoader("docker_info.pdf")
pdf_docs = pdf_loader.load()

# 关键步骤:分块!
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,        # 每块约 500 字符(中文)
    chunk_overlap=50,      # 块间重叠 50 字符,避免切断句子
    separators=["\n\n", "\n", ". ", "? ", "! ", "; ", " ", '"']
)
split_docs = text_splitter.split_documents(pdf_docs)  # 分块后的文档列表

# 创建向量库(使用分块后的文档)
db = Chroma.from_documents(split_docs, embedding=embedding)

# 构建 QA 链
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",  # 把检索结果拼接进 prompt
    retriever=db.as_retriever(search_kwargs={"k": 2}),  # 返回最相关的2个文档
    return_source_documents=True  # 可选:返回引用的原文
)

# 查询
result = qa_chain.invoke({"query": "2015年6月,Docker牵头成立了什么组织"})
print("回答:", result["result"])
print("\n引用来源:")
for doc in result["source_documents"]:
    print("-" * 50)
    print(doc.page_content[:200])

解析:

这是更 完整、可控、可调试 的 RAG 实现方式。

步骤详解:
  1. 初始化模型

    • llm: 大模型(qwen3:8b)用于生成答案。
    • embedding: 嵌入模型(qwen3-embedding:0.6b)用于向量化。
  2. 加载文档

    • PyMuPDFLoader 读取 PDF,得到原始 Document 列表。
  3. 分块(Chunking)

    • RecursiveCharacterTextSplitter 按规则切分文本。
    • 设置 chunk_size=500 更适合中文长句,避免切在中间。
    • chunk_overlap=50 保证上下文连贯。
  4. 构建向量库

    • Chroma.from_documents(...):将分块后的文档存入向量库。
    • 元数据(如页码、标题)会自动保留。
  5. 构建 QA 链

    • RetrievalQA 是标准 RAG 链。
    • chain_type="stuff":把所有检索到的文档内容拼接进 Prompt。
    • retriever.search_kwargs={"k": 2}:只取最相关的 2 个文档。
    • return_source_documents=True:返回原始文档内容,方便溯源。
  6. 查询与输出

    • 输入问题:"2015年6月,Docker牵头成立了什么组织?"
    • 输出:
      • 回答(LLM 生成)
      • 引用来源(原文片段)

总结对比

方式 特点 适用场景
VectorstoreIndexCreator 简单快捷,一键完成 快速原型、学习演示
手动构建 RAG 链 控制力强,可调试,支持复杂逻辑 生产环境、需要溯源、优化性能

建议与优化

  1. 调整 chunk_size

    • 中文建议 300~500 字符,避免句子被截断。
  2. 启用持久化

    复制代码
    db = Chroma.from_documents(..., persist_directory="./my_db")

    这样下次无需重新加载和分块。

  3. 增加过滤器

    • 可以通过 metadata 过滤特定章节或页码。
  4. 使用 rerankerhybrid search

    • 提升检索准确率。
  5. 部署为 API

    • 用 FastAPI + LangChain 封装成服务。
相关推荐
UIUV6 分钟前
RAG技术学习笔记(含实操解析)
javascript·langchain·llm
神秘的猪头5 小时前
🚀 拒绝“一本正经胡说八道”!手把手带你用 LangChain 实现 RAG,打造你的专属 AI 知识库
langchain·llm·openai
栀秋6666 小时前
重塑 AI 交互边界:基于 LangChain 与 MCP 协议的全栈实践
langchain·llm·mcp
大模型真好玩7 小时前
LangChain DeepAgents 速通指南(三)—— 让Agent告别混乱:Tool Selector与Todo List中间件解析
人工智能·langchain·trae
是一碗螺丝粉1 天前
LangChain 链(Chains)完全指南:从线性流程到智能路由
前端·langchain·aigc
前端付豪1 天前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain
神秘的猪头1 天前
🔌 给 AI 装上“三头六臂”!实战大模型接入第三方 MCP 全攻略
langchain·llm·mcp
前端付豪2 天前
LangChain链 写一篇完美推文?用SequencialChain链接不同的组件
人工智能·python·langchain
神秘的猪头2 天前
🔌 把 MCP 装进大脑!手把手带你构建能“热插拔”工具的 AI Agent
langchain·llm·mcp
是一碗螺丝粉3 天前
5分钟上手LangChain.js:用DeepSeek给你的App加上AI能力
前端·人工智能·langchain