跳到主要内容

pipeline 后端:传统多模型流水线

30 秒导读: pipeline 是 MinerU 的"传统"解析后端。它不靠一个大模型端到端读版面,而是把 一堆各管一件事的专用小模型(版面检测 → 公式检测/识别 → 表格识别 → 文字 OCR)串成一条流水线, 每一步只解决一个子问题,最后把逐页的检测结果拼成统一的 middle_json。本章讲透这条"多个专用模型 串成流水线"的主线。

本章聚焦 mineru/backend/pipeline/,是 index 阅读地图里的第二章。 它的上游(谁调用它、字节怎么进来)见 01-orchestration; 它的产物 middle_json 之后怎么变成 Markdown,见 04-middle-json-and-markdown; 另一条走单个视觉语言模型的路线见 03-vlm-backend


1. 这是什么(零基础也能懂)

一句话定义: pipeline 后端 = 一条由多个专用 CV/OCR 模型接力组成的文档解析流水线, 输入是一页页 PDF 图,输出是每页上"哪里是标题、哪里是表格、哪里是公式、文字是什么"的结构化清单。

它解决什么问题: 一张扫描版或电子版 PDF 页面,对机器来说只是一堆像素。要把它变成能检索、 能渲染成 Markdown 的结构化数据,得先回答一连串问题:

  • 这页有哪些区块、各是什么类型(正文 / 标题 / 图 / 表 / 公式)?——版面检测
  • 每个公式的 LaTeX 是什么?——公式识别(MFR)
  • 每张表格的 HTML 结构是什么?——表格识别
  • 每块文字区域里的字是什么?——OCR

pipeline 的思路:一个子问题配一个专用小模型,而不是让一个大模型全包(那是 vlm 后端的活)。

一句话直觉: 把它想成一条流水线工厂——第一个工位(版面模型)先把页面切成一个个"零件盒" 并贴上标签,后面每个工位(公式、表格、OCR)只负责给自己那类盒子填内容,最后总装成一份零件清单。

用起来什么样: 使用者基本不直接碰本模块。上层入口(见 01-orchestration) 把 PDF 字节、语言、是否 OCR 传进来,本模块内部就把上面这条流水线跑一遍。对外的核心函数是 doc_analyze_streamingmineru/backend/pipeline/pipeline_analyze.py:157),它一边跑一边通过回调 on_doc_ready 把每份文档的结果吐出来。

本节不碰底层。往下才逐层展开。


2. 顶层全景(它大概怎么转)

2.1 五个源文件,各管一段

pipeline 后端就五个核心文件,正好对应"装配 → 编排 → 组批推理 → 结果转换"四个环节:

文件职责关键符号
model_init.py装配:把各专用模型初始化好、用单例缓存起来MineruPipelineModelAtomModelSingleton
pipeline_analyze.py编排:按页开窗、组批、驱动整条流水线、吐结果doc_analyze_streamingbatch_image_analyze
batch_analyze.py组批推理:真正把 layout→公式→表格→OCR 依次跑一遍BatchAnalyze.__call__
model_json_to_middle_json.py转换:把逐页模型检测结果转成 middle_jsonappend_batch_results_to_middle_jsonfinalize_middle_json
pipeline_magic_model.py转换时的辅助:把一页原始检测框整理成区块(本章略讲,详见第 6 节与 04MagicModel

2.2 数据怎么流

一页 PDF 图从进到出,走的是这条主线(从上到下是时间顺序):

一批 PIL 页面图 (images_with_extra_info)


┌───────────────────────────┐
│ ① 版面检测 layout │ PP-DocLayoutV2
│ 一页 → 一串带标签的框 │ 产出 images_layout_res
└───────────────────────────┘
│ 每页得到 layout_res:[{label,bbox,...}]

┌───────────────────────────┐
│ ② 公式识别 MFR │ 只挑 label∈{行内/行间公式} 的框
│ 框内图 → LaTeX │ 回填 res["latex"]
└───────────────────────────┘


┌───────────────────────────┐
│ ③ 表格识别 │ 裁出每张表 → 方向分类 → 有/无线分类
│ 表图 → HTML │ → 表内 OCR det+rec → 生成 html
└───────────────────────────┘


┌───────────────────────────┐
│ ④ 文字 OCR det + rec │ 非表区域: 检测文字框 → 识别文字
│ 区域图 → 文本+分数 │ 结果 extend 回 layout_res
└───────────────────────────┘
│ 返回补全后的 images_layout_res

┌───────────────────────────┐
│ ⑤ 转 middle_json │ 逐页 layout_dets → MagicModel → 区块
└───────────────────────────┘

怎么读这张图: 每个方框是一个工位;它只对"上一步给它贴好标签的那类框"动手,做完把结果回填到同一份 layout_res——所以最后一份 layout_res 就积累了全部信息。①的产物是后面②③④共同的"任务单"。

2.3 一条设计暗线:结果原地累积

整条流水线不是每步产出一个新对象、层层传递,而是所有步骤都往同一份 images_layout_res 里回填

  • 版面检测先把每页的框列出来。
  • 公式识别只是给公式框补个 latex 字段。
  • 表格识别把表内容写进表框的 table_res
  • OCR 把识别出的文字框 extendlayout_res

这样 BatchAnalyze.__call__ 最后 return images_layout_resbatch_analyze.py:978)就是全部结果。 理解这一点,后面读代码就不会迷路。


