feat(scope): make Belgium and North Sea operational default
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-22 02:11:48 +02:00
parent 46884cbbc9
commit 0aff8e3b8c
61 changed files with 2499 additions and 194 deletions
+102 -26
View File
@@ -5,6 +5,7 @@ from typing import Type
from app.core.config import Settings, get_settings
from app.schemas.detection import DetectionModelCapability
from app.services.segmentation_adapter import SamSegmentationAdapter, YoloSegmentationAdapter
from app.services.yolo_adapter import YoloDetectionAdapter
@@ -14,10 +15,16 @@ class ModelRegistryService:
settings: Settings | None = None,
yolo_adapter_class: Type[YoloDetectionAdapter] = YoloDetectionAdapter,
task_type: str = "object_detection",
yolo_seg_adapter_class: Type[YoloSegmentationAdapter] = YoloSegmentationAdapter,
sam_adapter_class: Type[SamSegmentationAdapter] = SamSegmentationAdapter,
) -> list[DetectionModelCapability]:
resolved_settings = settings or get_settings()
if task_type == "segmentation":
return ModelRegistryService.list_segmentation_model_capabilities()
return ModelRegistryService.list_segmentation_model_capabilities(
settings=resolved_settings,
yolo_seg_adapter_class=yolo_seg_adapter_class,
sam_adapter_class=sam_adapter_class,
)
if task_type != "object_detection":
return []
return [
@@ -52,15 +59,28 @@ class ModelRegistryService:
settings: Settings | None = None,
yolo_adapter_class: Type[YoloDetectionAdapter] = YoloDetectionAdapter,
task_type: str = "object_detection",
yolo_seg_adapter_class: Type[YoloSegmentationAdapter] = YoloSegmentationAdapter,
sam_adapter_class: Type[SamSegmentationAdapter] = SamSegmentationAdapter,
) -> 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):
for model in ModelRegistryService.list_model_capabilities(
settings=settings,
yolo_adapter_class=yolo_adapter_class,
task_type=task_type,
yolo_seg_adapter_class=yolo_seg_adapter_class,
sam_adapter_class=sam_adapter_class,
):
if model.model_id == normalized:
return model
return None
@staticmethod
def list_segmentation_model_capabilities() -> list[DetectionModelCapability]:
def list_segmentation_model_capabilities(
settings: Settings | None = None,
yolo_seg_adapter_class: Type[YoloSegmentationAdapter] = YoloSegmentationAdapter,
sam_adapter_class: Type[SamSegmentationAdapter] = SamSegmentationAdapter,
) -> list[DetectionModelCapability]:
resolved_settings = settings or get_settings()
return [
DetectionModelCapability(
model_id="segmentation-placeholder",
@@ -70,7 +90,7 @@ class ModelRegistryService:
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.",
limitation_message="Segmentation inference is not configured for this placeholder; no model is downloaded or executed.",
version=None,
),
DetectionModelCapability(
@@ -84,30 +104,86 @@ class ModelRegistryService:
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,
),
ModelRegistryService._configured_yolo_seg_capability(resolved_settings, yolo_seg_adapter_class),
ModelRegistryService._configured_sam_capability(resolved_settings, sam_adapter_class),
]
@staticmethod
def _configured_yolo_seg_capability(
settings: Settings,
adapter_class: Type[YoloSegmentationAdapter] = YoloSegmentationAdapter,
) -> DetectionModelCapability:
configured = False
status = "not_configured"
limitation = (
"YOLO segmentation is disabled. Set YOLO_SEG_ENABLED=true and YOLO_SEG_MODEL_PATH to a local "
"segmentation model file to enable inference. GeoIntel never downloads model weights automatically."
)
model_path = Path(settings.yolo_seg_model_path).expanduser() if settings.yolo_seg_model_path else None
if settings.yolo_seg_enabled:
if not adapter_class.dependencies_available():
status = "dependency_unavailable"
limitation = "Segmentation dependencies are not installed. Install backend optional extras with geointel-backend[ai]."
elif model_path is None:
limitation = "YOLO_SEG_MODEL_PATH is not set. GeoIntel will not download segmentation model weights automatically."
elif not model_path.exists() or not model_path.is_file():
limitation = "YOLO_SEG_MODEL_PATH does not point to an existing local model file. GeoIntel will not download segmentation model weights automatically."
else:
configured = True
status = "configured"
limitation = "Configured for local YOLO segmentation inference over an existing raster tile manifest."
return DetectionModelCapability(
model_id=settings.yolo_seg_model_id,
display_name=settings.yolo_seg_model_display_name,
framework="ultralytics/pytorch",
task_type="segmentation",
supported_classes=["building", "vegetation", "water", "landuse"],
configured=configured,
status=status,
limitation_message=limitation,
version=settings.yolo_seg_model_version,
)
@staticmethod
def _configured_sam_capability(
settings: Settings,
adapter_class: Type[SamSegmentationAdapter] = SamSegmentationAdapter,
) -> DetectionModelCapability:
configured = False
status = "not_configured"
limitation = (
"SAM is disabled. Set SAM_ENABLED=true and SAM_MODEL_PATH to a local SAM-compatible model file to "
"enable class-agnostic segmentation. GeoIntel never downloads model weights automatically."
)
model_path = Path(settings.sam_model_path).expanduser() if settings.sam_model_path else None
if settings.sam_enabled:
if not adapter_class.dependencies_available():
status = "dependency_unavailable"
limitation = "Segmentation dependencies are not installed. Install backend optional extras with geointel-backend[ai]."
elif model_path is None:
limitation = "SAM_MODEL_PATH is not set. GeoIntel will not download segmentation model weights automatically."
elif not model_path.exists() or not model_path.is_file():
limitation = "SAM_MODEL_PATH does not point to an existing local model file. GeoIntel will not download segmentation model weights automatically."
else:
configured = True
status = "configured"
limitation = "Configured for local class-agnostic SAM segmentation over an existing raster tile manifest."
return DetectionModelCapability(
model_id=settings.sam_model_id,
display_name=settings.sam_model_display_name,
framework="ultralytics/sam",
task_type="segmentation",
supported_classes=["segment"],
configured=configured,
status=status,
limitation_message=limitation,
version=settings.sam_model_version,
)
@staticmethod
def _configured_yolo_capability(
settings: Settings,