# MinerU Administrator & Developer Guide

This guide is for operators, integrators, and developers running MinerU in production or embedding it into a larger pipeline. It covers the full system architecture, every configuration knob, deployment topologies, security posture, performance tuning, code internals, and integration points.

For end-user usage, parsing recipes, and CLI quick-start, see the [MinerU User Guide](/opendatalab/MinerU/user-guide/).

---

## 1. Architecture Overview

MinerU is a self-contained document-parsing engine that converts PDFs, images, and Office files (DOCX, PPTX, XLSX) into structured Markdown and JSON. The system is organized into three distinct layers, each with clear responsibilities.

### 1.1 Three-Layer Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                      CLI / API Layer                        │
│  mineru (client.py)  │  mineru-api (fast_api.py)            │
│  mineru-gradio       │  mineru-router (router.py)           │
│  mineru-openai-server│  download-models                     │
├─────────────────────────────────────────────────────────────┤
│                     Backend Layer                           │
│  Pipeline Backend    │  VLM Backend    │  Hybrid Backend    │
│  (OCR + layout +     │  (vision-lang   │  (pipeline + VLM   │
│   formula + table)   │   model direct) │   combined)        │
│                      │                 │                    │
│  Office Backend (DOCX / PPTX / XLSX)                       │
├─────────────────────────────────────────────────────────────┤
│                      Model Layer                            │
│  Layout (DocLayoutV2)  │  OCR (PytorchPaddle)               │
│  Formula (Unimernet/FormulaNet+)  │  Table (SLANet+/UNet)  │
│  VLM (vLLM/LMDeploy)  │  Orientation Classification        │
│  Office Converters (DOCX/PPTX/XLSX)                        │
├─────────────────────────────────────────────────────────────┤
│                   Support Modules                           │
│  utils/ (31 modules)  │  data/ (I/O abstraction)           │
│  resources/ (static assets, language model)                 │
└─────────────────────────────────────────────────────────────┘
```

### 1.2 Layer Responsibilities

**CLI / API Layer** (`mineru/cli/`): All user-facing entry points. The main `mineru` CLI command handles local and API-based parsing. `mineru-api` exposes a FastAPI server for programmatic access. `mineru-router` provides load balancing across multiple API instances. `mineru-gradio` offers a browser-based UI. `mineru-openai-server` exposes a VLM endpoint with OpenAI-compatible protocol.

**Backend Layer** (`mineru/backend/`): Processing pipelines that orchestrate model inference:

| Backend | Module Path | Strategy |
|---------|-------------|----------|
| Pipeline | `mineru/backend/pipeline/` | Traditional: layout detection → OCR → formula recognition → table extraction → paragraph splitting → Markdown generation |
| VLM | `mineru/backend/vlm/` | Vision-language model processes pages directly, producing Markdown without intermediate steps |
| Hybrid | `mineru/backend/hybrid/` | Combines pipeline and VLM approaches for best-of-both accuracy |
| Office | `mineru/backend/office/` | Direct conversion of DOCX, PPTX, XLSX without ML models |

**Model Layer** (`mineru/model/`): Thin wrappers around deep learning models. Each model type has its own subdirectory with initialization, inference, and post-processing logic.

### 1.3 Key Design Decisions

- **Filesystem-only state**: No database. Jobs, outputs, and configuration all live on the filesystem.
- **Singleton model loading**: `ModelSingleton` ensures each ML model is loaded exactly once per process, preventing VRAM waste.
- **Protocol versioning**: `API_PROTOCOL_VERSION` constant in `api_protocol.py` ensures client/server compatibility. Mismatched versions raise explicit errors.
- **Atomic task management**: `AsyncTaskManager` handles concurrent parse requests with thread-safe task tracking.

### 1.4 Processing Pipeline Flow

The pipeline backend (the most complex path) processes documents through these stages:

```
Input (PDF/Image)
    │
    ▼
PDF Classification ─── auto-detect "txt" vs "ocr" method
    │                   (pdf_classify.py)
    ▼
Page Rendering ──────── PDF pages → images via pypdfium2
    │                   (pdf_image_tools.py)
    ▼
Batch Analysis ──────── All models run in batched inference
    │                   (batch_analyze.py)
    │
    ├── Layout Detection (DocLayoutV2)
    │       → region classification
    ├── OCR Text Extraction (PytorchPaddle)
    ├── Formula Recognition (Unimernet/FormulaNet+)
    ├── Table Detection
    │       ├── Wireless tables (SLANet+)
    │       ├── Wired tables (UNet)
    │       └── Table classification fallback
    └── Orientation Classification
    │
    ▼
MagicModel ──────────── Post-processing, 25+ methods
    │                   (pipeline_magic_model.py)
    ▼
Model JSON → Middle JSON conversion
    │   (model_json_to_middle_json.py)
    ▼
Paragraph Splitting ─── (para_split.py)
    │
    ▼
Table Merging ───────── Cross-page table merging
    │                   (table_merge.py)
    ▼
Content Generation ──── Markdown + content_list output
                        (pipeline_middle_json_mkcontent.py)
