> ## Documentation Index
> Fetch the complete documentation index at: https://docs.evermind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Tutor

> Build a personalized learning assistant that tracks progress and adapts

Build an AI tutor that remembers student progress, identifies knowledge gaps, and personalizes the learning experience. EverOS enables long-term memory that persists across study sessions.

## Architecture Overview

<img src="https://mintcdn.com/evermind/EtihzpTKZLqMUxY7/images/ai-tutor.png?fit=max&auto=format&n=EtihzpTKZLqMUxY7&q=85&s=60f5015830d2d2671495ea07150a44e8" alt="AI Tutor Architecture" width="1194" height="654" data-path="images/ai-tutor.png" />

Memory types for tutoring:

* **Profile**: Learning style, pace, strengths, goals
* **Episodic Memory**: Topic discussions, quiz results, explanations given

## Setup: Initialize Tutor

Install the EverOS SDK:

```bash theme={null}
pip install everos-cloud
```

```python theme={null}
from everos_cloud import EverOS
import time

client = EverOS()
memories = client.v1.memories

class AITutor:
    def __init__(self, subject: str):
        self.subject = subject

    def store_interaction(self, student_id: str, student_message: str, tutor_response: str):
        """Store a tutoring interaction."""
        now = int(time.time() * 1000)
        memories.add(
            user_id=student_id,
            messages=[
                {"role": "user", "timestamp": now, "content": student_message},
                {"role": "assistant", "timestamp": now + 1000, "content": tutor_response},
            ],
        )

    def store_student_message(self, student_id: str, content: str):
        """Store a student's message (e.g., learning goals)."""
        memories.add(
            user_id=student_id,
            messages=[
                {"role": "user", "timestamp": int(time.time() * 1000), "content": content},
            ],
        )

    def set_learning_goals(self, student_id: str, learning_goals: list):
        """Record a student's learning goals."""
        goals_text = ", ".join(learning_goals)
        self.store_student_message(
            student_id=student_id,
            content=f"My learning goals for {self.subject}: {goals_text}",
        )
```

## Track Learning Progress

Store quiz results and topic discussions to build a picture of student progress.

```python theme={null}
def record_quiz_result(self, student_id: str, topic: str, score: int, max_score: int, missed_concepts: list = None):
    """Record a quiz or assessment result."""
    percentage = (score / max_score) * 100

    result_message = f"Quiz completed on {topic}. Score: {score}/{max_score} ({percentage:.0f}%)."

    if missed_concepts:
        result_message += f" Concepts to review: {', '.join(missed_concepts)}."

    if percentage >= 90:
        result_message += " Excellent understanding demonstrated."
    elif percentage >= 70:
        result_message += " Good progress, some areas need reinforcement."
    else:
        result_message += " This topic needs more practice."

    self.store_interaction(student_id, f"I just finished the {topic} quiz.", result_message)

def record_explanation(self, student_id: str, topic: str, difficulty_level: str, understood: bool):
    """Record when a concept is explained."""
    status = "understood" if understood else "needs more explanation"

    message = f"Explained {topic} at {difficulty_level} level. Student {status}."

    if not understood:
        message += " Will revisit with different approach."

    self.store_interaction(
        student_id,
        f"Can you explain {topic} at a {difficulty_level} level?",
        message,
    )
```

## Identify Knowledge Gaps

Search memories to identify areas where the student struggles.

```python theme={null}
def identify_knowledge_gaps(self, student_id: str) -> list:
    """Analyze memory to find topics needing review."""
    resp = memories.search(
        filters={"user_id": student_id},
        query="needs review struggled difficult missed concepts not understood",
        method="vector",
        memory_types=["episodic_memory"],
        top_k=20,
    )
    results = resp.get("results", [])

    # Extract topics mentioned in struggling contexts
    gaps = []
    for mem in results:
        content = mem.get("memory", "").lower()
        if any(word in content for word in ["review", "struggled", "difficult", "missed", "not understood"]):
            gaps.append(mem.get("memory"))

    return gaps

def get_strong_topics(self, student_id: str) -> list:
    """Find topics the student has mastered."""
    resp = memories.search(
        filters={"user_id": student_id},
        query="excellent mastered understood good progress correct",
        method="vector",
        memory_types=["episodic_memory"],
        top_k=20,
    )
    results = resp.get("results", [])

    strengths = [
        mem.get("memory")
        for mem in results
        if any(word in mem.get("memory", "").lower()
               for word in ["excellent", "mastered", "understood well", "90%", "100%"])
    ]

    return strengths
```

