Spaces:
Running
Running
one q only
Browse files
app.py
CHANGED
@@ -96,28 +96,15 @@ def create_latex_document(content, questions_only=False):
|
|
96 |
\usepackage{amsmath,amssymb}
|
97 |
\usepackage[margin=1in]{geometry}
|
98 |
\begin{document}
|
99 |
-
\title{Mathematics
|
100 |
\maketitle
|
101 |
"""
|
102 |
latex_footer = r"\end{document}"
|
103 |
|
104 |
if questions_only:
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
if 'Solution:' in line:
|
109 |
-
processed_content.append('\n'.join(current_question))
|
110 |
-
current_question = []
|
111 |
-
continue
|
112 |
-
if any(line.startswith(f"{i})") for i in range(1, 4)):
|
113 |
-
if current_question:
|
114 |
-
processed_content.append('\n'.join(current_question))
|
115 |
-
current_question = [line]
|
116 |
-
elif current_question:
|
117 |
-
current_question.append(line)
|
118 |
-
if current_question:
|
119 |
-
processed_content.append('\n'.join(current_question))
|
120 |
-
content = '\n\n'.join(processed_content)
|
121 |
|
122 |
full_document = f"{latex_header}\n{content}\n{latex_footer}"
|
123 |
logger.debug(f"Created {'questions-only' if questions_only else 'full'} LaTeX document")
|
@@ -129,52 +116,24 @@ def create_latex_document(content, questions_only=False):
|
|
129 |
def save_to_temp_file(content, filename):
|
130 |
"""Save content to a temporary file and return the path"""
|
131 |
try:
|
132 |
-
# Create a temporary directory that persists
|
133 |
temp_dir = Path(tempfile.gettempdir()) / "math_test_files"
|
134 |
temp_dir.mkdir(exist_ok=True)
|
135 |
-
|
136 |
-
# Create the file path
|
137 |
file_path = temp_dir / filename
|
138 |
-
|
139 |
-
# Write the content
|
140 |
file_path.write_text(content, encoding='utf-8')
|
141 |
-
|
142 |
logger.debug(f"Saved content to temporary file: {file_path}")
|
143 |
return str(file_path)
|
144 |
except Exception as e:
|
145 |
logger.error(f"Error saving temporary file: {str(e)}")
|
146 |
raise
|
147 |
|
148 |
-
def
|
149 |
-
"""
|
150 |
try:
|
151 |
-
comp = int(computation)
|
152 |
-
prf = int(proof)
|
153 |
-
app = int(application)
|
154 |
-
|
155 |
-
if comp + prf + app != 3:
|
156 |
-
return False, "Total number of questions must equal 3"
|
157 |
-
if any(x < 0 for x in [comp, prf, app]):
|
158 |
-
return False, "Question counts cannot be negative"
|
159 |
-
return True, ""
|
160 |
-
except ValueError:
|
161 |
-
return False, "Please enter valid numbers"
|
162 |
-
|
163 |
-
def generate_test(subject, difficulty, computation_count, proof_count, application_count):
|
164 |
-
"""Generate a math test with enhanced difficulty scaling"""
|
165 |
-
try:
|
166 |
-
# Validate inputs
|
167 |
-
is_valid, error_message = validate_question_counts(
|
168 |
-
computation_count, proof_count, application_count
|
169 |
-
)
|
170 |
-
if not is_valid:
|
171 |
-
return error_message, None, None
|
172 |
-
|
173 |
if not os.environ.get('ANTHROPIC_API_KEY'):
|
174 |
logger.error("Anthropic API key not found")
|
175 |
return "Error: Anthropic API key not configured", None, None
|
176 |
|
177 |
-
logger.debug(f"Generating
|
178 |
|
179 |
# Check rate limit
|
180 |
now = datetime.now()
|
@@ -191,29 +150,18 @@ def generate_test(subject, difficulty, computation_count, proof_count, applicati
|
|
191 |
"Linear Algebra": ["matrices", "vector spaces", "eigenvalues", "linear transformations"],
|
192 |
}
|
193 |
|
194 |
-
|
195 |
-
logger.debug(f"Selected
|
196 |
-
|
197 |
-
# Create question type list based on user input
|
198 |
-
question_types = (
|
199 |
-
["computation"] * int(computation_count) +
|
200 |
-
["proof"] * int(proof_count) +
|
201 |
-
["application"] * int(application_count)
|
202 |
-
)
|
203 |
|
204 |
difficulty_params = get_difficulty_parameters(difficulty)
|
205 |
|
206 |
# Enhanced prompt for difficulty level 5
|
207 |
if difficulty == 5:
|
208 |
-
system_prompt = f"""You are an expert mathematics professor creating graduate-level exam
|
209 |
-
|
210 |
STRICT REQUIREMENTS:
|
211 |
-
1. Write exactly
|
212 |
-
- Question Types (in order): {', '.join(question_types)}
|
213 |
-
- Topics to cover: {', '.join(selected_topics)}
|
214 |
-
|
215 |
2. Advanced Difficulty Requirements:
|
216 |
-
|
217 |
MUST include:
|
218 |
- Novel applications of theoretical concepts
|
219 |
- Graduate-level mathematical reasoning
|
@@ -223,50 +171,37 @@ STRICT REQUIREMENTS:
|
|
223 |
|
224 |
Follow these specific constraints:
|
225 |
{chr(10).join(f' - {c}' for c in difficulty_params['constraints'])}
|
226 |
-
|
227 |
3. Style Reference:
|
228 |
-
|
229 |
-
|
230 |
-
4. Each question MUST:
|
231 |
- Bridge multiple mathematical domains
|
232 |
- Require deep theoretical understanding
|
233 |
- Test mastery of advanced concepts
|
234 |
- Demand innovative solution approaches
|
235 |
-
|
236 |
5. For LaTeX formatting:
|
237 |
- Use $ for inline math
|
238 |
- Use $$ on separate lines for equations and solutions
|
239 |
- Put each solution step on its own line in $$ $$
|
240 |
- DO NOT use \\begin{{aligned}} or similar environments
|
241 |
-
|
242 |
-
|
243 |
-
7. Include detailed solutions with thorough explanations of advanced concepts used
|
244 |
-
8. Maintain clear, precise formatting"""
|
245 |
else:
|
246 |
-
system_prompt = f"""You are an expert mathematics professor creating {difficulty_params['description']} exam
|
247 |
-
|
248 |
STRICT REQUIREMENTS:
|
249 |
-
1. Write exactly
|
250 |
-
- Question Types (in order): {', '.join(question_types)}
|
251 |
-
- Topics to cover: {', '.join(selected_topics)}
|
252 |
-
|
253 |
2. Difficulty Level Guidelines:
|
254 |
{difficulty_params['description'].upper()}
|
255 |
Follow these specific constraints:
|
256 |
{chr(10).join(f' - {c}' for c in difficulty_params['constraints'])}
|
257 |
-
|
258 |
3. Style Reference:
|
259 |
-
|
260 |
-
|
261 |
4. For LaTeX formatting:
|
262 |
- Use $ for inline math
|
263 |
- Use $$ on separate lines for equations and solutions
|
264 |
- Put each solution step on its own line in $$ $$
|
265 |
- DO NOT use \\begin{{aligned}} or similar environments
|
266 |
-
|
267 |
-
|
268 |
-
6. Include detailed solutions
|
269 |
-
7. Maintain clear formatting"""
|
270 |
|
271 |
logger.debug("Sending request to Anthropic API")
|
272 |
message = anthropic.messages.create(
|
@@ -275,7 +210,7 @@ STRICT REQUIREMENTS:
|
|
275 |
temperature=0.7,
|
276 |
messages=[{
|
277 |
"role": "user",
|
278 |
-
"content": f"{system_prompt}\n\nWrite
|
279 |
}]
|
280 |
)
|
281 |
|
@@ -291,22 +226,22 @@ STRICT REQUIREMENTS:
|
|
291 |
full_latex = create_latex_document(response_text, questions_only=False)
|
292 |
|
293 |
# Save to temporary files
|
294 |
-
questions_path = save_to_temp_file(questions_latex, "
|
295 |
-
full_path = save_to_temp_file(full_latex, "
|
296 |
|
297 |
logger.debug("Successfully created temporary files")
|
298 |
|
299 |
return response_text, questions_path, full_path
|
300 |
|
301 |
except Exception as e:
|
302 |
-
logger.error(f"Error generating
|
303 |
return f"Error: {str(e)}", None, None
|
304 |
|
305 |
# Create Gradio interface
|
306 |
with gr.Blocks() as interface:
|
307 |
-
gr.Markdown("# Advanced Mathematics
|
308 |
-
gr.Markdown("""Generates unique university-level mathematics
|
309 |
-
Each
|
310 |
|
311 |
with gr.Row():
|
312 |
with gr.Column():
|
@@ -324,7 +259,7 @@ with gr.Blocks() as interface:
|
|
324 |
"Topology"
|
325 |
],
|
326 |
label="Select Mathematics Subject",
|
327 |
-
info="Choose a subject for the
|
328 |
)
|
329 |
|
330 |
difficulty_slider = gr.Slider(
|
@@ -335,32 +270,18 @@ with gr.Blocks() as interface:
|
|
335 |
label="Difficulty Level",
|
336 |
info="1: Very Easy, 2: Easy, 3: Moderate, 4: Difficult, 5: Very Difficult"
|
337 |
)
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
info="Enter the number of computation questions (total must be 3)",
|
345 |
-
precision=0
|
346 |
-
)
|
347 |
-
proof_count = gr.Number(
|
348 |
-
value=1,
|
349 |
-
label="Number of Proof Questions",
|
350 |
-
info="Enter the number of proof questions (total must be 3)",
|
351 |
-
precision=0
|
352 |
-
)
|
353 |
-
application_count = gr.Number(
|
354 |
-
value=1,
|
355 |
-
label="Number of Application Questions",
|
356 |
-
info="Enter the number of application questions (total must be 3)",
|
357 |
-
precision=0
|
358 |
)
|
359 |
|
360 |
-
generate_btn = gr.Button("Generate
|
361 |
|
362 |
output_text = gr.Markdown(
|
363 |
-
label="Generated
|
364 |
latex_delimiters=[
|
365 |
{"left": "$$", "right": "$$", "display": True},
|
366 |
{"left": "$", "right": "$", "display": False}
|
@@ -368,17 +289,15 @@ with gr.Blocks() as interface:
|
|
368 |
)
|
369 |
|
370 |
with gr.Row():
|
371 |
-
questions_file = gr.File(label="
|
372 |
-
full_file = gr.File(label="
|
373 |
|
374 |
generate_btn.click(
|
375 |
-
|
376 |
inputs=[
|
377 |
subject_dropdown,
|
378 |
difficulty_slider,
|
379 |
-
|
380 |
-
proof_count,
|
381 |
-
application_count
|
382 |
],
|
383 |
outputs=[output_text, questions_file, full_file]
|
384 |
)
|
|
|
96 |
\usepackage{amsmath,amssymb}
|
97 |
\usepackage[margin=1in]{geometry}
|
98 |
\begin{document}
|
99 |
+
\title{Mathematics Question}
|
100 |
\maketitle
|
101 |
"""
|
102 |
latex_footer = r"\end{document}"
|
103 |
|
104 |
if questions_only:
|
105 |
+
# Modified to handle single question
|
106 |
+
processed_content = content.split('Solution:')[0]
|
107 |
+
content = processed_content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
|
109 |
full_document = f"{latex_header}\n{content}\n{latex_footer}"
|
110 |
logger.debug(f"Created {'questions-only' if questions_only else 'full'} LaTeX document")
|
|
|
116 |
def save_to_temp_file(content, filename):
|
117 |
"""Save content to a temporary file and return the path"""
|
118 |
try:
|
|
|
119 |
temp_dir = Path(tempfile.gettempdir()) / "math_test_files"
|
120 |
temp_dir.mkdir(exist_ok=True)
|
|
|
|
|
121 |
file_path = temp_dir / filename
|
|
|
|
|
122 |
file_path.write_text(content, encoding='utf-8')
|
|
|
123 |
logger.debug(f"Saved content to temporary file: {file_path}")
|
124 |
return str(file_path)
|
125 |
except Exception as e:
|
126 |
logger.error(f"Error saving temporary file: {str(e)}")
|
127 |
raise
|
128 |
|
129 |
+
def generate_question(subject, difficulty, question_type):
|
130 |
+
"""Generate a single math question"""
|
131 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
if not os.environ.get('ANTHROPIC_API_KEY'):
|
133 |
logger.error("Anthropic API key not found")
|
134 |
return "Error: Anthropic API key not configured", None, None
|
135 |
|
136 |
+
logger.debug(f"Generating {question_type} question for subject: {subject} at difficulty level: {difficulty}")
|
137 |
|
138 |
# Check rate limit
|
139 |
now = datetime.now()
|
|
|
150 |
"Linear Algebra": ["matrices", "vector spaces", "eigenvalues", "linear transformations"],
|
151 |
}
|
152 |
|
153 |
+
selected_topic = random.choice(topics.get(subject, ["general"]))
|
154 |
+
logger.debug(f"Selected topic: {selected_topic}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
|
156 |
difficulty_params = get_difficulty_parameters(difficulty)
|
157 |
|
158 |
# Enhanced prompt for difficulty level 5
|
159 |
if difficulty == 5:
|
160 |
+
system_prompt = f"""You are an expert mathematics professor creating a graduate-level exam question.
|
|
|
161 |
STRICT REQUIREMENTS:
|
162 |
+
1. Write exactly 1 graduate-level {question_type} question on {subject} covering {selected_topic}.
|
|
|
|
|
|
|
163 |
2. Advanced Difficulty Requirements:
|
164 |
+
This question must be suitable for PhD qualifying exams or advanced competitions.
|
165 |
MUST include:
|
166 |
- Novel applications of theoretical concepts
|
167 |
- Graduate-level mathematical reasoning
|
|
|
171 |
|
172 |
Follow these specific constraints:
|
173 |
{chr(10).join(f' - {c}' for c in difficulty_params['constraints'])}
|
|
|
174 |
3. Style Reference:
|
175 |
+
Question should be {difficulty_params['example_style']}
|
176 |
+
4. The question MUST:
|
|
|
177 |
- Bridge multiple mathematical domains
|
178 |
- Require deep theoretical understanding
|
179 |
- Test mastery of advanced concepts
|
180 |
- Demand innovative solution approaches
|
|
|
181 |
5. For LaTeX formatting:
|
182 |
- Use $ for inline math
|
183 |
- Use $$ on separate lines for equations and solutions
|
184 |
- Put each solution step on its own line in $$ $$
|
185 |
- DO NOT use \\begin{{aligned}} or similar environments
|
186 |
+
6. Include a detailed solution with thorough explanations of advanced concepts used
|
187 |
+
7. Maintain clear, precise formatting"""
|
|
|
|
|
188 |
else:
|
189 |
+
system_prompt = f"""You are an expert mathematics professor creating a {difficulty_params['description']} exam question.
|
|
|
190 |
STRICT REQUIREMENTS:
|
191 |
+
1. Write exactly 1 {question_type} question on {subject} covering {selected_topic}.
|
|
|
|
|
|
|
192 |
2. Difficulty Level Guidelines:
|
193 |
{difficulty_params['description'].upper()}
|
194 |
Follow these specific constraints:
|
195 |
{chr(10).join(f' - {c}' for c in difficulty_params['constraints'])}
|
|
|
196 |
3. Style Reference:
|
197 |
+
Question should be {difficulty_params['example_style']}
|
|
|
198 |
4. For LaTeX formatting:
|
199 |
- Use $ for inline math
|
200 |
- Use $$ on separate lines for equations and solutions
|
201 |
- Put each solution step on its own line in $$ $$
|
202 |
- DO NOT use \\begin{{aligned}} or similar environments
|
203 |
+
5. Include a detailed solution
|
204 |
+
6. Maintain clear formatting"""
|
|
|
|
|
205 |
|
206 |
logger.debug("Sending request to Anthropic API")
|
207 |
message = anthropic.messages.create(
|
|
|
210 |
temperature=0.7,
|
211 |
messages=[{
|
212 |
"role": "user",
|
213 |
+
"content": f"{system_prompt}\n\nWrite a question for {subject}."
|
214 |
}]
|
215 |
)
|
216 |
|
|
|
226 |
full_latex = create_latex_document(response_text, questions_only=False)
|
227 |
|
228 |
# Save to temporary files
|
229 |
+
questions_path = save_to_temp_file(questions_latex, "question.tex")
|
230 |
+
full_path = save_to_temp_file(full_latex, "full_question.tex")
|
231 |
|
232 |
logger.debug("Successfully created temporary files")
|
233 |
|
234 |
return response_text, questions_path, full_path
|
235 |
|
236 |
except Exception as e:
|
237 |
+
logger.error(f"Error generating question: {str(e)}")
|
238 |
return f"Error: {str(e)}", None, None
|
239 |
|
240 |
# Create Gradio interface
|
241 |
with gr.Blocks() as interface:
|
242 |
+
gr.Markdown("# Advanced Mathematics Question Generator")
|
243 |
+
gr.Markdown("""Generates a unique university-level mathematics question with solution using Claude 3.
|
244 |
+
Each question features different topics and difficulty levels. Limited to 25 requests per day.""")
|
245 |
|
246 |
with gr.Row():
|
247 |
with gr.Column():
|
|
|
259 |
"Topology"
|
260 |
],
|
261 |
label="Select Mathematics Subject",
|
262 |
+
info="Choose a subject for the question"
|
263 |
)
|
264 |
|
265 |
difficulty_slider = gr.Slider(
|
|
|
270 |
label="Difficulty Level",
|
271 |
info="1: Very Easy, 2: Easy, 3: Moderate, 4: Difficult, 5: Very Difficult"
|
272 |
)
|
273 |
+
|
274 |
+
question_type = gr.Radio(
|
275 |
+
choices=["computation", "proof", "application"],
|
276 |
+
label="Question Type",
|
277 |
+
info="Select the type of question you want",
|
278 |
+
value="computation"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
)
|
280 |
|
281 |
+
generate_btn = gr.Button("Generate Question")
|
282 |
|
283 |
output_text = gr.Markdown(
|
284 |
+
label="Generated Question Preview",
|
285 |
latex_delimiters=[
|
286 |
{"left": "$$", "right": "$$", "display": True},
|
287 |
{"left": "$", "right": "$", "display": False}
|
|
|
289 |
)
|
290 |
|
291 |
with gr.Row():
|
292 |
+
questions_file = gr.File(label="Question Only (LaTeX)")
|
293 |
+
full_file = gr.File(label="Question with Solution (LaTeX)")
|
294 |
|
295 |
generate_btn.click(
|
296 |
+
generate_question,
|
297 |
inputs=[
|
298 |
subject_dropdown,
|
299 |
difficulty_slider,
|
300 |
+
question_type
|
|
|
|
|
301 |
],
|
302 |
outputs=[output_text, questions_file, full_file]
|
303 |
)
|