Spaces:
Sleeping
Sleeping
| import os | |
| from dotenv import load_dotenv | |
| import openai | |
| import json | |
| from .base_agent import BaseAgent | |
| load_dotenv() | |
| class BloomsAssessmentAgent(BaseAgent): | |
| def __init__(self): | |
| super().__init__("BloomsAssessmentAgent") | |
| api_key = os.getenv("OPENAI_API_KEY") | |
| self.client = openai.OpenAI(api_key=api_key) | |
| self.bloom_levels = [ | |
| "Remembering", "Understanding", "Applying", | |
| "Analyzing", "Evaluating", "Creating" | |
| ] | |
| def generate_bloom_question(self, chapter, bloom_level): | |
| system_prompt = ( | |
| f"You are an expert educator creating a {bloom_level} level question according to Bloom's Taxonomy. " | |
| f"Generate ONE question that tests the student's ability at the {bloom_level} level for the given chapter. " | |
| "The question should be clear, concise, and appropriate for the chapter content. " | |
| "Return ONLY the question text, no additional formatting or explanation." | |
| ) | |
| user_prompt = ( | |
| f"Chapter: {chapter.name}\n" | |
| f"Modules in this chapter: {[m.name for m in chapter.modules]}\n" | |
| f"Bloom's Level: {bloom_level}\n" | |
| f"Generate a {bloom_level} level question." | |
| ) | |
| response = self.client.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt} | |
| ] | |
| ) | |
| return response.choices[0].message.content.strip() | |
| def evaluate_bloom_answer(self, question, user_answer, bloom_level, chapter): | |
| system_prompt = ( | |
| f"You are an expert educator evaluating a student's answer for a {bloom_level} level question. " | |
| "Evaluate the answer based on the specific cognitive skills required for this Bloom's level. " | |
| "Be STRICT about answer quality - vague, incomplete, or overly brief answers should receive low scores.\n\n" | |
| "**Evaluation Criteria:**\n" | |
| "- **Precision:** Is the answer specific and detailed enough for the Bloom's level?\n" | |
| "- **Relevance:** Does it directly address the question asked?\n" | |
| "- **Depth:** Does it demonstrate the expected cognitive complexity?\n" | |
| "- **Completeness:** Are all parts of the question addressed?\n\n" | |
| "**Automatic Penalties:**\n" | |
| "- Answers under 15 words: Maximum score of 3\n" | |
| "- Vague responses (yes/no, maybe, I think): Maximum score of 2\n" | |
| "- Off-topic or irrelevant answers: Score of 0-1\n\n" | |
| "You must respond with a JSON object containing:\n" | |
| "1. 'score': A number between 0 and 10\n" | |
| "2. 'feedback': Detailed explanation of the score and what was missing\n" | |
| "3. 'level_achieved': The Bloom's level the answer demonstrates\n" | |
| "4. 'hint': A subtle hint to guide toward better understanding (if score < 7)" | |
| ) | |
| user_prompt = ( | |
| f"Question (Bloom's Level: {bloom_level}): {question}\n" | |
| f"Student's Answer: {user_answer}\n" | |
| f"Chapter Context: {chapter.name}\n" | |
| "Evaluate this answer and provide the JSON response." | |
| ) | |
| response = self.client.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt} | |
| ] | |
| ) | |
| return response.choices[0].message.content.strip() | |
| def process(self, chapter): | |
| print(f"\n{'='*60}") | |
| print(f"BLOOM'S TAXONOMY ASSESSMENT") | |
| print(f"Chapter: {chapter.name}") | |
| print(f"{'='*60}") | |
| print("You will be asked 2 questions for each of the 6 Bloom's levels.") | |
| print("This comprehensive assessment will evaluate your mastery of the chapter.") | |
| results = {} | |
| total_score = 0 | |
| questions_asked = 0 | |
| for bloom_level in self.bloom_levels: | |
| level_scores = [] | |
| print(f"\n--- {bloom_level.upper()} LEVEL (2 Questions) ---") | |
| for question_num in range(1, 3): # 2 questions per level | |
| print(f"\n[Question {question_num}/2 for {bloom_level}]") | |
| question = self.generate_bloom_question(chapter, bloom_level) | |
| print(f"Question: {question}") | |
| user_answer = input("Your answer: ") | |
| evaluation_json = self.evaluate_bloom_answer(question, user_answer, bloom_level, chapter) | |
| try: | |
| evaluation = json.loads(evaluation_json) | |
| score = evaluation.get('score', 0) | |
| feedback = evaluation.get('feedback', 'No feedback provided') | |
| level_achieved = evaluation.get('level_achieved', bloom_level) | |
| hint = evaluation.get('hint', '') | |
| print(f"Score: {score}/10") | |
| print(f"Feedback: {feedback}") | |
| print(f"Level Demonstrated: {level_achieved}") | |
| # If score is low, provide hint and offer retry | |
| if score < 7 and hint: | |
| print(f"💡 Hint: {hint}") | |
| retry = input("\nYour answer needs improvement. Would you like to try again? (y/n): ").lower().strip() | |
| if retry == 'y': | |
| print("\n🔄 Please provide a more detailed and specific answer.") | |
| retry_answer = input("Your revised answer: ") | |
| # Re-evaluate the retry answer | |
| retry_evaluation_json = self.evaluate_bloom_answer(question, retry_answer, bloom_level, chapter) | |
| try: | |
| retry_evaluation = json.loads(retry_evaluation_json) | |
| retry_score = retry_evaluation.get('score', 0) | |
| retry_feedback = retry_evaluation.get('feedback', 'No feedback provided') | |
| retry_level = retry_evaluation.get('level_achieved', bloom_level) | |
| print(f"\nRetry Score: {retry_score}/10") | |
| print(f"Retry Feedback: {retry_feedback}") | |
| print(f"Retry Level Demonstrated: {retry_level}") | |
| # Use the better of the two scores | |
| final_score = max(score, retry_score) | |
| level_scores.append(final_score) | |
| total_score += final_score | |
| questions_asked += 1 | |
| except json.JSONDecodeError: | |
| print("Error evaluating retry answer. Using original score.") | |
| level_scores.append(score) | |
| total_score += score | |
| questions_asked += 1 | |
| else: | |
| level_scores.append(score) | |
| total_score += score | |
| questions_asked += 1 | |
| else: | |
| level_scores.append(score) | |
| total_score += score | |
| questions_asked += 1 | |
| except json.JSONDecodeError: | |
| print("Error evaluating answer. Defaulting to score 5.") | |
| level_scores.append(5) | |
| total_score += 5 | |
| questions_asked += 1 | |
| # Store results for this Bloom's level | |
| results[bloom_level] = { | |
| 'scores': level_scores, | |
| 'average_score': sum(level_scores) / len(level_scores), | |
| 'total_score': sum(level_scores) | |
| } | |
| # Calculate overall results | |
| max_possible = questions_asked * 10 | |
| average_score = total_score / questions_asked | |
| percentage = (total_score / max_possible) * 100 | |
| print(f"\n{'='*60}") | |
| print("COMPREHENSIVE ASSESSMENT RESULTS") | |
| print(f"{'='*60}") | |
| print(f"Total Score: {total_score}/{max_possible}") | |
| print(f"Average Score: {average_score:.1f}/10") | |
| print(f"Percentage: {percentage:.1f}%") | |
| # Enhanced mastery determination | |
| if percentage >= 85: | |
| mastery = "Excellent Mastery" | |
| recommendation = "Ready to advance to next level" | |
| elif percentage >= 70: | |
| mastery = "Good Understanding" | |
| recommendation = "Ready to advance with some review" | |
| elif percentage >= 55: | |
| mastery = "Basic Understanding" | |
| recommendation = "Review weak areas before advancing" | |
| else: | |
| mastery = "Needs Significant Review" | |
| recommendation = "Revisit chapter content and retake assessment" | |
| print(f"Mastery Level: {mastery}") | |
| print(f"Recommendation: {recommendation}") | |
| print(f"\nDetailed Breakdown by Bloom's Level:") | |
| for level, result in results.items(): | |
| avg = result['average_score'] | |
| print(f" {level}: {avg:.1f}/10 (Scores: {result['scores']})") | |
| # Determine if student should advance or review | |
| should_advance = percentage >= 70 | |
| return { | |
| 'chapter': chapter.name, | |
| 'total_score': total_score, | |
| 'max_possible': max_possible, | |
| 'average_score': average_score, | |
| 'percentage': percentage, | |
| 'mastery_level': mastery, | |
| 'recommendation': recommendation, | |
| 'should_advance': should_advance, | |
| 'detailed_results': results | |
| } |