Spaces:
Sleeping
Sleeping
| def normalize_emotional_state(persona): | |
| """Extract and normalize emotional state from the new persona structure.""" | |
| default = { | |
| "anxiety": 0.5, | |
| "trust": 0.5, | |
| "openness": 0.5, | |
| "mode": "baseline", | |
| "emotional_memory": [] | |
| } | |
| return persona.get("default_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["default_state"] = state | |
| return persona | |
| def get_current_mode(state): | |
| """Determine the client's current emotional mode based on emotional state values.""" | |
| anxiety = state.get("anxiety", 0.5) | |
| trust = state.get("trust", 0.5) | |
| openness = state.get("openness", 0.5) | |
| # Raised thresholds significantly to prevent premature crisis states | |
| if anxiety > 0.85: # Was 0.8 - now much harder to reach decompensating | |
| return "decompensating" | |
| if anxiety > 0.75 and trust < 0.25: # Was 0.6 and 0.3 - much higher bar for triggered | |
| return "triggered" | |
| if openness < 0.3 and trust < 0.4: # Was 0.4 and 0.5 - harder to be guarded | |
| return "guarded" | |
| if trust > 0.7 and openness > 0.7: # Was 0.6 - higher bar for trusting too | |
| return "trusting" | |
| if anxiety < 0.3 and openness > 0.6: # Was 0.4 and 0.5 - adjusted | |
| 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) | |
| # Reduced magnitude significantly - was causing too-fast emotional escalation | |
| positive_impact = (validation_score * 0.02 + open_q_score * 0.015 + empathy_score * 0.01) # Was 0.05, 0.04, 0.03 | |
| negative_impact = (advice_score * 0.03 + minimizing_score * 0.025) # Was 0.08, 0.06 | |
| changes = { | |
| "trust": positive_impact * 0.5 - negative_impact * 0.3, # Was 0.8 and 0.5 - reduced multipliers | |
| "anxiety": negative_impact * 0.3 - positive_impact * 0.2, # Was 0.5 and 0.3 - reduced | |
| "openness": positive_impact * 0.3 - negative_impact * 0.15 # Was 0.4 and 0.2 - reduced | |
| } | |
| word_count = len(student_response.split()) | |
| if word_count < 5: | |
| changes["trust"] -= 0.02 # Was 0.05 - reduced | |
| elif word_count > 100: | |
| changes["anxiety"] += 0.02 # Was 0.05 - reduced | |
| 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, persona=None): | |
| """Generate pedagogical feedback based on the literary interaction.""" | |
| response_lower = student_response.lower() | |
| notes = [] | |
| # Get character-specific context if available | |
| char_name = persona.get("persona_name", "the character") if persona else "the character" | |
| source_text = persona.get("source_text", {}) if persona else {} | |
| author = source_text.get("author", "the author") | |
| title = source_text.get("title", "the text") | |
| # Question quality - literary analysis focused | |
| if any(word in response_lower for word in ["why did you", "why do you", "why are you"]): | |
| notes.append("π <strong style='color: #2d3748;'>Literary Technique</strong>: 'Why' questions can sound accusatory. Consider using 'what' or 'how' to explore motivations more naturally (e.g., 'What were you thinking when...' or 'How did that moment feel?')") | |
| if any(word in response_lower for word in ["should", "need to", "have to"]): | |
| notes.append("π <strong style='color: #2d3748;'>Character Analysis Tip</strong>: Avoid directive language like 'should' - it judges the character. Instead, explore their perspective: 'What other choices did you consider?' This reveals internal conflict.") | |
| if response_lower.count("?") > 2: | |
| notes.append("π― <strong style='color: #2d3748;'>Focus Your Inquiry</strong>: Multiple questions can overwhelm. Pick your most important question for deeper exploration of theme, motivation, or symbolism.") | |
| # Question depth - connect to literary concepts | |
| if len(student_response.split()) < 8: | |
| if author and title: | |
| notes.append(f"π <strong style='color: #2d3748;'>Add Textual Context</strong>: Reference specific moments from '{title}' to ground your question. Connect to scenes, relationships, or conflicts from {author}'s narrative.") | |
| else: | |
| notes.append("π <strong style='color: #2d3748;'>Add Textual Context</strong>: Reference specific moments from the story to ground your question in the character's actual experiences.") | |
| if any(phrase in response_lower for phrase in ["tell me about", "tell me more", "what's that like", "how do you feel"]): | |
| notes.append("β <strong style='color: #2d3748;'>Strong Question</strong>: Open-ended questions like this encourage the character to reveal subtext, internal conflict, and thematic depth. This is effective literary analysis.") | |
| if any(word in response_lower for word in ["symbol", "represent", "meaning", "theme"]): | |
| notes.append("π <strong style='color: #2d3748;'>Excellent</strong>: You're connecting character experience to broader literary themes. This kind of analysis reveals how authors use character to explore universal ideas.") | |
| # Character engagement - literary context | |
| if mode == "triggered" and state.get("trust", 0) < 0.4: | |
| if author: | |
| notes.append(f"β οΈ <strong style='color: #2d3748;'>Character Defensive</strong>: Notice how {char_name} withdraws when challenged - this mirrors how {author} shows psychological realism. Try questions that validate their experience first.") | |
| else: | |
| notes.append("β οΈ <strong style='color: #2d3748;'>Character Defensive</strong>: The character is withdrawing. Try questions that validate their experience before probing deeper.") | |
| if mode == "trusting" and state.get("anxiety", 0) > 0.6: | |
| notes.append("β¨ <strong style='color: #2d3748;'>Key Moment</strong>: The character is vulnerable right now - this is where authors reveal crucial backstory and motivation. Press deeper into their fears and desires.") | |
| if mode == "decompensating": | |
| notes.append("π <strong style='color: #2d3748;'>Character State</strong>: The character is emotionally overwhelmed. In literary analysis, these breaking points often reveal theme. Consider: What does this breakdown tell us about the story's larger meaning?") | |
| if mode == "recovering": | |
| notes.append("π <strong style='color: #2d3748;'>Reflection Point</strong>: The character is stabilizing. Good time to ask: 'What have you learned?' or 'How have you changed?' - this reveals character development.") | |
| # Add literary context based on specific terms used | |
| if any(word in response_lower for word in ["choice", "decision", "decide"]): | |
| notes.append("π‘ <strong style='color: #2d3748;'>Theme Connection</strong>: You're exploring agency and choice - a key theme in literature. How does paralysis or action define this character?") | |
| if any(word in response_lower for word in ["family", "mother", "father", "parent", "sister", "brother"]): | |
| notes.append("π¨βπ©βπ§ <strong style='color: #2d3748;'>Family Dynamics</strong>: You're examining how family obligations shape identity - analyze how the author uses familial duty to explore broader social constraints.") | |
| if not notes: | |
| notes.append("β <strong style='color: #2d3748;'>Good Engagement</strong>: You're exploring the character thoughtfully. Consider connecting their responses to the story's central themes and conflicts.") | |
| # Join notes with proper line breaks for HTML rendering | |
| return "<br><br>".join(notes) |