LangChain RAG 核心入门:原理、完整流程与文档加载实战
2026/9/6 23:55:17 网站建设 项目流程

我挖掘了一个巨牛的 人工智能 学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

引言

搜索引擎知道一切,但不会总结;大模型会总结,但对你的私有数据一无所知。

有没有一种方案,能把两者的优势结合起来?

有。它叫 RAG(检索增强生成)——目前大模型落地应用最主流、最成熟的技术方案。无论是企业知识库、智能客服,还是 AI 搜索产品,背后几乎都跑着这套逻辑。

本文将从核心概念、完整工作流程,到基于 LangChain 的实战代码,带你一步步搭建一个属于自己的 RAG 问答系统。文章配套完整代码,复制即可运行。

一、RAG 核心概念与诞生背景

1.1 大模型与传统搜索引擎的优缺点

想要理解 RAG,我们可以通过「AI 大模型 + 搜索引擎」的组合逻辑快速吃透核心思想:

  • AI 大模型:擅长语义理解、文本总结、逻辑推理、对话生成;但存在致命短板——训练数据有截止日期,无法获取实时信息,也无法读取本地、企业私有数据

  • 传统搜索引擎:擅长抓取全网公开实时数据;但缺点是信息零散、冗余,需要人工筛选、总结、整合,无法自动生成精准答案。

简单来说:大模型有智商但没新知识、没私有知识;搜索引擎有海量实时数据但无理解和总结能力

而 RAG 技术的核心,就是将两者结合:给大模型配备「专属私有活字典」,让模型可以实时查阅自定义知识库,输出精准、合规、实时的答案。

1.2 RAG 与 AI 搜索的核心区别

  • AI 搜索:知识库是互联网公开数据,通过联网检索全网信息辅助回答。

  • RAG 检索增强生成:知识库是本地文档、企业私有文档、自定义数据,不依赖公网,完全私有化部署。

当用户向大模型提问时,RAG 会先在私有知识库中做语义检索,匹配相关上下文,再将「用户问题 + 检索到的私有上下文」一并交给大模型,最终生成贴合业务、贴合私有数据的精准答案。

二、RAG 完整工作流程

RAG 整体分为两大核心阶段:离线数据处理在线实时检索生成,也是 LangChain 整套组件的核心学习地图。

2.1 离线数据处理(知识库构建)

原始的 PDF、Markdown、Word 等文档无法直接用于向量检索,需要经过标准化处理,构建成可检索的结构化知识库,核心步骤如下:

  1. 文档加载(Document Loading):通过 LangChain 各类加载器,读取 PDF、MD、数据库、网页等百余种数据源,统一转为Document文档对象。

  2. 文本分割(Splitting):将超长文档切割为固定大小、语义完整的文本块,解决大模型上下文窗口限制、检索粒度粗糙的问题。

  3. 向量化存储(Embedding + Storage):通过嵌入模型将文本块转为向量数据,最终持久化存储到向量数据库,完成私有知识库构建。

2.2 在线检索生成(用户问答阶段)

  1. 检索(Retrieval):用户输入问题后,系统将问题向量化,在向量数据库中匹配相似度最高的文本块。

  2. 生成输出(Output):将「用户问题 + 检索得到的私有上下文」传入大模型,模型基于专属知识库生成精准、可靠的回答。

三、RAG 完整实战演示

本节基于「脚手架级微服务租房平台Q&A」文档(这里的文档你可以随意替换成你自己的),快速搭建最简 RAG 问答系统,实现自定义文档智能问答,要求模型精简作答(最多三句话)。

注意:文档内容越详细、语义越清晰,RAG 生成的回答就越精准、贴合业务

四、LangChain Document 文档核心类

Document是 LangChain 所有 RAG 应用的基础数据载体,所有文档加载、分割、存储操作,最终都是对 Document 对象处理。

4.1 Document 类核心参数

  • page_content:核心文本内容,字符串格式,存储文档正文。

  • metadata:元数据字典,存储文档来源、路径、页码、分类等附属信息。

  • id:可选唯一标识,推荐 UUID 格式,用于精准区分文档块。

4.2 手动创建 Document 对象

from langchain_core.documents import Document # 自定义文档对象列表 documents = [ Document( page_content="狗是很好的伴侣,以忠诚和友好而闻名。", metadata={"source": "mammal-pets-doc"}, ), Document( page_content="猫是独立的宠物,经常享受自己的空间。", metadata={"source": "mammal-pets-doc"}, ), ]

通常单个 Document 对象,对应原始文档的一个分页或一个文本块,是 RAG 处理的最小单元。

五、实战:PDF 文档加载(PyPDFLoader)

LangChain 提供PyPDFLoader专门用于解析本地 PDF 文件,自动将 PDF 每一页转换为一个独立的 Document 对象。

5.1 PDF 加载代码

from langchain_community.document_loaders import PyPDFLoader file_path = "../Docs/PDF/脚手架级微服务租房平台Q&A.pdf" loader = PyPDFLoader(file_path) # 加载PDF,每页对应一个Document docs = loader.load() # 查看文档基础信息 print(f"PDF 文件的总页数为:\n{len(docs)}\n") print(f"第一页文本内容前200字符:\n{docs[0].page_content[:200]}\n") print(f"第一页元数据:\n{docs[0].metadata}")

5.2 运行结果

