ADR-0069 — MinerU cloud PDF extractor (P3-d)¶
- Status: Accepted
- Date: 2026-07-10
- Feature: F12 (multi-format ingest) · v1.5 LLM Wiki parity, slice P3-d
- Relates: [[ADR-0051]] (pluggable PDF extractor seam), [[ADR-0066]] (parity program — amends I9 for opt-in cloud providers)
Context¶
The PDF extractor seam (ADR-0051) supports pypdf (default, pure-Python) and marker (local
ML microservice). LLM Wiki offers MinerU as a high-quality cloud extractor. ADR-0066 amended
I9 to permit cloud providers as opt-in, off by default, with an upload warning. This ADR adds
MinerU as a third pdf_extractor value under those constraints.
Decision¶
-
pdf_extractorgainsmineru(config_overrides_PDF_EXTRACTOR_VALUES= {pypdf, marker, mineru}). Default stayspypdf. Selectingmineruroutesextract_text()PDF dispatch to_extract_pdf_via_mineru(). -
Cloud call is best-effort with unconditional pypdf fallback. On ANY failure — missing API key, non-2xx, timeout, invalid/empty body — the adapter logs a WARNING and returns None; the caller falls back to pypdf. PDF ingest never breaks (mirrors the Marker contract).
-
The API key is a SECRET → env-only.
MINERU_API_KEY(settings.mineru_api_key) is read from the environment and is structurally excluded from the runtime config-override surface (config_overrides §2.4 — secrets are never PUT-able). Until the key is set, selectingmineruis a guaranteed no-op fallback: nothing is uploaded. The non-secretmineru_api_url(S21) andmineru_timeout_seconds(S22) ARE runtime-tunable viaPUT /config/app/{key}. -
I9 upload warning in the UI. The PDF settings page shows an amber warning whenever
mineruis selected: it uploads PDF content to an external service, stays off untilMINERU_API_KEYis set, and falls back to pypdf on error. -
Wire protocol is provisional. MinerU's public v4 API is task-based (submit → poll). This adapter implements a defensive submit-and-read contract; the exact endpoint/response shape MUST be validated against a live
MINERU_API_KEYbefore relying on cloud extraction. This is called out in the code and here — the seam, gating, fallback, and UX are complete and tested; the live cloud round-trip is the one untested piece (no key available in dev/CI).
Consequences¶
- Three PDF extractors: pypdf (default/offline), marker (local, high quality), mineru (cloud, opt-in). Privacy posture is explicit: only pypdf and marker keep content on-prem.
- Bounded by
mineru_timeout_seconds(I7); no loop. - Adding two runtime keys took ALLOWED_CONFIG_KEYS 20 → 22; snapshot tests updated accordingly.
Tests¶
backend/tests/test_p3d_mineru_seam.py — config-override validation, secret-exclusion, routing,
no-key-no-upload, mocked 2xx success, non-2xx fallback. Frontend: live-verified the option +
amber warning + mineru_api_url/timeout cards render (grouped nav, brand colours).