Skip to content

Latest commit

Β 

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸŽ“ Study Partner Agent

An AI-powered, agentic study companion that turns your own notes into an intelligent tutor.

Upload your documents β†’ start a session β†’ ask questions, generate flashcards, plan your exam schedule, and export revision sheets β€” all powered by RAG and a multi-node LangGraph pipeline.

πŸš€ Live Demo Β Β·Β  πŸ“– API Docs Β Β·Β  πŸ— Architecture


✨ Features

πŸ“„ Document Management

  • Upload PDF, DOCX, MD, and TXT files (up to 20MB each)
  • Files are stored on Cloudinary β€” no local disk dependency, production-safe on any free-tier host
  • Documents are scoped per subject and per user β€” full multi-tenancy

🧠 Intelligent Study Sessions

  • Start a session by selecting one or more documents from your library
  • Documents are parsed β†’ chunked β†’ embedded β†’ stored in ChromaDB on session start
  • ChromaDB collections are ephemeral β€” created on start, deleted on end β€” keeping storage clean
  • Query across all loaded documents in natural language

πŸ” RAG + Sufficiency Judge Pipeline

The core of the system is a multi-stage retrieval pipeline that goes beyond simple vector search:

  1. RAG Node (with Vector Reranking) β€” performs a two-stage retrieval. It first fetches a large candidate pool using cosine similarity, then passes them through a Cohere Rerank model (via ContextualCompressionRetriever) to score and extract only the most highly relevant chunks.
  2. Sufficiency Judge β€” a dedicated Gemini instance evaluates the retrieved context and returns one of three verdicts:
    • SUFFICIENT β†’ answers immediately from your notes
    • PARTIAL β†’ pauses and asks you whether to supplement with web search (Tavily) or Gemini's general knowledge
    • INSUFFICIENT β†’ same interrupt, letting you choose your fallback
  3. Human-in-the-loop interrupt β€” powered by LangGraph's checkpoint + interrupt system; the agent literally pauses its graph execution and waits for your decision before proceeding

πŸ€– Multi-Intent Routing

The agent classifies every message into one of six intents and routes through different graph branches accordingly:

Intent What happens
rag_query Retrieval β†’ Judge β†’ (Fallback?) β†’ Synthesis
content_generation Planner β†’ Flashcard generator / Revision sheet / RAG
study_planning Gap analysis β†’ Study plan builder β†’ Calendar (optional)
calendar_scheduling Direct calendar event builder β†’ Google Calendar
session_end Evaluator β†’ Summary β†’ Save & cleanup
chitchat Direct synthesis

πŸ—‚ Flashcard Generation

  • Ask the agent to create flashcards on any topic during a session
  • Cards are generated by Gemini using your notes as context (RAG-grounded)
  • Each card is persisted to MongoDB for easy access
  • Dedicated review interface to test your knowledge

πŸ“… Google Calendar Integration

  • OAuth 2.0 integration β€” connect your Google account from the app
  • Agent can propose a full study schedule based on gap analysis: missing topics get 3 sessions, shallow topics get 2, well-covered topics get 1
  • Before creating calendar events, the agent interrupts and shows you the proposed plan for confirmation (human-in-the-loop)
  • Events are created directly in your primary Google Calendar

πŸ“Š Session Evaluation & Summary

When you end a session, a pipeline runs automatically:

  • Evaluator node scores the session: topics covered, depth of discussion, weak moments, and an overall session score
  • Summary node generates a concise, human-readable session summary
  • Both are persisted to MongoDB and visible in the session history

πŸ“€ PDF Revision Sheet Export

  • Export a beautiful, formatted PDF revision sheet for any subject
  • The sheet is generated by the agent (RAG + Gemini) covering all session topics at exam-revision depth
  • Rendered with ReportLab β€” includes topic coverage indicators (βœ… well covered, ⚠️ needs work, ❌ missing)
  • Downloadable directly from the UI

🌐 Multi-language Support

  • The agent detects the language of queries and translates them to English before embedding search (since the embedding model is English-optimized)
  • Translation via the Hugging Face Inference API (NLLB-200)
  • Responses are generated in the same language as the user's notes

πŸ— Architecture

Agent Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Next.js Frontend                        β”‚
β”‚              (App Router Β· TypeScript Β· Tailwind CSS)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚ REST API
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      FastAPI Backend                            β”‚
β”‚                                                                 β”‚
β”‚   /auth  /subjects  /documents  /sessions  /chat  /flashcards  β”‚
β”‚   /export  /google-oauth                                        β”‚
β”‚                                                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                  LangGraph Agent                        β”‚  β”‚
β”‚   β”‚                                                         β”‚  β”‚
β”‚   β”‚  router β†’ rag β†’ sufficiency_judge β†’ [interrupt]        β”‚  β”‚
β”‚   β”‚       β†˜ planner β†’ flashcard_generator                  β”‚  β”‚
β”‚   β”‚       β†˜ gap_analysis β†’ study_plan_builder β†’ calendar   β”‚  β”‚
β”‚   β”‚       β†˜ evaluator β†’ summary_node β†’ save_node          β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
   β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚                                           β”‚
   β–Ό                                           β–Ό
