RAG系列:解析優(yōu)化 - 不同文件類型統(tǒng)一轉(zhuǎn)換成Markdown
引言
在 RAG 系統(tǒng)中,文件解析是構(gòu)建知識(shí)庫(kù)和實(shí)現(xiàn)高效信息檢索的關(guān)鍵環(huán)節(jié)。隨著系統(tǒng)需要處理的文件類型日益增多(如PDF、Word、Excel、PPT、HTML等),如何高效解析并利用這些異構(gòu)數(shù)據(jù)成為核心挑戰(zhàn)。
由于每種文件類型的數(shù)據(jù)結(jié)構(gòu)和內(nèi)容(如PDF的復(fù)雜排版、Excel的表格結(jié)構(gòu)、PPT的多媒體元素)都不一致,在實(shí)際的應(yīng)用場(chǎng)景中,我們需要對(duì)不同文件類型實(shí)現(xiàn)不同的解析器,解析之后還需要根據(jù)不同文件的結(jié)構(gòu)實(shí)現(xiàn)對(duì)應(yīng)的文檔分塊方法。整體來(lái)說(shuō),這樣的系統(tǒng)實(shí)現(xiàn)和維護(hù)成本都是比較高的,要把每種文件類型的解析都做到比較好是比較繁瑣的,但是文件解析如果做的不好,就會(huì)不同程度地影響后續(xù) RAG 系統(tǒng)流程,該種方案流程如下:
可能你會(huì)問(wèn),為什么需要這么多的解析器呢?不能把各種文件直接讀取成字節(jié)流后丟給 LLM 嗎?以當(dāng)前 LLM 的能力,無(wú)論是什么內(nèi)容都需要得組織成文本,它才能處理。而 PDF、Word、網(wǎng)頁(yè)等其實(shí)都是富文本,里面除了文字,通常還包含公式、圖片、表格、統(tǒng)計(jì)圖,排版方式也各不相同,甚至其中的格式也是很重要的內(nèi)容,而這也是文件解析的作用,把各種富文本轉(zhuǎn)換成 LLM 好理解的純文本的過(guò)程。
為什么是 Markdown
- 統(tǒng)一數(shù)據(jù)格式,降低解析復(fù)雜度:Markdown 以純文本形式保留了基本結(jié)構(gòu)(標(biāo)題、列表、代碼塊、表格),同時(shí)去除了冗余的格式信息(如字體、顏色);所有文件統(tǒng)一轉(zhuǎn)換為 Markdown 后,RAG 系統(tǒng)只需針對(duì)一種格式進(jìn)行后續(xù)處理(如分段、分句、實(shí)體提取),顯著降低代碼復(fù)雜度。
- 提升信息提取與語(yǔ)義理解能力: Markdown 的標(biāo)題語(yǔ)法(
#
、##
)可直接映射為文檔結(jié)構(gòu),便于模型快速定位關(guān)鍵信息;Markdown 的表格和代碼塊標(biāo)記(如`````)能保留原始數(shù)據(jù)的排版邏輯,幫助模型理解數(shù)據(jù)關(guān)系;通過(guò)-
、>
等符號(hào)標(biāo)記的列表和引用內(nèi)容,可輔助模型識(shí)別要點(diǎn)和上下文關(guān)聯(lián)。去除原始文件中的樣式、腳注、頁(yè)眉頁(yè)腳等非核心內(nèi)容,使文本更聚焦于語(yǔ)義信息。 - 優(yōu)化存儲(chǔ)與檢索效率:Markdown 文件體積小,適合大規(guī)模知識(shí)庫(kù)的存儲(chǔ)和快速加載;基于 Markdown 的結(jié)構(gòu)化文本可直接生成倒排索引,提升檢索速度和準(zhǔn)確性。
- 增強(qiáng)可維護(hù)性與可解釋性:開(kāi)發(fā)者可直接通過(guò)文本編輯器查看 Markdown 內(nèi)容,便于調(diào)試和驗(yàn)證解析結(jié)果;Markdown 文件易于進(jìn)行版本管理(如Git),支持團(tuán)隊(duì)協(xié)作和歷史追溯。
統(tǒng)一轉(zhuǎn)換成 Markdown 之后,可優(yōu)化成如下流程:
統(tǒng)一轉(zhuǎn)成 Markdown 之后,只需要將注意力專注在 Markdown 解析和處理上就可以了,這樣可以大幅降低整個(gè)系統(tǒng)的開(kāi)發(fā)、維護(hù)成本。
而將 PDF 轉(zhuǎn) Markdown、Word 轉(zhuǎn) Markdown 等有很多成熟的工具可以使用這樣就沒(méi)必要自己寫解析器來(lái)處理了,比如 MinerU[1] - 上海人工智能實(shí)驗(yàn)室開(kāi)源的項(xiàng)目、MarkItDown - Microsoft AutoGen 團(tuán)隊(duì)開(kāi)源的項(xiàng)目等等,這些項(xiàng)目都是專門用于將各種文件格式轉(zhuǎn)換為 Markdown,可以參考借鑒和使用。
本文完整代碼地址[2]
MinerU 使用方法
今天就以 CPU 運(yùn)行的方式來(lái)簡(jiǎn)單介紹下 MinerU 的使用方法(沒(méi)有找到類似 Nodejs 的工具,只能使用 Python 來(lái)介紹了...),更多內(nèi)容到 Github 上使用cpu快速體驗(yàn)[3]查看。
安裝 magic-pdf
conda create -n .venv 'pythnotallow=3.12' -y
conda activate .venv
pip install -U "magic-pdf[full]" -i https://mirrors.aliyun.com/pypi/simple
以上是官方示例。如果你沒(méi)有安裝 conda(不建議使用 uv,有兼容性問(wèn)題),可以直接使用 Python 的命令創(chuàng)建虛擬空間安裝:
python3.12 -m venv .venv
source .venv/bin/activate
pip install -U "magic-pdf[full]" -i https://mirrors.aliyun.com/pypi/simple
(截止到發(fā)文時(shí))這里需要注意,Python 的版本需要在 3.10 ~ 3.12 之間,不然 magic-pdf 會(huì)被自動(dòng)降級(jí)到 0.6.1。
下載模型文件
模型文件可以從 Hugging Face 或 Model Scope 下載,由于網(wǎng)絡(luò)原因,國(guó)內(nèi)用戶訪問(wèn) HF 可能會(huì)失敗,請(qǐng)使用 ModelScope。
pip install modelscope
wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models.py -O download_models.py
python download_models.py
修改配置文件【可選】
完成第二個(gè)步驟后,腳本會(huì)自動(dòng)生成用戶目錄下的 magic-pdf.json 文件,并自動(dòng)配置默認(rèn)模型路徑。 您可在【用戶目錄】下找到 magic-pdf.json 文件。
windows的用戶目錄為 "C:\Users\用戶名",
linux用戶目錄為 "/home/用戶名",
macOS用戶目錄為 "/Users/用戶名"。
您可修改該文件中的部分配置實(shí)現(xiàn)功能的開(kāi)關(guān),如表格識(shí)別功能:
{
// other config
"layout-config":{
"model":"doclayout_yolo"
},
"formula-config":{
"mfd_model":"yolo_v8_mfd",
"mfr_model":"unimernet_small",
"enable":true// 公式識(shí)別功能默認(rèn)是開(kāi)啟的,如果需要關(guān)閉請(qǐng)修改此處的值為"false"
},
"table-config":{
"model":"rapid_table",
"sub_model":"slanet_plus",
"enable":true,// 表格識(shí)別功能默認(rèn)是開(kāi)啟的,如果需要關(guān)閉請(qǐng)修改此處的值為"false"
"max_time":400
}
}
代碼示例
import os
from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader
from magic_pdf.data.dataset import PymuDocDataset
from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze
from magic_pdf.config.enums import SupportedPdfParseMethod
defmain():
# args
pdf_file_name = "2024少兒編程教育行業(yè)發(fā)展趨勢(shì)報(bào)告.pdf"# replace with the real pdf path
name_without_suff = pdf_file_name.split(".")[0]
# prepare env
local_image_dir, local_md_dir = "output/images", "output"
image_dir = str(os.path.basename(local_image_dir))
os.makedirs(local_image_dir, exist_ok=True)
image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(
local_md_dir
)
# read bytes
reader1 = FileBasedDataReader("")
pdf_bytes = reader1.read(pdf_file_name) # read the pdf content
# proc
# Create Dataset Instance
ds = PymuDocDataset(pdf_bytes)
# inference
if ds.classify() == SupportedPdfParseMethod.OCR:
infer_result = ds.apply(doc_analyze, ocr=True)
# pipeline
pipe_result = infer_result.pipe_ocr_mode(image_writer)
else:
infer_result = ds.apply(doc_analyze, ocr=False)
# pipeline
pipe_result = infer_result.pipe_txt_mode(image_writer)
# draw model result on each page
infer_result.draw_model(os.path.join(
local_md_dir, f"{name_without_suff}_model.pdf"))
# get model inference result
model_inference_result = infer_result.get_infer_res()
# draw layout result on each page
pipe_result.draw_layout(os.path.join(
local_md_dir, f"{name_without_suff}_layout.pdf"))
# draw spans result on each page
pipe_result.draw_span(os.path.join(
local_md_dir, f"{name_without_suff}_spans.pdf"))
# get markdown content
md_content = pipe_result.get_markdown(image_dir)
# dump markdown
pipe_result.dump_md(md_writer, f"{name_without_suff}.md", image_dir)
# get content list content
content_list_content = pipe_result.get_content_list(image_dir)
# dump content list
pipe_result.dump_content_list(
md_writer, f"{name_without_suff}_content_list.json", image_dir)
# get middle json
middle_json_content = pipe_result.get_middle_json()
# dump middle json
pipe_result.dump_middle_json(md_writer, f'{name_without_suff}_middle.json')
if __name__ == "__main__":
main()
運(yùn)行之后,會(huì)在本地生成提取到的圖片、中間過(guò)程文件以及最終生成的 Markdown 文件。
生成的 Markdown 文檔:
原始文檔:
可以看到,提取的結(jié)果還是比較符合預(yù)期的,圖片也都正確提取出來(lái)了。
結(jié)語(yǔ)
今天通過(guò)簡(jiǎn)單介紹 MinerU 的使用方法的同時(shí),來(lái)給大家?guī)?lái)一種文件解析優(yōu)化的思路,希望能對(duì)大家有所啟發(fā)。
引用鏈接
[1]
MinerU: https://github.com/opendatalab/MinerU
[2]
本文完整代碼地址: https://github.com/laixiangran/ai-learn-python/blob/main/app/file2Markdown.py
[3]
使用cpu快速體驗(yàn): https://github.com/opendatalab/MinerU/blob/master/README_zh-CN.md#%E4%BD%BF%E7%94%A8cpu%E5%BF%AB%E9%80%9F%E4%BD%93%E9%AA%8C