RAG标准流程之文档导入

上一篇文章中介绍了RAG的总体架构,本篇将对第一个部分RAG文档导入进行介绍和讨论

总体流程

基本流程:原始数据 -> 文本解析 -> 文本切片 (Chunking) -> 向量化 (Embedding) -> 存入向量数据库。

节点一:入口与类型判断 (node_entry)

作为数据加载流程的"总调度员",负责接收外部输入的文件,识别文件类型(PDF或Markdown),并根据类型开启相应的处理分支。同时,它提取文件名作为全局元数据,并初始化任务追踪状态,确保后续流程可追溯、可监控。

实现思路:

  1. 路由分发 : 采用轻量级的条件判断逻辑,通过文件后缀 (.pdf / .md) 决定激活 is_pdf_read_enabled 还是 is_md_read_enabled 状态位,实现不同格式文件的差异化处理。
  2. 元数据提取 : 在入口处统一提取文件名 (file_title),作为贯穿整个知识库构建流程的唯一标识,避免后续节点重复解析。
  3. 任务监控初始化 : 集成 task_utils,记录当前任务 ID 和初始状态,为前端提供实时的进度反馈。

节点二:PDF 转 Markdown (node_pdf_to_md)

解决非结构化 PDF 文档难以直接处理的痛点,利用 MinerU 高精度解析能力,将 PDF 转换为结构清晰、包含图片引用的 Markdown 格式,为后续的文本切分和图片理解打下基础。

实现思路:

  1. 云端算力卸载: 考虑到本地 OCR 和布局分析的资源消耗巨大,本节点采用"云端 API"模式,将繁重的解析任务卸载到 MinerU 服务端。
  2. 异步轮询机制 : 针对大文件解析耗时较长的问题,设计了"上传 -> 提交 -> 轮询 -> 下载"的异步交互流程,通过指数退避或固定间隔轮询状态,避免长连接超时。
  3. 完整性保障: 解析完成后,不仅提取 Markdown 文本,还同步下载并解压关联的图片资源,保持文档的多模态完整性。

关于解析PDF的两种方案对比

  1. UnstructuredPDFLoader的核心问题:
  • 信息提取不完整:它主要是一个文本提取工具,在处理包含超链接、复杂表格、数学公式的文档时能力不足,常导致关键信息丢失。

  • 依赖环境复杂:作为封装工具,其正常运作严重依赖unstructured库及其底层组件(如pdfplumber、poppler),安装过程容易出现依赖缺失或版本冲突问题。

  1. MinerU的局限性:
  • 部署与运行成本高:其基于深度学习的模型需要GPU以获得最佳性能,且安装部署比纯Python库复杂,对只想进行简单文本提取的用户来说门槛较高。
  • 处理扫描件时可能能力受限:对于纯图像格式的PDF,其OCR能力依赖于集成或额外的OCR引擎,并非其核心优势。

如果你的首要任务是构建RAG系统或处理简单文档,快速上手,应选UnstructuredPDFLoader;如果你的核心需求是深度解析含复杂表格、公式、版面的专业文档,并追求极致精度,则应选择MinerU。

节点三:图片处理 (node_md_img)

实现文档的"多模态语义对齐"。将 Markdown 中的本地图片路径转换为在线可访问的 MinIO 对象存储链接,并利用多模态大模型(VLM)生成图片内容的文字摘要,填入 alt 属性,使纯文本检索模型也能理解图片内容,将图片处理成需要的格式 多模态模型对图片的识别(自己 文件服务器 url 地址,避免相对地址切换无法访问问题)

实现思路:

  1. 图文解耦与持久化: 将图片从本地文件系统迁移到 MinIO 对象存储,实现计算节点与存储分离,确保知识库在不同环境下的可访问性。
  2. 语义增强: 引入 qwen3-vl-flash 或其他 VLM 模型(多模态模型),对每张图片进行"看图说话",将视觉信息转化为文本摘要。这使得原本不可被搜索的图片,能够通过文本语义被检索到(如搜索"架构图"能找到对应的图片)。
  3. 速率控制: 在调用 VLM API 时加入速率限制(Rate Limit),防止因图片过多触发并发风控。

节点四:文档切分 (node_document_split)

将长文档转化为适合向量检索的微观语义单元(Chunk)。通过智能切分策略,在保持语义完整性的前提下,控制切片长度,最大化检索的召回率和准确率。

实现思路:

  1. 结构化优先: 摒弃简单的固定字符数切分,优先依据 Markdown 标题层级(Headers)进行逻辑分块,确保同一知识点的连贯性。
  2. 递归优化: 对于超长段落,采用"段落 -> 句子"的递归切分策略。先按换行符切,若仍超长则按句号切,确保切片不会在句子中间截断。
  3. 上下文保留 : 在每个切片中保留 file_titleparent_title(父级标题),为后续的 LLM 回答提供丰富的上下文背景。

为什么需要对文本分块?

  1. 模型上下文窗口限制
  • 嵌入/重排序模型:如 BGE-base-zh-v1.5 的上下文窗口为 512 token,若直接处理超过此长度的文本,会导致语义截断,生成的信息不够精确或者有所缺失。

  • LLM:目前主流大模型上下文长度支持超过32k,但更消耗资源

  1. 检索精度优化
  • 提升相关性准确性:分块后,每个文本块的语义更集中,无关内容更少,向量相似度计算更精准,能够快速检索到与用户查询最相关的内容,减少误召回。

  • 避免噪声干扰:长文本中可能包含与查询无关的噪声信息,分块可将噪声信息与核心信息分离,避免噪声"稀释"核心内容的权重,提升检索效果。

  1. 保持语义完整性: 通过合理的分块策略(如 RecursiveCharacterTextSplitter 递归字符分块),可在拆分长文档的同时,保留文本的语义完整性,避免因切分导致的逻辑断裂,确保大模型能基于完整的证据生成连贯、准确的回答。
    常见的文本分块方法

  2. 固定长度分块(Fixed-Size Chunking)

