Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- src/__pycache__/api.cpython-310.pyc.1968822517424 +0 -0
- src/__pycache__/api.cpython-310.pyc.2277340322896 +0 -0
- src/__pycache__/api.cpython-310.pyc.2501683903856 +0 -0
- src/__pycache__/clarification_engine.cpython-310.pyc.1967529948912 +0 -0
- src/__pycache__/clarification_engine.cpython-310.pyc.2500390448176 +0 -0
- src/__pycache__/confidence_router.cpython-310.pyc.1967533499904 +0 -0
- src/__pycache__/confidence_router.cpython-310.pyc.2278401276224 +0 -0
- src/__pycache__/ensemble_router.cpython-310.pyc.1967533628336 +0 -0
- src/__pycache__/ensemble_router.cpython-310.pyc.2278401181456 +0 -0
- src/__pycache__/ensemble_router.cpython-310.pyc.2500391494464 +0 -0
- src/__pycache__/feature_extraction.cpython-310.pyc.1967533625168 +0 -0
- src/__pycache__/feature_extraction.cpython-310.pyc.2500390450464 +0 -0
- src/__pycache__/sla_predictor.cpython-310.pyc.1967533624288 +0 -0
- src/__pycache__/sla_predictor.cpython-310.pyc.2500610797296 +0 -0
- src/__pycache__/ticket_validator.cpython-310.pyc.1969230287904 +0 -0
- src/__pycache__/ticket_validator.cpython-310.pyc.2277999376528 +0 -0
- src/__pycache__/ticket_validator.cpython-310.pyc.2501789602848 +0 -0
- src/api.py +49 -0
src/__pycache__/api.cpython-310.pyc.1968822517424
ADDED
|
Binary file (24.9 kB). View file
|
|
|
src/__pycache__/api.cpython-310.pyc.2277340322896
ADDED
|
Binary file (24.9 kB). View file
|
|
|
src/__pycache__/api.cpython-310.pyc.2501683903856
ADDED
|
Binary file (24.9 kB). View file
|
|
|
src/__pycache__/clarification_engine.cpython-310.pyc.1967529948912
ADDED
|
Binary file (11.8 kB). View file
|
|
|
src/__pycache__/clarification_engine.cpython-310.pyc.2500390448176
ADDED
|
Binary file (11.7 kB). View file
|
|
|
src/__pycache__/confidence_router.cpython-310.pyc.1967533499904
ADDED
|
Binary file (10.5 kB). View file
|
|
|
src/__pycache__/confidence_router.cpython-310.pyc.2278401276224
ADDED
|
Binary file (10.5 kB). View file
|
|
|
src/__pycache__/ensemble_router.cpython-310.pyc.1967533628336
ADDED
|
Binary file (15.6 kB). View file
|
|
|
src/__pycache__/ensemble_router.cpython-310.pyc.2278401181456
ADDED
|
Binary file (15.5 kB). View file
|
|
|
src/__pycache__/ensemble_router.cpython-310.pyc.2500391494464
ADDED
|
Binary file (15.5 kB). View file
|
|
|
src/__pycache__/feature_extraction.cpython-310.pyc.1967533625168
ADDED
|
Binary file (11.7 kB). View file
|
|
|
src/__pycache__/feature_extraction.cpython-310.pyc.2500390450464
ADDED
|
Binary file (11.7 kB). View file
|
|
|
src/__pycache__/sla_predictor.cpython-310.pyc.1967533624288
ADDED
|
Binary file (3.8 kB). View file
|
|
|
src/__pycache__/sla_predictor.cpython-310.pyc.2500610797296
ADDED
|
Binary file (3.79 kB). View file
|
|
|
src/__pycache__/ticket_validator.cpython-310.pyc.1969230287904
ADDED
|
Binary file (6.27 kB). View file
|
|
|
src/__pycache__/ticket_validator.cpython-310.pyc.2277999376528
ADDED
|
Binary file (6.27 kB). View file
|
|
|
src/__pycache__/ticket_validator.cpython-310.pyc.2501789602848
ADDED
|
Binary file (6.27 kB). View file
|
|
|
src/api.py
CHANGED
|
@@ -372,6 +372,54 @@ def _result_forced_to_category(result: Dict, category: str, confidence: float, r
|
|
| 372 |
return adjusted
|
| 373 |
|
| 374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
def _apply_direct_signal_overrides(result: Dict, text: str, direct_intents: List[str]) -> Dict:
|
| 376 |
if len(direct_intents) >= 2:
|
| 377 |
return result
|
|
@@ -551,6 +599,7 @@ def route_ticket(req: TicketRequest):
|
|
| 551 |
unique_intents = list(dict.fromkeys(segment_intents or direct_intents))
|
| 552 |
is_multi_intent = len(unique_intents) >= 2
|
| 553 |
result = _apply_direct_signal_overrides(result, clean_text, unique_intents)
|
|
|
|
| 554 |
if is_multi_intent:
|
| 555 |
unique_intents = _order_intents_by_probability(unique_intents, result)
|
| 556 |
|
|
|
|
| 372 |
return adjusted
|
| 373 |
|
| 374 |
|
| 375 |
+
def _update_result_probabilities(result: Dict, probs: Dict[str, float]) -> Dict:
|
| 376 |
+
adjusted = dict(result)
|
| 377 |
+
total = sum(max(float(value), 0.0) for value in probs.values())
|
| 378 |
+
if total <= 0:
|
| 379 |
+
return adjusted
|
| 380 |
+
|
| 381 |
+
normalized = {
|
| 382 |
+
category: max(float(probs.get(category, 0.0)), 0.0) / total
|
| 383 |
+
for category in CATEGORY_NAMES
|
| 384 |
+
}
|
| 385 |
+
ranking = sorted(normalized.items(), key=lambda item: item[1], reverse=True)
|
| 386 |
+
entropy = float(-sum(p * np.log(p + 1e-9) for p in normalized.values()))
|
| 387 |
+
margin = float(ranking[0][1] - ranking[1][1])
|
| 388 |
+
|
| 389 |
+
adjusted.update({
|
| 390 |
+
'top_category': ranking[0][0],
|
| 391 |
+
'confidence': round(float(ranking[0][1]), 4),
|
| 392 |
+
'entropy': round(entropy, 4),
|
| 393 |
+
'margin': round(margin, 4),
|
| 394 |
+
'all_probs': {key: round(float(value), 4) for key, value in normalized.items()},
|
| 395 |
+
'category_ranking': [(key, round(float(value), 4)) for key, value in ranking],
|
| 396 |
+
'top_two_classes': [ranking[0][0], ranking[1][0]],
|
| 397 |
+
})
|
| 398 |
+
return adjusted
|
| 399 |
+
|
| 400 |
+
|
| 401 |
+
def _has_explicit_churn_signal(text: str) -> bool:
|
| 402 |
+
return bool(re.search(
|
| 403 |
+
r'\b(?:cancel|cancelling|canceling|switching|switch to|competitor|'
|
| 404 |
+
r'leaving|terminate|churn|not renew|non-renew|renewal risk)\b',
|
| 405 |
+
text,
|
| 406 |
+
flags=re.I,
|
| 407 |
+
))
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
def _apply_probability_guardrails(result: Dict, text: str) -> Dict:
|
| 411 |
+
probs = dict(result.get('all_probs') or {})
|
| 412 |
+
churn_prob = float(probs.get('churn_risk', 0.0))
|
| 413 |
+
|
| 414 |
+
if churn_prob > 0.05 and not _has_explicit_churn_signal(text):
|
| 415 |
+
probs['churn_risk'] = 0.04
|
| 416 |
+
adjusted = _update_result_probabilities(result, probs)
|
| 417 |
+
adjusted['probability_guardrail'] = 'churn_dampened_without_explicit_churn_signal'
|
| 418 |
+
return adjusted
|
| 419 |
+
|
| 420 |
+
return result
|
| 421 |
+
|
| 422 |
+
|
| 423 |
def _apply_direct_signal_overrides(result: Dict, text: str, direct_intents: List[str]) -> Dict:
|
| 424 |
if len(direct_intents) >= 2:
|
| 425 |
return result
|
|
|
|
| 599 |
unique_intents = list(dict.fromkeys(segment_intents or direct_intents))
|
| 600 |
is_multi_intent = len(unique_intents) >= 2
|
| 601 |
result = _apply_direct_signal_overrides(result, clean_text, unique_intents)
|
| 602 |
+
result = _apply_probability_guardrails(result, clean_text)
|
| 603 |
if is_multi_intent:
|
| 604 |
unique_intents = _order_intents_by_probability(unique_intents, result)
|
| 605 |
|