joshuarauh's picture
added topics dictionary, added randomized difficulty distribution, made temperature dynamic
2f3d61a verified
raw
history blame
6.03 kB
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()