问:PDF 文件的总页数为: 32 问:第一页文本内容的前200个字符是: 脚手架级微服务租房平台 通用问题 1. 为什么做这个项目? • 回答1:(出于兴趣爱好开发) 大学期间,我和同学在外合租过一段时间,使用了一些租房平台,于是我有个想法,自己能不能开发一个租房平台,可以让我将理论知识与实践相结合。我希望通过实际项目来加深对Java编程语言和相关技术的理解。于是我便查找了一些资料,看了一些开源项目,进行了一些改进。 • 回答2:(开源项目的解释) 这个 问:第一页元数据: {'producer': 'pdfcpu v0.8.1 dev', 'creator': 'Chromium', 'creationdate': '2025-08-28T17:52:34+08:00', 'moddate': '2025-08-28T17:52:34+08:00', 'source': '../PDF/脚手架级微服务租房平台Q&A.pdf', 'total_pages': 32, 'page': 0, 'page_label': '1'}

拓展:对于含图片、图表、扫描件的复杂 PDF,可将页面转为图片,通过多模态大模型解析,精度远高于纯文本解析。并且PDF文档解析不了图片

六、实战:Markdown 文档加载(UnstructuredMarkdownLoader)

Markdown 是技术文档主流格式,LangChain 通过UnstructuredMarkdownLoader实现 MD 文件加载,支持两种加载模式,适配不同业务场景。

6.1 环境依赖安装

pip install "unstructured[md]" nltk

6.2 single 模式(整文档单对象加载)

默认模式,将整个 MD 文件合并为单个 Document 对象,适合整体读取文档、简单分割场景。

from langchain_community.document_loaders import UnstructuredMarkdownLoader from langchain_core.documents import Document markdown_path = "../Docs/Markdown/脚手架级微服务租房平台Q&A.md" loader = UnstructuredMarkdownLoader(markdown_path) data = loader.load() # 校验结果:仅生成一个文档对象 assert len(data) == 1 assert isinstance(data[0], Document) print(data[0].page_content[:200]) print(data[0].metadata)

6.3 elements 模式(结构化拆分加载)

按文档元素类型拆分,将标题、段落、列表、表格、图片单独拆分为 Document 对象,保留文档层级结构,适合精细化解析、结构化检索场景。

from langchain_community.document_loaders import UnstructuredMarkdownLoader markdown_path = "../Docs/Markdown/脚手架级微服务租房平台Q&A.md" loader = UnstructuredMarkdownLoader(markdown_path, mode="elements") data = loader.load() print(f"文档总个数:\n{len(data)}\n") print("前三个文档元素详情:") for document in data[:3]: print(f"{document}\n") # 查看所有文档元素类型 print("文档包含的所有元素类型:") #生成器表达式的写法 print(set(doc.metadata["category"] for doc in data))

补充:生成器表达式的写法以及调用流程:

顺序描述

书写:表达式 for 变量 in 数据源执行流程:

  1. 右侧for document in docs先取出一个 document
  2. 运行左侧表达式,得到一个值
  3. 将该值送入 set 做去重存储
  4. 循环直到 docs 全部遍历完

3.我对生成表达式的理解

set(表达式 for document in docs)会完整遍历一次 for 循环,每一轮循环拿到 document 后,执行前面的表达式算出一个值,把算出的值存入集合自动去重。

对于上面的代码含义就是:

data列表中,取出每一个文档doc,找到它的元数据metadata里的"category"字段,把所有不同的值收集起来,打印出来。

举个极简例子验证

nums = [1,2,2,3] res = set(x*10 for x in nums)

循环过程: x=1 → 110=10 → 放入集合x=2 → 210=20 → 放入集合 x=2 → 210=20 → 重复,丢弃x=3 → 310=30 → 放入集合 最终 {10,20,30} 这里x*10是计算,不是把 x 赋值给x*10

6.4 运行结果与元素类型解析

运行后文档被拆分为441 个结构化文档对象,包含以下核心元素类型:

  • Title:各级标题,包含层级深度、父子关联 ID

  • NarrativeText:正文叙述段落

  • ListItem:有序/无序列表项

  • Table:表格内容

  • Image:图片资源

  • UncategorizedText:脚注、注释、页眉页脚等未分类文本

通过parent_idelement_id可以还原 MD 文档完整层级结构,实现精准的结构化检索。

整体代码:

七、总结

本文我们从零梳理了 RAG 的核心思想与完整工作流程,并通过 LangChain 实战演示了 PDF、Markdown 文档的加载与解析。总结一下关键要点:

  • RAG = 大模型 + 私有知识库,解决模型“有智商无知识”的痛点

  • 知识库构建分为两步:文档加载 → 文本分割 → 向量存储

  • LangChain 的 Document 是所有 RAG 操作的最小数据单元

  • PyPDFLoader按页加载 PDF,UnstructuredMarkdownLoader支持按元素结构化拆分 MD

当然,这只是 RAG 的入门第一步。后续我们还将深入:

  • 文本分割策略(如何切分才能不丢失语义?)

  • 向量嵌入与检索优化(如何让召回更精准?)

  • 高级 RAG 技术(HyDE、RAPTOR、Self-RAG 等)

如果你也对 RAG 感兴趣,欢迎点赞、在看、转发三连,你的支持是我持续更新的最大动力!有任何问题也欢迎在评论区留言交流,我会尽量回复~

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询