SolusOps/Study-with-ChampAI
0
1from __future__ import annotations2from typing import List3from quiz.models import Question, Quest4from services.model_router import ModelRouter5from services.json_parser import extract_json6from config.prompts import QUIZ_AGENT_BATCH_SYSTEM7 8class QuizAgent:9 def __init__(self, router: ModelRouter): self._router = router10 11 def generate_for_quest(self, quest: Quest, source_text: str = "",12 questions_per_quest: int = 3, language: str = "en") -> List[Question]:13 """14 Single Nemotron call generates all questions for a quest (regular + boss).15 source_text grounds questions in actual material, reducing hallucination.16 """17 source_snippet = source_text[:800] if source_text else "No source provided."18 prompt = (19 f"Quest: {quest.name}\n"20 f"Topics: {', '.join(quest.topics)}\n"21 f"Boss topic: {quest.boss_topic}\n"22 f"Language: {language}\n"23 f"Source material:\n{source_snippet}\n\n"24 f"Generate {questions_per_quest} regular questions (is_boss:false) "25 f"and 1 boss question (is_boss:true) as the last item."26 )27 raw = self._router.reason(prompt, QUIZ_AGENT_BATCH_SYSTEM)28 try:29 data = extract_json(raw)30 except ValueError as exc:31 raise ValueError(f"QuizAgent: {exc}") from exc32 33 questions = []34 for q_data in data.get("questions", []):35 questions.append(Question(36 text=q_data["question"],37 topic=q_data.get("topic", quest.boss_topic),38 options=q_data["options"],39 correct_idx=q_data["correct_idx"],40 explanation=q_data.get("explanation", ""),41 difficulty=q_data.get("difficulty", "medium"),42 q_type=q_data.get("type", "mcq"),43 is_boss=q_data.get("is_boss", False),44 source_excerpt=source_snippet[:200],45 language=language,46 ))47 return questions48 