ChaiGaram is a local AI-powered learning assistant. It captures educational webpages, course lessons, selected text, and watched video captions; indexes that material; answers questions from it; generates grounded quizzes; tracks performance; and builds a mastery dashboard and study plan.
- React 19, TanStack Start, TanStack Router, React Query, and Tailwind CSS
- Chrome/Edge Manifest V3 browser extension
- FastAPI and Pydantic
- Ollama
embeddinggemmafor embeddings - Ollama
llama3.2:3bfor generation - ChromaDB for persistent semantic search
- SQLite locally or PostgreSQL in production for quiz analytics
- Optional Firebase Authentication and Firestore for user profiles
The current implementation uses Ollama and ChromaDB. Older references to Gemini, OpenAI, or TF-IDF do not describe the active pipeline.
Educational webpage or video
|
v
Chrome/Edge extension
- extracts useful page text
- captures captions already watched
- provides tutor and quiz UI
|
v
FastAPI backend (:8000)
| | |
| | +--> SQLite/PostgreSQL
| | quiz sessions and attempts
| |
| +--> Ollama llama3.2:3b
| answers, summaries, and quizzes
|
+--> Ollama embeddinggemma --> ChromaDB
document/query vectors indexed lesson chunks
|
v
React dashboard (:8080)
- courses and topics
- mastery and quiz history
- study plan and recommendations
The extension and React dashboard are separate clients of the same FastAPI backend.
chaigaram/
|-- backend/
| |-- app.py FastAPI application and route registration
| |-- models.py Pydantic request validation models
| |-- run.py Backend runner
| `-- routes/
| |-- health.py Service diagnostics
| |-- rag.py Ingestion, retrieval, tutor, and quiz APIs
| |-- jobs.py Pollable background AI jobs
| |-- learning_data.py Dashboard data and history deletion
| |-- recommendations.py Assessment-based recommendations
| `-- settings.py Runtime Ollama configuration
|-- ml/
| |-- rag_engine.py Chunking, embeddings, and ChromaDB
| |-- llm_service.py Grounded generation and validation
| |-- analytics.py SQLite/PostgreSQL quiz persistence
| |-- calibration.py Difficulty and mastery formulas
| `-- graph_generator.py Chart payload generation
|-- frontend/
| |-- src/routes/ Dashboard screens
| |-- src/components/ Shared UI and quiz components
| `-- src/lib/ API clients, queries, types, and Firebase
|-- extension/
| |-- manifest.json Extension definition
| |-- background.js Backend API bridge
| |-- content.js Capture logic and page overlay
| |-- popup.* Extension popup
| `-- options.* Connection settings
|-- tests/ Backend and AI guardrail tests
`-- start_all.bat Windows setup and launcher
The extension's content.js runs on normal HTTP and HTTPS pages.
For documents it locates the main article/content container and removes navigation, forms, sidebars, comments, recommendations, advertisements, scripts, and decorative content. It keeps useful headings, paragraphs, lists, code, quotations, and captions.
For videos it collects captions from native text tracks, YouTube caption data, or visible caption elements. Only captions at or before the current playback position are used, so a quiz cannot use future video content.
Captured context is limited to 48,000 characters. Video quizzes require at least 50 caption words.
ml/rag_engine.py splits text into approximately 220-word chunks with a 40-word overlap. It sends each chunk to Ollama's /api/embed endpoint using embeddinggemma and stores the vectors and metadata in ChromaDB.
The default local vector database is:
data/chroma
Stored metadata includes topic, course, source, URL, timestamp, video position, dwell time, and ingestion time.
When a learner asks a question or requests a quiz, the query is embedded with the same model. ChromaDB returns the closest chunks using cosine distance.
When active page content is supplied, retrieval is restricted to that exact document. This prevents unrelated saved material from leaking into a page-specific answer or quiz.
ml/llm_service.py sends the retrieved evidence to the configured Ollama model. The model must use only supplied evidence, cite chunk IDs, treat source content as untrusted data, report insufficient context, and produce English text.
Quiz output must match a Pydantic JSON schema. The backend checks that:
- every question has exactly four distinct choices
- the answer exactly matches one choice
- citations belong to retrieved chunks
- the evidence quote appears verbatim in cited material
- questions and answers overlap with their evidence
- questions are not duplicates
- output is in English using Latin script
Invalid output is retried up to three times and then rejected.
Complete generated quizzes, including correct answers, are stored on the server. The browser receives public questions and a quiz_id, not the answers.
On submission, the backend loads the stored quiz, evaluates answers, updates mastery, and saves the attempt. The default local database is:
data/analytics.sqlite3
GET /api/learning/data derives courses, topics, history, activity, recommendations, and study events from ChromaDB metadata and persisted quiz attempts. React Query refreshes this data every 15 seconds.
difficulty = clamp(mastery / 100 + 0.15 - error_penalty, 0.25, 0.85)
Each recent error contributes a 0.03 penalty, up to 0.15.
- Below
0.50: foundational recall 0.50to0.69: intermediate comprehension0.70and above: advanced application and synthesis
mastery_delta = (quiz_score - current_mastery) * 0.22
new_mastery = current_mastery + mastery_delta
mastery = quiz performance * 0.40
+ time on section * 0.35
+ revisit frequency * 0.25
Time is capped at 100% after 15 tracked minutes. Revisit frequency is capped at 100% after five indexed documents for a topic.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/health |
Ollama, model, ChromaDB, and analytics status |
POST |
/api/settings/ai-config |
Change the active Ollama chat model |
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/rag/topics |
List indexed topics |
POST |
/api/rag/ingest |
Index pasted lesson material |
POST |
/api/rag/retrieve |
Retrieve relevant chunks |
POST |
/api/rag/ask |
Answer from active-source evidence |
POST |
/api/rag/summarize |
Teach and summarize a source |
POST |
/api/rag/generate-quiz |
Generate and store a grounded quiz |
POST |
/api/rag/evaluate-quiz |
Score answers and persist mastery |
POST |
/api/rag/stream-transcript |
Index a caption or selected-text segment |
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/learning/data |
Return the complete dashboard dataset |
GET |
/api/learning/topic-state |
Return one topic's state |
DELETE |
/api/learning/history/{id} |
Delete a source and orphaned assessments |
GET |
/api/recommendations/smart |
Return assessment-based recommendations |
POST |
/api/jobs |
Start a slow AI operation |
GET |
/api/jobs/{job_id} |
Poll job status and result |
Interactive API documentation is available at http://127.0.0.1:8000/docs while the backend is running.
- Overview: courses, average mastery, quiz count, study events, recommendations, and activity
- Courses: captured course/source catalogue and topic telemetry
- Mastery: sortable topic scores, radar visualization, and signal breakdown
- Practice: manual note ingestion, quiz generation, and assessment history
- Plan: generated review events, retention chart, and
.icsexport - Next up: impact-ranked recommendations
- History: captured pages/videos and deletion controls
- Extension: installation instructions and service status
- Profile: optional Google sign-in and Firestore profile editing
- Settings: Ollama model selection and pipeline health
- Python 3.10 or newer
- Node.js 18 or newer
- npm
- Ollama
- Chrome or Microsoft Edge for the extension
ollama pull embeddinggemma
ollama pull llama3.2:3bEnsure Ollama is running at http://127.0.0.1:11434.
cd chaigaram
pip install -r backend/requirements.txt
python -m uvicorn backend.app:app --port 8000 --reloadIn a second terminal:
cd chaigaram/frontend
npm install
npm run devOpen http://localhost:8080.
You can also run:
cd chaigaram
.\start_all.batThe launcher installs dependencies, builds the frontend, and starts both servers. It does not install or start Ollama.
- Keep FastAPI running on port 8000.
- Open
chrome://extensionsoredge://extensions. - Enable Developer mode.
- Select Load unpacked.
- Choose the
chaigaram/extensiondirectory. - Open an educational webpage or video with English captions.
- Use the popup to open the assistant, learn the page, or save a selection.
The options page allows changing the backend and dashboard URLs.
Backend variables can be placed in chaigaram/.env:
OLLAMA_BASE_URL=http://127.0.0.1:11434
OLLAMA_EMBED_MODEL=embeddinggemma
OLLAMA_CHAT_MODEL=llama3.2:3b
# Optional remote ChromaDB
CHROMA_HOST=
CHROMA_PORT=8000
CHROMA_SSL=false
CHROMA_COLLECTION=chaigaram_lessons
# Optional PostgreSQL; SQLite is used when omitted
DATABASE_URL=The frontend API URL can be configured in frontend/.env.local:
VITE_API_BASE_URL=http://127.0.0.1:8000/apiFirebase is used only for Google authentication and profile documents. Add these values to frontend/.env.local:
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=Enable Google authentication, create Firestore, and publish frontend/firestore.rules. See frontend/FIREBASE_SETUP.md for details.
Run backend tests:
cd chaigaram
python -m unittest discover -s tests -vType-check and build the frontend:
cd chaigaram/frontend
npx tsc --noEmit
npm run buildTests cover source isolation, minimum caption scope, grounded evidence quotations, English-only quiz output, history grouping and deletion, recommendations, and study-plan generation.
- FastAPI endpoints do not currently require authentication.
- Learning data is global to one backend instance and is not separated by Firebase user ID.
- CORS allows all origins and should be restricted before deployment.
- Background AI jobs are stored in memory and disappear after a restart.
- Study events are generated dynamically rather than persisted as editable tasks.
- The calibration module describes an MCQ/short-answer mix, but the active generator creates MCQs only.
- Difficulty currently uses mastery and recent errors; other signals are displayed but do not directly change difficulty.
- Firebase protects profile documents only, not ChromaDB or quiz analytics.
start_all.batdoes not verify or start Ollama.
With the default configuration, lesson content, embeddings, and quiz analytics remain on the local machine. The extension sends only explicitly captured page text, selections, and visible or watched captions to the configured backend.
If the backend, ChromaDB, PostgreSQL, or Ollama URL is changed to a remote service, captured content will be sent to that service and should be protected with authentication and transport security.