AI Tutor & RAG Runtime
Cách EduGap vận hành LangGraph tutor, RAG retrieval, citation validation, guardrails và streaming chat.
AI tutor của EduGap là một Socratic RAG agent: câu trả lời phải bám vào tài liệu khóa học, thích ứng theo trạng thái học viên và không đưa lời giải trực tiếp cho bài kiểm tra hoặc lab.
Source map
| Thành phần | File chính |
|---|---|
| Chat endpoint | src/api/routes.py |
| Agent graph | src/agents/graph.py |
| Analyze node | src/agents/nodes/analyze_node.py |
| Academic response node | src/agents/nodes/respond_node.py |
| General response node | src/agents/nodes/respond_general_node.py |
| Pedagogical reflection | src/agents/nodes/pedagogical_reflection_node.py |
| RAG retrieval | src/services/rag.py |
| Citation validator | src/services/citation_validator.py |
Graph lifecycle
flowchart LR
Start["Chat request"] --> Analyze["analyze_node"]
Analyze -->|"intent = general"| General["respond_general"]
Analyze -->|"intent = academic"| Academic["respond_academic"]
Academic --> Check{"Contains code or direct answer pattern?"}
Check -->|"No"| End["END"]
Check -->|"Yes"| Reflect["pedagogical_reflection"]
Reflect -->|"Needs rewrite, max 2 attempts"| Academic
Reflect -->|"Accepted"| End
General --> EndThe graph optimizes latency by skipping the reflection step when the answer has no code block and no direct MCQ answer pattern.
Request lifecycle
/api/v1/chatvalidates that a student can only chat as themselves.- Backend loads mastery/profile from cache or database.
- If
session_idexists, backend validates the session; otherwise it creates achat_sessionsrow. - Backend loads recent chat history and long-term memory.
- LangGraph receives query, mode, course/concept context, profile and history.
- Response is saved to
chat_messages. - A background task extracts long-term facts from the conversation.
- Timing and trace metadata are logged to Braintrust.
RAG retrieval strategy
RAGService retrieves official course material from Supabase:
- Normalize query and check retrieval cache.
- Resolve concept code when
concept_idis present. - Apply day-aware document regex filters for course-day-specific context.
- Generate embedding with
text-embedding-3-smallor OpenRouter-compatible embedding config. - Call Supabase RPC
match_slidesover pgvector. - Optionally run keyword fallback when semantic similarity is weak.
- Optionally retry global search if the day filter is too narrow.
- Add neighboring slides for stronger local context.
- Deduplicate logical document versions and cache final results.
Citation validation
Academic answers should cite retrieved sources. The validator checks citation tags against the actual retrieved slide list:
| Case | Behavior |
|---|---|
| Citation source and slide match retrieved context | Mark as valid |
| Citation references a source not retrieved | Mark as invalid/hallucinated |
| Important claim has no valid citation | Metadata flags low citation confidence |
Frontend receives citation metadata through the chat response contract and can show citations, warnings or confidence state without trusting raw LLM text alone.
Guardrails
EduGap protects academic integrity in three places:
- Prompt policy: The tutor is instructed to guide with Socratic questions and hints, not full answers.
- Active quiz context: When a learner is in an active quiz, the tutor must stay at conceptual/analogy hint levels.
- Reflection node: Responses containing code blocks or direct answer phrasing can be routed through a pedagogical review step and rewritten.
Streaming behavior
The BFF route forwards text/event-stream unchanged and sets headers for no buffering. This allows chat UI to show progressive states while preserving the same backend auth and tracing path as non-streaming chat.