## Schedule Reviews with Episodic Memory

Store review reminders as part of the tutoring conversation. Search for them later to surface due reviews.

```python theme={null}
def schedule_review(self, student_id: str, topic: str, review_date_str: str):
    """Schedule a topic review by storing it as an episodic memory."""
    self.store_interaction(
        student_id,
        f"When should I review {topic}?",
        f"You should review {topic} on {review_date_str}. This topic needs reinforcement based on recent quiz results.",
    )

def get_due_reviews(self, student_id: str) -> list:
    """Search for stored review reminders."""
    resp = memories.search(
        filters={"user_id": student_id},
        query="review remember study practice scheduled review",
        method="vector",
        memory_types=["episodic_memory"],
        top_k=10,
    )
    return [mem.get("memory") for mem in resp.get("results", [])]
```

## Personalized Question Generation

Use memory context to generate adaptive questions.

```python theme={null}
def generate_adaptive_question(self, student_id: str, topic: str) -> dict:
    """Generate a question adapted to student's level."""

    # Get student's profile and learning style
    profile_resp = memories.search(
        filters={"user_id": student_id},
        query=f"learning style pace {topic}",
        method="vector",
        memory_types=["profile"],
        top_k=5,
    )
    profile_memories = profile_resp.get("results", [])

    # Get topic progress
    progress_resp = memories.search(
        filters={"user_id": student_id},
        query=f"{topic} quiz score understanding",
        method="vector",
        memory_types=["episodic_memory"],
        top_k=5,
    )
    progress_memories = progress_resp.get("results", [])

    # Format for LLM
    context = {
        "profile": [m.get("memory") for m in profile_memories],
        "progress": [m.get("memory") for m in progress_memories],
        "topic": topic,
    }

    # Generate question with LLM (placeholder)
    return {
        "context": context,
        "prompt": f"Generate a {topic} question appropriate for this student's level",
    }
```

## Complete AI Tutor Implementation

```python theme={null}
from everos_cloud import EverOS
import time
from datetime import datetime, timedelta

client = EverOS()
memories = client.v1.memories

class AITutor:
    def __init__(self, subject: str):
        self.subject = subject

    def _store(self, student_id: str, student_msg: str, tutor_msg: str):
        """Store a tutoring exchange."""
        now = int(time.time() * 1000)
        memories.add(
            user_id=student_id,
            messages=[
                {"role": "user", "timestamp": now, "content": student_msg},
                {"role": "assistant", "timestamp": now + 1000, "content": tutor_msg},
            ],
        )

    def _search(self, student_id: str, query: str,
                memory_types: list = None, top_k: int = 5) -> list:
        """Search student memories."""
        resp = memories.search(
            filters={"user_id": student_id},
            query=query,
            method="vector",
            memory_types=memory_types or ["episodic_memory", "profile"],
            top_k=top_k,
        )
        return resp.get("results", [])

    def study_session(self, student_id: str, student_message: str) -> str:
        """Handle a study session interaction."""
        # Get learning context
        context = self._get_learning_context(student_id, student_message)

        # Get due reminders
        reminders = self._get_reminders(student_id)

        # Generate personalized response (implement with your LLM)
        response = self._generate_response(student_message, context, reminders)

        # Store the full exchange
        self._store(student_id, student_message, response)

        return response

    def record_assessment(self, student_id: str, topic: str, score: int, total: int, notes: str = ""):
        """Record quiz/assessment results."""
        pct = (score / total) * 100
        tutor_msg = f"Assessment on {topic}: {score}/{total} ({pct:.0f}%). {notes}"
        self._store(student_id, f"I just completed the {topic} assessment.", tutor_msg)

        # Schedule review if score is low
        if pct < 80:
            review_date = datetime.now() + timedelta(days=3)
            self._store(
                student_id,
                f"When should I review {topic}?",
                f"You should review {topic} by {review_date.strftime('%B %d')} - you scored {pct:.0f}%.",
            )

    def _get_learning_context(self, student_id: str, query: str) -> dict:
        return {
            "profile": self._search(student_id, query, memory_types=["profile"]),
            "progress": self._search(student_id, query, memory_types=["episodic_memory"]),
            "gaps": self._search(student_id, "struggled difficult needs review"),
        }

    def _get_reminders(self, student_id: str) -> list:
        return self._search(
            student_id,
            "review remember practice scheduled",
            memory_types=["episodic_memory"],
        )

    def _generate_response(self, message: str, context: dict, reminders: list) -> str:
        # Implement with your LLM
        return f"[Tutor response based on {len(context['progress'])} progress memories]"


# Usage Example
tutor = AITutor("Calculus")

# Set learning goals
memories.add(
    user_id="student_emma",
    messages=[
        {"role": "user", "timestamp": int(time.time() * 1000), "content": "My learning goals for Calculus: pass the AP exam, understand derivatives and integrals"},
    ],
)

# Study session
response = tutor.study_session("student_emma",
    "I'm having trouble understanding derivatives. Can you explain?")
print(f"Tutor: {response}")

# Record assessment
tutor.record_assessment("student_emma", "Basic Derivatives", 7, 10,
    "Struggled with chain rule applications")

# Another session - tutor now knows about the struggle
response = tutor.study_session("student_emma",
    "Can we practice more derivative problems?")
# Response will be informed by previous assessment results
```

## Spaced Repetition with Episodic Memory

Implement spaced repetition by storing review schedules as episodic memories and searching for them when needed.

```python theme={null}
def schedule_spaced_reviews(self, student_id: str, topic: str, mastery_level: int):
    """Schedule reviews using spaced repetition intervals."""
    # Intervals based on mastery (1 = new, 5 = mastered)
    intervals = {
        1: [1, 3, 7],      # New: review in 1, 3, 7 days
        2: [3, 7, 14],     # Learning: 3, 7, 14 days
        3: [7, 14, 30],    # Familiar: 7, 14, 30 days
        4: [14, 30, 60],   # Good: 14, 30, 60 days
        5: [30, 90],       # Mastered: 30, 90 days
    }

    review_days = intervals.get(mastery_level, [7, 14, 30])

    for days in review_days:
        review_date = datetime.now() + timedelta(days=days)
        self._store(
            student_id,
            f"Schedule my next review for {topic}.",
            f"Scheduled review: {topic} on {review_date.strftime('%B %d, %Y')}. "
            f"Current mastery level: {mastery_level}/5.",
        )
```

## Best Practices

<AccordionGroup>
  <Accordion title="Learning Profile Construction">
    Build rich profiles over time. Store learning preferences as messages so EverOS extracts them into profile memories.

    ```python theme={null}
    # Store learning preferences - EverOS extracts these into profile memories
    preferences = [
        "I learn better with visual examples",
        "I prefer to practice problems before theory",
        "I usually study in the evenings",
        "My goal is to pass the AP Calculus exam",
    ]

    for pref in preferences:
        memories.add(
            user_id="student_emma",
            messages=[
                {"role": "user", "timestamp": int(time.time() * 1000), "content": pref},
            ],
        )
    ```
  </Accordion>

  <Accordion title="Progress Granularity">
    Record specific, actionable progress notes.

    ```python theme={null}
    # Good: Specific and actionable
    "Scored 85% on integration by parts. Struggled with choosing u and dv."

    # Bad: Too vague
    "Did okay on integration quiz."
    ```
  </Accordion>

  <Accordion title="Adaptive Difficulty">
    Use memory to adjust question difficulty.

    ```python theme={null}
    def get_difficulty_level(context: dict) -> str:
        recent_scores = [m for m in context["progress"] if "%" in m.get("memory", "")]
        if not recent_scores:
            return "medium"

        # Parse scores and adjust
        # High scores -> harder questions
        # Low scores -> easier questions, more scaffolding
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Memory Types" icon="brain" href="/cloud/concepts/memcell">
    Learn about MemCell and how profile and episodic memories work
  </Card>

  <Card title="Python Integration" icon="python" href="/cookbook/python-integration">
    Production patterns for tutoring applications
  </Card>
</CardGroup>
