MinerU output linter/fixer — LLM tool-use loop that restructures (never generates) MinerU content_list. Machine-verified fidelity: C_out ⊆ C_in.
Project description
mineru-refine
🌏 中文文档:README.zh-CN.md
A post-processor (linter / fixer) for MinerU parse results.
It takes MinerU's content_list (an array of item objects), fixes the high-frequency
structural problems that parsing introduces — pseudo-headings, cross-page sentence
breaks, cross-page split tables, headers/footers mixed into the body, LaTeX / link
residue — and returns a content_list with the same schema, so downstream consumers
need zero changes.
Two core promises:
- Never adds a single character: it only removes and reorganizes; every content character in the output comes from the input, verified step by step by machine, and any violation is rolled back automatically (not enforced by prompting the LLM).
- fail-open: any exception / LLM unavailability → the input is returned unchanged
(
report["failOpen"] == True), never breaking the upstream pipeline.
This package is a native PyO3 binding of the Rust core implementation; its options and return values are structurally identical to the JS / Rust / HTTP versions.
Install
pip install mineru-refine
Requires Python ≥ 3.9.
Usage
import json
import mineru_refine
items = json.load(open("content_list.json"))
result = mineru_refine.refine(
items, # content_list (list[dict])
sha256="...", # optional: source-file SHA256; enables the in-process cache
max_iterations=None, # optional: hard cap on the fix loop; defaults to adaptive with suspect count
concurrency=8, # optional: number of suspects judged in parallel; 1 = strictly serial
image_dir="/abs/mineru/out", # optional: MinerU output dir; enables vision judging for split tables
fix_ocr_confusion=False, # optional: opt-in OCR character-confusion fix layer (CE0→CEO, etc.)
extra_confusion_pairs=None, # optional: extra allowlist pairs for confusion, e.g. ["0D"]
rewrite_garbled_tables=False, # optional: opt-in vision re-transcription layer for garbled tables (needs image_dir)
degrade_garbled_tables=False, # optional: opt-in fallback that demotes unrecoverable garbled tables to images
model_config=None, # optional: config-driven model swap (see "Swapping models" below)
chat=None, # optional: custom text-LLM callback (escape hatch; takes priority over model_config)
vision=None, # optional: custom vision-LLM object (escape hatch)
)
result["items"] # cleaned content_list (same schema; unknown fields passed through verbatim)
result["report"] # audit report: iterations / opCounts / dismissed / removedSpans
# / violations / tokenUsage / failOpen
# (with fix_ocr_confusion on, also confusionFixes etc.; see the main README)
Every removed span is recorded in report["removedSpans"] (itemId / original text /
reason), auditable line by line. fix_ocr_confusion=True turns on the confusion-fix
layer (direct replacement, LLM proposal + mechanical gates); once on, the output
contract changes from "remove-only" to a dual contract — see the "Confusion-fix layer"
section of the main README. rewrite_garbled_tables=True turns on vision
re-transcription for heavily garbled tables (mechanical detection selects tables judged
whole-table junk, Qwen-VL re-transcribes cell by cell against the crop, all recorded in
report["tableRewrites"]) — see the "Garbled-table re-transcription layer" section of
the main README. degrade_garbled_tables=True turns on the garbled-table fallback
(purely mechanical, runs after the re-transcription layer: tables still judged junk that
have an img_path are demoted to image, counted in report["tableDegraded"]) — see
the "Fallback demotion" section of the main README.
Standalone helper functions (none call the LLM):
mineru_refine.render_markdown(items) # items → full.md text (deterministic re-render)
mineru_refine.detect_suspects(items) # detect suspects only, returns the suspect list
Swapping models (custom LLMs)
By default the text role is DeepSeek and the vision role is Qwen-VL. Two mechanisms let you point them at any other LLM (e.g. MiniMax); see the main README for the full explanation.
1. model_config — config-driven, multi-vendor (recommended). A dict with two
independent roles (reasoning for text, vision for vision); each is
{provider?, model, key?, baseUrl?} (camelCase keys). Omit a role to fall back to the env
default.
mineru_refine.refine(
items,
image_dir="/abs/mineru/out",
model_config={
# MiniMax-M3 is OpenAI-compatible and multimodal, so one model serves both roles
"reasoning": {"provider": "openai", "model": "MiniMax-M3", "key": key, "baseUrl": "https://api.minimaxi.com/v1"},
"vision": {"provider": "openai", "model": "MiniMax-M3", "key": key, "baseUrl": "https://api.minimaxi.com/v1"},
},
)
provider accepts deepseek / aliyun (qwen, dashscope) / openai
(openai-compatible, custom) / anthropic (claude) / gemini (google) / ollama /
groq / xai (grok); omit it to infer from the model name.
2. Custom callbacks — the escape hatch (take priority over model_config). Pass your
own implementations when you need auth/proxy/model logic model_config can't express:
def chat(messages, tools):
# messages: list[dict] (OpenAI-style), tools: list[dict]
return {
"message": {"content": "...", "tool_calls": [...]}, # tool_calls optional
"finishReason": "stop",
"usage": {"prompt_tokens": 0, "completion_tokens": 0},
}
class Vision:
def judge_split_table(self, img_a: bytes, img_b: bytes):
return {"verdict": "merge", "reason": "...", "usage": {}} # verdict: "merge" | "dismiss"
def transcribe_table(self, img: bytes, cells_render: str): # optional; only for rewrite_garbled_tables
return {"cells": [{"row": 0, "col": 0, "text": "..."}], "usage": {}}
mineru_refine.refine(items, image_dir="/abs/mineru/out", chat=chat, vision=Vision())
Environment variables
| Variable | Required | Purpose |
|---|---|---|
DEEPSEEK_APIKEY |
Yes | Text judging (DeepSeek). If missing, refine goes straight to fail-open |
QWEN_APIKEY |
For vision judging | Qwen-VL judging of cross-page split tables; if missing, those suspects are skipped and the tables kept as-is |
The library itself does not read .env; set the environment variables in the host
program (or load .env yourself).
Building locally
just py-dev # repo root: build the wheel and install it into bindings/python/.venv
just publish-py # publish to PyPI: current-platform wheel + sdist (needs MATURIN_PYPI_TOKEN)
The full design docs for the detector, the fix operation set, and the fidelity gates are in the repository README.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mineru_refine-0.12.0.tar.gz.
File metadata
- Download URL: mineru_refine-0.12.0.tar.gz
- Upload date:
- Size: 493.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70f4e08844194d8bd985f1db0815b44218401787607aac7b911d9bd09d8da1c4
|
|
| MD5 |
84bb49374467b04bde70fc00a6499348
|
|
| BLAKE2b-256 |
da6b564ea23845fbac3905d3eff50a86319e5728a1ff18c7dae10d4a7e64f461
|
Provenance
The following attestation bundles were made for mineru_refine-0.12.0.tar.gz:
Publisher:
py-release.yml on LcpMarvel/mineru-refine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mineru_refine-0.12.0.tar.gz -
Subject digest:
70f4e08844194d8bd985f1db0815b44218401787607aac7b911d9bd09d8da1c4 - Sigstore transparency entry: 2148837542
- Sigstore integration time:
-
Permalink:
LcpMarvel/mineru-refine@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Branch / Tag:
refs/tags/v0.12.0 - Owner: https://github.com/LcpMarvel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
py-release.yml@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Trigger Event:
push
-
Statement type:
File details
Details for the file mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.6 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6fa884ed3f10de471812fc5bf45d1fae00bb38683e95067be57e148e3757246
|
|
| MD5 |
acf329868edb6c7df9e098ca2f29417f
|
|
| BLAKE2b-256 |
d1a35efe46b333d6e78f301136767355efa6e725bf56729eec26ffc9b73b1a79
|
Provenance
The following attestation bundles were made for mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
py-release.yml on LcpMarvel/mineru-refine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
a6fa884ed3f10de471812fc5bf45d1fae00bb38683e95067be57e148e3757246 - Sigstore transparency entry: 2148837578
- Sigstore integration time:
-
Permalink:
LcpMarvel/mineru-refine@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Branch / Tag:
refs/tags/v0.12.0 - Owner: https://github.com/LcpMarvel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
py-release.yml@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Trigger Event:
push
-
Statement type:
File details
Details for the file mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34da5a23afbf9eef5177d6abc1df36d4010fd11cad6240eaa8912caa65ed66cc
|
|
| MD5 |
bee5d387582f62c4ebee1ab0403050ae
|
|
| BLAKE2b-256 |
14b50eb43b3abfb667eb5034621327b2a15201e85a33fb9c719aebb0e3b80785
|
Provenance
The following attestation bundles were made for mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
py-release.yml on LcpMarvel/mineru-refine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mineru_refine-0.12.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
34da5a23afbf9eef5177d6abc1df36d4010fd11cad6240eaa8912caa65ed66cc - Sigstore transparency entry: 2148837597
- Sigstore integration time:
-
Permalink:
LcpMarvel/mineru-refine@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Branch / Tag:
refs/tags/v0.12.0 - Owner: https://github.com/LcpMarvel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
py-release.yml@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Trigger Event:
push
-
Statement type:
File details
Details for the file mineru_refine-0.12.0-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: mineru_refine-0.12.0-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cfc373b56b1043004eb5a0a6bac0782209279a6729a494b61665ce64abf45fa5
|
|
| MD5 |
96582f79f3ca63103ff8e2f016adb0da
|
|
| BLAKE2b-256 |
930487191c03714f0362d10a1d45776b8cd657826d205c5dc3a9c9aa8b5a5613
|
Provenance
The following attestation bundles were made for mineru_refine-0.12.0-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
py-release.yml on LcpMarvel/mineru-refine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mineru_refine-0.12.0-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
cfc373b56b1043004eb5a0a6bac0782209279a6729a494b61665ce64abf45fa5 - Sigstore transparency entry: 2148837626
- Sigstore integration time:
-
Permalink:
LcpMarvel/mineru-refine@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Branch / Tag:
refs/tags/v0.12.0 - Owner: https://github.com/LcpMarvel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
py-release.yml@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Trigger Event:
push
-
Statement type:
File details
Details for the file mineru_refine-0.12.0-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: mineru_refine-0.12.0-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d38d680e731cea1395300a8d108fb8792b16777925c0dcc25d257668a6409c1
|
|
| MD5 |
8c2b72dde9905384f387afe172feee3f
|
|
| BLAKE2b-256 |
486880fca93033ce08be3bef358699561597a23f228d6e9a8d759c26102454c1
|
Provenance
The following attestation bundles were made for mineru_refine-0.12.0-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
py-release.yml on LcpMarvel/mineru-refine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mineru_refine-0.12.0-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
6d38d680e731cea1395300a8d108fb8792b16777925c0dcc25d257668a6409c1 - Sigstore transparency entry: 2148837669
- Sigstore integration time:
-
Permalink:
LcpMarvel/mineru-refine@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Branch / Tag:
refs/tags/v0.12.0 - Owner: https://github.com/LcpMarvel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
py-release.yml@dbb64eba9ee04edced4407acf662cd7bebbda49d -
Trigger Event:
push
-
Statement type: