RAG预处理增强:让Fastgpt/Dify召回更多东西
目前的FastGPT、Dify(或者其他同类产品),在知识库召回上有个共性:本质上召回的依然是分片后的文本块,也就是纯文本信息。不过,如果我们在预处理上做点文章,不仅能提升召回精度,还能让图片、公式、表格这些内容也一并被召回。下面就把这套预处理方法拆开来讲。
01 原理以及实现
本文中涉及的预处理方法已集成到 pdfdeal 包中(需要 0.2.4 或更高版本),直接从 PyPI 安装即可:
pip install --upgrade pdfdeal
整体思路并不复杂。以 PDF 文档为例,先将其转换为 Markdown 格式,再对 MD 文件进行一系列操作。大致分为三步:
- :这一步借助转换工具还原原始文档中的公式和整体结构。如果工具足够强,表格和纯图片也能被保留下来。
转换文档
- :按自然段落把文本拆开。相比滑动窗口那种一刀切的分块方式,段落级别的拆分能显著提升每个分块内文本的相关性。
拆分段落
- :对于不需要 OCR 的图片(比如示意图),将其上传到云存储(如阿里 OSS、S3、Cloudflare R2),然后用 Markdown 格式的 URL 替换本地路径。这样一来,图片也能被召回。
转换图片
题外话:什么是“纯图片”?
举个例子:下图中蓝色方框部分是表格,应该被识别为表格(此处识别为 HTML 格式的表格);红色方框部分展示的是原理图,不应该被 OCR 处理,而是原样保留。目前主流的转换工具都有能力做到这一点。

⚠️ 注意
从这里开始,默认你已经安装了最新版的 pdfdeal,并且待处理的 PDF 文件放在
./Files 文件夹中。
02 转换文档:PDF 转 Markdown
选一个能满足以上所有需求的转换工具——结构保留、公式识别、表格识别、图片保持——并不难。Doc2X 是一个不错的选择,它免费且功能完备,pdfdeal 包中也内置了对其的支持。
当然,如果你偏好其他工具,完全可以自由选择。以下是用 pdfdeal 调用 Doc2X 进行转换的示例代码:
from pdfdeal import Doc2X
from pdfdeal.file_tools import get_files, unzips
Client = Doc2X()
out_type = "md"
file_list, rename_list = get_files(path="./Files", mode="pdf", out=out_type)
success, failed, flag = Client.pdf2file(
pdf_file=file_list,
output_path="./Output",
output_names=rename_list,
output_format=out_type,
)
print(success, failed, flag)
zips = []
for file in success:
if file.endswith(".zip"):
zips.append(file)
success, failed, flag = unzips(zip_paths=zips)
print(success, failed, flag)
执行后,你会得到类似这样的输出:
['./Output/2408.07888v1.zip', './Output/1706.03762v7.zip'] [{'error': '', 'path': ''}, {'error': '', 'path': ''}] False
['./Output/2408.07888v1', './Output/1706.03762v7'] ['', ''] False
03 拆分段落
大多数 RAG 应用都支持自定义分隔符来切分文档。我们可以利用这一点,在段落之间插入标记,让分段按自然逻辑进行——毕竟滑动窗口往往是按固定长度切分,缺乏语义边界。

pdfdeal 提供了现成的方法。这里选择直接替换源文件模式:
# 上接 step1 中的代码
from pdfdeal.file_tools import auto_split_mds
succese, failed, flag = auto_split_mds(mdpath="./Output", out_type="replace")
print(succese, failed, flag)
输出类似:
MD SPLIT: 2/2 files are successfully splited.
Note the split string is :=+=+=+=+=+=+=+=+=
['./1/1706.03762v7.md', './1/2408.07888v1.md'] [{'error': '', 'file': ''}, {'error': '', 'file': ''}] False
打开生成的 MD 文件,可以看到每个段落之间已经插入了分隔符:

04 转换图片为 URL
到目前为止,图片还是以本地路径形式存在的,像 。大多数 RAG 应用没法直接显示这种路径。解决方法很简单:把图片上传到云存储,让它们变成可访问的 URL。pdfdeal 同样有内置方法。