```

> [!NOTE]
> The VLM and hybrid backends skip most of these steps. VLM sends page images directly to a vision-language model. Hybrid combines both approaches, using pipeline for structure and VLM for content enhancement.

---

## 2. System Requirements

### 2.1 Hardware Requirements

| Component | Minimum | Recommended |
|-----------|---------|-------------|
| CPU | 4 cores | 8+ cores |
| RAM | 8 GB | 16+ GB |
| GPU (CUDA) | 4 GB VRAM | 8+ GB VRAM (NVIDIA) |
| GPU (alternatives) | MPS (Apple Silicon), NPU (Ascend), DCU, GCU, KunlunXin, MACA, MLU, MUSA, PPU, CoreX | — |
| Disk | 10 GB for models | 20+ GB (models + working space) |

> [!IMPORTANT]
> GPU is strongly recommended for production use. Without GPU acceleration, the pipeline backend falls back to CPU inference, which is dramatically slower. The `MINERU_DEVICE_MODE` environment variable controls device selection.

### 2.2 Software Requirements

| Dependency | Purpose |
|------------|---------|
| Python 3.10+ | Runtime |
| PyTorch (with CUDA/MPS/NPU) | Model inference |
| pypdfium2 | PDF rendering |
| FastAPI + Uvicorn | API server |
| Gradio | Web UI |
| Click | CLI framework |
| httpx | Async HTTP client |
| loguru | Structured logging |
| OpenCV (cv2) | Image processing |
| numpy | Array operations |
| BeautifulSoup | HTML parsing |
| Pydantic | Data validation |
| fasttext | Language detection |
| vLLM / LMDeploy | VLM inference engines (optional, for VLM/hybrid backends) |

### 2.3 Supported Accelerator Platforms

MinerU provides dedicated Dockerfiles for each platform:

| Platform | Dockerfile | Notes |
|----------|-----------|-------|
| NVIDIA CUDA | `Dockerfile` (global) | Primary supported platform |
| Ascend NPU | `Dockerfile.ascend` | Huawei Atlas hardware |
| DCU | `Dockerfile.dcu` | Hygon DCU |
| GCU | `Dockerfile.gcu` | Enflame GCU |
| KunlunXin | `Dockerfile.kunlunxin` | Baidu XPU |
| MACA | `Dockerfile.maca` | MetaX MACA |
| MLU | `Dockerfile.mlu` | Cambricon MLU |
| MUSA | `Dockerfile.musa` | Moore Threads MUSA |
| NPU | `Dockerfile.npu` | Generic NPU |
| PPU | `Dockerfile.ppu` | PPU accelerator |
| CoreX | `Dockerfile.corex` | Iluvatar CoreX |

China-specific variants (with `_cn` suffix) use domestic mirror sources.

---

## 3. Configuration Reference

### 3.1 Configuration File: `mineru.json`

Located by default at `~/mineru.json`, overridden by the `MINERU_TOOLS_CONFIG_JSON` environment variable. The configuration reader is in `mineru/utils/config_reader.py`.

```json
{
    "bucket_info": {
        "bucket-name-1": ["access_key", "secret_key", "endpoint"]
    },
    "latex-delimiter-config": {
        "display": {"left": "$$", "right": "$$"},
        "inline": {"left": "$", "right": "$"}
    },
    "llm-aided-config": {
        "title_aided": {
            "api_key": "your_api_key",
            "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
            "model": "qwen3.5-plus",
            "enable_thinking": false,
            "enable": false
        }
    },
    "models-dir": {
        "pipeline": "",
        "vlm": ""
    },
    "config_version": "1.3.1"
}
```

**Field reference:**

| Field | Type | Purpose |
|-------|------|---------|
| `bucket_info` | Object | S3-compatible bucket credentials. Keys are bucket names; values are `[access_key, secret_key, endpoint]` arrays. |
| `latex-delimiter-config.display` | Object | LaTeX display math delimiters (`left`/`right`). |
| `latex-delimiter-config.inline` | Object | LaTeX inline math delimiters (`left`/`right`). |
| `llm-aided-config.title_aided` | Object | LLM-assisted title extraction config. Set `enable: true` to activate. |
| `models-dir.pipeline` | String | Custom directory for pipeline model weights. Empty string uses default. |
| `models-dir.vlm` | String | Custom directory for VLM model weights. Empty string uses default. |
| `config_version` | String | Configuration schema version. Current: `1.3.1`. |

### 3.2 Environment Variables — Complete Reference

All 24 environment variables extracted from source, grouped by function:

#### Core Runtime

| Variable | Default | Source | Description |
|----------|---------|--------|-------------|
| `MINERU_DEVICE_MODE` | `None` (auto-detect) | `config_reader.py` | Force device mode: `cuda`, `mps`, `npu`, `cpu`, etc. When `None`, auto-detects available hardware. |
| `MINERU_LOG_LEVEL` | `INFO` | `client.py` | Log verbosity. Accepts standard Python logging levels: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`. |
| `MINERU_TOOLS_CONFIG_JSON` | `mineru.json` | `models_download.py` | Path to the configuration JSON file. |

#### Feature Toggles

| Variable | Default | Source | Description |
|----------|---------|--------|-------------|
| `MINERU_FORMULA_ENABLE` | (none) | `config_reader.py` | Enable/disable formula recognition. Overrides CLI `--formula` flag. |
| `MINERU_TABLE_ENABLE` | (none) | `config_reader.py` | Enable/disable table recognition. Overrides CLI `--table` flag. |
| `MINERU_TABLE_MERGE_ENABLE` | `true` | `runtime_utils.py` | Enable cross-page table merging. Set to `false` to disable. |
| `MINERU_FORMULA_CH_SUPPORT` | `False` | `model_init.py` | Enable Chinese formula recognition support. |
| `MINERU_OCR_DET_MASK_INLINE_FORMULA_ENABLE` | (none) | `config_reader.py` | Enable masking of inline formulas during OCR detection. |

#### API Server

| Variable | Default | Source | Description |
|----------|---------|--------|-------------|
| `MINERU_API_OUTPUT_ROOT` | (none) | `fast_api.py` | Root directory for API output files. If unset, uses a temp directory. |
| `MINERU_API_MAX_CONCURRENT_REQUESTS` | (none) | `config_reader.py` | Maximum concurrent parse requests the API server will accept. |
| `MINERU_API_DISABLE_ACCESS_LOG` | (none) | `api_client.py` | Set internally when launching local API servers to suppress access logs. |
| `MINERU_API_SHUTDOWN_ON_STDIN_EOF` | (none) | `api_client.py` | Set internally for managed local API servers; causes shutdown when parent process exits. |
| `MINERU_LOCAL_API_STARTUP_TIMEOUT_SECONDS` | `300.0` | `api_client.py` | Timeout (seconds) for local API server startup. Increase for slow model loading. |

#### Router / Load Balancer

| Variable | Default | Source | Description |
|----------|---------|--------|-------------|
| `CUDA_VISIBLE_DEVICES` | (none) | `router.py` | Standard CUDA variable. Router uses this to determine available GPUs for managed workers. |
| `MINERU_ROUTER_LOCAL_GPUS` | (none) | `router.py` | Explicit GPU list for router-managed workers. Overrides `CUDA_VISIBLE_DEVICES` parsing. |
| `MINERU_ROUTER_WORKER_HOST` | `127.0.0.1` | `router.py` | Bind address for router-spawned worker processes. |

#### Model & Performance

| Variable | Default | Source | Description |
|----------|---------|--------|-------------|
| `MINERU_MODEL_SOURCE` | `huggingface` | `models_download_utils.py` | Model download source. Options: `huggingface`, `modelscope`, etc. |
| `MINERU_VIRTUAL_VRAM_SIZE` | (none) | `model_utils.py` | Override detected VRAM size (MB). Useful for testing or when VRAM detection is inaccurate. |
| `MINERU_PROCESSING_WINDOW_SIZE` | (none) | `config_reader.py` | Number of pages processed per batch window. Affects memory usage and throughput. |
| `MINERU_LMDEPLOY_DEVICE` | (none) | `common.py` | Device target for LMDeploy VLM inference. |

#### PDF Rendering

| Variable | Default | Source | Description |
|----------|---------|--------|-------------|
| `MINERU_PDF_RENDER_TIMEOUT` | `None` | `os_env_config.py` | Timeout (seconds) for PDF page rendering. `None` means no timeout. |
| `MINERU_PDF_RENDER_THREADS` | `None` | `os_env_config.py` | Number of threads for parallel PDF rendering. `None` uses default. |

#### External

| Variable | Default | Source | Description |
|----------|---------|--------|-------------|
| `FTLANG_CACHE` | (none) | `language.py` | Cache directory for fasttext language detection model. |

> [!TIP]
> For production deployments, always set `MINERU_API_OUTPUT_ROOT` to a persistent directory. Without it, outputs go to a temporary directory that may be cleaned up by the OS.

### 3.3 Key Constants

These constants are defined in source and affect system behavior:

| Constant | Value | Location | Purpose |
|----------|-------|----------|---------|
| `API_PROTOCOL_VERSION` | (versioned) | `api_protocol.py` | Client/server protocol compatibility check |
| `TASK_STATUS_POLL_INTERVAL_SECONDS` | `1.0` | CLI | Polling interval for async task status |
| `TASK_RESULT_TIMEOUT_SECONDS` | `3600` | CLI | Maximum wait time for async task results (1 hour) |
| `LOCAL_API_STARTUP_TIMEOUT_SECONDS` | `300.0` | `api_client.py` | Default timeout waiting for local API server health |
| `LAYOUT_BASE_BATCH_SIZE` | `1` | Backend | Base batch size for layout model inference |
| `MFR_BASE_BATCH_SIZE` | `16` | Backend | Base batch size for formula recognition |
| `OCR_DET_BASE_BATCH_SIZE` | `8` | Backend | Base batch size for OCR detection |

---

## 4. Deployment & Scaling

### 4.1 Docker Deployment

MinerU provides a `compose.yaml` with four profiles:

| Profile | Service | Port | Purpose |
|---------|---------|------|---------|
| `openai-server` | VLM server | 30000 | OpenAI-compatible VLM endpoint |
| `api` | FastAPI server | 8000 | REST API for document parsing |
| `router` | Load balancer | 8002 | Multi-GPU load balancing |
| `gradio` | Web UI | 7860 | Browser-based parsing interface |

> [!WARNING]
> All Docker profiles require NVIDIA GPU with the NVIDIA Container Toolkit installed. The containers will fail to start without GPU access.

**Starting the API server:**

```bash
docker compose --profile api up -d
```

**Starting the router with multiple GPUs:**

```bash
docker compose --profile router up -d
```

**Starting the Gradio UI:**

```bash
docker compose --profile gradio up -d
```

### 4.2 Bare-Metal Deployment

```bash
# Install MinerU
pip install mineru

# Download models
download-models -s huggingface

# Start API server
mineru-api --host 0.0.0.0 --port 8000
```

> [!CAUTION]
> When binding to `0.0.0.0`, the `--allow-public-http-client` flag must be passed explicitly. Without it, the server enforces `public_http_client_policy.py` restrictions that block non-localhost connections. This is a deliberate security measure.

### 4.3 Multi-GPU Scaling with Router

The router (`mineru-router`) distributes parse requests across multiple API server instances:

```bash
# Option 1: Explicit upstream URLs
mineru-router --host 0.0.0.0 --port 8002 \
  --upstream-url http://gpu1:8000 \
  --upstream-url http://gpu2:8000 \
  --upstream-url http://gpu3:8000

# Option 2: Auto-spawn workers on local GPUs
mineru-router --host 0.0.0.0 --port 8002 \
  --local-gpus 0,1,2,3
```

**Router architecture:**

```
Client Request
    │
    ▼
┌──────────────────┐
│  mineru-router    │  Port 8002
│  (RouterSettings) │
│  (WorkerPool)     │
│  (RouterTaskRegistry)│
├──────────────────┤
│  Load Balancing   │
│  (round-robin)    │
└──┬───┬───┬───────┘
   │   │   │
   ▼   ▼   ▼
┌────┐┌────┐┌────┐
│GPU0││GPU1││GPU2│  mineru-api instances
│:8000│:8001│:8002│
└────┘└────┘└────┘
```

