guide / src /next_action /predict.py
sangram kumar yerra
phase 4 - NextAction MLP & Document Processor
b861cd9
Raw
History Blame Contribute Delete
3.05 kB
"""
NextActionPredictor inference helper.
Exposes recommend_action() used by the CMA tool recommend_action.
Falls back to DOMAIN_ACTION_PRIORS rule-based routing when no checkpoint exists.
The module-level NextActionPredictor instance is cached after the first call.
Call init_predictor() at server startup for a predictable load moment.
"""
from __future__ import annotations
import logging
from typing import Optional
from src.next_action.model import (
EscalationAction,
NextActionPredictor,
build_feature_vector,
entities_dict_to_flags,
)
logger = logging.getLogger(__name__)
_DEFAULT_MODEL_PATH = "models/next_action/model.pt"
_predictor: Optional[NextActionPredictor] = None
# ---------------------------------------------------------------------------
# Lifecycle helpers
# ---------------------------------------------------------------------------
def init_predictor(model_path: str = _DEFAULT_MODEL_PATH) -> NextActionPredictor:
"""
Explicitly initialise (or reload) the module-level NextActionPredictor.
Always succeeds: if the checkpoint is missing, the rule-based fallback is
used and a warning is logged. Call this at server startup so the load
happens at a known moment rather than on the first request.
"""
global _predictor
_predictor = NextActionPredictor(model_path)
if _predictor.uses_fallback:
logger.warning(
"NextActionPredictor is using rule-based fallback (no checkpoint at '%s'). "
"Train with: python -m src.next_action.train --output_path %s",
model_path, model_path,
)
return _predictor
# ---------------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------------
def recommend_action(
domain: str,
entities: dict,
prior_contact: bool = False,
model_path: str = _DEFAULT_MODEL_PATH,
) -> list[EscalationAction]:
"""
Return a ranked list of EscalationAction for *domain* and *entities*.
Args:
domain: The classified complaint domain (one of the 6 G.U.I.D.E. domains).
entities: Dict of entity_type → value from EvidenceNER, e.g.
{"ORG": "Flipkart", "AMOUNT": "₹4,299", "REF_ID": "OD-123"}.
PERSON is ignored (role reference, not a routing signal).
prior_contact: True if the user has already contacted the company without
resolution. Causes company_support to be deprioritised.
model_path: Path to the .pt checkpoint; falls back to rule-based if absent.
Returns:
All 6 EscalationActions sorted by confidence descending.
The caller (CMA) typically surfaces the top 2–3 to the user.
"""
global _predictor
if _predictor is None:
init_predictor(model_path)
entity_flags = entities_dict_to_flags(entities)
fv = build_feature_vector(domain, entity_flags, float(prior_contact))
return _predictor.predict(fv)