Spaces:
Running
Running
added topics dictionary, added randomized difficulty distribution, made temperature dynamic
2f3d61a
verified
import os | |
import gradio as gr | |
from anthropic import Anthropic | |
from datetime import datetime, timedelta | |
from collections import deque | |
import random | |
# Initialize Anthropic client | |
anthropic = Anthropic( | |
api_key=os.environ.get('ANTHROPIC_API_KEY') | |
) | |
# Request tracking | |
MAX_REQUESTS_PER_DAY = 25 | |
request_history = deque(maxlen=1000) | |
def check_api_key(): | |
"""Verify API key is configured""" | |
if not os.environ.get('ANTHROPIC_API_KEY'): | |
raise ValueError("Anthropic API key not found. Please configure it in HuggingFace Spaces settings.") | |
def check_rate_limit(): | |
"""Check if we're within rate limits""" | |
now = datetime.now() | |
while request_history and (now - request_history[0]) > timedelta(days=1): | |
request_history.popleft() | |
return len(request_history) < MAX_REQUESTS_PER_DAY | |
def clean_latex(text): | |
"""Simple LaTeX cleaning""" | |
text = text.replace('\n', '\n\n') | |
return text | |
def generate_test(subject): | |
"""Generate a math test with enhanced variety""" | |
try: | |
check_api_key() | |
if not check_rate_limit(): | |
return "Daily request limit reached. Please try again tomorrow." | |
request_history.append(datetime.now()) | |
# Randomly select focus areas and difficulty levels | |
topics = { | |
"Single Variable Calculus": ["limits", "derivatives", "integrals", "series", "applications"], | |
"Multivariable Calculus": ["partial derivatives", "multiple integrals", "vector fields", "optimization", "surface integrals"], | |
"Linear Algebra": ["matrices", "vector spaces", "eigenvalues", "linear transformations", "inner products"], | |
# ... add topics for other subjects | |
} | |
selected_topics = random.sample(topics.get(subject, ["general"]), min(3, len(topics.get(subject, ["general"])))) | |
difficulty_distribution = random.choice([ | |
"one easy, one medium, one challenging", | |
"two medium, one very challenging", | |
"one medium, two challenging" | |
]) | |
system_prompt = f"""You will write math exam questions. Follow these requirements EXACTLY: | |
1. Write exactly 3 university-level questions focusing on these specific topics: {', '.join(selected_topics)} | |
2. Make the questions {difficulty_distribution} | |
3. For each question, use a different type of mathematical thinking (e.g., computation, proof, application, conceptual understanding) | |
4. Ensure questions are unique and not commonly found in textbooks | |
5. For LaTeX math formatting: | |
- Use $ for simple inline math | |
- For equations and solution steps, use $$ on separate lines | |
- For multi-step solutions, put each step on its own line in $$ $$ | |
- DO NOT use \\begin{{aligned}} or any other environments | |
6. Number each question as 1), 2), 3) | |
7. Include detailed solutions after each question | |
8. Keep formatting simple and clear | |
Important: Make these questions distinct from standard textbook problems. Incorporate real-world applications, | |
interdisciplinary connections, or creative scenarios where appropriate.""" | |
# Vary temperature based on subject complexity | |
base_temperature = 0.7 | |
complexity_adjustment = random.uniform(-0.1, 0.1) | |
temperature = min(1.0, max(0.5, base_temperature + complexity_adjustment)) | |
message = anthropic.messages.create( | |
model="claude-3-opus-20240229", | |
max_tokens=1500, | |
temperature=temperature, | |
messages=[{ | |
"role": "user", | |
"content": f"{system_prompt}\n\nWrite an exam for {subject}." | |
}] | |
) | |
# Extract usage information | |
input_tokens = message.usage.input_tokens | |
output_tokens = message.usage.output_tokens | |
input_cost = (input_tokens / 1000) * 0.015 | |
output_cost = (output_tokens / 1000) * 0.075 | |
total_cost = input_cost + output_cost | |
usage_stats = f""" | |
\n---\nUsage Statistics: | |
• Input Tokens: {input_tokens:,} | |
• Output Tokens: {output_tokens:,} | |
• Total Tokens: {input_tokens + output_tokens:,} | |
Cost Breakdown: | |
• Input Cost: ${input_cost:.4f} | |
• Output Cost: ${output_cost:.4f} | |
• Total Cost: ${total_cost:.4f} | |
""" | |
if hasattr(message, 'content') and len(message.content) > 0: | |
response_text = message.content[0].text | |
formatted_response = clean_latex(response_text) + usage_stats | |
return formatted_response | |
else: | |
return "Error: No content in response" | |
except ValueError as e: | |
return f"Configuration Error: {str(e)}" | |
except Exception as e: | |
return f"Error: {str(e)}" | |
# Subject choices remain the same | |
subjects = [ | |
"Single Variable Calculus", | |
"Multivariable Calculus", | |
"Linear Algebra", | |
"Differential Equations", | |
"Real Analysis", | |
"Complex Analysis", | |
"Abstract Algebra", | |
"Probability Theory", | |
"Numerical Analysis", | |
"Topology" | |
] | |
# Create Gradio interface | |
interface = gr.Interface( | |
fn=generate_test, | |
inputs=gr.Dropdown( | |
choices=subjects, | |
label="Select Mathematics Subject", | |
info="Choose a subject for the exam questions" | |
), | |
outputs=gr.Markdown( | |
label="Generated Test", | |
latex_delimiters=[ | |
{"left": "$$", "right": "$$", "display": True}, | |
{"left": "$", "right": "$", "display": False} | |
] | |
), | |
title="Advanced Mathematics Test Generator", | |
description="""Generates unique university-level mathematics exam questions with solutions using Claude 3 Opus. | |
Each test features different topics and difficulty levels. Limited to 25 requests per day.""", | |
theme="default", | |
allow_flagging="never" | |
) | |
if __name__ == "__main__": | |
interface.launch() |