Key classes in the router:

| Class | Purpose |
|-------|---------|
| `RouterSettings` | Configuration for router behavior |
| `WorkerPool` | Manages upstream API server instances |
| `WorkerState` | Tracks health and load of each worker |
| `RouterTaskRegistry` | Maps async task IDs to upstream workers |
| `ManagedLocalServer` | Spawns and manages local API server processes |

### 4.4 VLM Preloading

For backends using VLM models, preloading prevents cold-start latency:

```bash
# API server with VLM preloading
mineru-api --host 0.0.0.0 --port 8000 --enable-vlm-preload

# Router with VLM preloading on workers
mineru-router --host 0.0.0.0 --port 8002 \
  --local-gpus 0,1 --enable-vlm-preload
```

The `vlm_preload.py` module handles model warmup during server startup rather than on first request.

---

## 5. Operations

### 5.1 API Endpoints — Complete Reference

#### FastAPI Server (`mineru-api`)

| Method | Path | Auth | Description |
|--------|------|------|-------------|
| `POST` | `/file_parse` | None | Synchronous document parsing. Blocks until complete. |
| `POST` | `/submit_parse_task` | None | Submit async parse task. Returns task ID immediately. |
| `GET` | `/get_async_task_status` | None | Poll status of an async task by ID. |
| `GET` | `/get_async_task_result` | None | Retrieve results of a completed async task. |
| `GET` | `/health` | None | Health check. Returns server status and model readiness. |

**Synchronous parse (`POST /file_parse`):**

```bash
curl -X POST http://localhost:8000/file_parse \
  -F "file=@document.pdf" \
  -F "method=auto" \
  -F "backend=hybrid-auto-engine"
```

**Async parse workflow:**

```bash
# 1. Submit task
TASK_ID=$(curl -s -X POST http://localhost:8000/submit_parse_task \
  -F "file=@document.pdf" | jq -r '.task_id')

# 2. Poll status (repeats every 1 second)
curl -s "http://localhost:8000/get_async_task_status?task_id=$TASK_ID"

# 3. Get result when complete
curl -s "http://localhost:8000/get_async_task_result?task_id=$TASK_ID"
```

#### Router (`mineru-router`)

| Method | Path | Auth | Description |
|--------|------|------|-------------|
| `POST` | `/file_parse` | None | Synchronous parse, routed to best available worker. |
| `POST` | `/submit_parse_task` | None | Async parse, routed to least-loaded worker. |
| `GET` | `/get_router_task_status` | None | Task status (router resolves which upstream holds the task). |
| `GET` | `/get_router_task_result` | None | Task result from upstream worker. |
| `GET` | `/health` | None | Router health + upstream worker status. |

### 5.2 CLI Command Reference (Server-Side)

#### `mineru-api` — FastAPI Server

```bash
mineru-api [OPTIONS]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--host` | `127.0.0.1` | Bind address |
| `--port` | `8000` | Bind port |
| `--reload` | `false` | Enable auto-reload on code changes (dev only) |
| `--allow-public-http-client` | `false` | Allow non-localhost HTTP connections |
| `--enable-vlm-preload` | `false` | Preload VLM models at startup |

#### `mineru-router` — Load Balancer

```bash
mineru-router [OPTIONS]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--host` | `127.0.0.1` | Bind address |
| `--port` | `8002` | Bind port |
| `--upstream-url` | (none) | Upstream API server URL (repeatable) |
| `--local-gpus` | (none) | Comma-separated GPU IDs to auto-spawn workers |
| `--worker-host` | `127.0.0.1` | Bind address for auto-spawned workers |
| `--enable-vlm-preload` | `false` | Preload VLM models on workers |

#### `mineru-openai-server` — VLM Server

```bash
mineru-openai-server [OPTIONS]
```

| Flag | Default | Description |
|------|---------|-------------|
| `-e`, `--engine` | (required) | VLM inference engine (`vllm` or `lmdeploy`) |

#### `download-models` — Model Downloader

```bash
download-models [OPTIONS]
```

| Flag | Default | Description |
|------|---------|-------------|
| `-s`, `--source` | (none) | Model source: `huggingface`, `modelscope` |
| `-m`, `--model_type` | (none) | Model type to download |

### 5.3 Logging

MinerU uses `loguru` for structured logging throughout the codebase.

**Log level control:**

```bash
# Via environment variable
export MINERU_LOG_LEVEL=DEBUG
mineru-api --host 0.0.0.0 --port 8000
```

Valid levels: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`.

**Access log suppression:**

When the CLI spawns a local API server, it sets `MINERU_API_DISABLE_ACCESS_LOG` internally to reduce noise. For production deployments where you manage the API server directly, access logs are enabled by default.

### 5.4 Health Checks

The `/health` endpoint on both the API server and router returns server status:

```bash
# API server health
curl http://localhost:8000/health

# Router health (includes upstream worker status)
curl http://localhost:8002/health
```

> [!TIP]
> Use the health endpoint in container orchestration (Docker health checks, Kubernetes liveness probes). The endpoint verifies model readiness, not just HTTP responsiveness.

### 5.5 Model Management

**Downloading models:**

```bash
# From Hugging Face (default)
download-models -s huggingface