3. 核心机制一:模型装配(model_init.py)

3.1 要解决的小问题

流水线要用到七八个模型(版面、公式、OCR、有线表、无线表、表分类、表方向分类……), 它们初始化都很贵(要下载权重、加载到显存)。同一个进程里反复解析多份 PDF,绝不能每次都重建。 所以需要:按配置缓存、只建一次、线程安全

3.2 两层单例

装配用了两层单例,一层管"整套流水线模型组合",一层管"单个原子模型":

单例缓存的东西缓存键符号
ModelSingleton一整套 pipeline 模型(lang, formula_enable, table_enable)pipeline_analyze.py:33
AtomModelSingleton单个原子模型按模型类型不同,见下model_init.py:148

ModelSingleton.get_modelpipeline_analyze.py:44)在缓存未命中时调 custom_model_initpipeline_analyze.py:61)→ 构造一个 MineruPipelineModel

MineruPipelineModel.__init__model_init.py:231)就是"总装配单":它按开关把公式模型、 版面模型、OCR、以及一整套表格模型(有线表 / 无线表 / 表分类 / 表方向分类)逐个从 AtomModelSingleton 取出来挂到 self 上。注意它只取,不重复造——真正的构造在原子单例里。

3.3 AtomModelSingleton 的分键缓存

AtomModelSingleton.get_atom_modelmodel_init.py:159)的巧妙处在于缓存键随模型类型而变

  • OCR 模型:键含 (名字, det_db_box_thresh, 语言, det_db_unclip_ratio, enable_merge_det_boxes)—— 因为不同阈值/语言要的是不同的 OCR 实例。
  • 版面 / MFR:键只含 (名字, device)——一个设备上共用一份。
  • 表分类等无参模型:键就是名字本身。

未命中时调 atom_model_initmodel_init.py:189),它是一个大 if/elif 分发器,把 AtomicModel.Layoutpp_doclayout_v2_model_init.MFRmfr_model_init.OCRocr_model_init…… (model_init.py:191-222)逐一路由到各自的构造函数。

3.4 公式模型可切换

一个值得注意的细节:公式识别默认用 unimernet_small,但可用环境变量 MINERU_FORMULA_CH_SUPPORT 切到 pp_formulanet_plus_m(对中文公式更好)。这个开关在 model_init.py:62-69 读取,mfr_model_initmodel_init.py:115)据此二选一构造。

3.5 推理锁:一个默认关闭的实验开关

model_init.py:22-30 定义了三把推理阶段锁(layout / mfr / ocr)和一个总开关 PIPELINE_INFERENCE_LOCKS_ENABLED。它们保护"pipeline 与 hybrid 共享的同一个原子模型对象 不被多线程同时进入"。

关键在 _run_with_inference_lockmodel_init.py:33):开关默认为 False,此时直接调用、 根本不进锁;只有设了环境变量才在锁内执行。run_layout_inference / run_mfr_inference / run_ocr_inferencemodel_init.py:42-60)就是三个薄封装,batch_analyze.py 里每次真实推理 都经它们包一层,这样"要不要加锁"能一处切换。与之相对,模型装配用的 PIPELINE_MODEL_INIT_LOCKmodel_init.py:22)是始终生效的 RLock,保证单例只建一次。


4. 核心机制二:开窗组批与流式产出(pipeline_analyze.py)

4.1 要解决的小问题

一次可能传进来多份 PDF、每份很多页。如果一页一页推理,GPU 利用率低;如果一次全塞进去, 显存扛不住。所以需要一个固定大小的处理窗口:跨文档凑够一批页再推一次,推完立刻释放这批页的图。

