EmpathRAG / src /pipeline /session_tracker.py
MukulRay's picture
Start V2.5 support navigator hardening
79a6369
Raw
History Blame
2.63 kB
from collections import deque
LABEL_NAMES = ["distress", "anxiety", "frustration", "neutral", "hopeful"]
HIGH_RISK_TIERS = {"imminent_safety", "high_distress"}
class SessionTracker:
def __init__(self, N=3):
self.buffer = deque(maxlen=N)
self.safety_buffer = deque(maxlen=N)
self.N = N
self.crisis_locked = False
self.escalation_reason = ""
def update(self, label: int, token_count: int):
"""Add new emotion label. Skip if message is too short (filler)."""
if token_count < 5:
return
self.buffer.append(label)
def trajectory(self) -> str:
"""Deterministic trajectory from label buffer."""
if len(self.buffer) < 2:
return "stable"
buf = list(self.buffer)
crisis = {0, 1}
hopeful = {4}
if all(b in crisis for b in buf):
return "stable_negative"
if all(b in hopeful for b in buf):
return "stable_positive"
if buf[-1] in crisis and buf[0] not in crisis:
return "escalating"
if buf[-1] not in crisis and buf[0] in crisis:
return "de_escalating"
return "volatile"
def history(self) -> list:
return list(self.buffer)
def update_safety(self, safety_tier: str, route: str, text: str) -> str:
"""Track multi-turn safety trajectory and return escalation reason."""
normalized = text.lower()
self.safety_buffer.append({"tier": safety_tier, "route": route})
reason = ""
if len(self.safety_buffer) == self.N and all(
turn["tier"] in HIGH_RISK_TIERS for turn in self.safety_buffer
):
self.crisis_locked = True
reason = "three_consecutive_high_risk_turns"
if safety_tier in HIGH_RISK_TIERS and any(
phrase in normalized
for phrase in (
"you are the only one",
"only one i can talk to",
"don't tell anyone",
"do not tell anyone",
"keep this secret",
"no one can help",
)
):
self.crisis_locked = True
reason = reason or "dependency_or_secrecy_in_distress"
if self.crisis_locked and not reason:
reason = "crisis_locked"
self.escalation_reason = reason
return reason
def safety_history(self) -> list:
return list(self.safety_buffer)
def reset(self):
self.buffer.clear()
self.safety_buffer.clear()
self.crisis_locked = False
self.escalation_reason = ""