File size: 5,017 Bytes
7c0c809
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import streamlit as st
from typing import Dict
from datetime import datetime
import anthropic
from src.utils.session import get_tutor_context
from src.utils.config import get_anthropic_api_key

class AITutorService:
    def __init__(self):
        self.initialize_client()
        self.load_avatar_assets()

    def initialize_client(self):
        """Initialize Anthropic client"""
        self.client = anthropic.Anthropic(api_key=get_anthropic_api_key())

    def load_avatar_assets(self):
        """Load avatar assets and animations"""
        self.avatar_states = {
            'neutral': """
                <svg width="100" height="100" viewBox="0 0 100 100">
                    <circle cx="50" cy="50" r="45" fill="#4A90E2"/>
                    <circle cx="35" cy="40" r="5" fill="white"/>
                    <circle cx="65" cy="40" r="5" fill="white"/>
                    <path d="M 30 60 Q 50 70 70 60" stroke="white" fill="none" stroke-width="3"/>
                </svg>
            """,
            'thinking': """
                <svg width="100" height="100" viewBox="0 0 100 100">
                    <circle cx="50" cy="50" r="45" fill="#4A90E2"/>
                    <circle cx="35" cy="40" r="5" fill="white"/>
                    <circle cx="65" cy="40" r="5" fill="white"/>
                    <path d="M 30 65 Q 50 65 70 65" stroke="white" fill="none" stroke-width="3"/>
                </svg>
            """,
            'happy': """
                <svg width="100" height="100" viewBox="0 0 100 100">
                    <circle cx="50" cy="50" r="45" fill="#4A90E2"/>
                    <circle cx="35" cy="40" r="5" fill="white"/>
                    <circle cx="65" cy="40" r="5" fill="white"/>
                    <path d="M 30 60 Q 50 80 70 60" stroke="white" fill="none" stroke-width="3"/>
                </svg>
            """
        }

    def display_avatar(self, state: str = 'neutral'):
        """Display the AI tutor avatar"""
        st.markdown(f"""
            <div style="display: flex; justify-content: center; margin: 20px 0;">
                {self.avatar_states.get(state, self.avatar_states['neutral'])}
            </div>
        """, unsafe_allow_html=True)

    def generate_response(self, user_input: str) -> str:
        """Generate contextualized response using Claude"""
        context = get_tutor_context()
        prompt = self.build_prompt(user_input, context)

        # Generate response using Claude
        message = self.client.messages.create(
            model="claude-3-opus-20240229",
            max_tokens=1024,
            temperature=0.7,
            system="You are an expert AI tutor, skilled at explaining complex concepts clearly and engaging students in their learning journey. Provide detailed, accurate explanations while maintaining an encouraging tone.",
            messages=[
                {
                    "role": "user",
                    "content": prompt
                }
            ]
        )
        
        response = message.content[0].text
        
        # Analyze sentiment (Claude can do this as part of its response)
        sentiment_score = 0.8 if any(word in response.lower() for word in ['great', 'excellent', 'good job', 'well done']) else 0.5
        
        # Update engagement metrics
        self.update_engagement_metrics(user_input, response, sentiment_score)
        
        return response

    def build_prompt(self, user_input: str, context: Dict) -> str:
        """Build a context-aware prompt for Claude"""
        topic_context = f"Current topic: {context['current_topic']}\n" if context['current_topic'] else ""
        
        chat_context = "\n".join([
            f"Student: {msg['content']}" if msg['role'] == 'user' else f"Tutor: {msg['content']}"
            for msg in context['chat_history'][-3:]
        ])
        
        return f"""
        You are an educational AI tutor helping a student learn.
        
        {topic_context}
        Difficulty level: {context['difficulty_level']}
        Learning style: {context['learning_style']}
        
        Previous conversation:
        {chat_context}
        
        Student: {user_input}
        
        Provide a clear, helpful response that:
        1. Addresses the student's question directly
        2. Explains concepts in an engaging way
        3. Uses examples when appropriate
        4. Encourages deeper understanding
        5. Maintains a supportive tone

        If the question is about code, include working code examples.
        If the topic is complex, break it down into simpler parts.
        """

    def update_engagement_metrics(self, user_input: str, response: str, sentiment_score: float):
        """Update student engagement metrics"""
        context = get_tutor_context()
        context['engagement_metrics'].append({
            'timestamp': datetime.now().isoformat(),
            'sentiment_score': sentiment_score,
            'interaction_length': len(user_input)
        })