4.2 是否要 OCR:先给每份文档定性

进流水线前,每份 PDF 先由 _get_ocr_enablepipeline_analyze.py:88)决定要不要走 OCR:

parse_method行为
'auto'classify(pdf_bytes),判为 'ocr'(扫描件)才开 OCR
'ocr'强制开
其他(如 'txt'关(电子版直接取文本层)

这个 ocr_enable 会一路带到 OCR 环节,决定文字是"从 PDF 文本层取"还是"真跑 OCR 识别"。

4.3 处理窗口怎么开

doc_analyze_streamingpipeline_analyze.py:157)的主循环(:225 起)是这样组批的:

  1. 为每份文档建一个 context:180),记住它的页码游标 next_page_idx、自己的 middle_json 等。
  2. 取窗口大小 window_size = get_processing_window_size(default=64):207)。
  3. 每轮从各文档依次取页填满一个 batch_capacity=window_size 的批(:232-262)—— 即一批里可能混着 doc0 的尾页 + doc1 的头页,跨文档凑批。
  4. 这批图交给 batch_image_analyze:271)跑完整条流水线。
  5. result_offset批结果切回各文档:285-299),再 append_batch_results_to_middle_json 落进各自的 middle_json
  6. 某文档所有页都处理完(next_page_idx >= page_count),立刻 _finalize_processing_window_context:301)做收尾并回调 on_doc_ready 把它吐出去。

4.4 流式的意义

on_doc_ready 是回调式产出:先处理完的文档先返回,不用等整批全部做完。零页文档(如空 PDF) 在开跑前就由 _emit_zero_page_contexts:143)直接吐出。收尾时无论成功失败,finally:324-328)都会关掉所有还没关的 pdfium 文档句柄——资源管理很谨慎。

4.5 组批参数由显存动态决定

batch_image_analyzepipeline_analyze.py:331)在真正调 BatchAnalyze 前,先根据显存算一个 batch_ratio:353-363)——显存越大、批越大:

显存 (GB)batch_ratio
≥ 3216
≥ 168
≥ 84
≥ 62
< 61

这个 batch_ratio 会乘到各阶段的基础批大小上(见下节)。它还顺手判断了 NPU 环境、以及 torch ≥ 2.8 时是否开 OCR-det 组批(:369-377),把这些一并传给 BatchAnalyze


5. 核心机制三:组批推理主流程(batch_analyze.py)

这是本章的心脏。BatchAnalyze.__call__batch_analyze.py:408)把一批页图跑完整条流水线。 下面按它的执行顺序拆解。各阶段的基础批大小是常量(batch_analyze.py:38-41):

常量用途
LAYOUT_BASE_BATCH_SIZE1版面检测批基数
MFR_BASE_BATCH_SIZE16公式识别批基数
OCR_DET_BASE_BATCH_SIZE8OCR 检测批基数
TABLE_Wired_Wireless_CLS_BATCH_SIZE16表格分类批大小

5.1 阶段①:版面检测 → 一份"任务单"

# 示意,非源码;对应 batch_analyze.py:426-430
# 一次把整批 PIL 图喂给版面模型,得到每页的框列表
images_layout_res += self.model.layout_model.batch_predict(
pil_images,
batch_size=min(8, batch_ratio * 1), # LAYOUT_BASE_BATCH_SIZE=1
)

每页产出一个 layout_res 列表,每项是 {label, bbox, score, ...}label 是后面所有分支的依据: table 归表格环节,display_formula/inline_formula 归公式环节,正文类标签归 OCR 环节。 版面模型是 PP-DocLayoutV2model/layout/pp_doclayoutv2.py),除了检测框还预测阅读顺序 (reading order,模型内有专门的 ReadingOrder 子模块)。

5.2 阶段②:公式检测 + 识别(MFR)

版面模型已经把公式检测出来了(框带 inline_formula/display_formula 标签),所以这里只做识别

# 示意,非源码;对应 batch_analyze.py:434-457
if self.formula_enable:
# 从版面结果里挑出所有公式框,按页收集
images_mfd_res = [[res for res in page if res["label"] in
("display_formula", "inline_formula")]
for page in images_layout_res]
# 一次识别整批公式框内的图 → LaTeX
formulas = self.model.mfr_model.batch_predict(images_mfd_res, np_images, ...)
# 把 latex 回填进原来的公式框
for page_i, page_formulas in enumerate(formulas):
for res, out in zip(images_mfd_res[page_i], page_formulas):
res["latex"] = out.get("latex", "")

