33997778f6
- Add .gitignore excluding .env, __pycache__, test_files (copyrighted PDFs), session logs, marker/ submodule, and other generated/private files - Add .env with local config (gitignored); expand .env.example with all supported environment variables - docker-compose.yml: all hardcoded values now use default pattern - Containerfile: install marker-pdf from GitHub instead of local submodule; fix AMD_COMPUTE default to false; sanitize default OLLAMA_HOST - Remove marker/ submodule from git tracking (keep local checkout via .gitignore) - Remove session transcript and copyrighted ENISA PDFs from git tracking - Sanitize local IPs in README, kubernetes deployment, deploy-podman.sh - Fix hardcoded paths in convert_both.py and compare_conversions.py - Update requirements.txt to reference GitHub instead of local --editable
223 lines
7.3 KiB
Markdown
223 lines
7.3 KiB
Markdown
# marker-api
|
|
|
|
Flask API wrapper around [marker](https://github.com/VikParuchuri/marker) — converts PDFs, DOCX, XLSX, PPTX, EPUB, images (PNG/JPG/BMP/GIF/TIFF/WEBP/HEIC), and HTML to Markdown (JSON/HTML/chunks).
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### Container (recommended)
|
|
|
|
```bash
|
|
# Build and run with Podman/Docker
|
|
podman build -t marker-api -f Containerfile .
|
|
podman run -d --rm \
|
|
--name marker-api \
|
|
-p 8000:8000 \
|
|
-e AMD_COMPUTE=false \
|
|
-e TORCH_DEVICE=cpu \
|
|
marker-api
|
|
|
|
# Or use docker-compose
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Bare-metal
|
|
|
|
```bash
|
|
git clone https://github.com/your-org/marker-api.git /app/marker-api
|
|
pip install -e /app/marker-api/marker[full] flask gunicorn
|
|
PORT=8000 python /app/marker-api/app.py
|
|
```
|
|
|
|
### Health Check
|
|
|
|
```bash
|
|
curl http://localhost:8000/health
|
|
# {"status":"ok","ollama":"http://localhost:11434","torch_device":"cpu","supported_formats":["docx","epub","html","jpg",...]}
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoints
|
|
|
|
### `GET /`
|
|
|
|
HTML documentation page listing all endpoints and parameters.
|
|
|
|
### `GET /health`
|
|
|
|
Returns server status, torch device, supported file formats, and configuration.
|
|
|
|
### `POST /marker`
|
|
|
|
Convert a single file. Accepts **multipart/form-data** or **application/json**.
|
|
|
|
#### Multipart form-data
|
|
|
|
```bash
|
|
curl -X POST http://localhost:8000/marker \
|
|
-F "file=@document.pdf" \
|
|
-F "output_format=markdown" \
|
|
-F "force_ocr=false"
|
|
```
|
|
|
|
When `output_format=markdown`, the response is the raw `.md` content as a file download. All other formats return JSON.
|
|
|
|
#### JSON body (base64)
|
|
|
|
```bash
|
|
curl -X POST http://localhost:8000/marker \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"file_b64": "<base64>",
|
|
"filename": "document.pdf",
|
|
"output_format": "markdown",
|
|
"force_ocr": false
|
|
}'
|
|
```
|
|
|
|
### `POST /v1/conversions`
|
|
|
|
Same as `/marker` but always returns JSON, wrapping the result with an `id` (UUID) field and `filename`.
|
|
|
|
### `POST /v1/files/convert`
|
|
|
|
Same as `/marker` but always returns JSON with `filename`, `format`, `output`, `images_b64`, and `metadata`.
|
|
|
|
---
|
|
|
|
## Parameters
|
|
|
|
| Parameter | Type | Default | Description |
|
|
|-----------|------|---------|-------------|
|
|
| `file` / `file_b64` | file / string | **required** | The document to convert |
|
|
| `output_format` | string | `markdown` | `markdown`, `json`, `html`, `chunks` |
|
|
| `force_ocr` | bool | `false` | Force OCR on all pages (fixes garbled text) |
|
|
| `paginate_output` | bool | `false` | Separate pages with horizontal rules |
|
|
| `page_range` | string | all | Comma-separated pages/ranges: `"0,5-10"` |
|
|
| `disable_image_extraction` | bool | `false` | Skip embedded image extraction |
|
|
| `processors` | string | auto | Comma-separated full module paths for custom processors |
|
|
| `config_json` | string | none | Path to JSON config file |
|
|
| `converter_cls` | string | auto | Full module path of converter (e.g. `marker.converters.table.TableConverter`) |
|
|
| `use_llm` | bool | `false` | Use an LLM to improve accuracy |
|
|
| `llm_service` | string | `marker.services.ollama.OllamaService` | LLM service class: `gemini`, `vertex`, `claude`, `openai`, `azure_openai`, `ollama` |
|
|
| `block_correction_prompt` | string | none | Custom prompt for LLM block correction |
|
|
| `redo_inline_math` | bool | `false` | Re-process inline math with LLM |
|
|
| `strip_existing_ocr` | bool | `false` | Remove existing OCR text and re-OCR |
|
|
| `debug` | bool | `false` | Enable debug logging |
|
|
|
|
---
|
|
|
|
## Supported Formats
|
|
|
|
PDF, DOCX, XLSX, PPTX, EPUB, PNG, JPG, BMP, GIF, TIFF, WEBP, HEIC, HTML, HTM.
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `OLLAMA_HOST` | `http://localhost:11434` | Ollama instance for OCR fallback / LLM |
|
|
| `DEESEEK_OCR_MODEL` | `deepseek-ocr` | OCR model name in Ollama |
|
|
| `AMD_COMPUTE` | `false` | Enable AMD ROCm GPU support |
|
|
| `TORCH_DEVICE` | auto | PyTorch device: `rocm`, `cuda`, `cpu` |
|
|
| `MODEL_DTYPE` | `float32` | Model dtype: `float32`, `bfloat16` |
|
|
| `PORT` | `8000` | Listening port |
|
|
| `HOST` | `0.0.0.0` | Listening host |
|
|
|
|
---
|
|
|
|
## PowerShell Batch Script
|
|
|
|
A PowerShell script (`marker-convert-powershell/marker-convert.ps1`) is provided for batch conversion.
|
|
|
|
### Usage
|
|
|
|
```powershell
|
|
.\marker-convert-powershell\marker-convert.ps1 -TargetFolder .\documents
|
|
|
|
# With options
|
|
.\marker-convert-powershell\marker-convert.ps1 .\documents `
|
|
-Force -MaxConcurrency 8 -OutputFormat json -UseLlm -LlmService marker.services.ollama.OllamaService
|
|
|
|
# Remote API
|
|
.\marker-convert-powershell\marker-convert.ps1 .\documents -ApiUrl http://10.0.0.5:8000/marker
|
|
```
|
|
|
|
### Parameters
|
|
|
|
| Parameter | Type | Default | Description |
|
|
|-----------|------|---------|-------------|
|
|
| `-TargetFolder` | string | (required) | Folder to scan recursively |
|
|
| `-ApiUrl` | uri | `http://localhost:8000/marker` | Marker API endpoint |
|
|
| `-OutputFormat` | string | `markdown` | `markdown`, `json`, `html`, `chunks` |
|
|
| `-Force` | switch | off | Overwrite existing `.md` files |
|
|
| `-MaxConcurrency` | int | 4 | Concurrent workers (1-32) |
|
|
| `-Timeout` | int | 300 | HTTP timeout in seconds (30-1800) |
|
|
| `-PageRange` | string | "" | Page range e.g. `"0,5-10"` |
|
|
| `-ForceOcr` | switch | off | Force OCR on all pages |
|
|
| `-DisableImageExtraction` | switch | off | Skip image extraction |
|
|
| `-UseLlm` | switch | off | Enable LLM enhancement |
|
|
| `-LlmService` | string | `marker.services.ollama.OllamaService` | LLM service class |
|
|
| `-Processors` | string | "" | Custom processor module paths |
|
|
| `-ConfigJson` | string | "" | Path to JSON config file |
|
|
| `-ConverterCls` | string | "" | Custom converter class path |
|
|
|
|
The script writes a CSV report (`_marker_convert_results.csv`) next to each converted file.
|
|
|
|
---
|
|
|
|
## Deployment
|
|
|
|
### AMD GPU (ROCm)
|
|
|
|
Set `AMD_COMPUTE=true` and `TORCH_DEVICE=cuda` in the container environment.
|
|
|
|
#### Vega 20 / GFX906 Support (e.g., powermac)
|
|
For older AMD GPU architectures like Vega 20 (GFX906), AMD dropped standard ROCm PyTorch support. This project fully supports GFX906 out of the box by using a patched GFX906 PyTorch base image (`mixa3607/pytorch-gfx906:v2.7.1-rocm-6.3.3`).
|
|
|
|
To run the container on GFX906 GPUs with hardware acceleration:
|
|
```bash
|
|
docker run -d --name marker-api \
|
|
--network=host \
|
|
--device /dev/kfd --device /dev/dri \
|
|
--group-add 984 --group-add 988 \
|
|
-e AMD_COMPUTE=true \
|
|
-e TORCH_DEVICE=cuda \
|
|
-e CUDA_VISIBLE_DEVICES=1 \
|
|
-e HSA_OVERRIDE_GFX_VERSION=9.0.6 \
|
|
marker-api:latest \
|
|
gunicorn --bind 0.0.0.0:8000 --workers 1 --timeout 300 --worker-class gthread --threads 4 app:app_instance
|
|
```
|
|
|
|
*Note on first run:* The very first conversion on a ROCm GPU will take 2-3 minutes as MIOpen compiles convolution kernels for your exact GPU. Subsequent runs are fully cached and take ~4-5 seconds per document.
|
|
*Note on memory:* If other services (e.g., llama-servers) are utilizing GPU 0, restrict `marker-api` to GPU 1 (`CUDA_VISIBLE_DEVICES=1`) and use a single worker (`--workers 1`) to prevent HIP Out-Of-Memory errors.
|
|
|
|
### CPU-only
|
|
|
|
```bash
|
|
TORCH_DEVICE=cpu AMD_COMPUTE=false podman run ... marker-api
|
|
```
|
|
|
|
### GPU (CUDA)
|
|
|
|
Override the PyTorch index URL during build, or use the existing ROCm image with `TORCH_DEVICE=cuda`.
|
|
|
|
---
|
|
|
|
## Response Codes
|
|
|
|
| Code | Meaning |
|
|
|------|---------|
|
|
| `200` | Successful conversion (markdown returned as file download, others as JSON) |
|
|
| `400` | Missing file or invalid body |
|
|
| `500` | Conversion error (details in JSON body) |
|
|
|
|
Error responses have the shape:
|
|
|
|
```json
|
|
{"success": false, "error": "error message"}
|
|
```
|