atropos/environments/community/examcraft/visual_question_demo.py

475 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 json
import os
import random
from typing import Any, Dict, Tuple
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?\n"
"2x + 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("🤖 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("\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(" 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("\n👨‍🎓 Student Response:")
answered_option = question_data["options"][student_answer]
print(f" Answered: {student_answer}) {answered_option}")
option_text = question_data["options"][correct_answer]
print(f" Correct answer: {correct_answer}) {option_text}")
result_icon = "✅ CORRECT" if is_correct else "❌ INCORRECT"
print(f" Result: {result_icon}")
# Show explanation
print("\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("\n📈 Learning Progress:")
topic_title = target_topic.replace("_", " ").title()
improvement = new_prof - old_prof
print(
f" {topic_title}: {old_prof:.1%}{new_prof:.1%} (+{improvement:.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("\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("\n🎯 Adaptive Teaching Demonstrated:")
topics_targeted = set(item["topic"] for item in self.session_history)
print(f" - Targeted {len(topics_targeted)} different topics")
print(" - Difficulty adapted based on performance")
print(" - 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()