关键点:识别结果直接写回原框的 latex 字段,不新建对象——又是"原地累积"那条暗线。 公式模型(MFR)是 unimernet_smallpp_formulanet_plus_m(见 3.4)。 若 formula_enable=False,则把所有 inline_formula 框直接删掉(batch_analyze.py:462-465)。

5.3 阶段③:表格识别——最曲折的一段

表格是流水线里步骤最多的一支,因为一张表要先摆正、再定类型、再读文字、最后拼 HTML。 整段在 batch_analyze.py:520-699,子步骤如下:

表框 → [方向分类] → [有线/无线分类] → [表内 OCR det] → [表内 OCR rec] → [无线表模型] → [有线表模型] → 清理 HTML

准备:裁表 + 抽取表内 inline object。:495-517 为每张表裁出两种尺度的图 (wireless_table_img 原尺度、wired_table_img 放大 10/3)。更巧的是 _extract_table_inline_objectsbatch_analyze.py:318):它把落在表格框内的图片和公式从版面结果里 "摘出来",记下它们相对表格的位置与内容(图片编码成 <img ...>、公式包成 <eq>latex</eq>), 并从 layout_res 里移除——这样它们不会被当成普通文字,稍后再回填进表格 HTML 的对应单元格。

方向分类:522-546):table_ori_cls 模型判断表是否被旋转了 90/270 度, _apply_table_rotate_labelbatch_analyze.py:260)据此把表图转正。

有线/无线分类:548-558):table_cls 给每张表打 cls_label(有线 wired_table / 无线 wireless_table)和置信度。

表内 OCR 检测(det):560-602):这是"公式遮罩"(mask inline formula)第一次出场。 _build_table_ocr_det_itemsbatch_analyze.py:99)把表内 inline object 的区域涂掉再送去检测 ——否则公式/图片会被误检成一堆文字框。检测出的文字框经 _append_table_ocr_det_resultbatch_analyze.py:134)排序、裁图,按语言分组存进 rec_img_lang_group,为下一步 rec 组批做准备。

表内 OCR 识别(rec):604-634):按语言分批调 ocr_engine.ocr(..., det=False), 把识别出的文字table_id 回填到对应表的 ocr_result。同一份表的所有 cropped 图凑一批识别, 就是"OCR rec 分组"。

inline object 回填:636-655):把先前摘出的图片/公式 token 作为特殊 ocr_result 项塞回去, 再 _sort_table_ocr_result 按位置排序——这样表格模型拿到的"单元格文字流"里就带着 <img>/<eq>

跑表格模型:657-688):先对所有表用无线表模型 wireless_table_model.batch_predict (组批)生成初版 HTML;再挑出"分类为有线、或无线但置信度 < 0.9"的表(:664-672), 用有线表模型 UnetTableModel 逐张 predict 覆盖(有线表结构更规整,专用模型效果更好)。

清理 HTML:690-699):只保留 <table>...</table> 之间的内容。

5.4 阶段④:正文文字 OCR(det + rec)

表格之外的正文区域走通用 OCR。分检测识别两步,都按语言分组组批。

OCR 检测(det)batch_analyze.py:702-798):对每个待 OCR 区域裁图、BGR 转换,然后 _get_masked_det_imagebatch_analyze.py:90)在 mask_inline_formula_for_ocr_det 开启时 把公式区域涂掉(mask inline formula 第二次出场,逻辑同表内,避免公式被检成文字)。 所有裁图按语言 lang_groups 分组(:736-739),每组一次 ocr_model.text_detector.batch_predict。检出的框经 sorted_boxes(排序)、merge_det_boxes (合并相邻框)、update_det_boxes(按公式位置修正),再 get_ocr_result_list extend 回该页 layout_res:778-795)。若开关关闭则回退逐张处理(:800-840)。

OCR 识别(rec)batch_analyze.py:842-921):扫一遍所有 layout_res,凡带 _need_ocr_rec 标记的项,收集其裁图按语言分组img_crop_lists_by_lang),每组一次 ocr_model.ocr(det=False) 批量识别。识别结果写进 text/score,并做低质量过滤 (置信度低于阈值、或命中一串已知误识别短串如 '(204号'/'(cid:)' 的,直接删掉,:897-919)。

印章 OCR:923-970):label=="seal" 的框单独用 lang="seal" 的 OCR 模型跑一遍。

