Task 4.3 closes the loop on Chunk 4: the FastAPI lifespan now selects fake vs real clients via IX_TEST_MODE (new AppConfig field), wires /healthz probes to the live selfcheck() on OllamaClient / SuryaOCRClient, and spawns the worker with a production Pipeline factory that builds SetupStep -> OCRStep -> GenAIStep -> ReliabilityStep -> ResponseHandler over the injected clients. Factories: - make_genai_client(cfg) -> FakeGenAIClient | OllamaClient - make_ocr_client(cfg) -> FakeOCRClient | SuryaOCRClient (spec §6.2) Probes run the async selfcheck on a fresh event loop in a short-lived thread so they're safe to call from either sync callers or a live FastAPI handler without stalling the request loop. Drops the worker-loop spawn_worker_task stub — the app module owns the production spawn directly. Tests: +11 unit tests (5 factories + 6 app-wiring / probe adapter / pipeline build). Full suite: 236 passed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
34 lines
1.1 KiB
Python
34 lines
1.1 KiB
Python
"""OCR subsystem: protocol + fake + real Surya client + factory.
|
|
|
|
Real engines (Surya today, Azure DI / AWS Textract … deferred) plug in
|
|
behind :class:`OCRClient`. The factory :func:`make_ocr_client` picks
|
|
between :class:`FakeOCRClient` (when ``IX_TEST_MODE=fake``) and
|
|
:class:`SuryaOCRClient` (production). Unknown engine names raise so a
|
|
typo'd ``IX_OCR_ENGINE`` surfaces at startup, not later.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from ix.config import AppConfig
|
|
from ix.contracts.response import OCRDetails, OCRResult
|
|
from ix.ocr.client import OCRClient
|
|
from ix.ocr.fake import FakeOCRClient
|
|
from ix.ocr.surya_client import SuryaOCRClient
|
|
|
|
|
|
def make_ocr_client(cfg: AppConfig) -> OCRClient:
|
|
"""Return the :class:`OCRClient` configured for the current run."""
|
|
|
|
if cfg.test_mode == "fake":
|
|
return FakeOCRClient(canned=OCRResult(result=OCRDetails()))
|
|
if cfg.ocr_engine == "surya":
|
|
return SuryaOCRClient()
|
|
raise ValueError(f"Unknown ocr_engine: {cfg.ocr_engine!r}")
|
|
|
|
|
|
__all__ = [
|
|
"FakeOCRClient",
|
|
"OCRClient",
|
|
"SuryaOCRClient",
|
|
"make_ocr_client",
|
|
]
|