MongoDB Atlas                           ChromaDB (local)
(users, subjects,                       Ephemeral session
 documents, sessions,                   vector collections
 flashcards)                            (created & deleted
                                         per session)

Key Design Choices

1. Ephemeral vector stores per session Rather than maintaining a single persistent vector index per user, each study session gets its own short-lived ChromaDB collection. This means documents are embedded fresh per session β€” isolation is perfect, there are no cross-session contamination bugs, and cleanup is trivially simple (delete the collection when the session ends).

2. Sufficiency Judge as a circuit breaker A raw vector similarity score is a poor signal for answer quality. A score of 0.72 might mean the notes are perfect, or it might mean the best chunk you have is only tangentially related. The Sufficiency Judge pattern uses a second LLM call to read both the question and the retrieved context and make a semantic judgment β€” exactly what a human would do. This drastically reduces hallucinations from answering confidently with bad context.

3. Dual Gemini key separation Two separate Gemini API keys are used: one dedicated to the Sufficiency Judge (a fast, deterministic classification task at temperature=0) and one for all answer synthesis. This prevents a burst of synthesis calls from hitting the judge's rate limit and vice versa.

4. LangGraph interrupts for human-in-the-loop Two points in the graph pause execution and wait for user input:

  • After the judge returns PARTIAL/INSUFFICIENT β€” let the user pick fallback strategy
  • Before creating Google Calendar events β€” show the proposed plan and wait for confirmation

This is implemented with LangGraph's interrupt_before + MemorySaver checkpointer. The graph state is frozen in memory, the API returns to the client, and when the user responds, the graph resumes from the exact checkpoint.

5. Document storage on Cloudinary as raw assets Documents are uploaded with resource_type="raw" so Cloudinary treats them as file storage (not image CDN). This bypasses Cloudinary's PDF delivery restrictions that apply to image-type assets. The backend downloads files at session start using an archive API call for authenticated access.

6. Gemini API embeddings (no local model) Embeddings use Google's gemini-embedding-001 via API rather than a local sentence-transformers model. This eliminates a ~500MB model download on deployment, making the backend compatible with free-tier cloud hosts that have strict RAM and disk limits.


πŸ›  Tech Stack

Backend

Layer Technology
API Framework FastAPI + Uvicorn
Agent Orchestration LangGraph (StateGraph with interrupts)
LLM Google Gemini 2.5 Flash
Embeddings Google Gemini Embedding API (gemini-embedding-001)
Vector Reranking Cohere Rerank API (langchain-cohere)
Vector Store ChromaDB (ephemeral, per-session)
Database MongoDB Atlas (Motor async driver)
Document Storage Cloudinary
Web Search Fallback Tavily Search API
PDF Parsing PyMuPDF (fitz) + pypdf
PDF Export ReportLab
Auth JWT (python-jose) + bcrypt
Google OAuth google-auth + google-api-python-client

Frontend

Layer Technology
Framework Next.js 14 (App Router)
Language TypeScript
Styling Tailwind CSS
HTTP Client Axios / fetch

πŸ” Authentication

  • Email/password registration and login with bcrypt hashing and JWT tokens
  • Google OAuth 2.0 β€” sign in with Google; OAuth tokens are stored encrypted in MongoDB and used for Google Calendar API calls
  • All API routes are protected with JWT bearer token authentication
  • Rate limiting via SlowAPI on sensitive endpoints

πŸ“ Project Structure

study-agent/
β”œβ”€β”€ agent/
β”‚   β”œβ”€β”€ graph.py            # LangGraph topology definition
β”‚   β”œβ”€β”€ nodes.py            # All node implementations
β”‚   β”œβ”€β”€ state.py            # AgentState TypedDict
β”‚   β”œβ”€β”€ sufficiency_judge.py # RAG quality evaluator
β”‚   β”œβ”€β”€ tavily_search.py    # Web search fallback
β”‚   └── tools.py            # search_notes, flashcards, study_plan, etc.
β”œβ”€β”€ routes/
β”‚   β”œβ”€β”€ auth.py             # Register, login
β”‚   β”œβ”€β”€ chat.py             # Chat endpoint (drives the LangGraph agent)
β”‚   β”œβ”€β”€ documents.py        # Upload, list, delete documents
β”‚   β”œβ”€β”€ sessions.py         # Start, end, list sessions
β”‚   β”œβ”€β”€ flashcards.py       # List flashcards
β”‚   β”œβ”€β”€ export.py           # PDF revision sheet export
β”‚   └── google_oauth.py     # Google OAuth flow
β”œβ”€β”€ db/
β”‚   └── chroma.py           # ChromaDB session collection manager
β”œβ”€β”€ utils/
β”‚   β”œβ”€β”€ embedder.py         # Gemini embedding API wrapper
β”‚   β”œβ”€β”€ file_parser.py      # PDF/DOCX/MD/TXT β†’ LangChain Documents
β”‚   └── chunker.py          # Document chunking strategies
β”œβ”€β”€ frontend/               # Next.js application
β”œβ”€β”€ server.py               # FastAPI app + lifespan startup
β”œβ”€β”€ models.py               # Pydantic request/response models
└── cleanup.py              # Orphaned session cleanup job

🀝 Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you'd like to change.


About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages