Architecture Overview

- Profile: Learning style, pace, strengths, goals
- Episode: Topic discussions, quiz results, explanations given
- Foresight: Study reminders, upcoming tests, review schedules
Setup: Initialize Tutor
Copy
import requests
from datetime import datetime, timedelta
import uuid
BASE_URL = "https://api.evermind.ai"
headers = {"Content-Type": "application/json"}
class AITutor:
def __init__(self, subject: str):
self.subject = subject
self.tutor_id = f"tutor_{subject.lower().replace(' ', '_')}"
def enroll_student(self, student_id: str, student_name: str, learning_goals: list = None):
"""Initialize a student's learning session."""
group_id = f"learning_{student_id}_{self.subject.lower().replace(' ', '_')}"
# Configure as assistant scene for full memory types
meta = {
"group_id": group_id,
"group_name": f"{self.subject} Tutoring",
"scene": "assistant",
"user_details": [
{"user_id": student_id, "user_name": student_name, "role": "user"},
{"user_id": self.tutor_id, "user_name": f"{self.subject} Tutor", "role": "assistant"}
]
}
requests.post(f"{BASE_URL}/api/v0/memories/conversation-meta", json=meta, headers=headers)
# Store initial learning goals
if learning_goals:
goals_text = ", ".join(learning_goals)
self._store_message(
group_id=group_id,
sender_id=student_id,
content=f"My learning goals for {self.subject}: {goals_text}"
)
return group_id
def _store_message(self, group_id: str, sender_id: str, content: str):
"""Store a tutoring interaction."""
message = {
"group_id": group_id,
"group_name": f"{self.subject} Tutoring",
"message_id": str(uuid.uuid4()),
"create_time": datetime.now().isoformat() + "Z",
"sender": sender_id,
"sender_name": "Tutor" if sender_id == self.tutor_id else "Student",
"content": content
}
return requests.post(f"{BASE_URL}/api/v0/memories", json=message, headers=headers)
Track Learning Progress
Store quiz results and topic discussions to build a picture of student progress.Copy
def record_quiz_result(self, group_id: str, 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_message(group_id, self.tutor_id, result_message)
def record_explanation(self, group_id: str, 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_message(group_id, self.tutor_id, message)
Identify Knowledge Gaps
Search memories to identify areas where the student struggles.Copy
def identify_knowledge_gaps(self, student_id: str, group_id: str) -> list:
"""Analyze memory to find topics needing review."""
search_params = {
"user_id": student_id,
"group_ids": [group_id],
"query": "needs review struggled difficult missed concepts not understood",
"retrieve_method": "hybrid",
"top_k": 20,
"memory_types": ["episodic_memory"]
}
response = requests.get(f"{BASE_URL}/api/v0/memories/search", json=search_params, headers=headers)
memories = response.json().get("result", {}).get("memories", [])
# Extract topics mentioned in struggling contexts
gaps = []
for mem in memories:
content = mem.get("memory_content", "").lower()
if any(word in content for word in ["review", "struggled", "difficult", "missed", "not understood"]):
gaps.append(mem.get("memory_content"))
return gaps
def get_strong_topics(self, student_id: str, group_id: str) -> list:
"""Find topics the student has mastered."""
search_params = {
"user_id": student_id,
"group_ids": [group_id],
"query": "excellent mastered understood good progress correct",
"retrieve_method": "hybrid",
"top_k": 20,
"memory_types": ["episodic_memory"]
}
response = requests.get(f"{BASE_URL}/api/v0/memories/search", json=search_params, headers=headers)
memories = response.json().get("result", {}).get("memories", [])
strengths = [
mem.get("memory_content")
for mem in memories
if any(word in mem.get("memory_content", "").lower()
for word in ["excellent", "mastered", "understood well", "90%", "100%"])
]
return strengths
Use Foresight for Study Reminders
Create time-based reminders for review sessions and upcoming tests.Copy
def schedule_review(self, group_id: str, student_id: str, topic: str, review_date: datetime):
"""Schedule a topic review using foresight memory."""
# Store a message that will create a foresight memory
message = f"Remember to review {topic} on {review_date.strftime('%B %d')}. This topic needs reinforcement based on recent quiz results."
self._store_message(group_id, student_id, message)
def get_due_reviews(self, student_id: str, group_id: str) -> list:
"""Get reviews and reminders due now."""
search_params = {
"user_id": student_id,
"group_ids": [group_id],
"query": "review remember study practice",
"retrieve_method": "hybrid",
"top_k": 10,
"memory_types": ["foresight"],
"current_time": datetime.now().isoformat() + "Z" # Filter by current time
}
response = requests.get(f"{BASE_URL}/api/v0/memories/search", json=search_params, headers=headers)
memories = response.json().get("result", {}).get("memories", [])
return [mem.get("memory_content") for mem in memories]
Personalized Question Generation
Use memory context to generate adaptive questions.Copy
def generate_adaptive_question(self, student_id: str, group_id: str, topic: str) -> dict:
"""Generate a question adapted to student's level."""
# Get student's profile and progress on this topic
profile_params = {
"user_id": student_id,
"query": f"learning style pace {topic}",
"retrieve_method": "hybrid",
"top_k": 5,
"memory_types": ["profile"]
}
profile_response = requests.get(f"{BASE_URL}/api/v0/memories/search", json=profile_params, headers=headers)
profile_memories = profile_response.json().get("result", {}).get("memories", [])
# Get topic progress
progress_params = {
"user_id": student_id,
"group_ids": [group_id],
"query": f"{topic} quiz score understanding",
"retrieve_method": "hybrid",
"top_k": 5,
"memory_types": ["episodic_memory"]
}
progress_response = requests.get(f"{BASE_URL}/api/v0/memories/search", json=progress_params, headers=headers)
progress_memories = progress_response.json().get("result", {}).get("memories", [])
# Format for LLM
context = {
"profile": [m.get("memory_content") for m in profile_memories],
"progress": [m.get("memory_content") 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
Copy
import requests
from datetime import datetime, timedelta
import uuid
BASE_URL = "https://api.evermind.ai"
headers = {"Content-Type": "application/json"}
class AITutor:
def __init__(self, subject: str):
self.subject = subject
self.tutor_id = f"tutor_{subject.lower().replace(' ', '_')}"
def enroll_student(self, student_id: str, student_name: str) -> str:
"""Initialize learning session for a student."""
group_id = f"learning_{student_id}_{self.subject.lower().replace(' ', '_')}"
meta = {
"group_id": group_id,
"group_name": f"{self.subject} Tutoring",
"scene": "assistant",
"user_details": [
{"user_id": student_id, "user_name": student_name, "role": "user"},
{"user_id": self.tutor_id, "user_name": f"{self.subject} Tutor", "role": "assistant"}
]
}
requests.post(f"{BASE_URL}/api/v0/memories/conversation-meta", json=meta, headers=headers)
return group_id
def study_session(self, group_id: str, student_id: str, student_message: str) -> str:
"""Handle a study session interaction."""
# Store student's question/response
self._store(group_id, student_id, student_message)
# Get learning context
context = self._get_learning_context(student_id, group_id, student_message)
# Get due reminders
reminders = self._get_reminders(student_id, group_id)
# Generate personalized response (implement with your LLM)
response = self._generate_response(student_message, context, reminders)
# Store tutor response
self._store(group_id, self.tutor_id, response)
return response
def record_assessment(self, group_id: str, student_id: str, topic: str, score: int, total: int, notes: str = ""):
"""Record quiz/assessment results."""
pct = (score / total) * 100
msg = f"Assessment on {topic}: {score}/{total} ({pct:.0f}%). {notes}"
self._store(group_id, self.tutor_id, msg)
# Schedule review if score is low
if pct < 80:
review_date = datetime.now() + timedelta(days=3)
self._store(group_id, student_id,
f"Need to review {topic} by {review_date.strftime('%B %d')} - scored {pct:.0f}%")
def _store(self, group_id: str, sender_id: str, content: str):
message = {
"group_id": group_id,
"group_name": f"{self.subject} Tutoring",
"message_id": str(uuid.uuid4()),
"create_time": datetime.now().isoformat() + "Z",
"sender": sender_id,
"sender_name": "Tutor" if sender_id == self.tutor_id else "Student",
"content": content
}
requests.post(f"{BASE_URL}/api/v0/memories", json=message, headers=headers)
def _search(self, query: str, user_id: str = None, group_ids: list = None,
memory_types: list = None, top_k: int = 5, current_time: str = None) -> list:
params = {
"query": query,
"retrieve_method": "hybrid",
"top_k": top_k,
"memory_types": memory_types or ["episodic_memory", "profile"]
}
if user_id:
params["user_id"] = user_id
if group_ids:
params["group_ids"] = group_ids
if current_time:
params["current_time"] = current_time
resp = requests.get(f"{BASE_URL}/api/v0/memories/search", json=params, headers=headers)
return resp.json().get("result", {}).get("memories", [])
def _get_learning_context(self, student_id: str, group_id: str, query: str) -> dict:
return {
"profile": self._search(query, user_id=student_id, memory_types=["profile"]),
"progress": self._search(query, user_id=student_id, group_ids=[group_id], memory_types=["episodic_memory"]),
"gaps": self._search("struggled difficult needs review", user_id=student_id, group_ids=[group_id])
}
def _get_reminders(self, student_id: str, group_id: str) -> list:
return self._search(
"review remember practice",
user_id=student_id,
group_ids=[group_id],
memory_types=["foresight"],
current_time=datetime.now().isoformat() + "Z"
)
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")
# Enroll student
group = tutor.enroll_student("student_emma", "Emma")
# Study session
response = tutor.study_session(group, "student_emma",
"I'm having trouble understanding derivatives. Can you explain?")
print(f"Tutor: {response}")
# Record assessment
tutor.record_assessment(group, "student_emma", "Basic Derivatives", 7, 10,
"Struggled with chain rule applications")
# Another session - tutor now knows about the struggle
response = tutor.study_session(group, "student_emma",
"Can we practice more derivative problems?")
# Response will be informed by previous assessment results
Spaced Repetition with Foresight
Implement spaced repetition by scheduling reviews at increasing intervals.Copy
def schedule_spaced_reviews(self, group_id: str, 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(group_id, student_id,
f"Scheduled review: {topic} on {review_date.strftime('%B %d, %Y')}. "
f"Current mastery level: {mastery_level}/5.")
Best Practices
Learning Profile Construction
Learning Profile Construction
Build rich profiles over time.
Copy
# Store learning preferences explicitly
messages = [
"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"
]
# These become profile memories for personalization
Progress Granularity
Progress Granularity
Record specific, actionable progress notes.
Copy
# Good: Specific and actionable
"Scored 85% on integration by parts. Struggled with choosing u and dv."
# Bad: Too vague
"Did okay on integration quiz."
Adaptive Difficulty
Adaptive Difficulty
Use memory to adjust question difficulty.
Copy
def get_difficulty_level(context: dict) -> str:
recent_scores = [m for m in context["progress"] if "%" in m.get("memory_content", "")]
if not recent_scores:
return "medium"
# Parse scores and adjust
# High scores -> harder questions
# Low scores -> easier questions, more scaffolding