Files
parking_solution/apps/vision/vision_service/settings.py
T
julian 6933406ae3 feat(vision): scaffold apps/vision ANPR microservice (FastAPI, stub recognizer)
Skeleton of the host-side vision service per the packaging decision: a Python/FastAPI
app at apps/vision/, uv-managed, wired into the Turbo graph via a thin package.json
shim (dev/lint/test/build → uv/uvicorn/ruff/pytest). A per-package turbo.json sets
build outputs [] so the no-op build is warning-free.

Endpoints: GET /health (readiness + model version) and POST /analyze (raw
octet-stream body, so Node POSTs Snapshot.bytes directly; empty→400, oversize→413,
recognizer-not-ready→503). The recognizer is a Protocol with a StubRecognizer (no
models, boots/tests offline — the dev/CI default) and a FastAlprRecognizer (the real
MIT YOLOv9+CCT/ONNX stack, lazily imported; missing models ⇒ ready=False, not a crash)
— the device-adapter pattern applied to the model. fast-alpr + onnxruntime are an
optional `alpr` extra, so `uv sync` needs no model download.

Verified: turbo run lint|test|build includes @parking/vision and stays green; uv run
mypy strict-clean; uvicorn boots and serves /health + /analyze live; pnpm workspace
6→7. Not built yet: the Node VisionClient adapter, a Dockerfile + model fetch, and
Job 2 (vehicle verification). Updates the packaging decision (As-scaffolded) + log.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
2026-06-19 15:37:38 +02:00

38 lines
1.4 KiB
Python

"""Runtime configuration, from environment (prefix VISION_).
Offline-first: every default is local and works with no network. The recognizer is
chosen by `recognizer` — "stub" (no models, deterministic placeholder) or "fast_alpr"
(the real MIT YOLOv9+CCT/ONNX stack, installed via the `alpr` extra).
"""
from __future__ import annotations
from typing import Literal
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_prefix="VISION_", env_file=".env", extra="ignore")
host: str = "0.0.0.0"
port: int = 8089
# Which recognizer to load. "stub" needs no model weights (boots anywhere, for
# dev/CI); "fast_alpr" loads the real models (requires the `alpr` extra installed).
recognizer: Literal["stub", "fast_alpr"] = "stub"
# fast-alpr model names (only used when recognizer="fast_alpr"). Defaults match the
# library defaults; swap the OCR for the 40+country EU model to benchmark Albanian
# plates. See wiki/entities/opencv-anpr-service.md "Recognizer evaluation".
detector_model: str = "yolo-v9-t-384-license-plate-end2end"
ocr_model: str = "cct-xs-v2-global-model"
# Below this OCR confidence the read is returned but flagged low_confidence, so the
# Node side can fall back to the ticket path rather than trust it.
min_confidence: float = 0.5
def get_settings() -> Settings:
return Settings()