Spaces:
Running
Running
| from __future__ import annotations | |
| from typing import List | |
| from quiz.models import Question, Quest | |
| from services.model_router import ModelRouter | |
| from services.json_parser import extract_json | |
| from config.prompts import QUIZ_AGENT_BATCH_SYSTEM | |
| class QuizAgent: | |
| def __init__(self, router: ModelRouter): self._router = router | |
| def generate_for_quest(self, quest: Quest, source_text: str = "", | |
| questions_per_quest: int = 3, language: str = "en") -> List[Question]: | |
| """ | |
| Single Nemotron call generates all questions for a quest (regular + boss). | |
| source_text grounds questions in actual material, reducing hallucination. | |
| """ | |
| source_snippet = source_text[:800] if source_text else "No source provided." | |
| prompt = ( | |
| f"Quest: {quest.name}\n" | |
| f"Topics: {', '.join(quest.topics)}\n" | |
| f"Boss topic: {quest.boss_topic}\n" | |
| f"Language: {language}\n" | |
| f"Source material:\n{source_snippet}\n\n" | |
| f"Generate {questions_per_quest} regular questions (is_boss:false) " | |
| f"and 1 boss question (is_boss:true) as the last item." | |
| ) | |
| raw = self._router.reason(prompt, QUIZ_AGENT_BATCH_SYSTEM) | |
| try: | |
| data = extract_json(raw) | |
| except ValueError as exc: | |
| raise ValueError(f"QuizAgent: {exc}") from exc | |
| questions = [] | |
| for q_data in data.get("questions", []): | |
| questions.append(Question( | |
| text=q_data["question"], | |
| topic=q_data.get("topic", quest.boss_topic), | |
| options=q_data["options"], | |
| correct_idx=q_data["correct_idx"], | |
| explanation=q_data.get("explanation", ""), | |
| difficulty=q_data.get("difficulty", "medium"), | |
| q_type=q_data.get("type", "mcq"), | |
| is_boss=q_data.get("is_boss", False), | |
| source_excerpt=source_snippet[:200], | |
| language=language, | |
| )) | |
| return questions | |