RAG 技术全栈指南 | 第二章 数据加载与文本分块

59 阅读4分钟

总结

文末四张思维导图拆解分块全策略,小白也能秒懂!

image.png

image.png

一、数据加载

概念:在 RAG 系统中,数据加载是整个数据处理流水线的第一步,核心是将非结构化文档转换为程序可处理的结构化数据。

重要性:它是实现高质量检索与生成的前提,输入质量直接决定后续输出效果。

1.1 文档加载器

主要功能

  1. 解析 PDF、Word、Markdown 等不同格式的原始文档,提取纯文本内容
  2. 在解析过程中同步抽取文档来源、页码、作者等关键元数据
  3. 将文本和元数据整理成统一的数据结构,方便后续切分、向量化和入库

当前主流RAG文档加载器

image.png

1.2 使用 Unstructured 库

Unstructured文档处理库

  1. 支持 PDF、Word、Excel、HTML、Markdown 等多种文档格式
  2. 可以自动识别标题、段落、表格、列表等文档结构,同时保留相应的元数据信息

使用 Unstructured 库加载并解析一个PDF文件

from unstructured.partition.auto import partition

# PDF文件路径
pdf_path = "../../data/C2/pdf/rag.pdf"

# 使用Unstructured加载并解析PDF文档
elements = partition(
    filename=pdf_path,
    content_type="application/pdf"
)

# 打印解析结果
print(f"解析完成: {len(elements)} 个元素, {sum(len(str(e)) for e in elements)} 字符")

# 统计元素类型
from collections import Counter
types = Counter(e.category for e in elements)
print(f"元素类型: {dict(types)}")

# 显示所有元素
print("\n所有元素:")
for i, element in enumerate(elements, 1):
    print(f"Element {i} ({element.category}):")
    print(element)
    print("=" * 60)

partition 函数参数解析

参数名解释
filename文档文件路径
content_type可选参数,指定MIME类型(如"application/pdf"),可绕过自动文件类型检测
url可选参数,远程文档 URL,支持直接处理网络文档
include_page_breaks布尔值,是否在输出中包含页面分隔符
strategy处理策略,可选 "auto"、"fast"、"hi_res" 等
encoding文本编码格式,默认自动检测

使用不同处理策略进行解析:hi_res VS ocr_only

from unstructured.partition.pdf import partition_pdf
from collections import Counter

# PDF文件路径
pdf_path = "../../data/C2/pdf/rag.pdf"

def analyze_pdf_elements(elements, strategy_name):
    """分析并打印PDF解析元素的统计信息"""
    # 基础统计
    total_elements = len(elements)
    total_chars = sum(len(str(e)) for e in elements)
    print(f"\n===== {strategy_name} 解析结果 =====")
    print(f"解析完成: {total_elements} 个元素, {total_chars} 字符")
    
    # 元素类型统计
    types = Counter(e.category for e in elements)
    print(f"元素类型: {dict(types)}")
    
    # 显示前3个元素示例(避免输出过长)
    print("\n前3个元素示例:")
    for i, element in enumerate(elements[:3], 1):
        print(f"Element {i} ({element.category}):")
        print(str(element)[:200] + "..." if len(str(element)) > 200 else str(element))
        print("-" * 60)

# 1. 使用 hi_res 策略解析(适合原生PDF,有可复制文本)
print("开始使用 hi_res 策略解析 PDF...")
hi_res_elements = partition_pdf(
    filename=pdf_path,
    strategy="hi_res"  # 高精度解析,优先提取原生文本
)
analyze_pdf_elements(hi_res_elements, "hi_res")

# 2. 使用 ocr_only 策略解析(适合扫描件PDF,无原生文本)
print("\n开始使用 ocr_only 策略解析 PDF...")
ocr_elements = partition_pdf(
    filename=pdf_path,
    strategy="ocr_only"  # 纯OCR解析,将PDF转为图片后识别文本
)
analyze_pdf_elements(ocr_elements, "ocr_only")

# 3. 对比两种策略的核心差异
print("\n===== 两种策略对比 =====")
print(f"hi_res 元素数量: {len(hi_res_elements)}, ocr_only 元素数量: {len(ocr_elements)}")
print(f"hi_res 字符总数: {sum(len(str(e)) for e in hi_res_elements)}, ocr_only 字符总数: {sum(len(str(e)) for e in ocr_elements)}")
  1. partition_pdf 函数:Unstructured 专门用于 PDF 解析的函数,比通用的 partition 更灵活,支持指定解析策略。
  2. strategy 参数:
维度hi_res 策略ocr_only 策略
解析速度快(直接提取文本)慢(先转图片再 OCR)
元素类型丰富(Title、ListItem、Text 等)单一(主要是 Text 类型)
字符准确性高(无识别错误)可能有识别错误(如错别字、乱码)
适用场景原生 PDF(可复制文本)扫描件 / 图片 PDF(不可复制文本)

二、文本分块

将加载后的长篇文档,切分成更小、更易于处理的单元。

2.1 作用

满足模型上下文限制

  1. 嵌入模型 (Embedding Model):负责将文本块转换为向量。这类模型有严格的输入长度上限。任何超出此限制的文本块在输入时都会被截断,导致信息丢失
  2. 大语言模型 (LLM):负责根据检索到的上下文生成答案。LLM同样有上下文窗口限制。如果单个块过大,可能会导致只能容纳少数几个相关的块,限制了LLM回答问题时可参考的信息广度。

“块”不是越大越好

image.png

2.2 常见分块策略

固定大小分块

image.png

递归字符分块

image.png

语义分块

image.png

基于文档结构的分块

image.png

学习资料参考:开源组织Datawhale all-in-rag项目