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)