jmisak's picture
Update engine/drift.py
6f393d2 verified
def normalize_emotional_state(persona):
"""Extract and normalize emotional state from the new persona structure."""
default = {
"emotional_tension": 0.0,
"relational_openness": 0.0,
"narrative_fluidity": 0.0,
"guilt": 0.0,
"mode": "baseline"
}
return persona.get("emotional_state", default).copy()
def apply_context_shift(persona, scenario):
"""Apply contextual scenario effects to persona's current emotional state."""
state = normalize_emotional_state(persona)
effects = scenario.get("effects", {})
for key, change in effects.items():
if key in state and isinstance(state[key], (int, float)):
current_value = state[key]
new_value = current_value + change
state[key] = max(0.0, min(1.0, round(new_value, 3)))
persona["emotional_state"] = state
return persona
def get_current_mode(state):
"""Determine the client's current emotional mode based on emotional state values."""
tension = state.get("emotional_tension", 0.5)
openness = state.get("relational_openness", 0.5)
fluidity = state.get("narrative_fluidity", 0.5)
if tension > 0.8:
return "crisis"
if tension > 0.6 and openness < 0.3:
return "defensive"
if fluidity < 0.4 and openness < 0.5:
return "guarded"
if openness > 0.6 and fluidity > 0.6:
return "vulnerable"
if tension < 0.4 and fluidity > 0.5:
return "recovering"
return state.get("mode", "baseline")
def calculate_state_change(state, student_response):
"""Calculate how the student's response affects the client's emotional state."""
if hasattr(student_response, 'value'):
student_response = student_response.value
student_response = str(student_response) if student_response is not None else ""
response_lower = student_response.lower()
validating_words = ["understand", "sounds like", "seems", "feel", "must be", "makes sense"]
open_questions = ["tell me more", "what's that like", "how", "what"]
empathy_phrases = ["hard", "difficult", "challenging", "tough"]
advice_words = ["should", "need to", "have to", "must", "why don't you"]
minimizing = ["just", "simply", "easy", "only", "at least"]
validation_score = sum(1 for word in validating_words if word in response_lower)
open_q_score = sum(1 for phrase in open_questions if phrase in response_lower)
empathy_score = sum(1 for phrase in empathy_phrases if phrase in response_lower)
advice_score = sum(1 for word in advice_words if word in response_lower)
minimizing_score = sum(1 for word in minimizing if word in response_lower)
positive_impact = (validation_score * 0.05 + open_q_score * 0.04 + empathy_score * 0.03)
negative_impact = (advice_score * 0.08 + minimizing_score * 0.06)
changes = {
"relational_openness": positive_impact * 0.8 - negative_impact * 0.5,
"emotional_tension": negative_impact * 0.5 - positive_impact * 0.3,
"narrative_fluidity": positive_impact * 0.4 - negative_impact * 0.2,
"guilt": empathy_score * 0.05 if "guilt" in response_lower else 0.0
}
word_count = len(student_response.split())
if word_count < 5:
changes["relational_openness"] -= 0.05
elif word_count > 100:
changes["emotional_tension"] += 0.05
return changes
def apply_response_effects(state, student_response):
"""Apply the effects of the student's response to the client's emotional state."""
changes = calculate_state_change(state, student_response)
for key, change in changes.items():
if key in state and isinstance(state[key], (int, float)):
current_value = state[key]
new_value = current_value + change
state[key] = max(0.0, min(1.0, round(new_value, 3)))
return state
def generate_teaching_note(state, student_response, mode):
"""Generate teaching feedback based on the interaction."""
response_lower = student_response.lower()
notes = []
if any(word in response_lower for word in ["should", "need to", "have to"]):
notes.append("⚠️ Advice-giving detected. Consider asking open questions instead of giving directives.")
if any(word in response_lower for word in ["just", "simply", "only"]):
notes.append("⚠️ Potential minimizing language. Avoid words that might diminish the client's experience.")
if response_lower.count("?") > 2:
notes.append("⚠️ Multiple questions detected. Consider asking one question at a time to avoid overwhelming the client.")
if len(student_response.split()) < 10:
notes.append("💡 Very brief response. Consider adding validation or reflection before asking questions.")
if any(phrase in response_lower for phrase in ["sounds like", "seems", "hear you"]):
notes.append("✅ Good use of reflection and validation.")
if "tell me more" in response_lower or "what's that like" in response_lower:
notes.append("✅ Effective use of open-ended questions.")
if mode == "defensive" and state.get("relational_openness", 0) < 0.4:
notes.append("📊 Client is emotionally guarded. Consider using reflection or shared experience.")
if mode == "vulnerable" and state.get("emotional_tension", 0) > 0.6:
notes.append("📊 Client is opening up under emotional strain. Proceed with care.")
if mode == "crisis":
notes.append("🚨 Client may be emotionally overwhelmed. Consider grounding or referral.")
if not notes:
notes.append("✅ Solid therapeutic response. Continue building rapport.")
return "\n".join(notes)