PDF导入RAG后乱码、空白或顺序错乱怎么办?文档解析完整排查

文章摘要

PDF导入知识库后出现乱码、空白、文字顺序错乱,是企业RAG项目最常见的数据源故障。根因可能是扫描件没有文本层、字体使用自定义编码、双栏版式阅读顺序错误、表格被拆散、OCR语言配置不正确,或者解析结果未经质量校验就直接分块。本文给出从PDF类型识别、文本层检测、字体与编码、OCR、版面恢复到入库质量门禁的完整排查流程。

一、先不要急着调整Embedding模型

典型现象:

上传PDF
→ 成功生成向量
→ 搜索不到正确内容

开发者常见的第一反应是:

  • 换Embedding模型;
  • 调高Top K;
  • 调低相似度阈值;
  • 更换向量数据库。

但如果解析出的原始文本已经错误,后续任何检索优化都无法补救。

第一步应该查看:

PDF解析后的原始文本

而不是直接查看最终问答结果。

二、先判断PDF属于哪种类型

1. 文字型PDF

可以在阅读器中选中文字并复制。

通常可以直接提取文本,但仍可能存在:

  • 字体编码异常;
  • 阅读顺序错误;
  • 页眉页脚混入;
  • 表格结构丢失。

2. 扫描型PDF

每一页本质上是一张图片。

特征:

  • 无法选中文字;
  • 文本提取结果为空;
  • 文件来自扫描仪或拍照;
  • 页面有明显阴影和倾斜。

必须使用OCR。

3. 混合型PDF

部分页面有文本层,部分页面是扫描图。

常见于:

  • 合同附件;
  • 盖章文件;
  • 多来源合并文件;
  • 旧档案数字化。

需要逐页判断,不能只根据第一页决定整个文件的解析方式。

三、文本为空怎么排查

检测每页字符数:

from pypdf import PdfReader


def inspect_pdf(path: str) -> list[dict]:
    reader = PdfReader(path)
    result = []

    for index, page in enumerate(reader.pages):
        text = page.extract_text() or ""
        result.append({
            "page": index + 1,
            "char_count": len(text.strip()),
            "preview": text[:100]
        })

    return result

判定规则可以是:

字符数大于100 → 可能是文字页
字符数1—100 → 需要人工检查
字符数为0 → 大概率需要OCR

阈值应根据文档类型调整。

四、为什么复制正常,程序却提取乱码

PDF存储的未必是Unicode文本。

它可能保存:

字形编号
+字体映射
+页面坐标

阅读器能够根据字体映射显示正确字符,但解析库可能无法恢复原始Unicode。

表现为:

□□□
乱码符号
不可见字符
字母顺序异常

处理方式:

  1. 更换PDF解析引擎;
  2. 检查是否存在ToUnicode映射;
  3. 对问题页进行OCR;
  4. 对解析结果做字符异常检测;
  5. 保留原页图片用于追溯。

五、建立乱码检测器

import re


def calculate_garbled_ratio(text: str) -> float:
    if not text:
        return 1.0

    suspicious = re.findall(
        r"[\uFFFD\x00-\x08\x0B\x0C\x0E-\x1F]",
        text
    )

    return len(suspicious) / len(text)

还可以统计:

  • 替换字符
  • 连续方框;
  • 控制字符;
  • 中文文档中的异常拉丁字符比例;
  • 单字重复;
  • 无空格长串。

命中阈值后自动转OCR流程。

六、双栏和多栏版式为什么会错序

页面视觉顺序可能是:

左栏从上到下
→ 右栏从上到下

简单解析器可能按坐标输出:

左栏第一行
→ 右栏第一行
→ 左栏第二行
→ 右栏第二行

最终文本会像句子被交叉拼接。

解决方案需要版面分析:

检测文本块
→ 判断栏区域
→ 计算阅读顺序
→ 按区域合并

测试时应重点选择:

  • 学术论文;
  • 产品手册;
  • 报纸;
  • 双栏招标文件;
  • 多栏参数表。

