Files
geointel/backend/app/services/model_registry_service.py
T
Codex 6ea3586a3e
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled
Initial GeoIntel V1 foundation
2026-06-16 23:36:32 +02:00

145 lines
6.6 KiB
Python

from __future__ import annotations
from pathlib import Path
from typing import Type
from app.core.config import Settings, get_settings
from app.schemas.detection import DetectionModelCapability
from app.services.yolo_adapter import YoloDetectionAdapter
class ModelRegistryService:
@staticmethod
def list_model_capabilities(
settings: Settings | None = None,
yolo_adapter_class: Type[YoloDetectionAdapter] = YoloDetectionAdapter,
task_type: str = "object_detection",
) -> list[DetectionModelCapability]:
resolved_settings = settings or get_settings()
if task_type == "segmentation":
return ModelRegistryService.list_segmentation_model_capabilities()
if task_type != "object_detection":
return []
return [
DetectionModelCapability(
model_id="yolo-placeholder",
display_name="YOLO detector placeholder",
framework="ultralytics/pytorch",
task_type="object_detection",
supported_classes=["building", "road", "water", "landuse"],
configured=False,
status="not_configured",
limitation_message="YOLO/PyTorch inference is not configured in Sprint 8; no model is downloaded or executed.",
version=None,
),
ModelRegistryService._configured_yolo_capability(resolved_settings, yolo_adapter_class),
DetectionModelCapability(
model_id="manual-fixture-detector",
display_name="Manual fixture detector",
framework="fixture",
task_type="object_detection",
supported_classes=["building"],
configured=True,
status="configured",
limitation_message="Fixture detector is for explicit tests/demo fixtures only and is not production inference.",
version="fixture-v1",
),
]
@staticmethod
def get_model_capability(
model_id: str,
settings: Settings | None = None,
yolo_adapter_class: Type[YoloDetectionAdapter] = YoloDetectionAdapter,
task_type: str = "object_detection",
) -> DetectionModelCapability | None:
normalized = model_id.strip()
for model in ModelRegistryService.list_model_capabilities(settings=settings, yolo_adapter_class=yolo_adapter_class, task_type=task_type):
if model.model_id == normalized:
return model
return None
@staticmethod
def list_segmentation_model_capabilities() -> list[DetectionModelCapability]:
return [
DetectionModelCapability(
model_id="segmentation-placeholder",
display_name="Segmentation placeholder",
framework="placeholder",
task_type="segmentation",
supported_classes=["building", "vegetation", "water", "landuse"],
configured=False,
status="not_configured",
limitation_message="Segmentation inference is not configured in Sprint 9; no SAM/YOLO-seg model is downloaded or executed.",
version=None,
),
DetectionModelCapability(
model_id="fixture-segmenter",
display_name="Fixture segmenter",
framework="fixture",
task_type="segmentation",
supported_classes=["building", "vegetation", "water", "landuse"],
configured=True,
status="configured",
limitation_message="Fixture segmenter is for explicit tests/demo fixtures only and is not production inference.",
version="fixture-v1",
),
DetectionModelCapability(
model_id="yolo-seg-configured",
display_name="Configured YOLO segmentation",
framework="ultralytics/pytorch",
task_type="segmentation",
supported_classes=["building", "vegetation", "water", "landuse"],
configured=False,
status="not_configured",
limitation_message="YOLO-seg is not configured in Sprint 9. GeoIntel will not download segmentation model weights automatically.",
version=None,
),
DetectionModelCapability(
model_id="sam-configured",
display_name="Configured SAM segmentation",
framework="sam",
task_type="segmentation",
supported_classes=["building", "vegetation", "water", "landuse"],
configured=False,
status="not_configured",
limitation_message="SAM is not configured in Sprint 9 and is not installed as a backend dependency.",
version=None,
),
]
@staticmethod
def _configured_yolo_capability(
settings: Settings,
yolo_adapter_class: Type[YoloDetectionAdapter],
) -> DetectionModelCapability:
configured = False
status = "not_configured"
limitation = "YOLO is disabled. Set YOLO_ENABLED=true and YOLO_MODEL_PATH to a local model file to enable inference."
model_path = Path(settings.yolo_model_path).expanduser() if settings.yolo_model_path else None
if settings.yolo_enabled:
if not yolo_adapter_class.dependencies_available():
status = "dependency_unavailable"
limitation = "YOLO dependencies are not installed. Install backend optional extras with geointel-backend[ai]."
elif model_path is None:
limitation = "YOLO_MODEL_PATH is not set. GeoIntel will not download model weights automatically."
elif not model_path.exists() or not model_path.is_file():
limitation = "YOLO_MODEL_PATH does not point to an existing local model file. GeoIntel will not download model weights automatically."
else:
configured = True
status = "configured"
limitation = "Configured for local YOLO inference over an existing raster tile manifest."
return DetectionModelCapability(
model_id=settings.yolo_model_id,
display_name=settings.yolo_model_display_name,
framework="ultralytics/pytorch",
task_type="object_detection",
supported_classes=["building", "road", "water", "landuse"],
configured=configured,
status=status,
limitation_message=limitation,
version=settings.yolo_model_version,
)