各原子模型的一句话职责:

模型目录干什么模型
model/layout/pp_doclayoutv2.py版面检测 + 阅读顺序PP-DocLayoutV2
model/ocr/pytorch_paddle.py文字检测 + 识别(PyTorch 版 Paddle OCR)PP-OCRv6
model/mfr/unimernet/公式图 → LaTeX(默认)unimernet_small
model/mfr/pp_formulanet_plus_m/公式图 → LaTeX(中文增强,可选)PP-FormulaNet_plus-M
model/table/rec/slanet_plus/无线表格 → HTMLSLANet-plus
model/table/rec/unet_table/有线表格 → HTMLUNet 表格模型
model/table/cls/表格分类 / 方向分类Paddle 表分类

OCR 升级说明:pipeline 后端的 OCR 模型已升至 PP-OCRv6(见仓库 README.md:88)。


6. 核心机制四:逐页检测结果 → middle_json

流水线返回的 images_layout_res 还是"逐页原始检测框",要变成统一中间表示 middle_json。 这一步在 model_json_to_middle_json.py

6.1 起点与容器

init_middle_jsonmodel_json_to_middle_json.py:234)建一个空壳: {"pdf_info": [], "_backend": "pipeline", "_version_name": __version__}。 每处理完一批,doc_analyze_streaming 就调 append_batch_results_to_middle_jsonmodel_json_to_middle_json.py:107)把这批页追加进去。

6.2 每页怎么转

append_batch_results_to_middle_jsonappend_page_model_infos_to_middle_json:72)→ 对每页调 page_model_info_to_page_infomodel_json_to_middle_json.py:28)。这一步的核心是交给 MagicModel

# 示意,非源码;对应 model_json_to_middle_json.py:34-62
magic_model = MagicModel(page_model_info, page, scale, page_pil_img, page_w, page_h, ocr_enable)
preproc_blocks = magic_model.get_preproc_blocks() # 整理好的区块
discarded_blocks = magic_model.get_discarded_blocks() # 丢弃的区块
all_image_spans = magic_model.get_all_image_spans() # 图/表/公式截图
# 把图/表/公式的 span 真正截图存盘
for span in all_image_spans:
span = cut_image_and_table(span, page_pil_img, ...)
page_info = make_page_info_dict(preproc_blocks, page_index, page_w, page_h, discarded_blocks)

MagicModel 是"从原始框到区块"的翻译器:把一页零散的检测框整理成有层级的 preproc_blocks (正文/标题/图/表/公式各归其位),并挑出图/表/公式区域的 span 去截图落盘。它的内部细节属于 04-middle-json-and-markdown 的范畴,本章只需知道它是这一步的主角。 产物 make_page_info_dict:256)是一页的 page_info,追加进 middle_json["pdf_info"]

6.3 全文档收尾

一份文档所有页都追加完后,finalize_middle_jsonmodel_json_to_middle_json.py:225)做文档级后处理, 分服务端与确定性两部分:

  • apply_server_side_postprocess:211)→ _apply_post_ocr:148):对还没识别文字的 span 再补一轮 OCR(依赖 OCR 模型,只能在服务端做)。
  • finalize_middle_json_from_preproc:216):一串确定性后处理—— optimize_formula_number_blocks(公式编号)、para_split(段落切分)、 cross_page_table_merge(跨页表格合并)、apply_title_leveling_to_pdf_info(标题分级)、 _post_block_process(把 doc_titletitle level=1 等收口)。

拆成两半是为了客户端/服务端复用:确定性部分可以在客户端跑,只有依赖模型的 post-OCR 必须在服务端。 doc_analyze_streamingclient_side_output_generation 参数(pipeline_analyze.py:121-129)就是据此 选择只做服务端 post-OCR、还是走完整 finalize。


7. 巧妙之处(可带走的技术)

  • 原地累积而非层层传递。 整条流水线所有阶段都往同一份 images_layout_res 回填,最后一行 return images_layout_resbatch_analyze.py:978)即全部结果。省去大量中间对象。

  • 公式遮罩(mask inline formula)保护 OCR 检测。 送 OCR 检测前把公式/图片区域涂掉 (_get_masked_det_imagebatch_analyze.py:90;表内同理 _build_table_ocr_det_items:99), 避免公式被误检成一堆碎文字框——一个很实用的"预处理防污染"技巧。

  • 跨文档开窗组批。 doc_analyze_streaming 的窗口跨多份文档凑批(pipeline_analyze.py:232-262), 最大化 GPU 批利用率,同时用 result_offset 精确把批结果切回各文档(:285-299)。

  • 按语言分组再组批。 OCR det/rec 和表内 OCR 都先按 lang 分组再各自组批 (batch_analyze.py:736:874:605),因为不同语言用不同 rec 模型,分组才能凑成有效批。

  • 表格 inline object 摘出—回填。 先把表内图片/公式摘出(:318),OCR 时遮罩、识别后再作为 特殊 token 回填排序(:636-655),让表格模型输出的 HTML 里带上 <img>/<eq>

  • 有线表的二次覆盖。 先全体走无线表模型出初稿,再对判为有线(或低置信)的表用 UNet 有线表模型 覆盖(batch_analyze.py:657-688)——用便宜的模型兜底、贵的专用模型精修。


8. 边界与局限

  • 强依赖版面检测的准确性。 ①的框错了,后面②③④全跟着错——它是整条链的"任务单来源"。

  • 表格是最脆弱的一环。 方向分类、有/无线分类、表内 OCR、模型拼 HTML 环环相扣,代码里对分类失败 用 try/except 降级(batch_analyze.py:543:555),可见这里最容易出问题。

  • 多模型 = 多次显存进出。 每个阶段后都 clean_vram:432:460:798);小显存下 batch_ratio=1pipeline_analyze.py:363)会显著变慢。这也是 vlm 后端存在的动机之一 (见 03-vlm-backend)。

  • 推理锁默认关闭。 三把推理锁默认不生效(model_init.py:35),多线程共享同一模型对象的 并发安全靠的是"默认单线程调用"这个前提;hybrid 后端与它共享原子模型时需留意 (见 05-hybrid-and-office)。


9. 横向对比

维度pipeline(本章)vlm(03
解析方式多个专用小模型串成流水线单个视觉语言模型端到端
显存/部署模型多、进出频繁,但单模型小一个大模型,部署更重
可控性每步可单独调参/降级端到端,中间不可插手
产物都汇成统一 middle_json04同上

hybrid 后端复用了本章的部分原子模型(layout/ocr/mfr),把传统流水线与 VLM 结合,见 05-hybrid-and-office


10. 代码地图(导航索引)

主题文件路径符号
流式编排入口mineru/backend/pipeline/pipeline_analyze.pydoc_analyze_streaming
组批参数 + 调 BatchAnalyzemineru/backend/pipeline/pipeline_analyze.pybatch_image_analyze
是否 OCR 判定mineru/backend/pipeline/pipeline_analyze.py_get_ocr_enable
整套模型缓存mineru/backend/pipeline/pipeline_analyze.pyModelSingleton / custom_model_init
组批推理主流程mineru/backend/pipeline/batch_analyze.pyBatchAnalyze.__call__
表内 inline object 抽取mineru/backend/pipeline/batch_analyze.py_extract_table_inline_objects
表内 OCR-det 输入构造(遮罩)mineru/backend/pipeline/batch_analyze.py_build_table_ocr_det_items
正文 OCR-det 遮罩mineru/backend/pipeline/batch_analyze.py_get_masked_det_image
模型总装配mineru/backend/pipeline/model_init.pyMineruPipelineModel
原子模型单例mineru/backend/pipeline/model_init.pyAtomModelSingleton / atom_model_init
推理锁封装mineru/backend/pipeline/model_init.pyrun_layout_inference / run_mfr_inference / run_ocr_inference
原子模型名常量mineru/backend/pipeline/model_list.pyAtomicModel
批结果追加 middle_jsonmineru/backend/pipeline/model_json_to_middle_json.pyappend_batch_results_to_middle_json
逐页转 page_infomineru/backend/pipeline/model_json_to_middle_json.pypage_model_info_to_page_info
文档级收尾mineru/backend/pipeline/model_json_to_middle_json.pyfinalize_middle_json
从原始框整理区块mineru/backend/pipeline/pipeline_magic_model.pyMagicModel
版面模型mineru/model/layout/pp_doclayoutv2.pyPPDocLayoutV2LayoutModel
OCR 模型mineru/model/ocr/pytorch_paddle.pyPytorchPaddleOCR
公式模型mineru/model/mfr/unimernet/Unimernet.pyUnimernetModel
无线表模型mineru/model/table/rec/slanet_plus/main.pyPaddleTableModel
有线表模型mineru/model/table/rec/unet_table/main.pyUnetTableModel