Skip to content

10. Interview Prep Guide

2-minute architecture script

Universal OCR is an async microservice that turns PDFs and images into Markdown and HTML. The browser or any HTTP client posts a file to FastAPI and gets a job id. Celery workers do the heavy lifting while Redis stores progress. The default path runs PaddleX layout detection, then sends each text block to a vision-language model — either a local Paddle VL server or any LiteLLM-compatible model. We also support whole-page VLM, NVIDIA NeMo Retriever Parse, and Sarvam behind the same job API. Results are files on disk; the React dashboard polls every two seconds and shows HTML and Markdown previews. There is no agent loop and no SQL database — it is a focused OCR utility with pluggable inference backends.

5-minute architecture script

Expand the 2-minute version with:

  1. Why async: multi-page PDFs and VLM latency exceed HTTP request budgets (ADR 1).
  2. Layout path detail: PP-DocLayoutV3 labels → skip VLM for figures → parallel block OCR → stitch MD/HTML with page markers.
  3. Model routing: blank/paddleocr-vl* → Paddle client; else LiteLLM; singletons + prewarm avoid cold start.
  4. Third-party branches: nvidia/sarvam/vlm short-circuit before layout; Sarvam metadata normalized into shared schema.
  5. Storage: Redis DB 0 job hashes (24h TTL), Celery on DB 1, jobs/{uuid}/ artifacts.
  6. Frontend: single-page Vite app, mode select, history sheet, iframe HTML preview.
  7. Ops: make start or amd64 Docker full stack; Apple Silicon needs Rosetta for Paddle images.
  8. Honest limits: no auth, ephemeral storage, provider-dependent quality.

Likely system design questions

Question Answer sketch
Sync vs async OCR? Async — long GPU/API work; scale workers independently
Why not WebSockets? Polling sufficient; simpler failure modes (ADR 6)
How to scale? More Celery workers + shared volume + Redis; watch GPU memory with solo pool
How to add a provider? New extractor + branch in run_ocr_job + frontend mode entry
Consistency of Redis vs disk? Best-effort; TTL can leave orphans — call out as gap

Likely backend questions

  • Explain get_models cache invalidation on model name change
  • Difference between vlm_async_concurrency and vlm_max_workers
  • How ZIP download is built and cleaned up
  • Why Celery uses Redis DB 1
  • How custom OCR prompts apply only on LiteLLM path

Likely frontend questions

  • Polling interval and cleanup on unmount/reset
  • Why both md and html are fetched on done
  • XSS implications of srcDoc
  • No router / no global store rationale

Likely infra / security questions

  • Compose password mismatch
  • amd64 platform pin
  • Missing auth and upload limits
  • Where secrets live

Likely data / OCR questions

  • What IMAGE_LABELS do
  • How PDF pages are rasterized (PyMuPDF DPI)
  • NVIDIA JPEG backoff and Gemma fallback
  • Sarvam coordinate normalization

STAR stories

Parallel block OCR

  • Situation: Page-level sequential VLM was too slow
  • Task: Cut turnaround without losing layout fidelity
  • Action: Parallelize blocks with semaphore/thread pool; stream progress to Redis
  • Result: Interactive progress UX; tunable concurrency per provider

Provider abstraction

  • Situation: Stakeholders wanted NVIDIA and Sarvam trials without forking the API
  • Task: Keep one job contract
  • Action: Mode branch in Celery + shared download/metadata endpoints
  • Result: Dashboard mode switch for A/B comparison

Cold start mitigation

  • Situation: First job after worker boot was painfully slow
  • Task: Remove model load from the critical path
  • Action: Process singletons + optional prewarm on API and worker start
  • Result: Steady-state latency dominated by inference, not init

Weak spots to acknowledge

  • No authentication or multi-tenancy
  • Upload size not enforced server-side
  • Redis TTL vs disk retention drift
  • Limited live-provider automated tests
  • Prefetch multiplier comment vs value mismatch
  • HTML preview sanitization

Short answers

What was hard?
Coordinating layout detection, heterogeneous VLM APIs, and progress UX without turning the service into a full document platform.

What would you improve?
Auth + upload limits, disk GC, provider contract tests, sanitize HTML preview, fix compose Redis auth consistency.

What are you proud of?
The hybrid layout+VLM design and the ability to swap inference backends behind one async job API.