This document provides various usage examples for ThinkParse.
ThinkParse provides two API interfaces:
- Official MinerU API (
/file_parse) - Synchronous compatibility interface for single-host or simple integrations - Async Queue API (
/api/v1/tasks/*) - Asynchronous, compatible with mineru-tianshu project format
- Official MinerU API Examples
- Async Queue API Examples
- Python Client Examples
- cURL Command Examples
- JavaScript/TypeScript Examples
- Common Scenarios
The /file_parse endpoint is compatible with the official MinerU API. It submits tasks and waits for completion, returning results directly.
Note:
/file_parseis intended for compatibility and single-host usage. For production deployments with S3 storage, multiple workers, or multiple nodes, use the async queue API instead.
curl -X POST "http://localhost:8000/file_parse" \
-F "files=@document.pdf" \
-F "backend=pipeline" \
-F "lang_list=ch" \
-F "parse_method=auto" \
-F "return_md=true" \
-F "return_images=false"import requests
# Submit and get results immediately
files = {'files': open('document.pdf', 'rb')}
data = {
'backend': 'pipeline',
'lang_list': 'ch',
'parse_method': 'auto',
'return_md': 'true',
'return_middle_json': 'false',
'return_images': 'false'
}
response = requests.post('http://localhost:8000/file_parse', files=files, data=data)
result = response.json()
# Results are directly in the response
for pdf_name, pdf_result in result['results'].items():
print(f"File: {pdf_name}")
print(f"Markdown: {pdf_result.get('md_content', '')[:100]}...")curl -X POST "http://localhost:8000/file_parse" \
-F "files=@document1.pdf" \
-F "files=@document2.pdf" \
-F "backend=pipeline" \
-F "lang_list=ch" \
-F "lang_list=en"The async queue API provides better scalability for production deployments and batch processing.
It is the recommended interface for S3 storage, multi-worker, and multi-node production deployments.
import requests
# Submit task
url = "http://localhost:8000/api/v1/tasks/submit"
files = {'file': open('document.pdf', 'rb')}
data = {
'backend': 'pipeline',
'lang': 'ch',
'method': 'auto',
'formula_enable': 'true',
'table_enable': 'true',
'priority': '0'
}
response = requests.post(url, files=files, data=data)
result = response.json()
task_id = result['task_id']
print(f"Task submitted: {task_id}")
# Query task status
status_url = f"http://localhost:8000/api/v1/tasks/{task_id}"
while True:
status_response = requests.get(status_url)
status = status_response.json()
if status['task']['status'] == 'completed':
print("Task completed!")
print(f"Markdown content: {status.get('markdown_content', '')[:100]}...")
break
elif status['task']['status'] == 'failed':
print(f"Task failed: {status['task']['error_message']}")
break
import time
time.sleep(2)Refer to examples/client_example.py for a complete async client example.
import asyncio
import aiohttp
from pathlib import Path
async def submit_and_wait(file_path: str):
async with aiohttp.ClientSession() as session:
# Submit task
data = aiohttp.FormData()
data.add_field('file', open(file_path, 'rb'), filename=Path(file_path).name)
data.add_field('backend', 'pipeline')
data.add_field('lang', 'ch')
async with session.post('http://localhost:8000/api/v1/tasks/submit', data=data) as resp:
result = await resp.json()
task_id = result['task_id']
# Wait for completion
while True:
async with session.get(f'http://localhost:8000/api/v1/tasks/{task_id}') as resp:
status = await resp.json()
if status['task']['status'] == 'completed':
return status
elif status['task']['status'] == 'failed':
raise Exception(status['task']['error_message'])
await asyncio.sleep(2)
# Usage
result = asyncio.run(submit_and_wait('document.pdf'))curl -X POST "http://localhost:8000/api/v1/tasks/submit" \
-F "file=@document.pdf" \
-F "backend=pipeline" \
-F "lang=ch" \
-F "method=auto" \
-F "formula_enable=true" \
-F "table_enable=true" \
-F "priority=0"Response example:
{
"success": true,
"task_id": "abc123-def456-ghi789",
"status": "pending",
"message": "Task submitted successfully",
"file_name": "document.pdf",
"created_at": "2024-01-01T12:00:00",
"backend": "pipeline",
"priority": 0
}curl "http://localhost:8000/api/v1/tasks/abc123-def456-ghi789"Response example (in progress):
{
"success": true,
"task": {
"task_id": "abc123-def456-ghi789",
"status": "processing",
"file_name": "document.pdf",
"backend": "pipeline"
},
"timestamp": "2024-01-01T12:00:30"
}Response example (completed):
{
"success": true,
"task": {
"task_id": "abc123-def456-ghi789",
"status": "completed",
"file_name": "document.pdf",
"backend": "pipeline",
"completed_at": "2024-01-01T12:01:00"
},
"markdown_content": "# Document Title\n\nContent here...",
"images": [],
"timestamp": "2024-01-01T12:01:00"
}curl -X DELETE "http://localhost:8000/api/v1/tasks/abc123-def456-ghi789"curl "http://localhost:8000/api/v1/queue/stats"curl "http://localhost:8000/api/v1/health"// Submit task
async function submitTask(file, options = {}) {
const formData = new FormData();
formData.append('file', file);
formData.append('backend', options.backend || 'pipeline');
formData.append('lang', options.lang || 'ch');
formData.append('method', options.method || 'auto');
formData.append('formula_enable', options.formula_enable !== false);
formData.append('table_enable', options.table_enable !== false);
formData.append('priority', options.priority || 0);
const response = await fetch('http://localhost:8000/api/v1/tasks/submit', {
method: 'POST',
body: formData
});
return await response.json();
}
// Query task status
async function getTaskStatus(taskId) {
const response = await fetch(`http://localhost:8000/api/v1/tasks/${taskId}`);
return await response.json();
}
// Wait for task completion
async function waitForTask(taskId, timeout = 600000) {
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
const status = await getTaskStatus(taskId);
if (status.task.status === 'completed') {
return status;
} else if (status.task.status === 'failed') {
throw new Error(status.task.error_message);
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
throw new Error('Task timeout');
}
// Usage example
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async (e) => {
const file = e.target.files[0];
const result = await submitTask(file);
console.log('Task submitted:', result.task_id);
try {
const finalStatus = await waitForTask(result.task_id);
console.log('Task completed:', finalStatus.markdown_content);
} catch (error) {
console.error('Task failed:', error);
}
});import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:8000/api/v1'
});
// Submit task
async function submitTask(file, options = {}) {
const formData = new FormData();
formData.append('file', file);
Object.entries(options).forEach(([key, value]) => {
formData.append(key, value);
});
const response = await api.post('/tasks/submit', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
return response.data;
}
// Query task status
async function getTaskStatus(taskId) {
const response = await api.get(`/tasks/${taskId}`);
return response.data;
}import asyncio
import aiohttp
from pathlib import Path
async def batch_process(files: list[str]):
async with aiohttp.ClientSession() as session:
# Submit all tasks
tasks = []
for file_path in files:
data = aiohttp.FormData()
data.add_field('file', open(file_path, 'rb'), filename=Path(file_path).name)
data.add_field('backend', 'pipeline')
data.add_field('lang', 'ch')
async with session.post('http://localhost:8000/api/v1/tasks/submit', data=data) as resp:
result = await resp.json()
tasks.append(result['task_id'])
# Wait for all tasks to complete
results = []
for task_id in tasks:
while True:
async with session.get(f'http://localhost:8000/api/v1/tasks/{task_id}') as resp:
status = await resp.json()
if status['task']['status'] == 'completed':
results.append(status)
break
elif status['task']['status'] == 'failed':
results.append({'task_id': task_id, 'error': status['task']['error_message']})
break
await asyncio.sleep(2)
return results
# Usage
files = ['doc1.pdf', 'doc2.pdf', 'doc3.pdf']
results = asyncio.run(batch_process(files))# Submit high priority task
high_priority_response = requests.post(
'http://localhost:8000/api/v1/tasks/submit',
files={'file': open('urgent.pdf', 'rb')},
data={'backend': 'pipeline', 'priority': '10'} # High priority
)
# Submit low priority task
low_priority_response = requests.post(
'http://localhost:8000/api/v1/tasks/submit',
files={'file': open('normal.pdf', 'rb')},
data={'backend': 'pipeline', 'priority': '0'} # Low priority
)# PDF file - Use MinerU
response = requests.post(
'http://localhost:8000/api/v1/tasks/submit',
files={'file': open('document.pdf', 'rb')},
data={'backend': 'pipeline', 'lang': 'ch'}
)
# Office document - Automatically use MarkItDown
response = requests.post(
'http://localhost:8000/api/v1/tasks/submit',
files={'file': open('document.docx', 'rb')},
data={'backend': 'pipeline', 'lang': 'ch'}
)
# Image file - Use MinerU OCR
response = requests.post(
'http://localhost:8000/api/v1/tasks/submit',
files={'file': open('image.png', 'rb')},
data={'backend': 'pipeline', 'method': 'ocr', 'lang': 'ch'}
)import requests
from requests.exceptions import RequestException
def submit_task_safe(file_path: str, max_retries: int = 3):
for attempt in range(max_retries):
try:
with open(file_path, 'rb') as f:
response = requests.post(
'http://localhost:8000/api/v1/tasks/submit',
files={'file': f},
data={'backend': 'pipeline', 'lang': 'ch'},
timeout=30
)
response.raise_for_status()
return response.json()
except RequestException as e:
if attempt == max_retries - 1:
raise
print(f"Attempt {attempt + 1} failed: {e}, retrying...")
import time
time.sleep(2 ** attempt) # Exponential backoff
return Noneimport requests
import time
def monitor_queue(interval: int = 5):
while True:
response = requests.get('http://localhost:8000/api/v1/queue/stats')
stats = response.json()
print(f"Pending: {stats['stats']['pending']}")
print(f"Processing: {stats['stats']['processing']}")
print(f"Active Workers: {stats['workers']['active_workers']}")
print("-" * 40)
time.sleep(interval)
# Usage
monitor_queue()400 Bad Request: Invalid request parameters413 Payload Too Large: File size exceeds limit422 Unprocessable Entity: Unsupported file format or parameter validation failed500 Internal Server Error: Internal server error503 Service Unavailable: Service unavailable (e.g., Worker not running)
import requests
try:
response = requests.post(
'http://localhost:8000/api/v1/tasks/submit',
files={'file': open('document.pdf', 'rb')},
data={'backend': 'pipeline'}
)
response.raise_for_status()
result = response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 413:
print("File too large. Maximum size: 100MB")
elif e.response.status_code == 422:
print("Invalid file format or parameters")
print(e.response.json())
else:
print(f"HTTP Error: {e}")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")For more example code, please refer to:
examples/client_example.py- Complete Python async client example- API Documentation:
http://localhost:8000/docs(Swagger UI) - API Documentation (ReDoc):
http://localhost:8000/redoc