# From ModelScope (faster in China)
export MINERU_MODEL_SOURCE=modelscope
download-models -s modelscope
```

**Custom model directories:**

Set in `mineru.json`:

```json
{
    "models-dir": {
        "pipeline": "/opt/models/pipeline",
        "vlm": "/opt/models/vlm"
    }
}
```

**Model singleton behavior:**

The `ModelSingleton` class in `mineru/backend/pipeline/model_init.py` ensures each model type is loaded exactly once. Models are loaded lazily on first use unless VLM preloading is enabled. The `AtomicModel` enum defines all model types:

| AtomicModel | Purpose |
|-------------|---------|
| `Layout` | Page layout detection (DocLayoutV2) |
| `MFD` | Math formula detection |
| `MFR` | Math formula recognition |
| `OCR` | Text extraction (PytorchPaddle) |
| `WirelessTable` | Borderless table recognition (SLANet+) |
| `WiredTable` | Bordered table recognition (UNet) |
| `TableCls` | Table type classification |
| `ImgOrientationCls` | Image orientation detection |

---

## 6. Performance

### 6.1 Batch Size Tuning

Model inference uses batched processing. Base batch sizes scale with available VRAM:

| Model | Base Batch Size | Scaling |
|-------|----------------|---------|
| Layout (DocLayoutV2) | 1 | Scales with VRAM |
| Formula Recognition (MFR) | 16 | Scales with VRAM |
| OCR Detection | 8 | Scales with VRAM |

**VRAM override:**

```bash
# Force VRAM size detection (MB)
export MINERU_VIRTUAL_VRAM_SIZE=8192
```

The `model_utils.py` module manages VRAM detection and batch size calculation.

### 6.2 Processing Window

The `MINERU_PROCESSING_WINDOW_SIZE` variable controls how many pages are processed in each batch window. Larger windows improve throughput on long documents but increase peak memory usage.

### 6.3 PDF Rendering Performance

```bash
# Set render timeout per page (seconds)
export MINERU_PDF_RENDER_TIMEOUT=30

# Parallel rendering threads
export MINERU_PDF_RENDER_THREADS=4
```

The `pdf_image_tools.py` module uses `pypdfium2` for PDF-to-image conversion. Thread count defaults to a system-appropriate value when unset.

### 6.4 Concurrent Request Limiting

```bash
# Limit API server to 4 concurrent parse requests
export MINERU_API_MAX_CONCURRENT_REQUESTS=4
```

Without this limit, the server accepts all incoming requests, which can exhaust GPU memory.

### 6.5 Table Merging

Cross-page table merging (`table_merge.py`) detects tables that span page boundaries and stitches them together. This adds post-processing time proportional to the number of tables detected.

```bash
# Disable if not needed (slight speedup on table-heavy documents)
export MINERU_TABLE_MERGE_ENABLE=false
```

The `TableMergeState` class tracks merge state across pages.

### 6.6 Multi-GPU Throughput

For maximum throughput, deploy one `mineru-api` instance per GPU behind a `mineru-router`:

```bash
# 4-GPU setup
mineru-router --port 8002 --local-gpus 0,1,2,3
```

Each worker gets exclusive access to one GPU via `CUDA_VISIBLE_DEVICES` isolation. The router distributes requests across workers.

---

## 7. Security

### 7.1 Network Security

**Public binding protection:**

The `public_http_client_policy.py` module enforces a security policy when the API server binds to non-localhost addresses. Without the explicit `--allow-public-http-client` flag, the server rejects requests from external IPs.

```bash
# Secure: localhost only (default)
mineru-api --host 127.0.0.1 --port 8000

