learnbee_mcp / src /learnbee /session_state.py
AlexFocus's picture
added gamification and evolution
e468c5f
"""Session state management for tracking child interactions and adaptive personalization."""
from dataclasses import dataclass, field
from typing import List, Dict
@dataclass
class SessionState:
"""Tracks the state of a learning session for adaptive personalization."""
# Interaction tracking
total_messages: int = 0
correct_answers: int = 0
incorrect_answers: int = 0
questions_asked_by_child: int = 0
# Engagement metrics
short_responses: int = 0 # 1-5 words
detailed_responses: int = 0 # 6+ words
emoji_count: int = 0
exclamation_count: int = 0
# Adaptive difficulty
current_difficulty_adjustment: str = "neutral" # "easier", "neutral", "harder"
# Topics explored
topics_discussed: List[str] = field(default_factory=list)
# Gamification (will be used by GamificationTracker)
stars_earned: int = 0
badges_unlocked: List[str] = field(default_factory=list)
def analyze_message(self, message: str) -> Dict[str, any]:
"""
Analyze a child's message to extract engagement and comprehension signals.
Args:
message: The child's message
Returns:
Dictionary with analysis results
"""
self.total_messages += 1
# Count words
words = message.split()
word_count = len(words)
# Track response length
if word_count <= 5:
self.short_responses += 1
else:
self.detailed_responses += 1
# Count engagement markers
emoji_count = sum(1 for char in message if ord(char) > 127000) # Simple emoji detection
exclamation_count = message.count('!')
question_count = message.count('?')
self.emoji_count += emoji_count
self.exclamation_count += exclamation_count
if question_count > 0:
self.questions_asked_by_child += 1
# Calculate engagement level
engagement_score = 0
if word_count > 5:
engagement_score += 2
if emoji_count > 0:
engagement_score += 1
if exclamation_count > 0:
engagement_score += 1
if question_count > 0:
engagement_score += 2
engagement_level = "low" if engagement_score < 2 else "medium" if engagement_score < 4 else "high"
return {
"word_count": word_count,
"engagement_level": engagement_level,
"has_question": question_count > 0,
"has_emoji": emoji_count > 0,
"has_exclamation": exclamation_count > 0
}
def record_answer_quality(self, is_correct: bool):
"""
Record whether the child's answer was correct.
Args:
is_correct: True if answer was correct, False otherwise
"""
if is_correct:
self.correct_answers += 1
else:
self.incorrect_answers += 1
# Update difficulty adjustment based on success rate
total_answers = self.correct_answers + self.incorrect_answers
if total_answers >= 3: # Need at least 3 answers to adjust
success_rate = self.correct_answers / total_answers
if success_rate < 0.4:
self.current_difficulty_adjustment = "easier"
elif success_rate > 0.8:
self.current_difficulty_adjustment = "harder"
else:
self.current_difficulty_adjustment = "neutral"
def get_adaptive_context(self) -> str:
"""
Generate adaptive context string for the system prompt.
Returns:
String with adaptive instructions based on session state
"""
context_parts = []
# Difficulty adjustment
if self.current_difficulty_adjustment == "easier":
context_parts.append(
"ADAPTIVE INSTRUCTION: The child is struggling. Simplify your language, "
"break problems into smaller steps, and provide more hints and encouragement."
)
elif self.current_difficulty_adjustment == "harder":
context_parts.append(
"ADAPTIVE INSTRUCTION: The child is excelling! Increase the challenge, "
"ask deeper questions, and introduce more complex concepts."
)
# Engagement adjustment
if self.total_messages >= 3:
engagement_ratio = self.detailed_responses / max(self.total_messages, 1)
if engagement_ratio < 0.3:
context_parts.append(
"ENGAGEMENT NOTE: The child is giving short responses. Make your questions "
"more exciting, use more of your character's personality, and relate to their interests."
)
elif engagement_ratio > 0.7:
context_parts.append(
"ENGAGEMENT NOTE: The child is highly engaged with detailed responses! "
"Match their energy and enthusiasm. Present bonus challenges and celebrate their curiosity."
)
# Question-asking behavior
if self.questions_asked_by_child >= 2:
context_parts.append(
"CURIOSITY NOTE: The child is asking great questions! Encourage this curiosity "
"and turn their questions into exciting learning opportunities."
)
return "\n".join(context_parts) if context_parts else ""
def get_session_summary(self) -> Dict[str, any]:
"""
Get a summary of the current session state.
Returns:
Dictionary with session statistics
"""
total_answers = self.correct_answers + self.incorrect_answers
success_rate = (self.correct_answers / total_answers * 100) if total_answers > 0 else 0
return {
"total_messages": self.total_messages,
"correct_answers": self.correct_answers,
"incorrect_answers": self.incorrect_answers,
"success_rate": success_rate,
"questions_asked": self.questions_asked_by_child,
"stars_earned": self.stars_earned,
"badges_unlocked": len(self.badges_unlocked),
"difficulty_adjustment": self.current_difficulty_adjustment
}