目前 pdfdeal 内置了阿里 OSS 和 Cloudflare R2(兼容 S3 协议)的上传方法,也支持自定义上传函数。这里以阿里 OSS 为例——开通 OSS 的教程网上很多,注意两点:
- Bucket 要设置公网可访问,否则没法用:

- 密钥(AccessKey)要有 OSS 的读写权限:

假设密钥已经通过环境变量配置好了。再安装阿里 OSS 的上传包:
pip install -U oss2
然后执行转换:
# 上接 Step2 中的代码
from pdfdeal.FileTools.Img.Ali_OSS import Ali_OSS
from pdfdeal.file_tools import mds_replace_imgs
import os
ossupload = Ali_OSS(
OSS_ACCESS_KEY_ID=os.environ.get("OSS_ACCESS_KEY_ID"),
OSS_ACCESS_KEY_SECRET=os.environ.get("OSS_ACCESS_KEY_SECRET"),
Endpoint=os.environ.get("Endpoint"),
Bucket=os.environ.get("Bucket"),
)
succese, failed, flag = mds_replace_imgs(
path="Output",
replace=ossupload,
threads=5,
)
print(succese, failed, flag)
再次查看 MD 文档,图片已被替换为 URL。在 RAG 应用中召回时,这些图片就能直接显示了:

05 完整程序
下面是一个完整的流水线脚本,把上面三个步骤串起来:
from pdfdeal import Doc2X
from pdfdeal.file_tools import get_files, unzips, auto_split_mds, mds_replace_imgs
from pdfdeal.FileTools.Img.Ali_OSS import Ali_OSS
import os
Client = Doc2X()
out_type = "md"
file_list, rename_list = get_files(path="./Files", mode="pdf", out=out_type)
success, failed, flag = Client.pdf2file(
pdf_file=file_list,
output_path="./Output",
output_names=rename_list,
output_format=out_type,
)
print(success, failed, flag)
zips = []
for file in success:
if file.endswith(".zip"):
zips.append(file)
success, failed, flag = unzips(zip_paths=zips)
print(success, failed, flag)
succese, failed, flag = auto_split_mds(mdpath="./Output", out_type="replace")
print(succese, failed, flag)
ossupload = Ali_OSS(
OSS_ACCESS_KEY_ID=os.environ.get("OSS_ACCESS_KEY_ID"),
OSS_ACCESS_KEY_SECRET=os.environ.get("OSS_ACCESS_KEY_SECRET"),
Endpoint=os.environ.get("Endpoint"),
Bucket=os.environ.get("Bucket"),
)
succese, failed, flag = mds_replace_imgs(
path="Output",
replace=ossupload,
threads=5,
)
print(succese, failed, flag)
06 接入 RAG 应用
FastGPT
按照正常的知识库导入流程,将上面得到的 MD 文档导入。在第二步数据处理时,选择自定义处理规则,填入我们之前插入的分隔符:

可以看到数据是严格按照段落分段的:

以下是召回的演示效果:

Dify
⚠️ 注意
截至 Dify 0.7.1 版本,它对 Markdown 文件处理依然存在 Bug——无论怎么设置,都会自动删除文件中的所有 URL 以及 HTML 标签。所以,请务必将 MD 格式改为 TXT 格式后再上传。
先将所有文件的扩展名从 .md 改为 .txt。然后按正常知识库导入流程,将 TXT 文件导入。在第二步数据处理时,选择自定义处理规则,填入分段标识符:

验证一下:数据同样是按段落分段的:

以下是召回演示:

07 召回效果演示
公式 / 表格召回


坦白说,公式和表格能正确召回,主要归功于 Doc2X 的格式转换能力,pdfdeal 的预处理在这里更像是一个辅助包装。不过,如果没有段落拆分和图片 URL 化这一步,图里那些公式表格在 RAG 里根本捞不出来。
题外话:关于分块效果
FastGPT 对 Markdown 文档有专门的拆分适配。在刚才的演示中,当某个章节(比如 #4)内容较多时,FastGPT 会自动在分块开头加上章节标题。而 Dify 即使上传 MD 文档,也没有这个动作。

这就是为什么同样的预处理文件,在两个平台上的最终体验会略有差异。选哪个平台,可以根据对标题追加的需求来决定。
-
- 关于宇宙的好的网名有哪些
- 角色扮演 | 1
- 网名