CoolFace
Apppublic

shalev396/video-quiz-generator

sourceHugging Facemitupdated 16h agoView on Hugging Face
0likes
App README

๐Ÿ“ AI Quiz Generator

Upload an audio or video recording (a lecture, talk or meeting) or paste a transcript. The Space transcribes it with Whisper, asks Qwen2.5-Instruct for a multiple-choice quiz in strict JSON, checks the reply against the schema and lets you take the quiz and get graded. The reply is parsed leniently (code fences, smart quotes, trailing commas and stray quotes are fixed; whole question objects are salvaged from a broken reply) but every question is validated strictly. When the quiz is not valid the model gets up to 2 repair turns, then one fresh generation with light seeded sampling (plus 1 repair turn).

API

/predict, inputs, in order:

#nametypenotes
0mediafile or nullaudio/video file; only the first 180 s are used
1transcriptstringused only when media is null
2n_questionsnumber2 to 10
3difficultystringeasy, medium, hard or mixed

Outputs: [quiz, seconds, device]. seconds is a float, device is "gpu" or "cpu", and quiz is:

jsonc
{
  "questions": [
    {"question": "...", "options": ["...", "...", "...", "..."], "answer_index": 0, "explanation": "..."}
  ],
  "valid": true,                 // every schema check passed (incl. exactly n_questions questions)
  "valid_first_try": true,       // the first reply was valid: no repair turn or retry was needed
  "strict_json_first_try": true, // the first reply was valid JSON as written (no syntax fix)
  "attempts": 1,                 // model calls: 1 generation + repair turns (+ 1 fresh retry), at most 5
  "repairs": [],                 // repair turns run, in order: "fix" (corrected reply) | "more" (missing questions)
  "regenerated": false,          // true when the fresh sampled generation ran
  "parse": ["strict"],           // per attempt: "strict" | "lenient" | "salvaged" | "unreadable"
  "chosen_attempt": 1,           // which attempt was returned (the first valid one, else the one with most questions)
  "problems": [],                // what failed validation in the returned attempt
  "n_questions": 4,              // requested (clamped to 2-10)
  "n_delivered": 4,              // questions actually returned; < n_questions only when valid is false
  "difficulty": "mixed",
  "transcript": "...",           // the text the quiz was written from
  "source": "media",             // "media" | "text"
  "audio_seconds": 11.01,        // null for text input
  "audio_truncated": false,
  "asr_model": "openai/whisper-small",
  "llm_model": "Qwen/Qwen2.5-1.5B-Instruct"
}

When no attempt returns a single usable question, the call fails with an error message instead.

bash
S=https://shalev396-video-quiz-generator.hf.space
# pasted transcript
curl -X POST $S/gradio_api/call/predict -H "Content-Type: application/json" \
  -d '{"data": [null, "Honey bees live in colonies. A single queen lays the eggs, while workers collect nectar.", 3, "easy"]}'
# a media file by URL
WAV=https://huggingface.co/spaces/shalev396/video-quiz-generator/resolve/main/examples/jfk.wav
curl -X POST $S/gradio_api/call/predict -H "Content-Type: application/json" \
  -d "{\"data\": [{\"path\": \"$WAV\", \"meta\": {\"_type\": \"gradio.FileData\"}}, \"\", 2, \"mixed\"]}"
curl -N $S/gradio_api/call/predict/<event_id>
js
import { Client, handle_file } from "@gradio/client";
const client = await Client.connect("shalev396/video-quiz-generator");
const { data } = await client.predict("/predict", [
  handle_file("https://huggingface.co/spaces/shalev396/video-quiz-generator/resolve/main/examples/jfk.wav"),
  "", 2, "mixed",
]);
// data = [{questions: [...], valid: true, ...}, 4.2, "gpu"]

How it works

pipeline.py (in this Space) does everything: PyAV decodes the audio track to 16 kHz mono, Whisper transcribes it in 30 s windows, Qwen2.5-Instruct writes the quiz (greedy decoding, one worked example in the prompt), and the reply is validated, with the repair / retry turns above when needed. On ZeroGPU no new repair or retry call starts after half of the GPU time budget. There is no model repo: all three models are pretrained Hub checkpoints, preloaded at build time.

Hardware: ZeroGPU runs whisper-small + Qwen2.5-1.5B-Instruct. On CPU hardware the same code runs whisper-tiny + Qwen2.5-1.5B-Instruct (~2.5 min per quiz). Qwen2.5-0.5B was evaluated and rejected: 0/6 valid quizzes. There is no CPU fallback on ZeroGPU: a visitor without GPU quota gets the ZeroGPU error message.

Evaluation (schema-valid rate, LLM-judge scores) is in the training notebook.