feat: surgery pipeline API, video inference, voice confirm, and tests
- Add FastAPI routes for surgery start/end, results, pending confirmation (WAV upload), and health checks. - Implement RTSP/Hikvision capture, consumable classification, session manager, MinIO/Baidu voice resolution, and DB persistence. - Add documentation (client API, video backends, staging checklist) and sample camera/RTSP config. - Add pytest suite (API contract, session manager, voice, repositories, pipeline persistence) and httpx dev dependency. - Replace deprecated HTTP_422_UNPROCESSABLE_ENTITY with HTTP_422_UNPROCESSABLE_CONTENT. - Fix SurgeryPipeline DB reads to use an explicit transaction with autobegin disabled. Made-with: Cursor
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
# Production: PostgreSQL + API. Set strong secrets via environment or `.env` (not committed).
|
||||
# Production stack for the current codebase: FastAPI + PostgreSQL.
|
||||
# The API hard-fails on startup if the database is not reachable, so DB health is required.
|
||||
#
|
||||
# Published API port defaults to 38080 on the host (override with API_PORT).
|
||||
#
|
||||
# GPU (NVIDIA) inference: uv.lock pins torch/torchvision from the PyTorch *CPU* index (see pyproject.toml).
|
||||
# For CUDA on Linux, use a separate image/lockfile that installs torch+cu*, NVIDIA Container Toolkit on the host,
|
||||
# and assign GPUs to the api service (deploy.resources.reservations.devices).
|
||||
services:
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
@@ -21,13 +28,47 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-operation_room}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-operation_room}
|
||||
POSTGRES_HOST: db
|
||||
POSTGRES_PORT: 5432
|
||||
CONSUMABLE_CLASSIFIER_IMGSZ: ${CONSUMABLE_CLASSIFIER_IMGSZ:-224}
|
||||
CONSUMABLE_CLASSIFIER_DEVICE: ${CONSUMABLE_CLASSIFIER_DEVICE:-}
|
||||
CONSUMABLE_CLASSIFIER_TOPK: ${CONSUMABLE_CLASSIFIER_TOPK:-5}
|
||||
TEAR_ACTION_IMGSZ: ${TEAR_ACTION_IMGSZ:-224}
|
||||
TEAR_ACTION_DEVICE: ${TEAR_ACTION_DEVICE:-}
|
||||
TEAR_ACTION_TOPK: ${TEAR_ACTION_TOPK:-5}
|
||||
# Video backends (RTSP / optional Hikvision SDK) — see docs/video-backends.md
|
||||
VIDEO_DEFAULT_BACKEND: ${VIDEO_DEFAULT_BACKEND:-rtsp}
|
||||
VIDEO_RTSP_URL_TEMPLATE: ${VIDEO_RTSP_URL_TEMPLATE:-}
|
||||
VIDEO_RTSP_URLS_JSON_FILE: ${VIDEO_RTSP_URLS_JSON_FILE:-}
|
||||
VIDEO_RTSP_URLS_JSON: ${VIDEO_RTSP_URLS_JSON:-}
|
||||
VIDEO_CAMERA_BACKEND_OVERRIDES_JSON: ${VIDEO_CAMERA_BACKEND_OVERRIDES_JSON:-}
|
||||
HIKVISION_SDK_ENABLED: ${HIKVISION_SDK_ENABLED:-false}
|
||||
HIKVISION_LIB_DIR: ${HIKVISION_LIB_DIR:-/opt/hikvision/lib}
|
||||
HIKVISION_DEVICE_IP: ${HIKVISION_DEVICE_IP:-}
|
||||
HIKVISION_USER: ${HIKVISION_USER:-}
|
||||
HIKVISION_PASSWORD: ${HIKVISION_PASSWORD:-}
|
||||
HIKVISION_PREVIEW_RTSP_TEMPLATE: ${HIKVISION_PREVIEW_RTSP_TEMPLATE:-}
|
||||
ports:
|
||||
- "${API_PORT:-8000}:8000"
|
||||
- "${API_PORT:-38080}:8000"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"python",
|
||||
"-c",
|
||||
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
volumes:
|
||||
pgdata_prod:
|
||||
|
||||
Reference in New Issue
Block a user