Akbub's picture
deploy: Nexus AI v0.2.0 - SAP C4C Lead Creation UI included in fresh frontend build
d1f3f31
Raw
History Blame Contribute Delete
3.19 kB
from __future__ import annotations
import json
import threading
from pathlib import Path
from typing import Any
from src.aspect_sentiment.probability_fusion import fuse_probabilities
REPO_ROOT = Path(__file__).resolve().parents[2]
MODEL_DIR = REPO_ROOT / "models"
CONVERSION_MODEL_PATH = MODEL_DIR / "sales_conversion_model.pkl"
MODEL_FEATURES_PATH = MODEL_DIR / "sales_conversion_features.pkl"
MODEL_METRICS_PATH = MODEL_DIR / "sales_conversion_metrics.json"
_MODEL_LOCK = threading.Lock()
_CONVERSION_MODEL: Any | None = None
_MODEL_FEATURES: list[str] | None = None
def load_model_metrics() -> dict[str, Any]:
if not MODEL_METRICS_PATH.exists():
return {}
try:
payload = json.loads(MODEL_METRICS_PATH.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
return {}
return payload if isinstance(payload, dict) else {}
def get_model_features() -> list[str]:
global _MODEL_FEATURES
if _MODEL_FEATURES is None:
with _MODEL_LOCK:
if _MODEL_FEATURES is None:
import joblib
_MODEL_FEATURES = list(joblib.load(MODEL_FEATURES_PATH))
return _MODEL_FEATURES
def get_conversion_model() -> Any:
global _CONVERSION_MODEL
if _CONVERSION_MODEL is None:
with _MODEL_LOCK:
if _CONVERSION_MODEL is None:
import joblib
_CONVERSION_MODEL = joblib.load(CONVERSION_MODEL_PATH)
return _CONVERSION_MODEL
def build_conversion_row(extraction: dict[str, Any]) -> tuple[Any, Any]:
import pandas as pd
row: dict[str, Any] = {
"budget": 0,
"sentiment_score": extraction.get("sentiment_score", 0),
"confidence_score": extraction.get("confidence_score", 0),
"hesitation_score": extraction.get("hesitation_score", 0),
"delay_flag": extraction.get("delay_flag", 0),
"feature_count": extraction.get("feature_count", 0),
"brand_count": extraction.get("brand_count", 0),
"interaction_length": extraction.get("interaction_length", 0),
}
from src.aspect_sentiment.mapping_engine import process_extractions
normalized = process_extractions(extraction.get("raw_features", []))
for key, value in normalized.to_xgboost_dict().items():
row[key] = value
explanation_row = pd.DataFrame([row])
model_row = explanation_row.copy()
model_features = get_model_features()
for column in model_features:
if column not in model_row.columns:
model_row[column] = 0
return model_row[model_features], explanation_row
def predict_with_trained_model(extraction: dict[str, Any], text: str, agent_text: str = "") -> dict[str, Any]:
model_row, _explanation_row = build_conversion_row(extraction)
xgboost_prob = float(get_conversion_model().predict_proba(model_row)[0][1])
raw_features = extraction.get("raw_features", [])
sentiment_score = float(extraction.get("sentiment_score", 0))
return fuse_probabilities(
xgboost_prob=xgboost_prob,
transcript=text,
raw_features=raw_features,
sentiment_score=sentiment_score,
agent_transcript=agent_text,
)