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:
@@ -261,6 +261,27 @@ def test_model_info_v2():
|
||||
assert data["is_active"] is True
|
||||
|
||||
|
||||
# ── Feature importance endpoint ──────────────────────────────────
|
||||
|
||||
|
||||
def test_feature_importance_heuristic():
|
||||
"""Dedicated endpoint returns heuristic drivers when no models are loaded."""
|
||||
resp = client.get("/avm/v2/feature-importance")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
|
||||
assert data["source"] == "heuristic"
|
||||
assert data["model_version"] == "ensemble-v2-heuristic"
|
||||
drivers = data["drivers"]
|
||||
assert len(drivers) > 0
|
||||
importances = [d["importance"] for d in drivers]
|
||||
assert importances == sorted(importances, reverse=True)
|
||||
assert all(0 <= i <= 1 for i in importances)
|
||||
feature_names = {d["feature"] for d in drivers}
|
||||
assert "area_m2" in feature_names
|
||||
assert "neighborhood_score" in feature_names
|
||||
|
||||
|
||||
# ── Model versioning ────────────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user