前两篇解决了"怎么调模型"和"怎么编排流程",但模型有个绕不开的局限:它不知道你的私有文档,知识也停留在训练截止的那一天。RAG(检索增强生成)就是为此而生。这一篇讲 RAG 的前半场——索引:如何把一堆文档变成一个可以按语义检索的知识库;检索与问答是下一篇的主题。
一、为什么需要 RAG#
直接问模型公司内部的规章制度、上周刚发布的产品文档,它要么答不上来,要么一本正经地编(幻觉)。根源有三个:
- 知识滞后:模型的知识冻结在训练截止日;
- 幻觉:对不知道的东西,模型倾向于编造而不是承认不知道;
- 微调太贵:为了让模型"记住"你的文档去做续训,成本高、更新慢,文档一变又要重训。
RAG 的思路简单直接:不改模型,改输入。把你的文档做成一个可检索的知识库,用户提问时先从库里检索出最相关的几段内容,连同问题一起塞进提示词,让模型"看着资料回答"。
整个体系分成两条流程:
- 索引流程(离线,本篇):文档加载 → 切分成块 → 向量化 → 存入向量数据库;
- 检索流程(在线,下篇):把问题向量化 → 与库中的块做相似度比对 → 选出 Top-K → 交给模型生成答案。
下面沿着索引流程的四步走一遍。
二、第一步:文档加载#
LangChain 用统一的 Document 对象承载文档内容——page_content 是正文,metadata 是来源、位置等元数据。各种格式的文件通过对应的文档加载器(Document Loader)转成 Document。
结构化程度高的文本(txt、md)加载很直接:
from langchain_community.document_loaders import TextLoader
docs = TextLoader(file_path="sample.md", encoding="utf-8").load()
print(docs[0].page_content[:100])
对 Markdown、Word 这类有结构的文档,Unstructured 系列加载器提供两种模式:
from langchain_community.document_loaders import UnstructuredMarkdownLoader
# single 模式:整个文件合成一个 Document
docs = UnstructuredMarkdownLoader(file_path="sample.md", mode="single").load()
# elements 模式:按标题、段落等结构元素拆成多个 Document
docs = UnstructuredMarkdownLoader(file_path="sample.md", mode="elements").load()
Word 文档换成 UnstructuredWordDocumentLoader,用法完全一样。至于 PDF——简单版式的用 pypdf 系加载器就够了;但扫描件、多栏排版、带表格公式的复杂 PDF,业界通行做法是先交给专门的解析服务(如 MinerU、Marker 这类工具)转成 Markdown,再按普通文本加载。别在"用通用加载器硬啃复杂 PDF"上浪费时间,解析质量决定了整个知识库的上限。


还没有公开留言,成为第一个写下回声的人。