feat(ai-services): AVM v2 residential — expanded features, training pipeline, model versioning

Add neighborhood_score, developer_reputation, floor_level, direction premiums
to the multi-model ensemble. Implement real Optuna-based training pipeline
for XGBoost/LightGBM/CatBoost with grouped train/val/test splits. Add
file-based model registry with rollback and list-versions endpoints.
23 Python tests covering all new features.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-16 17:55:03 +07:00
parent 6cf2c23170
commit 9eaec46a37
4 changed files with 743 additions and 56 deletions

View File

@@ -1,6 +1,6 @@
"""AVM v2 ensemble router — residential property valuation."""
from fastapi import APIRouter
from fastapi import APIRouter, HTTPException
from app.models.avm_v2 import (
ABComparisonRequest,
@@ -8,6 +8,7 @@ from app.models.avm_v2 import (
AVMv2ModelInfo,
AVMv2PredictRequest,
AVMv2PredictResponse,
AVMv2RollbackRequest,
AVMv2TrainRequest,
AVMv2TrainResponse,
)
@@ -30,7 +31,9 @@ def predict_v2(req: AVMv2PredictRequest) -> AVMv2PredictResponse:
def train_v2(req: AVMv2TrainRequest) -> AVMv2TrainResponse:
"""Trigger model retraining with Optuna hyperparameter optimization.
Requires training data pipeline (Phase 3). Currently returns scaffold.
Loads training data from the model directory, runs Optuna for each
model in the ensemble, saves versioned artifacts, and registers
the new version in the model registry.
"""
return avm_v2_service.train(req)
@@ -49,3 +52,22 @@ def compare_v1(req: ABComparisonRequest) -> ABComparisonResponse:
def model_info_v2() -> AVMv2ModelInfo:
"""Get current active ensemble model information."""
return avm_v2_service.get_model_info()
@router.get("/versions", response_model=list[AVMv2ModelInfo])
def list_versions() -> list[AVMv2ModelInfo]:
"""List all registered model versions with their metrics and status."""
return avm_v2_service.list_versions()
@router.post("/rollback", response_model=AVMv2ModelInfo)
def rollback(req: AVMv2RollbackRequest) -> AVMv2ModelInfo:
"""Rollback to a previously trained model version.
Copies the target version's artifacts to the active model directory,
reloads models, and updates the registry.
"""
try:
return avm_v2_service.rollback(req.target_version)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))