Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -33,7 +33,8 @@ class QuizGenerator:
|
|
33 |
messages=[
|
34 |
{
|
35 |
"role": "system",
|
36 |
-
"content": "You are a quiz generator. Create clear questions with concise answer options.
|
|
|
37 |
},
|
38 |
{
|
39 |
"role": "user",
|
@@ -49,68 +50,105 @@ class QuizGenerator:
|
|
49 |
return self._validate_questions(questions, num_questions)
|
50 |
|
51 |
except Exception as e:
|
|
|
|
|
52 |
raise QuizGenerationError(f"Failed to generate questions: {str(e)}")
|
53 |
|
54 |
def _create_prompt(self, text: str, num_questions: int) -> str:
|
55 |
-
return f"""
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
[
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
|
80 |
def _parse_response(self, response_text: str) -> List[Dict]:
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
def _validate_questions(self, questions: List[Dict], num_questions: int) -> List[Question]:
|
|
|
92 |
validated = []
|
|
|
93 |
for q in questions:
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
continue
|
96 |
-
validated.append(Question(
|
97 |
-
question=q["question"].strip(),
|
98 |
-
options=[opt.strip()[:100] for opt in q["options"]],
|
99 |
-
correct_answer=int(q["correct_answer"]) % 4
|
100 |
-
))
|
101 |
|
102 |
if not validated:
|
103 |
raise ValueError("No valid questions after validation")
|
104 |
-
|
105 |
return validated[:num_questions]
|
106 |
|
107 |
def _is_valid_question(self, question: Dict) -> bool:
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
class FontManager:
|
116 |
"""Manages font installation and loading for the certificate generator"""
|
|
|
33 |
messages=[
|
34 |
{
|
35 |
"role": "system",
|
36 |
+
"content": """You are a quiz generator. Create clear questions with concise answer options.
|
37 |
+
Always return valid JSON array of questions. Format answers as short, clear phrases."""
|
38 |
},
|
39 |
{
|
40 |
"role": "user",
|
|
|
50 |
return self._validate_questions(questions, num_questions)
|
51 |
|
52 |
except Exception as e:
|
53 |
+
print(f"Error in generate_questions: {str(e)}")
|
54 |
+
print(f"Response content: {response.choices[0].message.content if response else 'No response'}")
|
55 |
raise QuizGenerationError(f"Failed to generate questions: {str(e)}")
|
56 |
|
57 |
def _create_prompt(self, text: str, num_questions: int) -> str:
|
58 |
+
return f"""Generate exactly {num_questions} multiple choice questions based on the following text. Follow these rules strictly:
|
59 |
+
|
60 |
+
1. Each question must be clear and focused
|
61 |
+
2. Provide exactly 4 options for each question
|
62 |
+
3. Mark the correct answer with index (0-3)
|
63 |
+
4. Keep all options concise (under 10 words)
|
64 |
+
5. Return ONLY a JSON array with this exact format:
|
65 |
+
[
|
66 |
+
{{
|
67 |
+
"question": "Clear question text here?",
|
68 |
+
"options": [
|
69 |
+
"Brief option 1",
|
70 |
+
"Brief option 2",
|
71 |
+
"Brief option 3",
|
72 |
+
"Brief option 4"
|
73 |
+
],
|
74 |
+
"correct_answer": 0
|
75 |
+
}}
|
76 |
+
]
|
77 |
+
|
78 |
+
Text to generate questions from:
|
79 |
+
{text}
|
80 |
+
|
81 |
+
Important: Return only the JSON array, no other text or formatting."""
|
82 |
|
83 |
def _parse_response(self, response_text: str) -> List[Dict]:
|
84 |
+
"""Parse response with improved error handling"""
|
85 |
+
try:
|
86 |
+
# Clean up the response text
|
87 |
+
cleaned_text = response_text.strip()
|
88 |
+
cleaned_text = cleaned_text.replace('```json', '').replace('```', '').strip()
|
89 |
+
|
90 |
+
# Find the JSON array
|
91 |
+
start_idx = cleaned_text.find('[')
|
92 |
+
end_idx = cleaned_text.rfind(']')
|
93 |
+
|
94 |
+
if start_idx == -1 or end_idx == -1:
|
95 |
+
raise ValueError("No valid JSON array found in response")
|
96 |
+
|
97 |
+
json_text = cleaned_text[start_idx:end_idx + 1]
|
98 |
|
99 |
+
# Attempt to parse the JSON
|
100 |
+
try:
|
101 |
+
return json.loads(json_text)
|
102 |
+
except json.JSONDecodeError as e:
|
103 |
+
print(f"JSON Parse Error: {str(e)}")
|
104 |
+
print(f"Attempted to parse: {json_text}")
|
105 |
+
raise
|
106 |
+
|
107 |
+
except Exception as e:
|
108 |
+
print(f"Error parsing response: {str(e)}")
|
109 |
+
print(f"Original response: {response_text}")
|
110 |
+
raise ValueError(f"Failed to parse response: {str(e)}")
|
111 |
|
112 |
def _validate_questions(self, questions: List[Dict], num_questions: int) -> List[Question]:
|
113 |
+
"""Validate questions with improved error checking"""
|
114 |
validated = []
|
115 |
+
|
116 |
for q in questions:
|
117 |
+
try:
|
118 |
+
if not self._is_valid_question(q):
|
119 |
+
print(f"Invalid question format: {q}")
|
120 |
+
continue
|
121 |
+
|
122 |
+
validated.append(Question(
|
123 |
+
question=q["question"].strip(),
|
124 |
+
options=[str(opt).strip()[:100] for opt in q["options"]],
|
125 |
+
correct_answer=int(q["correct_answer"]) % 4
|
126 |
+
))
|
127 |
+
except Exception as e:
|
128 |
+
print(f"Error validating question: {str(e)}")
|
129 |
continue
|
|
|
|
|
|
|
|
|
|
|
130 |
|
131 |
if not validated:
|
132 |
raise ValueError("No valid questions after validation")
|
133 |
+
|
134 |
return validated[:num_questions]
|
135 |
|
136 |
def _is_valid_question(self, question: Dict) -> bool:
|
137 |
+
"""Check if question format is valid"""
|
138 |
+
try:
|
139 |
+
return (
|
140 |
+
isinstance(question, dict) and
|
141 |
+
all(key in question for key in ["question", "options", "correct_answer"]) and
|
142 |
+
isinstance(question["question"], str) and
|
143 |
+
isinstance(question["options"], list) and
|
144 |
+
len(question["options"]) == 4 and
|
145 |
+
all(isinstance(opt, str) for opt in question["options"]) and
|
146 |
+
isinstance(question["correct_answer"], (int, str)) and
|
147 |
+
int(question["correct_answer"]) in range(4)
|
148 |
+
)
|
149 |
+
except Exception as e:
|
150 |
+
print(f"Question validation error: {str(e)}")
|
151 |
+
return False
|
152 |
|
153 |
class FontManager:
|
154 |
"""Manages font installation and loading for the certificate generator"""
|