from __future__ import annotations from fastapi import FastAPI, HTTPException from fastapi.middleware.gzip import GZipMiddleware from pydantic import BaseModel from .cluster_service import ClusteringServiceError, cluster_embeddings, cluster_run from .models import ( ClusteringAlgorithm, PythonClusteringRequest, PythonClusteringResponse, PythonRunExecutionRequest, ReductionMethod, ) from .run_db_loader import load_run_and_embeddings app = FastAPI( title="DIP Clustering Service", version="2.0.0", description="Remote clustering backend for DIP embedding clustering runs.", ) app.add_middleware(GZipMiddleware, minimum_size=1024) class HealthResponse(BaseModel): status: str algorithms: list[str] reductionMethods: list[str] endpoints: list[str] @app.get("/health", response_model=HealthResponse) def health() -> HealthResponse: return HealthResponse( status="UP", algorithms=[algorithm.value for algorithm in ClusteringAlgorithm], reductionMethods=[method.value for method in ReductionMethod], endpoints=["/cluster", "/cluster-run"], ) @app.post("/cluster", response_model=PythonClusteringResponse) def cluster_direct(request: PythonClusteringRequest) -> PythonClusteringResponse: try: return cluster_embeddings(request) except ClusteringServiceError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc except Exception as exc: # pragma: no cover - last-resort guard raise HTTPException(status_code=500, detail=f"Unexpected clustering failure: {exc}") from exc @app.post("/cluster-run", response_model=PythonClusteringResponse) def cluster_by_run(request: PythonRunExecutionRequest) -> PythonClusteringResponse: try: metadata, items = load_run_and_embeddings(request.runId) return cluster_run(metadata, items) except ClusteringServiceError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc except Exception as exc: # pragma: no cover - last-resort guard raise HTTPException(status_code=500, detail=f"Unexpected clustering failure: {exc}") from exc