基于 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 封装成服务。
相关推荐
神云瑟瑟1 天前
看langchain理解python中的链式调用
python·langchain·链式调用
稳稳C91 天前
04|Langgraph | 从入门到实战 | 进阶篇 | 流式传输
python·ai·langchain·agent·langgraph
linmoo19861 天前
Langchain4j 系列之二十二 - Embedding Models
人工智能·langchain·embedding·嵌入模型·langchain4j
敏叔V5871 天前
LangChain × LlamaIndex:解锁复杂AI工作流与自定义工具集成的终极指南
人工智能·langchain
人工干智能1 天前
LangChain的提示模板template中的{tool_names}和{agent_scratchpad}
langchain·llm
San30.1 天前
LangChain 第二课:拒绝“废话”,用 Zod 强制 AI 输出标准 JSON
人工智能·langchain·json
敏叔V5871 天前
AI应用开发框架对比:LangChain vs. Semantic Kernel vs. DSPy 深度解析
人工智能·驱动开发·langchain
weixin_462446232 天前
使用 Chainlit +langchain+ LangGraph + MCP + Ollama 构建可视化 AI 工具 Agent(完整实战)
人工智能·langchain·agent·ai聊天·mcp server
南_山无梅落2 天前
create_deep_agent vs create_agent 的区别
人工智能·langchain·deepagent
红鼻子时代2 天前
第9篇:Middleware中间件
langchain·middleware中间件