七、OCR不是简单开关

OCR需要配置:

  • 语言;
  • 分辨率;
  • 页面旋转;
  • 倾斜校正;
  • 表格检测;
  • 版面分析;
  • 置信度阈值。

中文文件如果只启用英文识别,容易把:

0识别成O
1识别成l
金额小数点丢失
中文标点错位

高风险内容如合同金额、批号、日期和身份证号不能仅依赖OCR结果。

八、OCR质量如何评估

每个页面记录:

ocr_engine
ocr_language
ocr_confidence
rotation
image_dpi
char_count
processing_time

抽样检查:

  • 标题是否正确;
  • 数字是否正确;
  • 条款编号是否连续;
  • 页码是否混入正文;
  • 表格字段是否对应;
  • 专业术语是否错误。

可以建立字符级错误率:

CER = 错误字符数 / 真实字符数

九、页眉页脚会污染检索

如果每页都包含:

公司名称
保密文件
第12页/共80页

分块后这些文本会重复出现几十次,影响Embedding和关键词检索。

清理方法:

  1. 统计跨页重复行;
  2. 判断其坐标是否位于顶部或底部;
  3. 超过一定重复页数后标记为页眉页脚;
  4. 删除但保留页码Metadata。

不要直接删除所有短行,因为标题也可能很短。

十、表格不能当普通段落处理

错误结果:

产品A 100 20 产品B 200 30

模型无法判断:

  • 哪个数字对应哪个产品;
  • 100是库存还是价格;
  • 表头是什么;
  • 单位是什么。

建议输出为Markdown:

| 产品 | 库存 | 本月销量 |
|---|---:|---:|
| 产品A | 100 | 20 |
| 产品B | 200 | 30 |

并保存:

table_id
page
caption
headers
source_document

十一、公式和特殊符号怎么办

技术文档可能包含:

  • 数学公式;
  • 化学式;
  • 上下标;
  • 希腊字母;
  • 工程单位;
  • 流程图。

普通文本提取可能把:

m²
CO₂
α

变成错误字符。

处理策略:

  • 保留原始公式表示;
  • 使用支持公式识别的解析器;
  • 保存页面截图;
  • 对单位和数字做规则校验;
  • 关键参数进入结构化数据表。

十二、解析结果必须经过质量门禁

不要采用:

解析成功
→ 直接分块
→ 直接入库

推荐:

解析
→ 页面级质量检查
→ 文档级质量检查
→ 异常页OCR或人工处理
→ 清洗
→ 分块
→ 入库

质量指标:

empty_page_ratio
garbled_ratio
ocr_page_ratio
duplicate_line_ratio
table_count
image_count
average_chars_per_page
language_confidence

十三、建议的失败状态

PARSE_PENDING
PARSE_SUCCEEDED
PARSE_PARTIAL
OCR_REQUIRED
MANUAL_REVIEW
REJECTED
INDEXED

不要把“部分页面失败”的文档标记为完全成功。

十四、最小排查清单

□ PDF是否有文本层
□ 是否存在扫描页
□ 原始文本是否为空
□ 是否出现乱码字符
□ 阅读顺序是否正确
□ 页眉页脚是否清理
□ 表格结构是否保留
□ OCR语言是否正确
□ 数字、日期、单位是否准确
□ 异常页是否阻止入库

总结

PDF进入RAG前,必须先完成:

类型识别
→ 文本或OCR解析
→ 版面恢复
→ 表格处理
→ 清洗
→ 质量检查

乱码、空白和顺序错乱属于数据工程问题,不是Embedding或大模型问题。只有解析结果可读、完整、可追溯,后续Chunk和检索优化才有意义。

延伸阅读

如果你正在关注企业级 AI 应用、RAG、Agent、MCP 与大模型工程化落地,欢迎访问 智元界

https://www.zyentor.com/

智元界将持续分享可运行的技术实战、架构设计、问题排查与企业应用案例。