Skip to main content

Study Buddy with Hindsight Memory

Run this notebook

This recipe is available as an interactive Jupyter notebook. Open in GitHub →

A personalized study assistant that tracks what you've learned, identifies knowledge gaps, and helps with spaced repetition.

Features

  • Tracks study sessions and topics covered
  • Monitors confidence levels per topic
  • Identifies knowledge gaps
  • Suggests topics for spaced repetition review

Prerequisites

  • OpenAI API key
  • Hindsight running locally via Docker (see setup below)

Start Hindsight Locally

Before running this notebook, start Hindsight in a terminal:

export OPENAI_API_KEY="your-openai-api-key"

docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest

1. Install Dependencies

!pip install -q hindsight-client openai nest-asyncio

2. Configure OpenAI API Key

Enter your OpenAI API key when prompted (used by both Hindsight and the demo).

import getpass
import os

# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")

print("API key configured!")

3. Initialize Clients

import nest_asyncio
nest_asyncio.apply()

from datetime import datetime
from openai import OpenAI
from hindsight_client import Hindsight

# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)

openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

USER_ID = "student-demo"

print("Clients initialized!")

4. Define Helper Functions

def record_study_session(topic: str, notes: str, confidence: str = "medium") -> str:
"""Record a study session with topic, notes, and self-assessed confidence."""
today = datetime.now().strftime("%B %d, %Y")

content = f"""{today} - STUDY SESSION
Topic: {topic}
Confidence Level: {confidence}
Notes: {notes}"""

hindsight.retain(
bank_id=USER_ID,
content=content,
metadata={
"category": "study_session",
"topic": topic,
"confidence": confidence,
"date": today,
},
)

return f"Recorded study session on '{topic}' (confidence: {confidence})"


def record_question(topic: str, question: str, understood: bool) -> str:
"""Record a question asked during study."""
today = datetime.now().strftime("%B %d, %Y")

content = f"""{today} - QUESTION
Topic: {topic}
Question: {question}
Understood: {"Yes" if understood else "No - needs review"}"""

hindsight.retain(
bank_id=USER_ID,
content=content,
metadata={
"category": "question",
"topic": topic,
"understood": str(understood),
},
)

return f"Recorded question on '{topic}'"


def study_buddy(user_query: str) -> str:
"""Interact with the study buddy."""
memories = hindsight.recall(
bank_id=USER_ID,
query=f"study session topic notes questions {user_query}",
budget="high",
)

memory_context = ""
if memories and memories.results:
memory_context = "\n".join(f"- {m.text}" for m in memories.results[:8])

system_prompt = f"""You are a helpful study buddy and tutor.
You have access to the student's study history, including:
- Topics they've studied and their notes
- Their self-assessed confidence levels
- Questions they've asked and whether they understood the answers

Study History:
{memory_context if memory_context else "No study history recorded yet."}

Your role:
1. Answer questions about topics they're studying
2. Identify knowledge gaps based on their history
3. Suggest topics to review (spaced repetition)
4. Provide encouragement and study tips
5. Connect new concepts to things they've already learned

Be supportive and pedagogical. Reference their previous learning when relevant."""

response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query},
],
temperature=0.7,
max_tokens=800,
)

answer = response.choices[0].message.content

hindsight.retain(
bank_id=USER_ID,
content=f"Student asked: {user_query}\nExplanation given: {answer[:300]}...",
metadata={"category": "tutoring"},
)

return answer


def get_review_suggestions() -> str:
"""Get suggestions for topics to review."""
suggestions = hindsight.reflect(
bank_id=USER_ID,
query="""Analyze this student's study history and suggest:
1. Topics with low confidence that need more review
2. Topics studied a while ago that should be revisited
3. Questions that weren't fully understood
4. Connections between topics they might have missed

Prioritize by what would most improve their understanding.""",
budget="high",
)
return suggestions.text if hasattr(suggestions, 'text') else str(suggestions)


def get_knowledge_summary(topic: str = None) -> str:
"""Get a summary of what the student knows."""
query = f"Summarize what this student knows about {topic}" if topic else \
"Summarize this student's overall knowledge and progress"

summary = hindsight.reflect(
bank_id=USER_ID,
query=query,
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)

print("Helper functions defined!")

5. Record Study Sessions

print("Recording study sessions...")

sessions = [
{
"topic": "Classical Mechanics - Newton's Laws",
"notes": "Covered F=ma, action-reaction pairs, inertia. Solved problems on inclined planes.",
"confidence": "high",
},
{
"topic": "Classical Mechanics - Conservation of Momentum",
"notes": "Elastic vs inelastic collisions. Struggled with 2D collision problems.",
"confidence": "low",
},
{
"topic": "Classical Mechanics - Generalized Coordinates",
"notes": "Introduction to Lagrangian mechanics. Degrees of freedom concept.",
"confidence": "medium",
},
{
"topic": "Waves - Simple Harmonic Motion",
"notes": "SHM equations, period, frequency. Connected to springs and pendulums.",
"confidence": "high",
},
{
"topic": "Waves - Frequency Domain",
"notes": "Started Fourier transforms. Math is confusing, need more practice.",
"confidence": "low",
},
]

for session in sessions:
result = record_study_session(**session)
print(f" {result}")

6. Record Questions

print("Recording questions...")

questions = [
("Conservation of Momentum", "Why is momentum conserved in collisions?", True),
("Conservation of Momentum", "How do I solve 2D collision problems?", False),
("Generalized Coordinates", "What's the advantage of Lagrangian over Newtonian?", True),
("Frequency Domain", "When do I use Fourier transforms vs Laplace?", False),
]

for topic, question, understood in questions:
result = record_question(topic, question, understood)
print(f" {result}")

7. Interactive Study Session

import time

print("=" * 60)
print(" Study Session")
print("=" * 60)

queries = [
"Can you explain generalized coordinates again? I remember we covered it but I'm fuzzy on the details.",
"What topics should I review before my exam next week?",
"I'm still confused about 2D collision problems. Can you walk me through an example?",
]

for query in queries:
print(f"\nStudent: {query}")
print("-" * 40)
response = study_buddy(query)
print(f"Study Buddy: {response}")
time.sleep(1)

8. Get Review Suggestions

print("=" * 60)
print(" Recommended Review Topics")
print("=" * 60)
print(get_review_suggestions())

9. Knowledge Summary

print("=" * 60)
print(" Knowledge Summary")
print("=" * 60)
print(get_knowledge_summary())

10. Try Your Own Question

your_question = "What are my biggest knowledge gaps right now?"  # Change this!

print(f"You: {your_question}")
print("-" * 40)
print(f"Study Buddy: {study_buddy(your_question)}")

11. Cleanup

hindsight.close()
print("Client connection closed.")