Add system architecture document
Browse files- system_architecture.md +925 -0
system_architecture.md
ADDED
|
@@ -0,0 +1,925 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MathLingua β System Architecture Document
|
| 2 |
+
|
| 3 |
+
## 1. System Overview
|
| 4 |
+
|
| 5 |
+
MathLingua is a bilingual adaptive math tutoring application for Spanish-speaking students (grades 6β8) transitioning to English-medium mathematics education. The system presents math word problems with 4 scaffolded hint levels and uses a hybrid adaptive algorithm to personalize difficulty progression.
|
| 6 |
+
|
| 7 |
+
```
|
| 8 |
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 9 |
+
β MathLingua System β
|
| 10 |
+
β β
|
| 11 |
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββ β
|
| 12 |
+
β β Frontend β β Backend β β External Services β β
|
| 13 |
+
β β (Next.js) ββββΊβ (Firebase) ββββΊβ (LLM / SLM) β β
|
| 14 |
+
β ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββββββ¬ββββββββββββ β
|
| 15 |
+
β β β β β
|
| 16 |
+
β βΌ βΌ βΌ β
|
| 17 |
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββ β
|
| 18 |
+
β β Adaptive β β Firestore β β V1: Gemini API β β
|
| 19 |
+
β β Engine β β Database β β V2: Qwen2.5-3B SLM β β
|
| 20 |
+
β β (Client JS) β β β β (HF Inference EP) β β
|
| 21 |
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββ β
|
| 22 |
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
---
|
| 26 |
+
|
| 27 |
+
## 2. Component Architecture
|
| 28 |
+
|
| 29 |
+
### 2.1 Frontend β React / Next.js Application
|
| 30 |
+
|
| 31 |
+
**Technology**: Next.js 14+ (App Router), TypeScript, Tailwind CSS
|
| 32 |
+
**Hosting**: Firebase Hosting or Vercel
|
| 33 |
+
|
| 34 |
+
#### Key Pages/Routes
|
| 35 |
+
|
| 36 |
+
| Route | Component | Purpose |
|
| 37 |
+
|---|---|---|
|
| 38 |
+
| `/` | `LandingPage` | Login/signup, language preference |
|
| 39 |
+
| `/dashboard` | `StudentDashboard` | Progress overview, session history, MCS/LDS charts |
|
| 40 |
+
| `/practice` | `PracticeSession` | Adaptive practice from question database |
|
| 41 |
+
| `/solve` | `CustomProblem` | "Input your question" β Gemini/SLM processes user-submitted problems |
|
| 42 |
+
| `/session-report` | `SessionReport` | End-of-session summary with performance analytics |
|
| 43 |
+
|
| 44 |
+
#### Core Frontend Components
|
| 45 |
+
|
| 46 |
+
```
|
| 47 |
+
src/
|
| 48 |
+
βββ components/
|
| 49 |
+
β βββ ProblemDisplay/
|
| 50 |
+
β β βββ MathProblem.tsx # Renders word problem text
|
| 51 |
+
β β βββ HintScaffold.tsx # L1/L2/L3/L4 progressive hint UI
|
| 52 |
+
β β βββ AnswerInput.tsx # Numeric/expression answer entry
|
| 53 |
+
β β βββ SolutionReveal.tsx # L4 step-by-step solution display
|
| 54 |
+
β βββ Adaptive/
|
| 55 |
+
β β βββ DifficultyIndicator.tsx # Visual current-level indicator
|
| 56 |
+
β β βββ ProgressBar.tsx # Session progress (e.g., 7/20)
|
| 57 |
+
β β βββ SessionTimer.tsx # Time tracking per problem
|
| 58 |
+
β βββ Dashboard/
|
| 59 |
+
β β βββ EloChart.tsx # Elo rating over time (Recharts)
|
| 60 |
+
β β βββ TopicHeatmap.tsx # Performance by math topic
|
| 61 |
+
β β βββ LDSMCSPanel.tsx # Language Dependency & Math Confidence
|
| 62 |
+
β β βββ StreakBadge.tsx # Gamification elements
|
| 63 |
+
β βββ Shared/
|
| 64 |
+
β βββ BilingualToggle.tsx # EN/ES interface language switch
|
| 65 |
+
β βββ MathRenderer.tsx # KaTeX for math expressions
|
| 66 |
+
β βββ LoadingSkeleton.tsx
|
| 67 |
+
βββ lib/
|
| 68 |
+
β βββ adaptive-engine.ts # Elo + BKT + Thompson Sampling (client-side)
|
| 69 |
+
β βββ feature-engineer.ts # LDS & MCS computation
|
| 70 |
+
β βββ firebase.ts # Firebase SDK initialization
|
| 71 |
+
β βββ llm-client.ts # Gemini/SLM API abstraction
|
| 72 |
+
βββ hooks/
|
| 73 |
+
β βββ useAdaptiveSession.ts # Manages session state + engine calls
|
| 74 |
+
β βββ useStudentProfile.ts # Reads/writes Firestore student state
|
| 75 |
+
β βββ useQuestionQueue.ts # Pre-fetches next batch of questions
|
| 76 |
+
βββ types/
|
| 77 |
+
βββ index.ts # TypeScript interfaces for all data structures
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
#### Hint Scaffold UI Flow
|
| 81 |
+
|
| 82 |
+
```
|
| 83 |
+
βββββββββββοΏ½οΏ½οΏ½βββββββββββββββββββββββββββ
|
| 84 |
+
β Problem displayed in original β
|
| 85 |
+
β English at student's current level β
|
| 86 |
+
β β
|
| 87 |
+
β [Try to solve] [I need a hint β] β
|
| 88 |
+
ββββββββββββββββββββββββ¬βββββββββββββββ
|
| 89 |
+
β click
|
| 90 |
+
βΌ
|
| 91 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 92 |
+
β L1: Simplified English β
|
| 93 |
+
β "A store has 24 apples..." β
|
| 94 |
+
β β
|
| 95 |
+
β [Got it!] [Still stuck β] β
|
| 96 |
+
ββββββββββββββββββββββββ¬βββββββββββββββ
|
| 97 |
+
β click
|
| 98 |
+
βΌ
|
| 99 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 100 |
+
β L2: Bilingual Keywords Inline β
|
| 101 |
+
β "A store has 24 apples (manzanas)" β
|
| 102 |
+
β "divided equally (dividido β
|
| 103 |
+
β igualmente) among 6 boxes" β
|
| 104 |
+
β β
|
| 105 |
+
β [Got it!] [Still stuck β] β
|
| 106 |
+
ββββββββββββββββββββββββ¬βββββββββββββββ
|
| 107 |
+
β click
|
| 108 |
+
βΌ
|
| 109 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 110 |
+
β L3: Full Spanish Translation β
|
| 111 |
+
β "Una tienda tiene 24 manzanas β
|
| 112 |
+
β divididas igualmente entre 6 β
|
| 113 |
+
β cajas. ΒΏCuΓ‘ntas manzanas hay β
|
| 114 |
+
β en cada caja?" β
|
| 115 |
+
β β
|
| 116 |
+
β [Got it!] [Show me the answer β] β
|
| 117 |
+
ββββββββββββββββββββββββ¬βββββββββββββββ
|
| 118 |
+
β click
|
| 119 |
+
βΌ
|
| 120 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 121 |
+
β L4: Step-by-Step Solution β
|
| 122 |
+
β Step 1: Identify β 24 Γ· 6 β
|
| 123 |
+
β Step 2: Calculate β 24 Γ· 6 = 4 β
|
| 124 |
+
β Step 3: Answer β 4 apples per box β
|
| 125 |
+
β β
|
| 126 |
+
β [Next Problem β] β
|
| 127 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
Each hint interaction is logged with timestamp to compute `escalation_speed` and `scaffold_time_ratio` for the LDS formula.
|
| 131 |
+
|
| 132 |
+
---
|
| 133 |
+
|
| 134 |
+
### 2.2 Adaptive Engine (Client-Side JavaScript)
|
| 135 |
+
|
| 136 |
+
The adaptive engine runs **entirely in the browser** β no server round-trip needed for difficulty decisions. This ensures instant feedback and works offline after initial question batch load.
|
| 137 |
+
|
| 138 |
+
#### Engine Components
|
| 139 |
+
|
| 140 |
+
```
|
| 141 |
+
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 142 |
+
β Adaptive Engine (client-side) β
|
| 143 |
+
β β
|
| 144 |
+
β βββββββββββββββ ββββββββββββ ββββββββββββββ β
|
| 145 |
+
β β Elo Rating β β BKT β β Thompson β β
|
| 146 |
+
β β System β β Engine β β Sampler β β
|
| 147 |
+
β β β β β β β β
|
| 148 |
+
β β Updates β β P(know) β β Beta prior β β
|
| 149 |
+
β β student & β β per β β per level, β β
|
| 150 |
+
β β question β β topic β β ZPD window β β
|
| 151 |
+
β β ratings β β β β β β
|
| 152 |
+
β ββββββββ¬βββββββ ββββββ¬ββββββ βββββββ¬βββββββ β
|
| 153 |
+
β β β β β
|
| 154 |
+
β βΌ βΌ βΌ β
|
| 155 |
+
β βββββββββββββββββββββββββββββββββββββββββββββ β
|
| 156 |
+
β β Decision Orchestrator β β
|
| 157 |
+
β β β β
|
| 158 |
+
β β Input: weighted_outcome, features β β
|
| 159 |
+
β β Output: next_level, decision_type β β
|
| 160 |
+
β β (increase/maintain/decrease) β β
|
| 161 |
+
β βββββββββββββββββββββββββββββββββββββββββββββ β
|
| 162 |
+
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 163 |
+
```
|
| 164 |
+
|
| 165 |
+
#### Elo Update Formula
|
| 166 |
+
|
| 167 |
+
```
|
| 168 |
+
weighted_outcome = {
|
| 169 |
+
no_hint: 1.00 (solved without any scaffold)
|
| 170 |
+
L1_only: 0.75 (needed simplified English)
|
| 171 |
+
L2_used: 0.50 (needed bilingual keywords)
|
| 172 |
+
L3_used: 0.25 (needed full translation)
|
| 173 |
+
L4_used: 0.00 (needed answer reveal)
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
E_student = 1 / (1 + 10^((R_question - R_student) / 400))
|
| 177 |
+
R_student_new = R_student + K Γ (weighted_outcome - E_student)
|
| 178 |
+
|
| 179 |
+
K = 32 (default), increased to 48 for first 10 interactions (cold-start acceleration)
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
#### BKT Parameters (per topic)
|
| 183 |
+
|
| 184 |
+
| Parameter | Symbol | Default | Description |
|
| 185 |
+
|---|---|---|---|
|
| 186 |
+
| Prior knowledge | P(Lβ) | 0.10 | Initial probability student knows topic |
|
| 187 |
+
| Learn rate | P(T) | 0.15 | Probability of learning per opportunity |
|
| 188 |
+
| Slip | P(S) | 0.10 | Probability of incorrect despite knowing |
|
| 189 |
+
| Guess | P(G) | 0.25 | Probability of correct despite not knowing |
|
| 190 |
+
|
| 191 |
+
Slip is adjusted based on hint usage:
|
| 192 |
+
```
|
| 193 |
+
P(S)_adjusted = P(S) Γ (1 + 0.5 Γ hint_depth_normalized)
|
| 194 |
+
```
|
| 195 |
+
This models the intuition that using more scaffolds means apparent "correctness" is less certain.
|
| 196 |
+
|
| 197 |
+
#### Thompson Sampling with ZPD Windowing
|
| 198 |
+
|
| 199 |
+
```
|
| 200 |
+
For each candidate level l in ZPD window [current - 2, current + 3]:
|
| 201 |
+
sample ΞΈ_l ~ Beta(Ξ±_l, Ξ²_l)
|
| 202 |
+
score_l = ΞΈ_l Γ proximity_bonus(l, target_elo)
|
| 203 |
+
|
| 204 |
+
Select level = argmax(score_l)
|
| 205 |
+
|
| 206 |
+
proximity_bonus(l, target) = exp(-0.5 Γ ((elo_l - target) / 100)Β²)
|
| 207 |
+
```
|
| 208 |
+
|
| 209 |
+
ZPD window is asymmetric (+3 upward, -2 downward) to encourage upward progression while preventing catastrophic failure.
|
| 210 |
+
|
| 211 |
+
#### Progression Decision Rules
|
| 212 |
+
|
| 213 |
+
| Condition | Decision | Action |
|
| 214 |
+
|---|---|---|
|
| 215 |
+
| weighted_outcome β₯ 0.75 AND P(know) β₯ 0.70 | **Increase** | Move up 1 sub-level |
|
| 216 |
+
| weighted_outcome β₯ 0.85 AND streak β₯ 3 | **Skip** | Move up 2 sub-levels |
|
| 217 |
+
| 0.40 β€ weighted_outcome < 0.75 | **Maintain** | Stay at current level |
|
| 218 |
+
| weighted_outcome < 0.40 OR streak_wrong β₯ 2 | **Decrease** | Move down 1 sub-level |
|
| 219 |
+
| weighted_outcome < 0.25 AND P(know) < 0.30 | **Rapid Decrease** | Move down 2 sub-levels |
|
| 220 |
+
|
| 221 |
+
---
|
| 222 |
+
|
| 223 |
+
### 2.3 Firebase Backend
|
| 224 |
+
|
| 225 |
+
**Services Used**:
|
| 226 |
+
- Firebase Authentication (Google Sign-In, Email/Password)
|
| 227 |
+
- Cloud Firestore (student state, question database, session logs)
|
| 228 |
+
- Cloud Functions (LLM API calls, batch question generation, session reports)
|
| 229 |
+
- Firebase Hosting (static frontend assets)
|
| 230 |
+
|
| 231 |
+
#### Firestore Data Model
|
| 232 |
+
|
| 233 |
+
```
|
| 234 |
+
firestore/
|
| 235 |
+
βββ users/
|
| 236 |
+
β βββ {uid}/
|
| 237 |
+
β βββ profile: {
|
| 238 |
+
β β displayName, email, gradeLevel, preferredLanguage,
|
| 239 |
+
β β createdAt, lastActive
|
| 240 |
+
β β }
|
| 241 |
+
β βββ adaptiveState: {
|
| 242 |
+
β β currentElo: number, // e.g., 1050
|
| 243 |
+
β β currentLevel: string, // e.g., "2.1"
|
| 244 |
+
β β totalInteractions: number,
|
| 245 |
+
β β topicMastery: { // BKT P(know) per topic
|
| 246 |
+
β β "arithmetic": 0.72,
|
| 247 |
+
β β "fractions": 0.45,
|
| 248 |
+
β β "algebra_basic": 0.31,
|
| 249 |
+
β β ...
|
| 250 |
+
β β },
|
| 251 |
+
β β thompsonPriors: { // Beta(Ξ±,Ξ²) per level
|
| 252 |
+
β β "1.1": { alpha: 12, beta: 3 },
|
| 253 |
+
β β "1.2": { alpha: 8, beta: 5 },
|
| 254 |
+
β β ...
|
| 255 |
+
β β },
|
| 256 |
+
β β featureAverages: {
|
| 257 |
+
β β avgLDS: 0.42,
|
| 258 |
+
β β avgMCS: 0.61,
|
| 259 |
+
β β recentLDS_5: [0.3, 0.4, 0.5, 0.35, 0.45],
|
| 260 |
+
β β recentMCS_5: [0.6, 0.65, 0.58, 0.62, 0.7]
|
| 261 |
+
β β },
|
| 262 |
+
β β streakCount: number,
|
| 263 |
+
β β lastUpdated: timestamp
|
| 264 |
+
β β }
|
| 265 |
+
β βββ sessions/
|
| 266 |
+
β βββ {sessionId}/
|
| 267 |
+
β βββ metadata: {
|
| 268 |
+
β β startTime, endTime, questionsAttempted,
|
| 269 |
+
β β questionsCorrect, avgWeightedOutcome,
|
| 270 |
+
β β startElo, endElo, sessionLDS, sessionMCS
|
| 271 |
+
β β }
|
| 272 |
+
β βββ interactions/
|
| 273 |
+
β βββ {interactionId}: {
|
| 274 |
+
β questionId, level, topic,
|
| 275 |
+
β startTime, endTime, timeSpentMs,
|
| 276 |
+
β hintsUsed: [0,1,2,3,4], // which levels accessed
|
| 277 |
+
β hintTimestamps: { L1: ts, L2: ts, ... },
|
| 278 |
+
β maxHintLevel: number,
|
| 279 |
+
β answer: string,
|
| 280 |
+
β isCorrect: boolean,
|
| 281 |
+
β attempts: number,
|
| 282 |
+
β weightedOutcome: number,
|
| 283 |
+
β lds: number,
|
| 284 |
+
β mcs: number,
|
| 285 |
+
β eloBeforeUpdate: number,
|
| 286 |
+
β eloAfterUpdate: number,
|
| 287 |
+
β adaptiveDecision: string
|
| 288 |
+
β }
|
| 289 |
+
β
|
| 290 |
+
βββ questions/
|
| 291 |
+
β βββ {questionId}: {
|
| 292 |
+
β id, level, topic, subtopic,
|
| 293 |
+
β problemText, answer, answerNumeric,
|
| 294 |
+
β solutionSteps: [...],
|
| 295 |
+
β scaffolds: {
|
| 296 |
+
β L1_simplified: string,
|
| 297 |
+
β L2_bilingual: string,
|
| 298 |
+
β L3_spanish: string,
|
| 299 |
+
β L4_solution: string
|
| 300 |
+
β },
|
| 301 |
+
β readability: {
|
| 302 |
+
β fleschKincaid: number,
|
| 303 |
+
β wordCount: number,
|
| 304 |
+
β difficultWords: number,
|
| 305 |
+
β avgSyllables: number
|
| 306 |
+
β },
|
| 307 |
+
β eloRating: number,
|
| 308 |
+
β timesServed: number,
|
| 309 |
+
β avgOutcome: number,
|
| 310 |
+
β metadata: {
|
| 311 |
+
β source: "curated" | "generated",
|
| 312 |
+
β generatedBy: "gemini-2.0" | "qwen2.5-3b" | null,
|
| 313 |
+
β reviewedBy: string | null,
|
| 314 |
+
β createdAt: timestamp
|
| 315 |
+
β }
|
| 316 |
+
β }
|
| 317 |
+
β
|
| 318 |
+
βββ questionIndex/ // Denormalized for fast queries
|
| 319 |
+
β βββ byLevel/
|
| 320 |
+
β βββ {level}: {
|
| 321 |
+
β questionIds: [...],
|
| 322 |
+
β count: number
|
| 323 |
+
β }
|
| 324 |
+
β
|
| 325 |
+
βββ analytics/ // Aggregated (Cloud Functions)
|
| 326 |
+
βββ dailyStats/
|
| 327 |
+
β βββ {date}: { activeUsers, sessionsCompleted, ... }
|
| 328 |
+
βββ cohortProgress/
|
| 329 |
+
βββ {cohortId}: { avgElo, avgLDS, avgMCS, ... }
|
| 330 |
+
```
|
| 331 |
+
|
| 332 |
+
#### Firestore Security Rules
|
| 333 |
+
|
| 334 |
+
```javascript
|
| 335 |
+
rules_version = '2';
|
| 336 |
+
service cloud.firestore {
|
| 337 |
+
match /databases/{database}/documents {
|
| 338 |
+
// Users can only read/write their own data
|
| 339 |
+
match /users/{uid}/{document=**} {
|
| 340 |
+
allow read, write: if request.auth != null && request.auth.uid == uid;
|
| 341 |
+
}
|
| 342 |
+
// Questions are readable by all authenticated users
|
| 343 |
+
match /questions/{questionId} {
|
| 344 |
+
allow read: if request.auth != null;
|
| 345 |
+
allow write: if false; // Only admin/Cloud Functions
|
| 346 |
+
}
|
| 347 |
+
// Question index readable by all authenticated users
|
| 348 |
+
match /questionIndex/{document=**} {
|
| 349 |
+
allow read: if request.auth != null;
|
| 350 |
+
allow write: if false;
|
| 351 |
+
}
|
| 352 |
+
// Analytics only accessible by admin
|
| 353 |
+
match /analytics/{document=**} {
|
| 354 |
+
allow read, write: if false; // Cloud Functions only
|
| 355 |
+
}
|
| 356 |
+
}
|
| 357 |
+
}
|
| 358 |
+
```
|
| 359 |
+
|
| 360 |
+
---
|
| 361 |
+
|
| 362 |
+
### 2.4 Cloud Functions (Serverless Backend)
|
| 363 |
+
|
| 364 |
+
```
|
| 365 |
+
functions/
|
| 366 |
+
βββ onUserCreate.ts # Initialize adaptive state for new user
|
| 367 |
+
βββ generateScaffolds.ts # Call Gemini/SLM to create L1-L4 for a problem
|
| 368 |
+
βββ batchGenerateQuestions.ts # Generate next 20 questions for session queue
|
| 369 |
+
βββ processCustomProblem.ts # "Input your question" flow
|
| 370 |
+
βββ generateSessionReport.ts # End-of-session analytics
|
| 371 |
+
βββ updateQuestionStats.ts # Update question difficulty from outcomes
|
| 372 |
+
βββ scheduledAnalytics.ts # Daily aggregation (cron-triggered)
|
| 373 |
+
```
|
| 374 |
+
|
| 375 |
+
#### Key Cloud Function: `generateScaffolds`
|
| 376 |
+
|
| 377 |
+
```typescript
|
| 378 |
+
// Triggered when student submits a custom problem or when
|
| 379 |
+
// pre-generating scaffolds for database questions
|
| 380 |
+
|
| 381 |
+
interface ScaffoldRequest {
|
| 382 |
+
problemText: string;
|
| 383 |
+
studentGradeLevel: number;
|
| 384 |
+
currentLDS: number; // Informs simplification level
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
interface ScaffoldResponse {
|
| 388 |
+
L1_simplified: string; // Simplified English
|
| 389 |
+
L2_bilingual: string; // English with inline Spanish keywords
|
| 390 |
+
L3_spanish: string; // Full Spanish translation
|
| 391 |
+
L4_solution: string; // Step-by-step solution
|
| 392 |
+
answer: string;
|
| 393 |
+
answerNumeric: number;
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
// Prompt template for LLM
|
| 397 |
+
const SCAFFOLD_PROMPT = `
|
| 398 |
+
You are a bilingual math tutor helping Spanish-speaking students
|
| 399 |
+
(grades 6-8) learn math in English.
|
| 400 |
+
|
| 401 |
+
Given this math word problem:
|
| 402 |
+
"{problemText}"
|
| 403 |
+
|
| 404 |
+
Generate 4 scaffold levels:
|
| 405 |
+
|
| 406 |
+
**L1 (Simplified English):** Rewrite using shorter sentences,
|
| 407 |
+
simpler vocabulary (grade {adjustedGrade} reading level).
|
| 408 |
+
Keep all math content identical.
|
| 409 |
+
|
| 410 |
+
**L2 (Bilingual Keywords):** Take the original problem and add
|
| 411 |
+
Spanish translations in parentheses for key math and context
|
| 412 |
+
vocabulary. Format: "English word (palabra en espaΓ±ol)".
|
| 413 |
+
|
| 414 |
+
**L3 (Full Spanish Translation):** Translate the complete problem
|
| 415 |
+
to natural, grade-appropriate Spanish. Ensure mathematical
|
| 416 |
+
precision is maintained.
|
| 417 |
+
|
| 418 |
+
**L4 (Step-by-Step Solution):** Provide a clear, numbered
|
| 419 |
+
step-by-step solution in English with the final numerical answer.
|
| 420 |
+
|
| 421 |
+
Return as JSON with keys: L1_simplified, L2_bilingual, L3_spanish,
|
| 422 |
+
L4_solution, answer, answerNumeric.
|
| 423 |
+
`;
|
| 424 |
+
```
|
| 425 |
+
|
| 426 |
+
#### Key Cloud Function: `batchGenerateQuestions`
|
| 427 |
+
|
| 428 |
+
```typescript
|
| 429 |
+
// Called when student reaches question 17 of 20 (prefetch trigger)
|
| 430 |
+
// Selects next 20 questions from database based on adaptive state
|
| 431 |
+
|
| 432 |
+
export const batchGenerateQuestions = onCall(async (request) => {
|
| 433 |
+
const { uid } = request.auth;
|
| 434 |
+
const state = await getAdaptiveState(uid);
|
| 435 |
+
|
| 436 |
+
// Thompson Sampling selects level distribution for next batch
|
| 437 |
+
const levelDistribution = thompsonSampleBatch(
|
| 438 |
+
state.thompsonPriors,
|
| 439 |
+
state.currentLevel,
|
| 440 |
+
batchSize: 20
|
| 441 |
+
);
|
| 442 |
+
// e.g., { "2.1": 5, "2.2": 8, "2.3": 5, "2.4": 2 }
|
| 443 |
+
|
| 444 |
+
// Select questions avoiding recently served ones
|
| 445 |
+
const recentIds = await getRecentQuestionIds(uid, lookback: 100);
|
| 446 |
+
const questions = await selectQuestions(
|
| 447 |
+
levelDistribution,
|
| 448 |
+
excludeIds: recentIds,
|
| 449 |
+
topicBalance: state.topicMastery // Favor weaker topics
|
| 450 |
+
);
|
| 451 |
+
|
| 452 |
+
// Ensure all questions have scaffolds generated
|
| 453 |
+
const withScaffolds = await ensureScaffoldsGenerated(questions);
|
| 454 |
+
|
| 455 |
+
return { questions: withScaffolds, sessionBatchId: generateId() };
|
| 456 |
+
});
|
| 457 |
+
```
|
| 458 |
+
|
| 459 |
+
---
|
| 460 |
+
|
| 461 |
+
### 2.5 LLM Service Layer
|
| 462 |
+
|
| 463 |
+
#### V1: Gemini API (Current)
|
| 464 |
+
|
| 465 |
+
```
|
| 466 |
+
ββββββββββββββ HTTPS/REST ββββββββββββββββββββ
|
| 467 |
+
β Cloud β βββββββββββββββββββΊβ Google Gemini β
|
| 468 |
+
β Function β ββββββββββββββββββββ 2.0 Flash API β
|
| 469 |
+
ββββββββββββββ ββββββββββββββββββββ
|
| 470 |
+
|
| 471 |
+
Cost: ~$0.075 per 1M input tokens, ~$0.30 per 1M output tokens
|
| 472 |
+
Latency: 200-800ms per scaffold generation
|
| 473 |
+
Rate limit: 60 RPM (free tier), 1000 RPM (paid)
|
| 474 |
+
```
|
| 475 |
+
|
| 476 |
+
#### V2: Qwen2.5-3B SLM (Planned)
|
| 477 |
+
|
| 478 |
+
```
|
| 479 |
+
ββββββββββββββ HTTPS/REST ββββββββββββββββββββββββββββ
|
| 480 |
+
β Cloud β βββββββββββββββββββΊβ HF Inference Endpoint β
|
| 481 |
+
β Function β ββββββββββββββββββββ Qwen2.5-3B-Instruct β
|
| 482 |
+
ββββββββββββββ β (QLoRA fine-tuned) β
|
| 483 |
+
β GPU: T4 or L4 β
|
| 484 |
+
ββββββββββββββββββββββββββββ
|
| 485 |
+
|
| 486 |
+
Cost: ~$0.60/hr (T4) or ~$1.04/hr (L4)
|
| 487 |
+
Latency: 100-400ms per scaffold generation
|
| 488 |
+
Rate limit: Unlimited (dedicated endpoint)
|
| 489 |
+
```
|
| 490 |
+
|
| 491 |
+
#### LLM Client Abstraction
|
| 492 |
+
|
| 493 |
+
```typescript
|
| 494 |
+
// lib/llm-client.ts β Provider-agnostic interface
|
| 495 |
+
|
| 496 |
+
interface LLMProvider {
|
| 497 |
+
generateScaffolds(problem: string, context: ScaffoldContext): Promise<ScaffoldResponse>;
|
| 498 |
+
generateQuestion(level: string, topic: string): Promise<QuestionWithScaffolds>;
|
| 499 |
+
validateAnswer(problem: string, studentAnswer: string, correctAnswer: string): Promise<AnswerValidation>;
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
class GeminiProvider implements LLMProvider { ... }
|
| 503 |
+
class QwenSLMProvider implements LLMProvider { ... }
|
| 504 |
+
|
| 505 |
+
// Factory with fallback
|
| 506 |
+
function createLLMClient(): LLMProvider {
|
| 507 |
+
if (config.useSLM && config.slmEndpointAvailable) {
|
| 508 |
+
return new QwenSLMProvider(config.slmEndpoint);
|
| 509 |
+
}
|
| 510 |
+
return new GeminiProvider(config.geminiApiKey);
|
| 511 |
+
}
|
| 512 |
+
```
|
| 513 |
+
|
| 514 |
+
---
|
| 515 |
+
|
| 516 |
+
### 2.6 SLM Fine-Tuning Pipeline
|
| 517 |
+
|
| 518 |
+
```
|
| 519 |
+
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ
|
| 520 |
+
β Training β β Fine-Tune β β Deploy β
|
| 521 |
+
β Data Prep βββββΊβ QLoRA SFT βββββΊβ HF Inference EP β
|
| 522 |
+
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ
|
| 523 |
+
|
| 524 |
+
Step 1: Collect 2,000-5,000 scaffold examples from Gemini V1 usage
|
| 525 |
+
Step 2: Human review + quality filter β ~1,500 gold examples
|
| 526 |
+
Step 3: QLoRA fine-tune Qwen2.5-3B-Instruct
|
| 527 |
+
Step 4: Evaluate on held-out test set (BLEU, math accuracy, readability)
|
| 528 |
+
Step 5: Deploy to HF Inference Endpoint
|
| 529 |
+
Step 6: Shadow-test alongside Gemini (serve both, compare quality)
|
| 530 |
+
Step 7: Full cutover when SLM matches Gemini quality
|
| 531 |
+
```
|
| 532 |
+
|
| 533 |
+
**Fine-tuning Configuration:**
|
| 534 |
+
|
| 535 |
+
| Parameter | Value | Rationale |
|
| 536 |
+
|---|---|---|
|
| 537 |
+
| Base model | Qwen2.5-3B-Instruct | Best math+Spanish at 3B scale |
|
| 538 |
+
| Method | QLoRA (4-bit NF4) | Fits single 16GB GPU |
|
| 539 |
+
| LoRA rank (r) | 32 | Balance quality/efficiency for small dataset |
|
| 540 |
+
| LoRA alpha | 64 | Standard 2Γ rank |
|
| 541 |
+
| Target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj | Full attention + MLP |
|
| 542 |
+
| Learning rate | 2e-4 | Standard for QLoRA |
|
| 543 |
+
| Epochs | 3-5 | Small dataset, monitor val loss |
|
| 544 |
+
| Batch size | 4 (effective 16 with grad accum) | Memory constraint |
|
| 545 |
+
| Max sequence length | 1024 | Sufficient for problem + all 4 scaffolds |
|
| 546 |
+
| Warmup ratio | 0.05 | Short warmup for small dataset |
|
| 547 |
+
|
| 548 |
+
---
|
| 549 |
+
|
| 550 |
+
## 3. Data Flow Diagrams
|
| 551 |
+
|
| 552 |
+
### 3.1 Flow A: "Practice Problems" Mode
|
| 553 |
+
|
| 554 |
+
```
|
| 555 |
+
Student clicks "Start Practice"
|
| 556 |
+
β
|
| 557 |
+
βΌ
|
| 558 |
+
βββββββββββββββββββββββββββββββββββ
|
| 559 |
+
β 1. Load adaptive state from β
|
| 560 |
+
β Firestore (Elo, BKT, priors) β
|
| 561 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 562 |
+
β
|
| 563 |
+
βΌ
|
| 564 |
+
βββββββββββββββββββββββββββββββββββ
|
| 565 |
+
β 2. Thompson Sampling selects β
|
| 566 |
+
β next question level β
|
| 567 |
+
β (ZPD window: current Β±2/+3) β
|
| 568 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 569 |
+
β
|
| 570 |
+
βΌ
|
| 571 |
+
βββββββββββββββββββββββββββββββββββ
|
| 572 |
+
β 3. Fetch question from Firestoreβ
|
| 573 |
+
β by level + topic balancing β
|
| 574 |
+
β (avoid recently served) β
|
| 575 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 576 |
+
β
|
| 577 |
+
βΌ
|
| 578 |
+
βββββββββββββββββββββββββββββββββββ
|
| 579 |
+
β 4. Display problem, start timer β
|
| 580 |
+
β Student reads and attempts β
|
| 581 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 582 |
+
β
|
| 583 |
+
ββββββββββ΄βββββββββ
|
| 584 |
+
β Needs hints? β
|
| 585 |
+
βΌ No βΌ Yes
|
| 586 |
+
βββββββββββ βββββββββββββββββββββ
|
| 587 |
+
β Submit β β L1 β L2 β L3 β L4β
|
| 588 |
+
β answer β β (each click logged β
|
| 589 |
+
ββββββ¬βββββ β with timestamp) β
|
| 590 |
+
β ββββββββββ¬ββββββββββββ
|
| 591 |
+
β β
|
| 592 |
+
βΌ βΌ
|
| 593 |
+
βββββββββββββββββββββββββββββββββββ
|
| 594 |
+
β 5. Compute weighted_outcome β
|
| 595 |
+
β based on correctness + hints β
|
| 596 |
+
β Compute LDS and MCS β
|
| 597 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 598 |
+
β
|
| 599 |
+
βΌ
|
| 600 |
+
βββββββββββββββββββββββββββββββββββ
|
| 601 |
+
β 6. Update Elo (student + Q) β
|
| 602 |
+
β Update BKT P(know) for topic β
|
| 603 |
+
β Update Thompson Beta priors β
|
| 604 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 605 |
+
β
|
| 606 |
+
βΌ
|
| 607 |
+
βββββββββββββββββββββββββββββββββββ
|
| 608 |
+
β 7. Progression decision: β
|
| 609 |
+
β increase / maintain / decreaseβ
|
| 610 |
+
β Select next level β
|
| 611 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 612 |
+
β
|
| 613 |
+
βΌ
|
| 614 |
+
βββββββββββββββββββββββββββββββββββ
|
| 615 |
+
β 8. Save interaction to Firestoreβ
|
| 616 |
+
β Display "Next Problem" β
|
| 617 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 618 |
+
β
|
| 619 |
+
βΌ
|
| 620 |
+
ββββββββββ΄βββββββββ
|
| 621 |
+
β Q17 of 20? β
|
| 622 |
+
βΌ Yes βΌ No
|
| 623 |
+
βββββββββββββββ ββββββββββββ
|
| 624 |
+
β Prefetch β β Loop to β
|
| 625 |
+
β next batch β β step 2 β
|
| 626 |
+
β (Cloud Fn) β ββββββββββββ
|
| 627 |
+
βββββββββββββββ
|
| 628 |
+
β
|
| 629 |
+
At Q20: βΌ
|
| 630 |
+
βββββββββββββββββββββββββββββββββββ
|
| 631 |
+
β 9. Generate session report β
|
| 632 |
+
β (Cloud Function) β
|
| 633 |
+
β Show summary to student β
|
| 634 |
+
βββββββββββββββββββββββββββββββββββ
|
| 635 |
+
```
|
| 636 |
+
|
| 637 |
+
### 3.2 Flow B: "Input Your Question" Mode
|
| 638 |
+
|
| 639 |
+
```
|
| 640 |
+
Student types/pastes a math word problem
|
| 641 |
+
β
|
| 642 |
+
βΌ
|
| 643 |
+
βββββββββββββββββββββββββββββββββββ
|
| 644 |
+
β 1. Cloud Function: β
|
| 645 |
+
β processCustomProblem β
|
| 646 |
+
β - Validate it's a math β
|
| 647 |
+
β word problem β
|
| 648 |
+
β - Extract answer/solution β
|
| 649 |
+
β - Call Gemini/SLM to generateβ
|
| 650 |
+
β L1, L2, L3, L4 scaffolds β
|
| 651 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 652 |
+
β
|
| 653 |
+
βΌ
|
| 654 |
+
βββββββββββββββββββββββββββββββββββ
|
| 655 |
+
β 2. Estimate difficulty level β
|
| 656 |
+
β using readability metrics β
|
| 657 |
+
β (FK grade, word count, etc.) β
|
| 658 |
+
β Map to nearest Elo rating β
|
| 659 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 660 |
+
β
|
| 661 |
+
βΌ
|
| 662 |
+
βββββββββββββββββββββββββββββββββββ
|
| 663 |
+
β 3. Display problem with β
|
| 664 |
+
β scaffold buttons active β
|
| 665 |
+
β (same UI as Practice mode) β
|
| 666 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 667 |
+
β
|
| 668 |
+
βΌ
|
| 669 |
+
βββββββββββββββββββββββββββββββββββ
|
| 670 |
+
β 4. Student interacts, solves β
|
| 671 |
+
β Same hint tracking as β
|
| 672 |
+
β Practice mode β
|
| 673 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 674 |
+
β
|
| 675 |
+
βΌ
|
| 676 |
+
βββββββββββββββββββββββββββββββββββ
|
| 677 |
+
β 5. Update adaptive state β
|
| 678 |
+
β (Elo, BKT, Thompson) β
|
| 679 |
+
β Log interaction β
|
| 680 |
+
ββββββββββββββ¬βββββββββββββββββββββ
|
| 681 |
+
β
|
| 682 |
+
βΌ
|
| 683 |
+
βββββββββββββββββββββββββββββββββββ
|
| 684 |
+
β 6. Offer: "Try another?" or β
|
| 685 |
+
β "Switch to Practice Mode" β
|
| 686 |
+
β (where engine auto-selects) β
|
| 687 |
+
βββββββββββββββββββββββββββββββββββ
|
| 688 |
+
```
|
| 689 |
+
|
| 690 |
+
---
|
| 691 |
+
|
| 692 |
+
## 4. API Contracts
|
| 693 |
+
|
| 694 |
+
### 4.1 Client β Cloud Functions
|
| 695 |
+
|
| 696 |
+
```typescript
|
| 697 |
+
// POST /generateScaffolds
|
| 698 |
+
interface GenerateScaffoldsRequest {
|
| 699 |
+
problemText: string;
|
| 700 |
+
gradeLevel: number; // 6, 7, or 8
|
| 701 |
+
currentLDS: number; // 0.0-1.0, informs simplification
|
| 702 |
+
}
|
| 703 |
+
interface GenerateScaffoldsResponse {
|
| 704 |
+
scaffolds: {
|
| 705 |
+
L1_simplified: string;
|
| 706 |
+
L2_bilingual: string;
|
| 707 |
+
L3_spanish: string;
|
| 708 |
+
L4_solution: string;
|
| 709 |
+
};
|
| 710 |
+
answer: string;
|
| 711 |
+
answerNumeric: number;
|
| 712 |
+
estimatedLevel: string; // e.g., "2.3"
|
| 713 |
+
estimatedElo: number; // e.g., 1100
|
| 714 |
+
processingTimeMs: number;
|
| 715 |
+
}
|
| 716 |
+
|
| 717 |
+
// POST /batchGenerateQuestions
|
| 718 |
+
interface BatchRequest {
|
| 719 |
+
batchSize: number; // default 20
|
| 720 |
+
// Auth token provides uid β adaptive state looked up server-side
|
| 721 |
+
}
|
| 722 |
+
interface BatchResponse {
|
| 723 |
+
questions: QuestionWithScaffolds[];
|
| 724 |
+
sessionBatchId: string;
|
| 725 |
+
}
|
| 726 |
+
|
| 727 |
+
// POST /submitInteraction
|
| 728 |
+
interface InteractionSubmission {
|
| 729 |
+
sessionId: string;
|
| 730 |
+
questionId: string;
|
| 731 |
+
answer: string;
|
| 732 |
+
isCorrect: boolean;
|
| 733 |
+
timeSpentMs: number;
|
| 734 |
+
hintsUsed: number[]; // [0], [0,1], [0,1,2], etc.
|
| 735 |
+
hintTimestamps: Record<string, number>;
|
| 736 |
+
attempts: number;
|
| 737 |
+
}
|
| 738 |
+
interface InteractionResponse {
|
| 739 |
+
weightedOutcome: number;
|
| 740 |
+
lds: number;
|
| 741 |
+
mcs: number;
|
| 742 |
+
newElo: number;
|
| 743 |
+
newLevel: string;
|
| 744 |
+
decision: "increase" | "maintain" | "decrease" | "skip" | "rapid_decrease";
|
| 745 |
+
nextQuestion: QuestionWithScaffolds; // Pre-selected
|
| 746 |
+
}
|
| 747 |
+
|
| 748 |
+
// POST /generateSessionReport
|
| 749 |
+
interface SessionReportRequest {
|
| 750 |
+
sessionId: string;
|
| 751 |
+
}
|
| 752 |
+
interface SessionReportResponse {
|
| 753 |
+
summary: {
|
| 754 |
+
questionsAttempted: number;
|
| 755 |
+
questionsCorrect: number;
|
| 756 |
+
avgWeightedOutcome: number;
|
| 757 |
+
eloChange: number;
|
| 758 |
+
topicsStrong: string[];
|
| 759 |
+
topicsWeak: string[];
|
| 760 |
+
avgLDS: number;
|
| 761 |
+
avgMCS: number;
|
| 762 |
+
languageProgressNote: string; // Generated text about L2 progress
|
| 763 |
+
};
|
| 764 |
+
recommendations: string[]; // e.g., "Focus on fractions vocabulary"
|
| 765 |
+
}
|
| 766 |
+
```
|
| 767 |
+
|
| 768 |
+
---
|
| 769 |
+
|
| 770 |
+
## 5. Deployment Architecture
|
| 771 |
+
|
| 772 |
+
### 5.1 V1 Deployment (MVP)
|
| 773 |
+
|
| 774 |
+
```
|
| 775 |
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 776 |
+
β Firebase Project β
|
| 777 |
+
β β
|
| 778 |
+
β βββββββββββββββ βββββββββββββββ ββββββββββββββββββββ β
|
| 779 |
+
β β Firebase β β Cloud β β Cloud β β
|
| 780 |
+
β β Hosting β β Firestore β β Functions β β
|
| 781 |
+
β β (Next.js) β β (Database) β β (Node.js 20) β β
|
| 782 |
+
β β β β β β β β
|
| 783 |
+
β β Static + β β Student β β LLM calls β β
|
| 784 |
+
β β SSR pages β β state, β β Batch gen β β
|
| 785 |
+
β β β β questions, β β Reports β β
|
| 786 |
+
β β β β sessions β β β β
|
| 787 |
+
β ββββββββββββββββ ββββββββββββββββ βββββββββ¬βββββββββββ β
|
| 788 |
+
β β β
|
| 789 |
+
ββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββ
|
| 790 |
+
β
|
| 791 |
+
HTTPS β
|
| 792 |
+
βΌ
|
| 793 |
+
ββββββββββββββββββββ
|
| 794 |
+
β Google Gemini β
|
| 795 |
+
β 2.0 Flash API β
|
| 796 |
+
ββββββββββββββββββββ
|
| 797 |
+
|
| 798 |
+
Estimated monthly cost (100 students, 5 sessions/week):
|
| 799 |
+
- Firebase Hosting: Free tier (~$0)
|
| 800 |
+
- Firestore: ~$5/mo (reads/writes within free tier mostly)
|
| 801 |
+
- Cloud Functions: ~$10/mo (invocations + compute)
|
| 802 |
+
- Gemini API: ~$15-25/mo (scaffold generation)
|
| 803 |
+
- Total: ~$30-40/mo
|
| 804 |
+
```
|
| 805 |
+
|
| 806 |
+
### 5.2 V2 Deployment (SLM)
|
| 807 |
+
|
| 808 |
+
```
|
| 809 |
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 810 |
+
β Firebase Project β
|
| 811 |
+
β β
|
| 812 |
+
β βββββββββββββββ βββββββββββββββ ββββββββββββββββββββ β
|
| 813 |
+
β β Firebase β β Cloud β β Cloud β β
|
| 814 |
+
β β Hosting β β Firestore β β Functions β β
|
| 815 |
+
β ββββββββββββββββ ββββββββββββββββ βββββββββ¬βββββββββββ β
|
| 816 |
+
β β β
|
| 817 |
+
ββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββ
|
| 818 |
+
β
|
| 819 |
+
βββββββββββββββββββΌβββββββββββββββ
|
| 820 |
+
β β β
|
| 821 |
+
βΌ βΌ β
|
| 822 |
+
ββββββββββββββββββββ ββββββββββββββββ β
|
| 823 |
+
β HF Inference β β Gemini API β β
|
| 824 |
+
β Endpoint β β (fallback) β β
|
| 825 |
+
β Qwen2.5-3B β ββββββββββββββββ β
|
| 826 |
+
β QLoRA FT β β
|
| 827 |
+
β (T4 GPU) β Shadow testing: β
|
| 828 |
+
ββββββββββββββββββββ Both called, SLM β
|
| 829 |
+
response served, β
|
| 830 |
+
Gemini response β
|
| 831 |
+
logged for QA β
|
| 832 |
+
ββββββββββββββββββββββ
|
| 833 |
+
|
| 834 |
+
Estimated monthly cost (100 students):
|
| 835 |
+
- Firebase: ~$15/mo (same as V1)
|
| 836 |
+
- HF Inference Endpoint (T4, scale-to-zero): ~$50-100/mo
|
| 837 |
+
(active only during school hours, ~8hrs/day Γ 20 days)
|
| 838 |
+
- Gemini fallback: ~$5/mo (only when SLM is cold)
|
| 839 |
+
- Total: ~$70-120/mo (but no per-token costs at scale)
|
| 840 |
+
```
|
| 841 |
+
|
| 842 |
+
### 5.3 V3 Deployment (Scale)
|
| 843 |
+
|
| 844 |
+
```
|
| 845 |
+
When student count exceeds 500+, migrate to:
|
| 846 |
+
|
| 847 |
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 848 |
+
β β
|
| 849 |
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ β
|
| 850 |
+
β β Vercel β β Firebase β β Cloud Run β β
|
| 851 |
+
β β (Next.js) β β Firestore β β (API server) β β
|
| 852 |
+
β ββββββββββββββββ ββββββββββββββββ βββββββββ¬βββββββββββ β
|
| 853 |
+
β β β
|
| 854 |
+
β βββββββββββββββββββββββββββΌβββββββ β
|
| 855 |
+
β β β β β
|
| 856 |
+
β βΌ βΌ β β
|
| 857 |
+
β ββββββββββββββββββββ βββββββββββββββββββ β β
|
| 858 |
+
β β HF Inference EP β β IRT/DKT Model β β β
|
| 859 |
+
β β Qwen2.5-3B β β Server β β β
|
| 860 |
+
β β (Auto-scaling) β β (Python/FastAPI)β β β
|
| 861 |
+
β ββββββββββββββββββββ βββββββββββββββββββ β β
|
| 862 |
+
β β β
|
| 863 |
+
β + Deep Knowledge Tracing (DKT) replaces BKT β β
|
| 864 |
+
β + IRT item calibration from pooled student data β β
|
| 865 |
+
β + A/B testing framework for algorithm improvements β β
|
| 866 |
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 867 |
+
```
|
| 868 |
+
|
| 869 |
+
---
|
| 870 |
+
|
| 871 |
+
## 6. Technology Stack Summary
|
| 872 |
+
|
| 873 |
+
| Layer | Technology | Justification |
|
| 874 |
+
|---|---|---|
|
| 875 |
+
| Frontend Framework | Next.js 14+ (App Router) | SSR for SEO, React ecosystem, TypeScript |
|
| 876 |
+
| UI Styling | Tailwind CSS + shadcn/ui | Rapid prototyping, consistent design |
|
| 877 |
+
| Math Rendering | KaTeX | Fast client-side LaTeX rendering |
|
| 878 |
+
| Charts | Recharts | React-native charting for dashboards |
|
| 879 |
+
| Authentication | Firebase Auth | Google Sign-In, simple integration |
|
| 880 |
+
| Database | Cloud Firestore | Real-time sync, offline support, serverless |
|
| 881 |
+
| Serverless Functions | Firebase Cloud Functions (Node.js 20) | Low latency, Firebase integration |
|
| 882 |
+
| LLM (V1) | Google Gemini 2.0 Flash | Low cost, fast, good multilingual |
|
| 883 |
+
| SLM (V2) | Qwen2.5-3B-Instruct (QLoRA fine-tuned) | Best math+Spanish at 3B, Apache 2.0 |
|
| 884 |
+
| SLM Hosting | HF Inference Endpoints (T4, scale-to-zero) | Cost-effective, no infra management |
|
| 885 |
+
| Adaptive Engine | Client-side TypeScript | Zero-latency decisions, works offline |
|
| 886 |
+
| State Management | Zustand + Firestore sync | Lightweight, persists across sessions |
|
| 887 |
+
| Testing | Vitest + Playwright | Unit + E2E testing |
|
| 888 |
+
| CI/CD | GitHub Actions | Automated testing + Firebase deploy |
|
| 889 |
+
| Monitoring | Firebase Analytics + Crashlytics | User behavior + error tracking |
|
| 890 |
+
|
| 891 |
+
---
|
| 892 |
+
|
| 893 |
+
## 7. Security & Privacy Considerations
|
| 894 |
+
|
| 895 |
+
### 7.1 Data Protection
|
| 896 |
+
- **COPPA Compliance**: Students are minors (ages 11-14). No personally identifiable information stored beyond email/display name. No third-party tracking.
|
| 897 |
+
- **FERPA Alignment**: Performance data (Elo, LDS, MCS) is associated with uid only. Teachers/admins see aggregate data, never individual student identifiers.
|
| 898 |
+
- **Data Encryption**: Firestore encrypts at rest (AES-256). All API calls over HTTPS/TLS 1.3.
|
| 899 |
+
|
| 900 |
+
### 7.2 API Security
|
| 901 |
+
- Firebase Auth tokens required for all Cloud Function calls
|
| 902 |
+
- Gemini/SLM API keys stored in Firebase environment secrets (never client-side)
|
| 903 |
+
- Rate limiting on Cloud Functions to prevent abuse (max 10 scaffold generations per minute per user)
|
| 904 |
+
|
| 905 |
+
### 7.3 Content Safety
|
| 906 |
+
- All LLM-generated scaffolds pass through a validation function checking:
|
| 907 |
+
- Mathematical accuracy (answer matches expected)
|
| 908 |
+
- Appropriate content (no adult/violent themes)
|
| 909 |
+
- Language accuracy (Spanish translation verified against expected pattern)
|
| 910 |
+
- Questions from the curated database are pre-reviewed; generated questions flagged for human review
|
| 911 |
+
|
| 912 |
+
---
|
| 913 |
+
|
| 914 |
+
## 8. Performance Targets
|
| 915 |
+
|
| 916 |
+
| Metric | Target | Measurement |
|
| 917 |
+
|---|---|---|
|
| 918 |
+
| Time to first problem display | < 2 seconds | Lighthouse / Firebase Performance |
|
| 919 |
+
| Adaptive decision latency | < 50ms | Client-side (no network) |
|
| 920 |
+
| Scaffold generation (Gemini) | < 1.5 seconds | Cloud Function logs |
|
| 921 |
+
| Scaffold generation (SLM) | < 800ms | HF Inference EP metrics |
|
| 922 |
+
| Batch prefetch trigger β ready | < 5 seconds | 20 questions fetched at Q17 |
|
| 923 |
+
| Offline capability | Full session | After initial batch load |
|
| 924 |
+
| Concurrent users (V1) | 50 | Firebase free/Blaze tier |
|
| 925 |
+
| Concurrent users (V2) | 500+ | HF auto-scaling endpoint |
|