mirror of
https://github.com/NousResearch/atropos.git
synced 2026-04-28 17:29:30 +00:00
Add visual question generation demo
This commit is contained in:
parent
a71e977c91
commit
7c32f09912
2 changed files with 400 additions and 330 deletions
400
environments/hack0/examcraft/visual_question_demo.py
Normal file
400
environments/hack0/examcraft/visual_question_demo.py
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
ExamCraft: Demo with Visible Question Generation
|
||||
|
||||
This version shows the actual questions being generated by the teacher AI,
|
||||
perfect for demonstrating the adaptive teaching capabilities!
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import random
|
||||
from typing import Dict, List, Any, Tuple, Optional
|
||||
|
||||
class VisibleQuestionDemo:
|
||||
"""
|
||||
ExamCraft demo that shows the actual questions being generated.
|
||||
Great for video demonstrations!
|
||||
"""
|
||||
|
||||
def __init__(self, profile_path: str = "example_profile.json"):
|
||||
# Load student profile
|
||||
if os.path.exists(profile_path):
|
||||
with open(profile_path, 'r') as file:
|
||||
self.profile = json.load(file)
|
||||
else:
|
||||
self.profile = self._create_default_profile()
|
||||
|
||||
# Initialize student metrics
|
||||
self.reset_student()
|
||||
|
||||
# Question templates for realistic generation
|
||||
self.question_templates = {
|
||||
"vectors": {
|
||||
"easy": [
|
||||
{
|
||||
"question": "What is the result when you add vectors (2,3) and (1,4)?",
|
||||
"options": {"A": "(3,7)", "B": "(2,12)", "C": "(1,1)", "D": "(3,1)"},
|
||||
"correct": "A",
|
||||
"explanation": "Vector addition is component-wise: (2+1, 3+4) = (3,7)"
|
||||
},
|
||||
{
|
||||
"question": "Which operation can you perform on vectors?",
|
||||
"options": {"A": "Addition", "B": "Scalar multiplication", "C": "Dot product", "D": "All of the above"},
|
||||
"correct": "D",
|
||||
"explanation": "Vectors support addition, scalar multiplication, and dot product operations"
|
||||
}
|
||||
],
|
||||
"medium": [
|
||||
{
|
||||
"question": "Calculate the dot product of vectors (3,4) and (1,2):",
|
||||
"options": {"A": "11", "B": "7", "C": "5", "D": "10"},
|
||||
"correct": "A",
|
||||
"explanation": "Dot product: (3×1) + (4×2) = 3 + 8 = 11"
|
||||
},
|
||||
{
|
||||
"question": "What is the magnitude of vector (3,4)?",
|
||||
"options": {"A": "5", "B": "7", "C": "3.5", "D": "4.5"},
|
||||
"correct": "A",
|
||||
"explanation": "Magnitude = √(3² + 4²) = √(9 + 16) = √25 = 5"
|
||||
}
|
||||
],
|
||||
"hard": [
|
||||
{
|
||||
"question": "If vectors u and v are orthogonal, what is u·v?",
|
||||
"options": {"A": "1", "B": "0", "C": "-1", "D": "Undefined"},
|
||||
"correct": "B",
|
||||
"explanation": "Orthogonal vectors have dot product = 0 by definition"
|
||||
}
|
||||
]
|
||||
},
|
||||
"matrices": {
|
||||
"easy": [
|
||||
{
|
||||
"question": "What is the result of [1 2] + [3 4]?",
|
||||
"options": {"A": "[4 6]", "B": "[3 8]", "C": "[1 2]", "D": "[2 4]"},
|
||||
"correct": "A",
|
||||
"explanation": "Matrix addition: [1+3, 2+4] = [4, 6]"
|
||||
}
|
||||
],
|
||||
"medium": [
|
||||
{
|
||||
"question": "What is the determinant of [[2,1],[3,4]]?",
|
||||
"options": {"A": "5", "B": "8", "C": "11", "D": "7"},
|
||||
"correct": "A",
|
||||
"explanation": "det = (2×4) - (1×3) = 8 - 3 = 5"
|
||||
}
|
||||
],
|
||||
"hard": [
|
||||
{
|
||||
"question": "A matrix is invertible if and only if:",
|
||||
"options": {"A": "It's square", "B": "Det ≠ 0", "C": "All entries > 0", "D": "It's symmetric"},
|
||||
"correct": "B",
|
||||
"explanation": "A matrix is invertible iff its determinant is non-zero"
|
||||
}
|
||||
]
|
||||
},
|
||||
"linear_systems": {
|
||||
"easy": [
|
||||
{
|
||||
"question": "A system with no solutions is called:",
|
||||
"options": {"A": "Consistent", "B": "Inconsistent", "C": "Homogeneous", "D": "Independent"},
|
||||
"correct": "B",
|
||||
"explanation": "Inconsistent systems have no solutions"
|
||||
}
|
||||
],
|
||||
"medium": [
|
||||
{
|
||||
"question": "In Gaussian elimination, what creates a pivot?",
|
||||
"options": {"A": "Leading 1", "B": "Zero entry", "C": "Negative number", "D": "Largest element"},
|
||||
"correct": "A",
|
||||
"explanation": "Pivots are the leading 1's in row echelon form"
|
||||
}
|
||||
],
|
||||
"hard": [
|
||||
{
|
||||
"question": "For what values of k does the system have infinitely many solutions?\n2x + 3y = 6\n4x + 6y = k",
|
||||
"options": {"A": "k = 6", "B": "k = 12", "C": "k = 0", "D": "k = 3"},
|
||||
"correct": "B",
|
||||
"explanation": "The second equation must be a multiple of the first: k = 2×6 = 12"
|
||||
}
|
||||
]
|
||||
},
|
||||
"eigenvalues_eigenvectors": {
|
||||
"easy": [
|
||||
{
|
||||
"question": "An eigenvector of matrix A satisfies:",
|
||||
"options": {"A": "Av = λv", "B": "Av = v", "C": "Av = 0", "D": "Av = I"},
|
||||
"correct": "A",
|
||||
"explanation": "By definition: Av = λv where λ is the eigenvalue"
|
||||
}
|
||||
],
|
||||
"medium": [
|
||||
{
|
||||
"question": "To find eigenvalues, we solve:",
|
||||
"options": {"A": "det(A) = 0", "B": "det(A - λI) = 0", "C": "Av = 0", "D": "tr(A) = λ"},
|
||||
"correct": "B",
|
||||
"explanation": "Eigenvalues satisfy the characteristic equation det(A - λI) = 0"
|
||||
}
|
||||
],
|
||||
"hard": [
|
||||
{
|
||||
"question": "The sum of eigenvalues equals:",
|
||||
"options": {"A": "Determinant", "B": "Trace", "C": "Rank", "D": "Nullity"},
|
||||
"correct": "B",
|
||||
"explanation": "The sum of eigenvalues equals the trace of the matrix"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# Track teaching session
|
||||
self.question_count = 0
|
||||
self.session_history = []
|
||||
|
||||
def _create_default_profile(self) -> Dict[str, Any]:
|
||||
"""Create default student profile."""
|
||||
return {
|
||||
"student_id": "adaptive_learner_001",
|
||||
"target_grade": "11th grade",
|
||||
"learning_goal": "Master linear algebra concepts",
|
||||
"topics": [
|
||||
{"name": "vectors", "proficiency": 0.45},
|
||||
{"name": "matrices", "proficiency": 0.30},
|
||||
{"name": "linear_systems", "proficiency": 0.25},
|
||||
{"name": "eigenvalues_eigenvectors", "proficiency": 0.20}
|
||||
]
|
||||
}
|
||||
|
||||
def reset_student(self):
|
||||
"""Reset student to initial proficiency levels."""
|
||||
self.student_metrics = {}
|
||||
for topic in self.profile["topics"]:
|
||||
self.student_metrics[topic["name"]] = topic["proficiency"]
|
||||
|
||||
self.question_count = 0
|
||||
self.session_history = []
|
||||
|
||||
def generate_question(self, topic: str, difficulty: str) -> Dict[str, Any]:
|
||||
"""Generate a specific question for the topic and difficulty."""
|
||||
# Get question templates for this topic/difficulty
|
||||
topic_questions = self.question_templates.get(topic, {})
|
||||
difficulty_questions = topic_questions.get(difficulty, [])
|
||||
|
||||
if difficulty_questions:
|
||||
# Select a random question from available templates
|
||||
question_data = random.choice(difficulty_questions)
|
||||
|
||||
# Add metadata
|
||||
question_data.update({
|
||||
"topic": topic,
|
||||
"difficulty": difficulty,
|
||||
"generated_by": "ExamCraft Teacher AI"
|
||||
})
|
||||
|
||||
return question_data
|
||||
else:
|
||||
# Fallback question if no template available
|
||||
return {
|
||||
"topic": topic,
|
||||
"difficulty": difficulty,
|
||||
"question": f"Sample {difficulty} question about {topic}",
|
||||
"options": {"A": "Option A", "B": "Option B", "C": "Option C", "D": "Option D"},
|
||||
"correct": "A",
|
||||
"explanation": f"This demonstrates {difficulty} level understanding of {topic}",
|
||||
"generated_by": "ExamCraft Teacher AI (fallback)"
|
||||
}
|
||||
|
||||
def simulate_student_answer(self, question_data: Dict[str, Any]) -> Tuple[str, bool]:
|
||||
"""Simulate student answering the question."""
|
||||
topic = question_data["topic"]
|
||||
difficulty = question_data["difficulty"]
|
||||
correct_answer = question_data["correct"]
|
||||
|
||||
# Get student's current proficiency
|
||||
proficiency = self.student_metrics[topic]
|
||||
|
||||
# Adjust success probability based on difficulty
|
||||
difficulty_modifiers = {
|
||||
"easy": 0.25,
|
||||
"medium": 0.0,
|
||||
"hard": -0.25
|
||||
}
|
||||
modifier = difficulty_modifiers.get(difficulty, 0.0)
|
||||
|
||||
# Calculate success probability
|
||||
success_prob = max(0.15, min(0.90, proficiency + modifier))
|
||||
|
||||
# Determine if answer is correct
|
||||
is_correct = random.random() < success_prob
|
||||
|
||||
if is_correct:
|
||||
student_answer = correct_answer
|
||||
else:
|
||||
# Choose random incorrect answer
|
||||
options = list(question_data["options"].keys())
|
||||
options.remove(correct_answer)
|
||||
student_answer = random.choice(options)
|
||||
|
||||
return student_answer, is_correct
|
||||
|
||||
def update_student_learning(self, topic: str, is_correct: bool, difficulty: str):
|
||||
"""Update student's proficiency based on learning."""
|
||||
current_prof = self.student_metrics[topic]
|
||||
|
||||
# Learning rate based on correctness and difficulty
|
||||
if is_correct:
|
||||
base_improvement = 0.05
|
||||
else:
|
||||
# Student learns from mistakes with good explanations
|
||||
base_improvement = 0.03
|
||||
|
||||
# Difficulty affects learning
|
||||
difficulty_multipliers = {"easy": 0.7, "medium": 1.0, "hard": 1.3}
|
||||
multiplier = difficulty_multipliers.get(difficulty, 1.0)
|
||||
|
||||
improvement = base_improvement * multiplier
|
||||
|
||||
# Diminishing returns as proficiency increases
|
||||
diminishing_factor = (1.0 - current_prof) * 0.8 + 0.2
|
||||
improvement *= diminishing_factor
|
||||
|
||||
# Update proficiency
|
||||
new_prof = min(1.0, current_prof + improvement)
|
||||
self.student_metrics[topic] = new_prof
|
||||
|
||||
def get_weakest_topic(self) -> str:
|
||||
"""Find the topic where student is struggling most."""
|
||||
return min(self.student_metrics.items(), key=lambda x: x[1])[0]
|
||||
|
||||
def select_difficulty(self, topic: str) -> str:
|
||||
"""Select appropriate difficulty based on student proficiency."""
|
||||
proficiency = self.student_metrics[topic]
|
||||
|
||||
if proficiency < 0.4:
|
||||
return "easy"
|
||||
elif proficiency < 0.7:
|
||||
return "medium"
|
||||
else:
|
||||
return "hard"
|
||||
|
||||
def run_visual_demo(self, num_questions: int = 5):
|
||||
"""Run a demo showing actual question generation."""
|
||||
print("🎓 ExamCraft: Visual Question Generation Demo")
|
||||
print("=" * 60)
|
||||
|
||||
# Show initial state
|
||||
print("\n📊 Initial Student Proficiency:")
|
||||
for topic, prof in self.student_metrics.items():
|
||||
print(f" {topic.replace('_', ' ').title()}: {prof:.1%}")
|
||||
|
||||
print(f"\n🎯 Teacher AI will generate {num_questions} adaptive questions")
|
||||
print("🧠 Watch how it targets weak areas and adapts difficulty!\n")
|
||||
|
||||
for i in range(num_questions):
|
||||
print(f"\n{'='*20} Question {i+1} {'='*20}")
|
||||
|
||||
# Teacher AI analyzes student and selects topic/difficulty
|
||||
target_topic = self.get_weakest_topic()
|
||||
difficulty = self.select_difficulty(target_topic)
|
||||
current_prof = self.student_metrics[target_topic]
|
||||
|
||||
print(f"🤖 Teacher AI Analysis:")
|
||||
print(f" Weakest topic: {target_topic.replace('_', ' ').title()} ({current_prof:.1%})")
|
||||
print(f" Selected difficulty: {difficulty.upper()}")
|
||||
|
||||
# Generate the actual question
|
||||
print(f"\n📝 Generated Question:")
|
||||
question_data = self.generate_question(target_topic, difficulty)
|
||||
|
||||
print(f" Topic: {question_data['topic'].replace('_', ' ').title()}")
|
||||
print(f" Difficulty: {question_data['difficulty'].upper()}")
|
||||
print(f" Question: {question_data['question']}")
|
||||
print(f" Options:")
|
||||
for option, text in question_data['options'].items():
|
||||
print(f" {option}) {text}")
|
||||
|
||||
# Student answers
|
||||
student_answer, is_correct = self.simulate_student_answer(question_data)
|
||||
correct_answer = question_data['correct']
|
||||
|
||||
print(f"\n👨🎓 Student Response:")
|
||||
print(f" Answered: {student_answer}) {question_data['options'][student_answer]}")
|
||||
print(f" Correct answer: {correct_answer}) {question_data['options'][correct_answer]}")
|
||||
|
||||
result_icon = "✅ CORRECT" if is_correct else "❌ INCORRECT"
|
||||
print(f" Result: {result_icon}")
|
||||
|
||||
# Show explanation
|
||||
print(f"\n💡 Teacher's Explanation:")
|
||||
print(f" {question_data['explanation']}")
|
||||
|
||||
# Update student learning
|
||||
old_prof = current_prof
|
||||
self.update_student_learning(target_topic, is_correct, difficulty)
|
||||
new_prof = self.student_metrics[target_topic]
|
||||
|
||||
print(f"\n📈 Learning Progress:")
|
||||
print(f" {target_topic.replace('_', ' ').title()}: {old_prof:.1%} → {new_prof:.1%} (+{new_prof-old_prof:.1%})")
|
||||
|
||||
# Track this interaction
|
||||
self.question_count += 1
|
||||
self.session_history.append({
|
||||
"question_num": i + 1,
|
||||
"topic": target_topic,
|
||||
"difficulty": difficulty,
|
||||
"question": question_data,
|
||||
"student_answer": student_answer,
|
||||
"is_correct": is_correct,
|
||||
"proficiency_before": old_prof,
|
||||
"proficiency_after": new_prof
|
||||
})
|
||||
|
||||
# Final summary
|
||||
print(f"\n{'='*60}")
|
||||
print("📋 TEACHING SESSION SUMMARY")
|
||||
print(f"✨ Questions generated: {self.question_count}")
|
||||
|
||||
print(f"\n🏆 Final Student Proficiency:")
|
||||
for topic, prof in self.student_metrics.items():
|
||||
original_prof = next(t["proficiency"] for t in self.profile["topics"] if t["name"] == topic)
|
||||
improvement = prof - original_prof
|
||||
print(f" {topic.replace('_', ' ').title()}: {prof:.1%} (+{improvement:.1%})")
|
||||
|
||||
print(f"\n🎯 Adaptive Teaching Demonstrated:")
|
||||
topics_targeted = set(item["topic"] for item in self.session_history)
|
||||
print(f" - Targeted {len(topics_targeted)} different topics")
|
||||
print(f" - Difficulty adapted based on performance")
|
||||
print(f" - Each question included detailed explanations")
|
||||
|
||||
return self.session_history
|
||||
|
||||
|
||||
def main():
|
||||
"""Run the visual question generation demo."""
|
||||
demo = VisibleQuestionDemo()
|
||||
|
||||
print("🎬 ExamCraft: Question Generation Demo")
|
||||
print("Perfect for recording your hackathon video!\n")
|
||||
|
||||
num_questions = 5
|
||||
try:
|
||||
user_input = input(f"How many questions to generate? (default {num_questions}): ").strip()
|
||||
if user_input:
|
||||
num_questions = int(user_input)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Run the demo
|
||||
demo.run_visual_demo(num_questions)
|
||||
|
||||
print("\n🎥 This demo shows:")
|
||||
print("✓ Teacher AI analyzing student weaknesses")
|
||||
print("✓ Adaptive question generation with real content")
|
||||
print("✓ Student simulation and learning progression")
|
||||
print("✓ Detailed explanations and feedback")
|
||||
print("\nPerfect for your 1-minute hackathon demo video! 🚀")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue