feat: interactive quiz and pedagogical shortcuts (Je n'ai pas compris button) - #283
Conversation
- Add InteractiveQuiz.svelte: interactive MCQ modal with click-to-answer, correct/incorrect feedback with explanation, retry and final score screen - Update PedagogicalShortcuts.svelte: Multiple Choice opens interactive quiz - Add 'Je n ai pas compris' button: re-explains with analogy, example, table - Fix proxy timeout: TIMEOUT_DEFAULT 30s to 120s in ai/providers/proxy.py
|
thk you for your contribution. |
|
Hi, thk for contuning dev. |
There was a problem hiding this comment.
Pull request overview
This PR enhances the student chat experience by adding an interactive quiz flow and a new “I didn’t understand” pedagogical shortcut, while also increasing backend proxy timeouts to better accommodate longer LLM generations.
Changes:
- Adds an interactive MCQ quiz modal experience and passes recent chat context into shortcuts for quiz generation.
- Introduces a new “Je n’ai pas compris” shortcut that triggers multi-angle re-explanations.
- Increases default proxy timeout to reduce 502s during longer generations.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/src/lib/components/student/tutor/Chat.svelte | Adjusts assistant message initialization (placeholder message state). |
| ui/src/lib/components/student/pages/Chat.svelte | Tweaks layout/RightBar behavior and styling; introduces a new (currently unused) local state var. |
| ui/src/lib/components/chat/Shortcuts/PedagogicalShortcuts.svelte | Reworks pedagogical shortcuts UI, adds “Je n’ai pas compris”, and implements an inline quiz modal + generation flow. |
| ui/src/lib/components/chat/Shortcuts/InteractiveQuiz.svelte | Adds a standalone interactive quiz component with streaming JSON parsing. |
| ui/src/lib/components/chat/Messages/ContentRenderer.svelte | Adds quiz JSON detection and attempts to render a QuizWidget instead of Markdown. |
| ui/src/lib/components/chat/MessageInput.svelte | Passes recent conversation context into PedagogicalShortcuts for better quiz generation prompts. |
| ai/providers/proxy.py | Increases TIMEOUT_DEFAULT to 120s to support longer generations. |
| import Markdown from './Markdown.svelte'; | ||
| import QuizWidget from './QuizWidget.svelte'; | ||
| import { chatId, mobile, showArtifacts, showControls, showOverview } from '$lib/stores'; |
| <PedagogicalShortcuts on:submit={handleShortcut} conversationContext={ | ||
| history?.messages | ||
| ? Object.values(history.messages) | ||
| .filter(m => m?.role && m?.content) | ||
| .slice(-8) | ||
| .map(m => (m.role === 'user' ? 'Etudiant: ' : 'IA: ') + (typeof m.content === 'string' ? m.content : m.content?.[0]?.text || '')) | ||
| .join('\n') | ||
| : '' | ||
| } /> |
| type Phase = 'idle' | 'loading' | 'quiz' | 'results'; | ||
| let phase: Phase = 'idle'; |
| while (true) { | ||
| const { done, value } = await reader.read(); | ||
| if (done) break; | ||
| const chunk = decoder.decode(value, { stream: true }); | ||
| // Parser les lignes JSON du stream Ollama | ||
| for (const line of chunk.split('\n')) { | ||
| if (!line.trim()) continue; | ||
| try { | ||
| const parsed = JSON.parse(line); | ||
| if (parsed?.message?.content) { | ||
| fullText += parsed.message.content; | ||
| } | ||
| if (parsed?.done) break; | ||
| } catch {} | ||
| } | ||
| } |
| let chatData = {}; | ||
| let isRightBarVisible = false; | ||
| let sidebarOpen = true; | ||
|
|
| <!-- | ||
| InteractiveQuiz.svelte | ||
| Emplacement: ui/src/lib/components/chat/Shortcuts/InteractiveQuiz.svelte | ||
| --> | ||
| <script lang="ts"> | ||
| import { createEventDispatcher, getContext } from 'svelte'; | ||
| import { get } from 'svelte/store'; | ||
| import { models, settings, user } from '$lib/stores'; | ||
| import { generateChatCompletion } from '$lib/apis/ollama'; | ||
|
|
||
| const dispatch = createEventDispatcher(); | ||
| const i18n: any = getContext('i18n'); | ||
|
|
||
| export let conversationContext: string = ''; | ||
|
|
||
| type Phase = 'idle' | 'loading' | 'quiz' | 'results'; | ||
| let phase: Phase = 'idle'; | ||
| let questions: Question[] = []; |
| <button type="button" on:click={didntUnderstand} class="nav-button confused-theme"> | ||
| 🤔 Je n'ai pas compris | ||
| </button> |
|
Hi @IlhamELBOUAZOULI Per the project rule, documentation must be submitted in docs/ in the same Pull Request as the code . For this feature (interactive quiz modal + "I didn't understand" shortcut), this means at minimum:
Could you add these before this is ready for review? |
|
Thank you for the review! The documentation has been added in the second commit of this PR (
You can view the files here:
Please let me know if anything needs to be adjusted or expanded. Ready for re-review! Best regards, |
Adds an interactive MCQ quiz modal and a "I didn't understand" pedagogical
shortcut button to the student chat interface, improving the learning experience
with immediate feedback and adaptive re-explanation.
Added
InteractiveQuiz.svelte: new interactive quiz modal component with:PedagogicalShortcuts.svelte: re-explainsthe current concept in 3 different ways:
Changed
PedagogicalShortcuts.svelte: "Multiple Choice" button now opens theinteractive quiz modal instead of sending a plain text prompt to the chat
MessageInput.svelte: integrated InteractiveQuiz componentui/src/lib/components/student/tutor/Chat.svelte: updated to supportnew pedagogical shortcuts
ui/src/lib/components/student/pages/Chat.svelte: updated chat pageai/providers/proxy.py: increased TIMEOUT_DEFAULT from 30s to 120sto support LLM generation time
Fixed
Screenshots
Quiz - Multiple Choice Question

An interactive quiz modal displays an MCQ with 4 clickable options (A, B, C, D)
Quiz - Réponse correcte avec feedback

When the student selects the correct answer, it turns green ✅ with immediate explanation
Quiz - Incorrect Answer with Re-explanation

In case of a wrong answer, it turns red ❌, the correct answer is highlighted, and a re-explanation is displayed
Quiz - Final Results Screen

Once the quiz is completed, the student views their final score, percentage, and detailed summary
"I didn't understand" Button


Re-explains the concept using an analogy, a concrete example, and a visual table