核心逻辑:按照固定的字符数或 token 数(如 512 token)切分文本,设置固定的重叠长度(overlap),确保上下文连续性。

优点:实现简单、效率高,无需复杂逻辑,适合快速验证 RAG 流程。

缺点:易打断文本语义链路,破坏逻辑完整性,适合结构简单、语义连贯的短文本。

  1. 递归字符分块(Recursive Character Splitting)

核心逻辑:按层次化分隔符列表(如 \n\n、\n、.、, 等)进行递归切分,优先按大分隔符(段落分隔)切分,若块长度仍超标,再按小分隔符(句子分隔)切分,结合滑动窗口设置重叠。

优点:最大程度保留文本的自然语义边界,减少语义断裂,是目前最常用、适配性最广的分块方法(LangChain 中 RecursiveCharacterTextSplitter 为默认推荐)。

缺点:对分隔符不规范的文档(如无段落分隔的纯文本)效果较差。

  1. 小-大分块(Small-Large Chunking)

核心逻辑:维护两套向量数据库,一套按句子粒度切分(小块),用于精准匹配用户查询;另一套按段落粒度切分(大块),用于保留完整语义。检索时,先通过小块检索定位相关句子,再通过句子关联到对应的大块,获取完整上下文。

优点:兼顾检索精度和语义完整性,适合长文档、多段落的复杂场景。

缺点:架构复杂,维护成本高,需要额外处理小块与大块的关联关系。

  1. 基于 LLM 分块(LLM-Based Chunking)

核心逻辑:利用 LLM Agent 模拟人类的阅读理解过程,输入文本后,让 LLM 动态判断语义边界,自主决定分块大小和切分位置,生成符合语义的文本块。

优点:语义划分最精准,能够处理复杂结构、多领域的专业文档,适配性极强。

缺点:成本高,需频繁调用 LLM,效率低,不适合批量处理大量文档。

节点五:主体识别 (node_item_name_recognition)

提取文档的核心实体(如产品名称、特定概念),用于后续的精确过滤和去重。这是构建"实体-切片"关联的关键一步,支持基于实体的结构化查询。

实现思路:

  1. 上下文压缩: 取文档的前 K 个切片(通常包含标题和摘要)构建 Prompt,利用 LLM 强大的理解能力提取核心实体名称。
  2. 错误鲁棒性: 考虑到 LLM 输出的不确定性,增加了空结果处理和默认值兜底机制,确保流程不会因识别失败而中断。
  3. 向量化准备: 识别出的实体名称也会被向量化,用于在 Milvus 中进行基于实体的语义对齐(如搜索"iPhone"能关联到"苹果手机"的切片)。

节点六:向量化 (node_bge_embedding)

将人类可读的文本切片转化为机器可计算的向量表示。采用 BGE-M3 模型,同时生成稠密向量(Dense)和稀疏向量(Sparse),为"混合检索"提供底层数据支持。

实现思路:

  1. 双路编码: 利用 BGE-M3 的特性,一次推理同时产出语义向量(Dense,捕获语义相似度)和词汇向量(Sparse,捕获关键词匹配),兼顾语义理解和精确匹配。
  2. 归一化处理: 对稀疏向量进行 L2 归一化,消除文本长度带来的权重偏差,确保检索评分的公平性。
  3. 批处理优化: 针对大量切片,采用 Batch 处理模式调用模型,大幅提升 GPU/CPU 的计算利用率。

节点七:存入 Milvus (node_import_milvus)

数据加载流程的终点,负责将处理好的结构化数据(切片内容、元数据、向量)持久化存储到向量数据库中,构建可供即时查询的索引。

实现思路:

  1. 幂等性设计 : 在插入新数据前,根据 item_name 或文件 ID 清理旧数据,防止重复导入导致的数据污染。
  2. Schema 适配: 严格按照 Milvus 集合的 Schema 定义(主键、Dense字段、Sparse字段、JSON元数据字段)组织数据,确保插入成功率。
  3. 混合索引构建: 确保存入的数据能够支持 Milvus 的 Hybrid Search(Dense + Sparse 加权),最大化检索效果。
相关推荐
小码哥06812 分钟前
能碳管理系统:功能拆解、技术架构与源码采购避坑指南
架构·能源·能碳
会周易的程序员16 分钟前
aiDgeController 软PLC虚拟机stvm集成测试报告
c++·物联网·架构·集成测试·st·软plc·iec61131
一只小闪闪27 分钟前
easy-trans java数据通用翻译框架v2.3.0
java·后端·架构
江畔柳前堤1 小时前
字节跳动产品全景图:从应用表象到技术深海的七层解剖
人工智能·chatgpt·架构·json·batch
风123456789~1 小时前
【架构专栏】2.7 多媒体 知识点
架构
存在morning2 小时前
【Paimon 学习笔记 二】存储架构:快照、manifest、LSM 树、bucket
笔记·学习·架构
pnoker2 小时前
拆解 IoT DC3:六层微服务架构
java·物联网·spring cloud·微服务·架构
sukioe2 小时前
城智连响:基于 LangGraph 与四库分层架构的城市公共设施智能报修与派单系统
人工智能·python·ai·架构·langchain
harmony&2 小时前
Docker 容器技术从入门到实战:生态系统、安装部署与架构详解
docker·容器·架构