AI-Powered Adaptive Study Platform
Generate quizzes from any document or topic. Get instant feedback, score breakdowns, and Socratic coaching.
| Home & Generation | Quiz Taking | Feedback & Grading |
|---|---|---|
![]() |
![]() |
![]() |
- Document upload — PDF and TXT with text extraction and chunking
- Progressive quiz generation via SSE — questions stream to the browser as they're generated, with keep-alive pings and graceful disconnect recovery
- Topic-based quiz generation — no document needed; ask about any subject
- Question types — MCQ, true/false, and short answer; configurable mix per quiz
- Instant grading — MCQ and true/false graded instantly; short answers scored by the LLM with per-question feedback
- Results page — score breakdown, per-question review, and an AI-generated coaching summary
- Socratic coaching chat — post-quiz follow-up for any question
- Multi-provider LLM — run locally with Ollama (any model) or switch to Groq cloud API with a single env var; factory pattern, zero code changes
- Pluggable cache — in-memory by default, drops into Redis with
CACHE_BACKEND=redis - PostgreSQL persistence — optional; set
USE_DATABASE=trueto persist quizzes, documents, and answers across restarts via SQLAlchemy + Alembic; defaults to in-memory for local dev - Docker Compose — one command to start the full stack (backend, frontend, PostgreSQL, Redis) with health-check chaining and named volumes
- Structured logging — human-readable in dev, JSON in production; request ID on every response
- CI — GitHub Actions runs the full test suite on every push (no external services required)
- 51 tests — unit and integration tests for LLM services, caching, grading, document processing, and database round-trips; DB tests run against in-memory SQLite, no PostgreSQL server needed
LearnLoop supports two backends, switchable via a single environment variable:
| Provider | Config | Best for |
|---|---|---|
| Ollama (default) | LLM_PROVIDER=ollama |
Local dev, full privacy, no API key |
| Groq | LLM_PROVIDER=groq |
Fast cloud inference, free tier available |
ollama pull qwen3:1.7b # Fastest — 1.1GB, good for quick testing
ollama pull qwen3.5:4b # Balanced — 3.4GB, better quality
ollama pull qwen3.5:9b # High quality — 6.6GB, slower| Operation | Time |
|---|---|
| Quiz question (1 question / call) | ~1–3s |
| 8-question quiz (sequential, 1 per call) | ~12–25s |
| Document upload + parse | <2s |
| Answer grading (MCQ/TF) | instant |
| Answer grading (short answer) | ~2–4s |
| Operation | Single | Dual-Parallel |
|---|---|---|
| Topic quiz (10 mixed) | ~25–35s | ~15–20s |
| Document quiz (10 questions) | ~30–45s | ~20–30s |
| Answer grading (short answer) | ~3–5s | ~3–5s |
Enable 2x parallel inference with:
OLLAMA_NUM_PARALLEL=2 ollama serve# 1. Install dependencies
make setup-backend
make setup-frontend
# 2. Configure backend (copy and edit)
cp backend/.env.example backend/.env
# Set LLM_PROVIDER=ollama (default) or LLM_PROVIDER=groq + GROQ_API_KEY=...
# 3. Start backend + frontend
make run-backend # http://localhost:8000
make run-frontend # http://localhost:3000# Copy and edit the environment file
cp backend/.env.example backend/.env
# Set GROQ_API_KEY if using Groq, or leave LLM_PROVIDER=ollama
make docker-up # builds images, starts all 4 services
make docker-down # stop
make docker-reset # stop + delete all data volumesThe backend auto-runs alembic upgrade head on startup when USE_DATABASE=true (set automatically in Docker Compose).
All settings are controlled via environment variables (or backend/.env). See backend/.env.example for the full reference.
Key options:
| Variable | Default | Description |
|---|---|---|
LLM_PROVIDER |
ollama |
ollama or groq |
GROQ_API_KEY |
— | Required when LLM_PROVIDER=groq |
GROQ_MODEL |
llama-3.3-70b-versatile |
Any model available on Groq |
OLLAMA_MODEL |
qwen3:1.7b |
Any locally-pulled Ollama model |
USE_DATABASE |
false |
true to enable PostgreSQL persistence |
DATABASE_URL |
postgresql+asyncpg://... |
PostgreSQL connection string |
CACHE_BACKEND |
memory |
memory or redis |
REDIS_URL |
redis://localhost:6379/0 |
Redis connection string |
QUIZ_BATCH_SIZE |
1 |
Questions per LLM call (raise to 2–4 with Ollama or paid Groq) |
LOG_FORMAT |
text |
text (dev) or json (production) |
LearnLoop/
├── backend/ # FastAPI (Python 3.12)
│ ├── app/
│ │ ├── main.py # App entry, middleware, startup/shutdown hooks
│ │ ├── config.py # Pydantic Settings — all config from env vars
│ │ ├── models.py # Request/response Pydantic schemas
│ │ ├── database.py # Async SQLAlchemy engine + get_db() dependency
│ │ ├── db_models.py # ORM models: Document, Quiz, Question, Answer
│ │ ├── logging_config.py # Structured logging (text / JSON)
│ │ ├── middleware.py # RequestID middleware (skips SSE endpoints)
│ │ ├── routers/ # API routes: quiz, documents, chat
│ │ ├── services/
│ │ │ ├── llm_service.py # BaseLLMService ABC + Ollama impl + factory
│ │ │ ├── groq_llm_service.py # Groq provider
│ │ │ ├── quiz_service.py # Quiz generation, grading, dual-path persistence
│ │ │ ├── document_service.py # Upload, chunking, dual-path persistence
│ │ │ ├── cache_service.py # CacheBackend protocol + factory
│ │ │ └── redis_cache.py # Redis cache backend
│ │ └── prompts/ # LLM prompt templates
│ ├── alembic/ # Database migrations
│ ├── tests/ # 51 tests (pytest + pytest-asyncio)
│ ├── Dockerfile
│ └── entrypoint.sh # Runs migrations then starts uvicorn
├── frontend/ # Next.js 14 + TypeScript + Tailwind
│ ├── src/
│ │ ├── app/ # Pages: home, quiz, results
│ │ ├── components/ # UI components
│ │ ├── hooks/ # useQuiz state + SSE handling
│ │ └── lib/ # API client, types
│ └── Dockerfile # Multi-stage build with standalone output
├── .github/workflows/ci.yml # GitHub Actions CI
├── docker-compose.yml # postgres + redis + backend + frontend
├── Makefile
└── README.md
| Method | Path | Description |
|---|---|---|
| GET | /api/health |
Health check — LLM, DB, and cache status |
| POST | /api/documents/upload |
Upload PDF or TXT |
| POST | /api/quiz/generate |
Generate quiz (sync) |
| GET | /api/quiz/generate/stream |
Stream quiz questions via SSE ← recommended |
| POST | /api/quiz/{id}/answer |
Submit an answer |
| GET | /api/quiz/{id}/results |
Results + AI coaching summary |
| POST | /api/chat/coach |
Socratic coaching chat |
make test
# or directly:
cd backend && python -m pytest tests/ -vTests run entirely without external services — LLM calls are mocked, the DB fixture uses SQLite in-memory, and the Redis fixture uses fakeredis.
- SSE streaming quiz generation with keep-alive and disconnect recovery
- Parallel batch generation (Ollama
OLLAMA_NUM_PARALLEL) - Multi-provider LLM: Ollama and Groq with factory pattern
- Pluggable cache: in-memory and Redis
- PostgreSQL persistence with dual-path services (in-memory or DB)
- Alembic migrations
- Docker Compose — full stack containerization with health checks
- Structured JSON logging + request ID middleware
- CI pipeline (GitHub Actions)
- Full test suite — unit + DB integration, no external services required
- Phase A: Question Quality & Diversity
- Configurable temperature (0.5) for more creative question generation
- Aspect rotation across batches (definition → application → comparison → cause-effect → analysis)
- Seen-concepts injection to avoid repetition in multi-batch runs
- TF-IDF semantic dedup (scikit-learn) to reject near-duplicate questions
- Extract topic keywords from questions for diversity tracking
- Comprehensive test suite (
test_quality.py) with 10+ tests
- Phase B: Flashcards v2 — flashcards tied to quiz questions with priority for missed questions
- Phase C: Text-to-Speech (TTS) — browser Web Speech API for question playback; future Kokoro integration
- Phase D: User Authentication — JWT-based user accounts with optional authentication # TODO
- Phase E: Expert-in-the-Loop — expert corrections improve LLM prompts via few-shot injection
- User accounts — registration, login, and session management
- Results export — download quiz results and feedback as PDF
- Spaced repetition — schedule reviews based on performance (SM-2 algorithm)
- Progress tracking — mastery scores and learning analytics per topic
- Semantic search — find relevant content across uploaded documents
MIT