# Explicit public access (requires flag)
mineru-api --host 0.0.0.0 --port 8000 --allow-public-http-client
```

> [!WARNING]
> MinerU's API endpoints have no authentication. When exposing publicly, place the server behind a reverse proxy with authentication (e.g., nginx with basic auth, Traefik with middleware, or an API gateway).

### 7.2 Authentication

MinerU does not implement authentication or authorization at the application level. All API endpoints are unauthenticated. For production deployments:

- Use a reverse proxy with authentication
- Restrict network access via firewall rules
- Use Docker network isolation
- Consider VPN-only access for internal services

### 7.3 S3 Credential Handling

S3 credentials in `mineru.json` are stored as plaintext. The `bucket_info` field maps bucket names to credential arrays:

```json
{
    "bucket_info": {
        "my-bucket": ["ACCESS_KEY", "SECRET_KEY", "https://s3.endpoint.com"]
    }
}
```

> [!CAUTION]
> Protect `mineru.json` with appropriate file permissions (`chmod 600`) when it contains S3 credentials. Do not commit credentials to version control.

### 7.4 LLM API Key Handling

The `llm-aided-config` section stores API keys for LLM-assisted title extraction. Same plaintext storage concern as S3 credentials.

### 7.5 Input Validation

The system validates inputs at multiple points:

- File type validation: only PDF, DOCX, PPTX, XLSX, and image formats accepted
- Page range validation: `--start` and `--end` flags are bounds-checked
- URL validation: `--url` inputs are validated before fetching
- File size: implicitly limited by FastAPI's upload handling

### 7.6 Managed Server Lifecycle

The `ReusableLocalAPIServer` and `LocalAPIServer` classes in `api_client.py` spawn child API server processes. The `MINERU_API_SHUTDOWN_ON_STDIN_EOF` mechanism ensures child servers terminate when the parent process exits, preventing orphaned GPU-consuming processes.

---

## 8. Developer Internals

### 8.1 Module Reference

#### Core Engine (`mineru/backend/pipeline/`)

| Module | Lines | Purpose |
|--------|-------|---------|
| `pipeline_magic_model.py` | Large | `MagicModel` class with 25+ methods for post-processing model outputs. Central orchestrator for the pipeline backend. |
| `batch_analyze.py` | Medium | `BatchAnalyze` class. Runs all atomic models in batched inference, managing GPU memory allocation. |
| `model_init.py` | Medium | `ModelSingleton` pattern. `custom_model_init()` initializes models based on `AtomicModel` enum. `MINERU_FORMULA_CH_SUPPORT` toggle. |
| `pipeline_analyze.py` | Medium | Main entry point for pipeline processing. Orchestrates the full analysis flow. |
| `model_json_to_middle_json.py` | Medium | Converts raw model JSON output to the intermediate "middle JSON" format used by downstream stages. |
| `pipeline_middle_json_mkcontent.py` | Medium | Converts middle JSON to final Markdown output and `content_list` structured data. |
| `para_split.py` | Medium | Paragraph boundary detection and text splitting logic. |
| `model_list.py` | Small | `AtomicModel` enum defining all model types. |

#### CLI Layer (`mineru/cli/`)

| Module | Lines | Purpose |
|--------|-------|---------|
| `client.py` | 1091+ | Main `mineru` CLI. Click-based command with extensive option handling. Manages local API server lifecycle. |
| `fast_api.py` | 1563+ | FastAPI server implementation. All parse endpoints, async task management, file handling. |
| `router.py` | 1465+ | Load balancing router. Worker pool management, task routing, health monitoring. |
| `gradio_app.py` | 1079+ | Gradio web interface. File upload, progress display, result rendering. |
| `api_client.py` | Large | HTTP client for API communication. `LocalAPIServer` and `ReusableLocalAPIServer` for managed server lifecycle. |
| `api_protocol.py` | Small | `API_PROTOCOL_VERSION` constant for client/server compatibility. |
| `common.py` | Medium | Shared parsing logic used by both CLI and API paths. Backend dispatch based on `--backend` flag. |
| `output_paths.py` | Small | Output directory and file path resolution. |
| `vlm_preload.py` | Small | VLM model preloading during server startup. |
| `vlm_server.py` | Medium | OpenAI-compatible VLM server endpoint. |
| `models_download.py` | Small | `download-models` CLI command. Model download orchestration. |
| `visualization.py` | Small | Layout visualization utilities for debugging. |
| `public_http_client_policy.py` | Small | Security policy enforcement for public-facing servers. |

#### Model Layer (`mineru/model/`)

| Subdirectory | Key Classes | Purpose |
|-------------|-------------|---------|
| `layout/` | DocLayoutV2 | Page layout detection and region classification |
| `ocr/` | PytorchPaddle | OCR text extraction (PaddleOCR weights via PyTorch) |
| `mfr/` | Unimernet, FormulaNet+ | Mathematical formula recognition |
| `table/` | `PaddleTable`, `PaddleTableModel`, `UnetTableModel`, `WiredTableRecognition` | Table structure recognition (wireless via SLANet+, wired via UNet) |
| `ori_cls/` | — | Image orientation classification |
| `vlm/` | — | VLM model integration (vLLM, LMDeploy engines) |
| `docx/` | `DocxConverter` | DOCX → Markdown conversion |
| `pptx/` | `PptxConverter` | PPTX → Markdown conversion |
| `xlsx/` | `XlsxConverter` | XLSX → Markdown conversion |

#### Data I/O (`mineru/data/`)

| Module | Key Classes | Purpose |
|--------|-------------|---------|
| `data_reader_writer/` | Local, S3, MultiBucketS3 | File I/O abstraction supporting local filesystem and S3-compatible storage |
| `io/` | HTTP reader, S3 reader | Input readers for remote sources |
| `utils/` | `S3Config`, `PageInfo`, exceptions | Data schemas, path utilities, exception types |

Exception classes in `mineru/data/utils/`:

| Exception | Meaning |
|-----------|---------|
| `FileNotExisted` | Referenced file not found on filesystem or S3 |
| `InvalidConfig` | Configuration file malformed or missing required fields |
| `InvalidParams` | Invalid parameters passed to a function |
| `EmptyData` | Input document contains no extractable content |
| `CUDA_NOT_AVAILABLE` | GPU required but CUDA not available |

#### Utilities (`mineru/utils/` — 31 modules)

| Module | Purpose |
|--------|---------|
| `config_reader.py` | Reads `mineru.json` and environment variable overrides |
| `pdf_classify.py` | PDF type classification: determines `txt` (extractable text) vs `ocr` (image-based) |
| `pdf_image_tools.py` | PDF page rendering to images via pypdfium2 |
| `table_merge.py` | Cross-page table merging with `TableMergeState` tracking |
| `ocr_utils.py` | OCR bounding box processing and text alignment |
| `model_utils.py` | VRAM detection, batch size calculation, `MINERU_VIRTUAL_VRAM_SIZE` handling |
| `models_download_utils.py` | Model download helpers, source selection (`huggingface`/`modelscope`) |
| `runtime_utils.py` | Runtime feature flag reading (`MINERU_TABLE_MERGE_ENABLE`) |
| `os_env_config.py` | PDF render timeout and thread configuration |
| `language.py` | Language detection via fasttext (`FTLANG_CACHE` for model caching) |
| `bbox_utils.py` | Bounding box math (overlap, intersection, union) |
| `char_utils.py` | Character-level utilities |
| `draw_utils.py` | Debug visualization for bounding boxes |
| `hash_utils.py` | File hashing |

### 8.2 Key Enums and Types

```python
class AtomicModel(Enum):
    Layout = "layout"
    MFD = "mfd"
    MFR = "mfr"
    OCR = "ocr"
    WirelessTable = "wireless_table"
    WiredTable = "wired_table"
    TableCls = "table_cls"
    ImgOrientationCls = "img_orientation_cls"
```

```python
class BlockType:       # Layout block classification
class ContentType:     # Output content types (v1)
class ContentTypeV2:   # Output content types (v2)
class MakeMode:        # Markdown generation mode
class ModelPath:       # Model weight paths
class SplitFlag:       # Paragraph split markers
class ImageType:       # Image format types
class NotExtractType:  # Regions to skip during extraction
```

### 8.3 Code Patterns and Conventions

**Singleton pattern for models:**

```python
class ModelSingleton:
    _instance = None
    _models = {}

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
```

All model loading goes through `ModelSingleton` to prevent duplicate VRAM allocation.

**Backend dispatch:**

The `common.py` module dispatches to the appropriate backend based on the `--backend` CLI flag:

| Backend Value | Processing Path |
|--------------|-----------------|
| `pipeline` | Traditional OCR pipeline |
| `vlm` | Direct VLM inference |
| `hybrid-auto-engine` (default) | Hybrid pipeline + VLM |
| `office` | Office document conversion |

**Async task lifecycle:**

```python
class AsyncTaskManager:
    # Thread-safe task registry
    # submit_task() → task_id
    # get_status(task_id) → status dict
    # get_result(task_id) → output data
```

Tasks follow: `submitted` → `processing` → `completed` | `failed`.

**Data I/O abstraction:**

All file operations go through `data_reader_writer/` classes, allowing transparent switching between local filesystem and S3 storage. The `S3Config` class validates bucket credentials from `mineru.json`.

### 8.4 Repository Structure

```
mineru/
├── __init__.py
├── version.py                     # __version__ = "3.1.0"
├── cli/
│   ├── api_client.py              # HTTP client + local server management
│   ├── api_protocol.py            # API_PROTOCOL_VERSION
│   ├── client.py                  # Main `mineru` CLI (1091+ lines)
│   ├── common.py                  # Shared parse logic, backend dispatch
│   ├── fast_api.py                # FastAPI server (1563+ lines)
│   ├── gradio_app.py              # Gradio web UI (1079+ lines)
│   ├── models_download.py         # download-models CLI
│   ├── output_paths.py            # Output path resolution
│   ├── public_http_client_policy.py # Public binding security
│   ├── router.py                  # Load balancing router (1465+ lines)
│   ├── visualization.py           # Layout visualization
│   ├── vlm_preload.py             # VLM model preloading
│   └── vlm_server.py              # OpenAI-compatible VLM server
├── backend/
│   ├── pipeline/                  # Traditional OCR pipeline
│   │   ├── batch_analyze.py       # Batched model inference
│   │   ├── model_init.py          # ModelSingleton initialization
│   │   ├── model_json_to_middle_json.py
│   │   ├── model_list.py          # AtomicModel enum
│   │   ├── para_split.py          # Paragraph splitting
│   │   ├── pipeline_analyze.py    # Main pipeline entry
│   │   ├── pipeline_magic_model.py # MagicModel (25+ methods)
│   │   └── pipeline_middle_json_mkcontent.py
│   ├── vlm/                       # VLM-based parsing
│   ├── hybrid/                    # Hybrid pipeline+VLM
│   ├── office/                    # Office document parsing
│   └── utils/                     # Backend utilities
├── model/
│   ├── layout/                    # DocLayoutV2
│   ├── ocr/                       # PytorchPaddle OCR
│   ├── mfr/                       # Math formula recognition
│   ├── table/                     # Table recognition
│   ├── ori_cls/                   # Orientation classification
│   ├── vlm/                       # VLM model integration
│   ├── docx/                      # DocxConverter
│   ├── pptx/                      # PptxConverter
│   └── xlsx/                      # XlsxConverter
├── data/
│   ├── data_reader_writer/        # File I/O (local, S3)
│   ├── io/                        # Input readers (HTTP, S3)
│   └── utils/                     # Exceptions, schemas
├── utils/                         # 31 utility modules
│   ├── config_reader.py
│   ├── pdf_classify.py
│   ├── pdf_image_tools.py
│   ├── table_merge.py
│   ├── ocr_utils.py
│   ├── model_utils.py
│   ├── models_download_utils.py
│   └── ...
└── resources/
    ├── header.html
    └── fasttext-langdetect/lid.176.ftz
```

### 8.5 Testing

Tests are located in `tests/unittest/`. The `test_e2e.py` file contains end-to-end tests that exercise the full pipeline from input to output.

---

## 9. Integration Points

### 9.1 S3 Storage Integration

MinerU supports S3-compatible storage for both input and output:

```json
{
    "bucket_info": {
        "my-input-bucket": ["ACCESS_KEY", "SECRET_KEY", "https://s3.amazonaws.com"],
        "my-output-bucket": ["ACCESS_KEY", "SECRET_KEY", "https://s3.amazonaws.com"]
    }
}
```

The `MultiBucketS3` reader/writer supports multiple buckets with different credentials. Input files can be read directly from S3, and output can be written back to S3.

### 9.2 HTTP Input

Documents can be fetched from URLs for parsing:

```bash
mineru -u https://example.com/document.pdf -o ./output
```

The `data/io/` module handles HTTP fetching with appropriate timeout and error handling.

### 9.3 LLM-Assisted Processing

The `llm-aided-config` section enables LLM-assisted title extraction:

```json
{
    "llm-aided-config": {
        "title_aided": {
            "api_key": "your_api_key",
            "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
            "model": "qwen3.5-plus",
            "enable_thinking": false,
            "enable": true
        }
    }
}
```

When enabled, ambiguous titles detected during layout analysis are sent to the configured LLM for disambiguation.

### 9.4 VLM Server Integration

The `mineru-openai-server` command exposes a VLM endpoint compatible with the OpenAI API format:

```bash
# Start VLM server with vLLM engine
mineru-openai-server -e vllm

