【AI】六.RAG 检索增强生成之Loader实战 小滴课堂讲师 2025年09月18日 ai大模型, aigc 预计阅读 18 分钟 #### RAG系统链路和数据加载Loaders技术 ##### RAG系统与LLM交互架构图 * 注意 * 万丈高楼平地起,基础需要打牢固,一步步进行,然后学会举一反三使用 * 如果直接讲Agent智能体项目,那项目涉及到的很多技术就懵逼了,要学会思路  * **涉及的技术链路环节: 文档加载器->文档转换器->文本嵌入模型->向量存储->检索器** * RAG数据流水线示意图 ```markdown 原始数据 → 数据加载 → 预处理 → 向量化 → 存储 → 检索增强生成 ↗ ↗ ↗ PDF 文本清洗 嵌入模型 数据库 分块 网页 ```  ##### 文档加载器 (Document Loaders) * 外部数据多样性,包括在线,本地 或者数据库等来源 * 将不同来源的原始数据(如PDF、网页、JSON、、HTML、数据库等)转换为统一格式的文档对象,便于后续处理。 * **核心任务**:数据源适配与初步结构化 ##### LangChain里面的Loader * 接口文档地址【如果失效就忽略):https://python.langchain.com/docs/integrations/document_loaders/ ``` from langchain_community.document_loaders import ( TextLoader, #文本加载 PyPDFLoader, # PDF Docx2txtLoader, # Word UnstructuredHTMLLoader, # HTML CSVLoader, # CSV JSONLoader, # JSON SeleniumURLLoader, # 动态网页 WebBaseLoader #网页加载 ) ``` * LangChain 设计了一个统一的接口`BaseLoader`来加载和解析文档, ```python class BaseLoader(ABC): # noqa: B024 """Interface for Document Loader. Implementations should implement the lazy-loading method using generators to avoid loading all Documents into memory at once. `load` is provided just for user convenience and should not be overridden. """ # Sub-classes should not implement this method directly. Instead, they # should implement the lazy load method. def load(self) -> list[Document]: """Load data into Document objects.""" return list(self.lazy_load()) ``` * 将原始数据(如文件、API 响应、文本文件、网页、数据库等)转换为 LangChain 的 `Document` 对象 * `load`方法返回一个`Document`数组, 每个 `Document` 包含 * **`page_content`**: 文本内容 * **`metadata`**: 元数据(如来源、创建时间、作者等) ```python class Document(BaseMedia): """Class for storing a piece of text and associated metadata. Example: .. code-block:: python from langchain_core.documents import Document document = Document( page_content="Hello, world!", metadata={"source": "https://example.com"} ) """ page_content: str """String text.""" type: Literal["Document"] = "Document" ``` ##### Loader 的分类与常见类型 * 文件加载器(File Loaders) | Loader 类型 | 功能描述 | | :----------------------: | :----------------------------------: | | `TextLoader` | 加载纯文本文件(.txt) | | `CSVLoader` | 解析 CSV 文件,按行生成 Document | | `PyPDFLoader` | 提取 PDF 文本及元数据(基于 PyPDF2) | | `Docx2txtLoader` | 读取 Word 文档(.docx) | | `UnstructuredFileLoader` | 通用文件解析(支持多种格式) | * 网页加载器(Web Loaders) | Loader 类型 | 功能描述 | | :--------------: | :----------------------------: | | `WebBaseLoader` | 抓取网页文本内容 | | `SeleniumLoader` | 处理需要 JavaScript 渲染的页面 | * 数据库加载器(Database Loaders) | Loader 类型 | 功能描述 | | :-----------------: | :---------------------: | | `SQLDatabaseLoader` | 执行 SQL 查询并加载结果 | | `MongoDBLoader` | 从 MongoDB 中读取数据 | * 其他加载器 (自定义) ... #### 文档加载器Loaders技术多案例实战 ##### TextLoader - 加载纯文本文件 * ##### **通用参数** - **`encoding`**: 文件编码(默认 `utf-8`) - **`autodetect_encoding`**: 自动检测编码(如处理中文乱码) ```python from langchain_community.document_loaders import TextLoader # 文本加载 loader = TextLoader("data/test.txt") documents = loader.load() print(documents) print(len(documents)) #长度 print(documents[0].page_content[:100]) # 打印前100个字符 print(documents[0].metadata) # 输出: {'source': 'data/test.txt'} ``` ##### CSVLoader - 加载 CSV 文件 * 基础案例代码 ```python from langchain_community.document_loaders import CSVLoader loader = CSVLoader("data/test.csv", csv_args={"delimiter": ","}) documents = loader.load() # 每行转换为一个 Document,metadata 包含行号 print(len(documents)) print(documents[0].metadata) # 输出: {'source': 'data.csv', 'row': 0} print(documents[0].page_content) ``` * 可指定列名,按行生成文档 ```python from langchain_community.document_loaders import CSVLoader #loader = CSVLoader("data/test.csv", csv_args={"delimiter": ","}) loader = CSVLoader("data/test.csv", csv_args={"fieldnames": ["产品名称", "销售数量", "客户名称"]}) documents = loader.load() # 每行转换为一个 Document,metadata 包含行号 print(len(documents)) print(documents[1].metadata) # 输出: {'source': 'data.csv', 'row': 0} print(documents[1].page_content) ``` ##### JSONLoader - 加载 JSON 文件 * 核心参数详解 | 参数 | 类型 | 必填 | 说明 | | :-------------- | :------- | :--- | :----------------------------------------------- | | `file_path` | str | ✅ | JSON 文件路径 | | `jq_schema` | str | ✅ | jq 查询语法,定义数据提取逻辑 | | `content_key` | str | ❌ | 指定作为文本内容的字段(默认直接使用提取到的值) | | `metadata_func` | Callable | ❌ | 自定义元数据处理函数 | | `text_content` | bool | ❌ | 是否将提取内容强制转为字符串(默认 True) | * 必选参数 `jq_schema` * 必须使用 `jq_schema` 语法指定数据提取路径 * 支持更复杂的 JSON 结构解析 * jq 语法常用模式 | 场景 | jq_schema 示例 | 说明 | | :----------- | :----------------------------------- | :--------------------------- | | 提取根级数组 | `.[]` | 适用于 JSON 文件本身是数组 | | 嵌套对象提取 | `.data.posts[].content` | 提取 data.posts 下的 content | | 条件过滤 | `.users[] | select(.age > 18)` | 筛选年龄大于18的用户 | | 多字段合并 | `{name: .username, email: .contact}` | 组合多个字段为对象 | * 案例实战 * 安装依赖包 ``` pip install jq ``` * 编码实战 ```python from langchain_community.document_loaders import JSONLoader loader = JSONLoader( file_path="data/test.json", jq_schema=".articles[]", # 提取 articles 数组中的每个元素 content_key="content" # 指定 content 字段作为文本内容 ) docs = loader.load() print(len(docs)) print(docs[0] ``` #### PDF文档加载器实战和常见问题处理 ##### PyPDFLoader加载PDF文件 * `PyPDFLoader` 是 LangChain 中专门用于加载和解析 **PDF 文件** 的文档加载器。 * 它能将 PDF 按页拆分为多个 `Document` 对象,每个对象包含页面文本和元数据(如页码、来源路径等)。 * 适用于处理多页PDF文档的文本提取任务。 * 使用步骤 * 安装依赖库 ```python pip install pypdf ``` * 案例代码实战 ```python from langchain_community.document_loaders import PyPDFLoader # PDF加载 loader = PyPDFLoader("data/test.pdf") # 加载文档并按页分割 pages = loader.load() # 返回 Document 对象列表 # 查看页数 print(f"总页数: {len(pages)}") # 访问第一页内容 page_content = pages[0].page_content metadata = pages[0].metadata print(f"第一页内容:\n{page_content[:200]}...") # 预览前200字符 print(f"元数据: {metadata}") ``` * 按需加载, 通过 `load()` 方法的参数控制加载范围: ```python # 加载指定页码范围(例如第2页到第4页) pages = loader.load([1, 2, 3]) # 注意页码从0开始(第1页对应索引0) ``` * 提取所有文本合并为单个文档, 若需将全部页面内容合并为一个字符串: ```python full_text = "\n\n".join([page.page_content for page in pages]) print(f"合并后的全文长度: {len(full_text)} 字符") ``` * ##### 常见问题与解决方案 * PDF无法加载或内容为空 * 原因:PDF为扫描版图片或加密。 * 解决: * 使用OCR工具(如pytesseract+pdf2image)提取图片文本。 * 解密PDF后加载(需密码时,PyPDFLoader暂不支持直接解密) * 文本分块不理想 * 调整分块策略:选择合适的分隔符或分块大小 ```python text_splitter = RecursiveCharacterTextSplitter( separators=["\n\n", "\n", "."], # 按段落、句子分割 chunk_size=500, chunk_overlap=100 ) ``` ##### 高级技巧 * **批量处理PDF**:遍历文件夹内所有PDF文件。 ```python import os pdf_folder = "docs/" all_pages = [] for filename in os.listdir(pdf_folder): if filename.endswith(".pdf"): loader = PyPDFLoader(os.path.join(pdf_folder, filename)) all_pages.extend(loader.load()) ``` #### Loader进阶-PDF文档里面的图片提取解析 ##### 如何提取PDF里面的图片文案 * `PyPDFLoader` 仅提取文本,如果没配置第三方类库则会提取不了对应的图片文案 * 需结合其他库(如`camelot`、`pdfplumber`、`rapidocr-onnxruntime`)提取表格或图像。 * 如果需要提取,安装好依赖库后,设置`extract_images`参数为`True`。 ##### `RapidOCR-ONNXRuntime `介绍 * 是一个基于 ONNX Runtime 推理引擎的轻量级 OCR(光学字符识别)工具库,专注于高效、跨平台部署。 * 它是 [RapidOCR](https://github.com/RapidAI/RapidOCR) 项目的一个分支,实现了更高的推理速度和更低的资源占用 * 特点: * 跨平台支持:支持 Windows、Linux、macOS,以及移动端(Android/iOS)和嵌入式设备。 * 多语言识别:支持中文、英文、日文、韩文等多种语言,尤其擅长中英混合文本。 * 轻量级:模型体积小(约几 MB),适合资源受限的环境。 * 预处理与后处理集成:内置图像预处理(如二值化、方向校正)和文本后处理(如去除冗余字符)。 * RapidOCR-ONNXRuntime 与其他主流 OCR 工具的对比: | 工具 | 引擎 | 速度 | 准确率 | 语言支持 | 依赖项 | 适用场景 | | :----------------------- | :----------- | :--- | :----- | :------- | :----- | :--------------------- | | **RapidOCR-ONNXRuntime** | ONNX Runtime | ⭐⭐⭐⭐ | ⭐⭐⭐ | 多语言 | 少 | 跨平台、轻量级部署 | | **Tesseract** | 自研引擎 | ⭐⭐ | ⭐⭐ | 多语言 | 多 | 历史项目、简单场景 | | **EasyOCR** | PyTorch | ⭐⭐ | ⭐⭐⭐ | 多语言 | 多 | 快速原型开发 | | **Microsoft Read API** | 云端服务 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 多语言 | 无 | 企业级、高并发云端需求 | ##### 案例实战 * 安装依赖包 (**耗时会有点久**) ``` pip install rapidocr-onnxruntime ``` * 代码实战 ```python from langchain_community.document_loaders import PyPDFLoader loader = PyPDFLoader("data/pdf-img.pdf", extract_images=True) pages = loader.load() print(pages[0].page_content) ``` #### 网页加载器WebBaseLoader案例实战 ##### 什么是WebBaseLoader * `WebBaseLoader` 是 LangChain 中用于抓取 **静态网页内容** 的文档加载器。 * 通过 HTTP 请求直接获取网页 HTML,并提取其中的文本内容(自动清理标签、脚本等非文本元素) * 生成包含网页文本和元数据的 `Document` 对象 * 适用于新闻文章、博客、文档页面等静态内容的快速提取。 * 场景 * 知识库构建(知识问答、企业知识库)、舆情监控(新闻/社交媒体分析) * 竞品分析(产品功能/价格监控)、SEO 内容聚合 ##### 使用步骤 * 安装依赖库 ```python pip install beautifulsoup4 # HTML 解析依赖(默认已包含) pip install requests # 网络请求依赖(默认已包含) ``` * 目标网页要求 * 无需 JavaScript 渲染(动态内容需改用 `SeleniumURLLoader` ,但是很鸡肋,少用) * 未被反爬虫机制拦截(如需要,需配置代理或请求头) * 如果动态网页,且内容提取好,还是需要单独针对不同的网站写代码进行提取内容 ##### 案例实战 * 基础用法:加载单个网页 ```python import os #代码中设置USER_AGENT, 设置USER_AGENT的代码一定要放在WebBaseLoader 这个包前面,不然还是会报错 os.environ['USER_AGENT'] = 'Mozilla/5.0 (Windows NT 14.0; Win64; x64) AppleWebKit/567.36 (KHTML, like Gecko) Chrome/58.0.444.11 Safari/337.3' from langchain_community.document_loaders import WebBaseLoader #警告日志信息:USER_AGENT environment variable not set, consider setting it to identify your requests. # 初始化加载器,传入目标URL列表(可多个) urls = ["https://www.cnblogs.com"] loader = WebBaseLoader(urls) # 加载文档(返回Document对象列表) docs = loader.load() # 查看结果 print(f"提取的文本长度: {len(docs[0].page_content)} 字符") print(f"前200字符预览:\n{docs[0].page_content[:200]}...") print(f"元数据: {docs[0].metadata}") ``` * 批量加载多个网页 ```python import os #代码中设置USER_AGENT, 注意设置USER_AGENT的代码一定要放在WebBaseLoader 这个包前面,不然还是会报错 os.environ['USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3' from langchain_community.document_loaders import WebBaseLoader #警告日志信息:USER_AGENT environment variable not set, consider setting it to identify your requests. # 初始化加载器,传入目标URL列表(可多个) urls = [ "https://news.baidu.com/", # 新闻 "https://tieba.baidu.com/index.html" # 贴吧 ] loader = WebBaseLoader(urls) docs = loader.load() print(f"共加载 {len(docs)} 个文档") print("各文档来源:") for doc in docs: print(f"- {doc.metadata['source']}") ``` * 更多详细API和参数 https://python.langchain.com/docs/integrations/document_loaders/web_base/ #### Word文档加载器实战和常见问题处理 ##### `Docx2txtLoader`介绍 * 是 LangChain 中专门用于加载 **Microsoft Word 文档(.docx)** 的文档加载器。 * 提取文档中的纯文本内容(包括段落、列表、表格文字等),忽略复杂格式(如字体、颜色),生成统一的 `Document` 对象。 * 适用于从 Word 报告中快速提取结构化文本 ##### 使用步骤 * 安装依赖库 ```python pip install docx2txt # 核心文本提取库 ``` * 准备.docx文件:确保目标文件为 .docx 格式(旧版 .doc 需转换),且未被加密 * 案例代码实战 * 基础用法:加载单个Word文档 ```python from langchain_community.document_loaders import Docx2txtLoader # 初始化加载器,传入文件路径 loader = Docx2txtLoader("data/test1.docx") # 加载文档(返回单个Document对象) documents = loader.load() # 查看内容 print(f"文本长度: {len(documents[0].page_content)} 字符") print(f"前200字符预览:\n{documents[0].page_content[:200]}...") print(f"元数据: {documents[0].metadata}") ``` * 批量加载文档 ```python from langchain_community.document_loaders import Docx2txtLoader import os folder_path = "data/" all_docs = [] # 遍历文件夹内所有.docx文件 for filename in os.listdir(folder_path): if filename.endswith(".docx"): file_path = os.path.join(folder_path, filename) loader = Docx2txtLoader(file_path) all_docs.extend(loader.load()) # 合并所有文档 print(f"加载文件: {filename}") print(all_docs) ``` ##### 常见问题与解决方案 * 加载 .doc 文件报错 * 原因:docx2txt 仅支持 .docx 格式。 * 解决:使用 Word 将 .doc 另存为 .docx。 * 文档中的图片/图表未被提取 * 原因:Docx2txtLoader 仅提取文本,忽略图片。 * 解决:使用 python-docx 单独提取图片,也可以使用其他组件,类似OCR
评论区