feat(ai-services): dedicated GET /avm/v2/feature-importance endpoint (TEC-2760)

Exposes ensemble feature importance as a standalone endpoint per R5.1 spec.
Aggregates XGBoost (0.4) + LightGBM (0.35) + CatBoost (0.25) gain when trained
boosters are loaded; falls back to the curated heuristic ranking otherwise, so
callers can depend on the endpoint during scaffold/heuristic-only runs.

- Factored heuristic drivers into a shared constant (_HEURISTIC_DRIVERS)
- Added AVMv2FeatureImportanceResponse model (model_version + source + drivers)
- Added service.get_feature_importance() public method
- Added tests/test_avm_v2.py::test_feature_importance_heuristic (24 total pass)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-18 15:27:30 +07:00
parent 5731577fa9
commit 729afe2db6
4 changed files with 92 additions and 16 deletions

View File

@@ -5,6 +5,7 @@ from fastapi import APIRouter, HTTPException
from app.models.avm_v2 import (
ABComparisonRequest,
ABComparisonResponse,
AVMv2FeatureImportanceResponse,
AVMv2ModelInfo,
AVMv2PredictRequest,
AVMv2PredictResponse,
@@ -54,6 +55,17 @@ def model_info_v2() -> AVMv2ModelInfo:
return avm_v2_service.get_model_info()
@router.get("/feature-importance", response_model=AVMv2FeatureImportanceResponse)
def feature_importance_v2() -> AVMv2FeatureImportanceResponse:
"""Global feature importance for the active ensemble.
Aggregates XGBoost gain (0.4) + LightGBM gain (0.35) + CatBoost importance (0.25)
when trained boosters are loaded. Falls back to a curated heuristic ranking when
the service is running without artifacts.
"""
return avm_v2_service.get_feature_importance()
@router.get("/versions", response_model=list[AVMv2ModelInfo])
def list_versions() -> list[AVMv2ModelInfo]:
"""List all registered model versions with their metrics and status."""