# Or with LMDeploy engine
mineru-openai-server -e lmdeploy
```

This allows MinerU's VLM capabilities to be consumed by any OpenAI-compatible client.

### 9.5 Programmatic Python API

```python
from mineru.backend.pipeline.pipeline_analyze import pipeline_analyze
from mineru.backend.vlm import vlm_analyze
from mineru.backend.hybrid import hybrid_analyze
```

Direct Python imports bypass the CLI/API layer entirely. This is useful for embedding MinerU into larger Python applications.

### 9.6 Output Formats

MinerU produces two output types:

| Format | Description |
|--------|-------------|
| Markdown (`.md`) | Human-readable document with tables, formulas, and image references |
| Content List (JSON) | Structured representation with bounding boxes, content types, and page references |

The `MakeMode` enum controls which output format is generated.

---

## 10. Troubleshooting

### Error: `Protocol version mismatch`

**Cause:** Client and server are running different versions of MinerU with incompatible `API_PROTOCOL_VERSION` values.

**Solution:** Ensure both `mineru` CLI client and `mineru-api` server are the same version:

```bash
pip install --upgrade mineru
```

**Prevention:** Pin MinerU version in your requirements file and upgrade client and server together.

### Error: `Timed out while polling task status`

**Cause:** Async task exceeded `TASK_RESULT_TIMEOUT_SECONDS` (default: 3600 seconds / 1 hour). Common with very large PDFs or underpowered hardware.

**Solution:**

1. Check GPU utilization — the process may be stuck or OOM
2. Check server logs for errors during processing
3. For large documents, increase the timeout or use page range limiting (`--start` / `--end`)

**Prevention:** Set `MINERU_API_MAX_CONCURRENT_REQUESTS` to prevent overloading the server.

### Error: `HybridDependencyError`

**Cause:** The hybrid backend requires both pipeline and VLM dependencies. One or both are missing.

**Solution:** Install the full dependency set:

```bash
pip install mineru[full]
```

**Prevention:** Use the `pipeline` backend if VLM dependencies are unavailable.

### Error: `CUDA not available` / `CUDA_NOT_AVAILABLE`

**Cause:** PyTorch cannot find CUDA drivers or GPU hardware.

**Solution:**

1. Verify NVIDIA drivers: `nvidia-smi`
2. Verify PyTorch CUDA: `python -c "import torch; print(torch.cuda.is_available())"`
3. For CPU-only operation: `export MINERU_DEVICE_MODE=cpu`

**Prevention:** Use Docker images with pre-configured CUDA support.

### Error: `Empty PDF` / `EmptyData`

**Cause:** Input PDF contains no extractable pages or content.

**Solution:** Verify the PDF is not corrupt and contains actual content. Try opening in a PDF viewer.

### Error: `Unsupported file suffix`

**Cause:** Input file has an extension not in the supported set (PDF, DOCX, PPTX, XLSX, common image formats).

**Solution:** Rename the file with the correct extension or convert to a supported format.

### Error: Health check failure on startup

**Cause:** API server failed to become healthy within `MINERU_LOCAL_API_STARTUP_TIMEOUT_SECONDS` (default: 300 seconds). Usually caused by slow model downloads or loading.

**Solution:**

```bash
# Increase startup timeout
export MINERU_LOCAL_API_STARTUP_TIMEOUT_SECONDS=600

# Pre-download models before starting server
download-models -s huggingface
```

**Prevention:** Always run `download-models` before first server start.

### Error: Upstream unavailable/rejected (Router)

**Cause:** Router cannot reach any upstream API server, or all upstreams are rejecting requests (overloaded).

**Solution:**

1. Check upstream server health: `curl http://upstream:8000/health`
2. Check network connectivity between router and upstreams
3. Verify `--upstream-url` values are correct

**Prevention:** Monitor upstream health and scale horizontally when load increases.

> [!NOTE]
> For issues related to specific document types (Arabic text ordering, image segmentation anomalies, table extraction quality), see the [GitHub Issues](https://github.com/opendatalab/MinerU/issues) tracker. Known issues include #2551 (Arabic PDF parsing order), #4008 (image segmentation), and #4207 (table extraction).

---

## 11. Quick Reference

### Environment Variables Cheat Sheet

```bash
# Essential production settings
export MINERU_DEVICE_MODE=cuda
export MINERU_LOG_LEVEL=INFO
export MINERU_API_OUTPUT_ROOT=/data/mineru/output
export MINERU_API_MAX_CONCURRENT_REQUESTS=4
export MINERU_MODEL_SOURCE=huggingface

# Performance tuning
export MINERU_PDF_RENDER_THREADS=4
export MINERU_PDF_RENDER_TIMEOUT=30
export MINERU_VIRTUAL_VRAM_SIZE=8192
export MINERU_PROCESSING_WINDOW_SIZE=10

# Feature flags
export MINERU_FORMULA_ENABLE=true
export MINERU_TABLE_ENABLE=true
export MINERU_TABLE_MERGE_ENABLE=true
export MINERU_FORMULA_CH_SUPPORT=false

# Router settings
export MINERU_ROUTER_LOCAL_GPUS=0,1,2,3
export MINERU_ROUTER_WORKER_HOST=0.0.0.0
```

### Port Reference

| Service | Default Port | Command |
|---------|-------------|---------|
| API Server | 8000 | `mineru-api` |
| Router | 8002 | `mineru-router` |
| Gradio UI | 7860 | `mineru-gradio` |
| VLM Server | 30000 | `mineru-openai-server` |

### Backend Selection Guide

| Use Case | Backend | Flag |
|----------|---------|------|
| Best accuracy (default) | Hybrid | `--backend hybrid-auto-engine` |
| Fast, traditional OCR | Pipeline | `--backend pipeline` |
| VLM-only (no OCR models needed) | VLM | `--backend vlm` |
| Office documents | Office | (auto-detected by file extension) |

### Docker Profiles

```bash
docker compose --profile api up -d        # API server
docker compose --profile router up -d     # Load balancer
docker compose --profile gradio up -d     # Web UI
docker compose --profile openai-server up -d  # VLM server
```

---

_Generated May 2026 from opendatalab/MinerU at e88f6d6. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
