Spaces:
Runtime error
Runtime error
import gradio as gr | |
import pandas as pd | |
import json | |
import os | |
import re | |
import hashlib | |
from datetime import datetime | |
from PyPDF2 import PdfReader | |
from collections import defaultdict | |
from transformers import pipeline | |
from typing import Dict, List, Optional | |
# Initialize NER model (will load only if transformers is available) | |
try: | |
ner_pipeline = pipeline("ner", model="dslim/bert-base-NER") | |
except Exception as e: | |
print(f"Could not load NER model: {e}") | |
ner_pipeline = None | |
# ========== IMPROVED TRANSCRIPT PARSING ========== | |
def extract_gpa(text: str, gpa_type: str) -> str: | |
pattern = rf'{gpa_type}\s*([\d\.]+)' | |
match = re.search(pattern, text) | |
return match.group(1) if match else "N/A" | |
def extract_courses_from_table(text: str) -> Dict[str, List[Dict]]: | |
# This pattern matches the course table rows in the transcript | |
course_pattern = re.compile( | |
r'(\d{4}-\d{4})\s*' # School year | |
r'\|?\s*(\d+)\s*' # Grade level | |
r'\|?\s*([A-Z0-9]+)\s*' # Course code | |
r'\|?\s*([^\|]+?)\s*' # Course name (captures until next pipe) | |
r'(?:\|\s*[^\|]*){2}' # Skip Term and DstNumber | |
r'\|\s*([A-FW]?)\s*' # Grade (FG column) | |
r'(?:\|\s*[^\|]*)' # Skip Incl column | |
r'\|\s*([\d\.]+|inProgress)' # Credits | |
) | |
courses_by_grade = defaultdict(list) | |
for match in re.finditer(course_pattern, text): | |
year_range, grade_level, course_code, course_name, grade, credits = match.groups() | |
# Clean up course name | |
course_name = course_name.strip() | |
if 'DE:' in course_name: | |
course_name = course_name.replace('DE:', 'Dual Enrollment:') | |
if 'AP' in course_name: | |
course_name = course_name.replace('AP', 'AP ') | |
course_info = { | |
'name': f"{course_code} {course_name}", | |
'year': year_range, | |
'credits': credits | |
} | |
if grade and grade.strip(): | |
course_info['grade'] = grade.strip() | |
courses_by_grade[grade_level].append(course_info) | |
return courses_by_grade | |
def parse_transcript(file) -> tuple: | |
try: | |
if file.name.endswith('.pdf'): | |
text = '' | |
reader = PdfReader(file) | |
for page in reader.pages: | |
text += page.extract_text() + '\n' | |
# Extract GPA information | |
gpa_data = { | |
'weighted': extract_gpa(text, 'Weighted GPA'), | |
'unweighted': extract_gpa(text, 'Un-weighted GPA') | |
} | |
# Extract current grade level | |
grade_match = re.search(r'Current Grade:\s*(\d+)', text) | |
grade_level = grade_match.group(1) if grade_match else "Unknown" | |
# Extract all courses with grades and year taken | |
courses_by_grade = extract_courses_from_table(text) | |
# Prepare detailed output | |
output_text = f"Student Transcript Summary\n{'='*40}\n" | |
output_text += f"Current Grade Level: {grade_level}\n" | |
output_text += f"Weighted GPA: {gpa_data['weighted']}\n" | |
output_text += f"Unweighted GPA: {gpa_data['unweighted']}\n\n" | |
output_text += "Course History:\n{'='*40}\n" | |
# Sort grades numerically (09, 10, 11, 12) | |
for grade in sorted(courses_by_grade.keys(), key=int): | |
output_text += f"\nGrade {grade}:\n{'-'*30}\n" | |
for course in courses_by_grade[grade]: | |
output_text += f"- {course['name']}" | |
if 'grade' in course and course['grade']: | |
output_text += f" (Grade: {course['grade']})" | |
if 'credits' in course: | |
output_text += f" | Credits: {course['credits']}" | |
output_text += f" | Year: {course['year']}\n" | |
return output_text, { | |
"gpa": gpa_data, | |
"grade_level": grade_level, | |
"courses": dict(courses_by_grade) | |
} | |
else: | |
return "Unsupported file format (PDF only for transcript parsing)", None | |
except Exception as e: | |
return f"Error processing transcript: {str(e)}", None | |
# ========== ENHANCED LEARNING STYLE QUIZ ========== | |
learning_style_questions = [ | |
"When you study for a test, you prefer to:", | |
"When you need directions to a new place, you prefer:", | |
"When you learn a new skill, you prefer to:", | |
"When you're trying to concentrate, you:", | |
"When you meet new people, you remember them by:", | |
"When you're assembling furniture or a gadget, you:", | |
"When choosing a restaurant, you rely most on:", | |
"When you're in a waiting room, you typically:", | |
"When giving someone instructions, you tend to:", | |
"When you're trying to recall information, you:", | |
"When you're at a museum or exhibit, you:", | |
"When you're learning a new language, you prefer:", | |
"When you're taking notes in class, you:", | |
"When you're explaining something complex, you:", | |
"When you're at a party, you enjoy:", | |
"When you're trying to remember a phone number, you:", | |
"When you're relaxing, you prefer to:", | |
"When you're learning to use new software, you:", | |
"When you're giving a presentation, you rely on:", | |
"When you're solving a difficult problem, you:" | |
] | |
learning_style_options = [ | |
["Read the textbook (Reading/Writing)", "Listen to lectures (Auditory)", "Use diagrams/charts (Visual)", "Practice problems (Kinesthetic)"], | |
["Look at a map (Visual)", "Have someone tell you (Auditory)", "Write down directions (Reading/Writing)", "Try walking/driving there (Kinesthetic)"], | |
["Read instructions (Reading/Writing)", "Have someone show you (Visual)", "Listen to explanations (Auditory)", "Try it yourself (Kinesthetic)"], | |
["Need quiet (Reading/Writing)", "Need background noise (Auditory)", "Need to move around (Kinesthetic)", "Need visual stimulation (Visual)"], | |
["Their face (Visual)", "Their name (Auditory)", "What you talked about (Reading/Writing)", "What you did together (Kinesthetic)"], | |
["Read the instructions carefully (Reading/Writing)", "Look at the diagrams (Visual)", "Ask someone to explain (Auditory)", "Start putting pieces together (Kinesthetic)"], | |
["Online photos of the food (Visual)", "Recommendations from friends (Auditory)", "Reading the menu online (Reading/Writing)", "Remembering how it felt to eat there (Kinesthetic)"], | |
["Read magazines (Reading/Writing)", "Listen to music (Auditory)", "Watch TV (Visual)", "Fidget or move around (Kinesthetic)"], | |
["Write them down (Reading/Writing)", "Explain verbally (Auditory)", "Demonstrate (Visual)", "Guide them physically (Kinesthetic)"], | |
["See written words in your mind (Visual)", "Hear the information in your head (Auditory)", "Write it down to remember (Reading/Writing)", "Associate it with physical actions (Kinesthetic)"], | |
["Read all the descriptions (Reading/Writing)", "Listen to audio guides (Auditory)", "Look at the displays (Visual)", "Touch interactive exhibits (Kinesthetic)"], | |
["Study grammar rules (Reading/Writing)", "Listen to native speakers (Auditory)", "Use flashcards with images (Visual)", "Practice conversations (Kinesthetic)"], | |
["Write detailed paragraphs (Reading/Writing)", "Record the lecture (Auditory)", "Draw diagrams and charts (Visual)", "Doodle while listening (Kinesthetic)"], | |
["Write detailed steps (Reading/Writing)", "Explain verbally with examples (Auditory)", "Draw diagrams (Visual)", "Use physical objects to demonstrate (Kinesthetic)"], | |
["Conversations with people (Auditory)", "Watching others or the environment (Visual)", "Writing notes or texting (Reading/Writing)", "Dancing or physical activities (Kinesthetic)"], | |
["See the numbers in your head (Visual)", "Say them aloud (Auditory)", "Write them down (Reading/Writing)", "Dial them on a keypad (Kinesthetic)"], | |
["Read a book (Reading/Writing)", "Listen to music (Auditory)", "Watch TV/movies (Visual)", "Do something physical (Kinesthetic)"], | |
["Read the manual (Reading/Writing)", "Ask someone to show you (Visual)", "Call tech support (Auditory)", "Experiment with the software (Kinesthetic)"], | |
["Detailed notes (Reading/Writing)", "Verbal explanations (Auditory)", "Visual slides (Visual)", "Physical demonstrations (Kinesthetic)"], | |
["Write out possible solutions (Reading/Writing)", "Talk through it with someone (Auditory)", "Draw diagrams (Visual)", "Build a model or prototype (Kinesthetic)"] | |
] | |
def learning_style_quiz(*answers) -> str: | |
scores = { | |
"Visual": 0, | |
"Auditory": 0, | |
"Reading/Writing": 0, | |
"Kinesthetic": 0 | |
} | |
for i, answer in enumerate(answers): | |
if answer == learning_style_options[i][0]: | |
scores["Reading/Writing"] += 1 | |
elif answer == learning_style_options[i][1]: | |
scores["Auditory"] += 1 | |
elif answer == learning_style_options[i][2]: | |
scores["Visual"] += 1 | |
elif answer == learning_style_options[i][3]: | |
scores["Kinesthetic"] += 1 | |
max_score = max(scores.values()) | |
total_questions = len(learning_style_questions) | |
# Calculate percentages | |
percentages = {style: (score/total_questions)*100 for style, score in scores.items()} | |
# Sort styles by score (descending) | |
sorted_styles = sorted(scores.items(), key=lambda x: x[1], reverse=True) | |
# Prepare detailed results | |
result = "Your Learning Style Results:\n\n" | |
for style, score in sorted_styles: | |
result += f"{style}: {score}/{total_questions} ({percentages[style]:.1f}%)\n" | |
result += "\n" | |
# Determine primary and secondary styles | |
primary_styles = [style for style, score in scores.items() if score == max_score] | |
if len(primary_styles) == 1: | |
result += f"Your primary learning style is: {primary_styles[0]}\n\n" | |
# Add personalized tips based on primary style | |
if primary_styles[0] == "Visual": | |
result += "Tips for Visual Learners:\n" | |
result += "- Use color coding in your notes\n" | |
result += "- Create mind maps and diagrams\n" | |
result += "- Watch educational videos\n" | |
result += "- Use flashcards with images\n" | |
result += "- Highlight key information in different colors\n" | |
elif primary_styles[0] == "Auditory": | |
result += "Tips for Auditory Learners:\n" | |
result += "- Record lectures and listen to them\n" | |
result += "- Participate in study groups\n" | |
result += "- Explain concepts out loud to yourself\n" | |
result += "- Use rhymes or songs to remember information\n" | |
result += "- Listen to educational podcasts\n" | |
elif primary_styles[0] == "Reading/Writing": | |
result += "Tips for Reading/Writing Learners:\n" | |
result += "- Write detailed notes\n" | |
result += "- Create summaries in your own words\n" | |
result += "- Read textbooks and articles\n" | |
result += "- Make lists to organize information\n" | |
result += "- Rewrite your notes to reinforce learning\n" | |
else: # Kinesthetic | |
result += "Tips for Kinesthetic Learners:\n" | |
result += "- Use hands-on activities\n" | |
result += "- Take frequent movement breaks\n" | |
result += "- Create physical models\n" | |
result += "- Associate information with physical actions\n" | |
result += "- Study while walking or using a standing desk\n" | |
else: | |
result += f"You have multiple strong learning styles: {', '.join(primary_styles)}\n\n" | |
result += "You may benefit from combining different learning approaches:\n" | |
if "Visual" in primary_styles: | |
result += "- Create visual representations of what you're learning\n" | |
if "Auditory" in primary_styles: | |
result += "- Discuss concepts with others or record yourself explaining them\n" | |
if "Reading/Writing" in primary_styles: | |
result += "- Write summaries and read additional materials\n" | |
if "Kinesthetic" in primary_styles: | |
result += "- Incorporate physical movement into your study sessions\n" | |
# Add general study tips | |
result += "\nAdditional Study Tips for All Learners:\n" | |
result += "- Use the Pomodoro technique (25 min study, 5 min break)\n" | |
result += "- Teach concepts to someone else to reinforce your understanding\n" | |
result += "- Connect new information to what you already know\n" | |
result += "- Get adequate sleep to consolidate memories\n" | |
return result | |
# ========== ENHANCED STUDENT PROFILE SYSTEM ========== | |
def hash_sensitive_data(data: str) -> str: | |
"""Hash sensitive data for privacy protection""" | |
return hashlib.sha256(data.encode()).hexdigest() | |
def get_profile_list() -> List[str]: | |
"""Get list of available profiles""" | |
if not os.path.exists("student_profiles"): | |
return [] | |
return [f.replace("_profile.json", "").replace("_", " ") | |
for f in os.listdir("student_profiles") | |
if f.endswith('_profile.json')] | |
def save_profile(name: str, age: int, interests: str, transcript: dict, learning_style: str, | |
movie: str, movie_reason: str, show: str, show_reason: str, | |
book: str, book_reason: str, character: str, character_reason: str, | |
blog: str, goals: str, study_preferences: str) -> str: | |
"""Save student profile with enhanced features""" | |
# Convert age to int if it's a numpy number (from gradio Number input) | |
age = int(age) if age else 0 | |
# Create profile dictionary | |
profile_data = { | |
"name": name, | |
"age": age, | |
"interests": interests, | |
"transcript": transcript, | |
"learning_style": learning_style, | |
"favorites": { | |
"movie": movie, | |
"movie_reason": movie_reason, | |
"show": show, | |
"show_reason": show_reason, | |
"book": book, | |
"book_reason": book_reason, | |
"character": character, | |
"character_reason": character_reason | |
}, | |
"blog": blog, | |
"goals": goals, | |
"study_preferences": study_preferences, | |
"last_updated": datetime.now().isoformat(), | |
"security": { | |
"name_hash": hash_sensitive_data(name), | |
"interests_hash": hash_sensitive_data(interests) | |
} | |
} | |
# Save to file | |
os.makedirs("student_profiles", exist_ok=True) | |
filename = f"{name.replace(' ', '_')}_profile.json" | |
filepath = os.path.join("student_profiles", filename) | |
with open(filepath, "w") as f: | |
json.dump(profile_data, f, indent=2) | |
return f"Profile saved successfully as {filename}" | |
def load_profile(profile_name: str = None) -> Optional[Dict]: | |
"""Load student profile with error handling""" | |
if not os.path.exists("student_profiles"): | |
return None | |
if profile_name is None: | |
# Load the first profile if none specified | |
files = [f for f in os.listdir("student_profiles") if f.endswith('.json')] | |
if not files: | |
return None | |
filepath = os.path.join("student_profiles", files[0]) | |
else: | |
# Load specific profile | |
filename = f"{profile_name.replace(' ', '_')}_profile.json" | |
filepath = os.path.join("student_profiles", filename) | |
try: | |
with open(filepath, "r") as f: | |
return json.load(f) | |
except (FileNotFoundError, json.JSONDecodeError) as e: | |
print(f"Error loading profile: {e}") | |
return None | |
def transcript_display(transcript_dict: dict) -> str: | |
"""Format transcript data for display""" | |
if not transcript_dict or "courses" not in transcript_dict: | |
return "No course information available" | |
display = "### Detailed Course History\n" | |
courses_by_grade = transcript_dict["courses"] | |
if isinstance(courses_by_grade, dict): | |
# Sort grades numerically | |
for grade in sorted(courses_by_grade.keys(), key=int): | |
display += f"\n**Grade {grade}**\n" | |
for course in courses_by_grade[grade]: | |
display += f"- {course['name']}" | |
if 'grade' in course and course['grade']: | |
display += f" (Grade: {course['grade']})" | |
if 'credits' in course: | |
display += f" | Credits: {course['credits']}" | |
display += f" | Year: {course['year']}\n" | |
if 'gpa' in transcript_dict: | |
gpa = transcript_dict['gpa'] | |
display += "\n**GPA Information**\n" | |
display += f"- Unweighted: {gpa.get('unweighted', 'N/A')}\n" | |
display += f"- Weighted: {gpa.get('weighted', 'N/A')}\n" | |
return display | |
def generate_profile_summary(profile: dict) -> str: | |
"""Generate markdown summary of profile""" | |
if not profile: | |
return "No profile data available" | |
name = profile.get("name", "Unknown") | |
age = profile.get("age", "Unknown") | |
interests = profile.get("interests", "Not specified") | |
learning_style = profile.get("learning_style", "Not determined") | |
favorites = profile.get("favorites", {}) | |
blog = profile.get("blog", "") | |
goals = profile.get("goals", "") | |
study_preferences = profile.get("study_preferences", "") | |
markdown = f"""## Student Profile: {name} | |
**Age:** {age} | |
**Interests:** {interests} | |
**Learning Style:** {learning_style} | |
### Academic Information | |
{transcript_display(profile.get("transcript", {}))} | |
### Goals | |
{goals if goals else "_No goals specified_"} | |
### Study Preferences | |
{study_preferences if study_preferences else "_No study preferences specified_"} | |
### Favorites | |
- **Movie:** {favorites.get('movie', 'Not specified')} ({favorites.get('movie_reason', 'No reason given')}) | |
- **TV Show:** {favorites.get('show', 'Not specified')} ({favorites.get('show_reason', 'No reason given')}) | |
- **Book:** {favorites.get('book', 'Not specified')} ({favorites.get('book_reason', 'No reason given')}) | |
- **Character:** {favorites.get('character', 'Not specified')} ({favorites.get('character_reason', 'No reason given')}) | |
### Personal Blog | |
{blog if blog else "_No blog provided_"} | |
""" | |
return markdown | |
# ========== ENHANCED AI TEACHING ASSISTANT ========== | |
class TeachingAssistant: | |
def __init__(self): | |
self.conversation_history = [] | |
self.current_profile = None | |
def load_profile(self, profile_name: str = None) -> bool: | |
"""Load a student profile""" | |
self.current_profile = load_profile(profile_name) | |
if self.current_profile: | |
self.conversation_history.append( | |
(f"System: Loaded profile for {self.current_profile.get('name', 'unknown student')}", None) | |
) | |
return True | |
return False | |
def generate_response(self, message: str, history: List[tuple]) -> str: | |
"""Generate response based on message and history""" | |
# Add to conversation history | |
self.conversation_history.append((f"Student: {message}", None)) | |
if not self.current_profile: | |
return "Please complete and save your profile first using the previous tabs." | |
# Get profile data | |
name = self.current_profile.get("name", "") | |
learning_style = self.current_profile.get("learning_style", "") | |
grade_level = self.current_profile.get("transcript", {}).get("grade_level", "unknown") | |
gpa = self.current_profile.get("transcript", {}).get("gpa", {}) | |
interests = self.current_profile.get("interests", "") | |
courses = self.current_profile.get("transcript", {}).get("courses", {}) | |
goals = self.current_profile.get("goals", "") | |
study_preferences = self.current_profile.get("study_preferences", "") | |
# Contextual understanding | |
message_lower = message.lower() | |
# Greetings | |
if any(greet in message_lower for greet in ["hi", "hello", "hey"]): | |
return f"Hello {name}! How can I help you with your learning today?" | |
# Study help | |
elif any(word in message_lower for word in ["study", "learn", "prepare", "exam"]): | |
return self._generate_study_tips(learning_style, courses, study_preferences) | |
# Grade help | |
elif any(word in message_lower for word in ["grade", "gpa", "score"]): | |
return self._generate_grade_info(gpa, grade_level) | |
# Course help | |
elif any(word in message_lower for word in ["course", "class", "schedule", "transcript"]): | |
return self._generate_course_info(courses) | |
# Goal tracking | |
elif any(word in message_lower for word in ["goal", "target", "objective"]): | |
return self._handle_goals(message, goals) | |
# Resource recommendations | |
elif any(word in message_lower for word in ["resource", "material", "book", "video"]): | |
return self._recommend_resources(interests, learning_style) | |
# General help | |
elif "help" in message_lower: | |
return self._generate_help_message() | |
# Unknown query | |
else: | |
return ("I'm your personalized teaching assistant. I can help with:\n" | |
"- Study strategies based on your learning style\n" | |
"- Academic performance analysis\n" | |
"- Course planning and recommendations\n" | |
"- Goal setting and tracking\n\n" | |
"Try asking about how to study for your classes or about your academic progress!") | |
def _generate_study_tips(self, learning_style: str, courses: dict, study_preferences: str) -> str: | |
"""Generate personalized study tips""" | |
response = "Here are personalized study recommendations:\n\n" | |
# Learning style based tips | |
if "Visual" in learning_style: | |
response += ("**Visual Learner Tips:**\n" | |
"- Create colorful mind maps\n" | |
"- Use diagrams and charts\n" | |
"- Watch educational videos\n" | |
"- Highlight key information\n\n") | |
if "Auditory" in learning_style: | |
response += ("**Auditory Learner Tips:**\n" | |
"- Record and listen to lectures\n" | |
"- Participate in study groups\n" | |
"- Explain concepts out loud\n" | |
"- Use mnemonic devices\n\n") | |
if "Reading/Writing" in learning_style: | |
response += ("**Reading/Writing Learner Tips:**\n" | |
"- Write detailed notes\n" | |
"- Create summaries\n" | |
"- Read additional materials\n" | |
"- Make lists and outlines\n\n") | |
if "Kinesthetic" in learning_style: | |
response += ("**Kinesthetic Learner Tips:**\n" | |
"- Use hands-on activities\n" | |
"- Take movement breaks\n" | |
"- Create physical models\n" | |
"- Study while walking\n\n") | |
# Course-specific tips | |
if courses: | |
response += "\n**Course-Specific Suggestions:**\n" | |
for grade, course_list in courses.items(): | |
for course in course_list: | |
course_name = course.get('name', '') | |
if 'math' in course_name.lower(): | |
response += f"- For {course_name}: Practice problems daily\n" | |
elif 'science' in course_name.lower(): | |
response += f"- For {course_name}: Focus on concepts and applications\n" | |
elif 'history' in course_name.lower(): | |
response += f"- For {course_name}: Create timelines and context maps\n" | |
elif 'english' in course_name.lower(): | |
response += f"- For {course_name}: Read actively and annotate texts\n" | |
# Study preferences | |
if study_preferences: | |
response += f"\n**Your Study Preferences:**\n{study_preferences}\n" | |
# General tips | |
response += ("\n**General Study Strategies:**\n" | |
"- Use the Pomodoro technique (25 min study, 5 min break)\n" | |
"- Space out your study sessions\n" | |
"- Test yourself regularly\n" | |
"- Teach concepts to someone else\n") | |
return response | |
def _generate_grade_info(self, gpa: dict, grade_level: str) -> str: | |
"""Generate grade information response""" | |
response = (f"Your Academic Performance Summary:\n" | |
f"- Current Grade Level: {grade_level}\n" | |
f"- Unweighted GPA: {gpa.get('unweighted', 'N/A')}\n" | |
f"- Weighted GPA: {gpa.get('weighted', 'N/A')}\n\n") | |
# Add improvement suggestions | |
unweighted = float(gpa.get('unweighted', 0)) if gpa.get('unweighted', 'N/A') != 'N/A' else 0 | |
if unweighted < 2.0: | |
response += ("**Recommendations for Improvement:**\n" | |
"- Meet with teachers to identify weak areas\n" | |
"- Establish a regular study schedule\n" | |
"- Focus on foundational concepts\n") | |
elif unweighted < 3.0: | |
response += ("**Recommendations for Enhancement:**\n" | |
"- Identify your strongest subjects to build confidence\n" | |
"- Set specific grade improvement goals\n" | |
"- Develop better study habits\n") | |
elif unweighted < 3.5: | |
response += ("**Recommendations for Advancement:**\n" | |
"- Challenge yourself with honors/AP courses\n" | |
"- Develop deeper understanding in your strongest areas\n" | |
"- Focus on consistent performance\n") | |
else: | |
response += ("**Recommendations for Excellence:**\n" | |
"- Pursue advanced coursework\n" | |
"- Develop independent research projects\n" | |
"- Mentor other students to reinforce your knowledge\n") | |
return response | |
def _generate_course_info(self, courses: dict) -> str: | |
"""Generate course information response""" | |
if not courses: | |
return "No course information available in your profile." | |
response = "Your Course History:\n" | |
for grade in sorted(courses.keys(), key=int): | |
response += f"\n**Grade {grade}:**\n" | |
for course in courses[grade]: | |
response += f"- {course.get('name', 'Unknown')}" | |
if 'grade' in course: | |
response += f" (Grade: {course.get('grade', '')})" | |
response += "\n" | |
# Add recommendations | |
response += "\n**Course Recommendations:**\n" | |
highest_grade = max(courses.keys(), key=int) if courses else "0" | |
if highest_grade == "09": | |
response += "- Consider exploring different subjects to find your interests\n" | |
response += "- Build strong foundational skills in math and language arts\n" | |
elif highest_grade == "10": | |
response += "- Start focusing on your academic strengths\n" | |
response += "- Consider honors or AP courses in your strong subjects\n" | |
elif highest_grade == "11": | |
response += "- Focus on college preparatory courses\n" | |
response += "- Consider AP or dual enrollment courses\n" | |
elif highest_grade == "12": | |
response += "- Complete any remaining graduation requirements\n" | |
response += "- Consider advanced courses in your intended major\n" | |
return response | |
def _handle_goals(self, message: str, current_goals: str) -> str: | |
"""Handle goal-related queries""" | |
if "set" in message.lower() or "new" in message.lower(): | |
return ("To set new goals, please update your profile with your academic goals. " | |
"You can include:\n" | |
"- Short-term goals (weekly/monthly)\n" | |
"- Long-term goals (semester/yearly)\n" | |
"- Career or college preparation goals\n") | |
elif current_goals: | |
return f"Your current goals:\n{current_goals}\n\nWould you like to update them?" | |
else: | |
return ("You haven't set any goals yet. Setting clear academic goals can help you " | |
"stay focused and motivated. Would you like to set some goals now?") | |
def _recommend_resources(self, interests: str, learning_style: str) -> str: | |
"""Recommend learning resources""" | |
response = "Based on your profile, here are some resource recommendations:\n\n" | |
# Interest-based recommendations | |
if "science" in interests.lower(): | |
response += ("**Science Resources:**\n" | |
"- Khan Academy Science courses\n" | |
"- Crash Course YouTube channel\n" | |
"- Science Journal app for experiments\n\n") | |
if "math" in interests.lower(): | |
response += ("**Math Resources:**\n" | |
"- Brilliant.org interactive math\n" | |
"- 3Blue1Brown YouTube channel\n" | |
"- Wolfram Alpha for problem solving\n\n") | |
if "history" in interests.lower(): | |
response += ("**History Resources:**\n" | |
"- Hardcore History podcast\n" | |
"- Timeline apps for historical events\n" | |
"- Historical fiction books\n\n") | |
if "art" in interests.lower() or "music" in interests.lower(): | |
response += ("**Arts Resources:**\n" | |
"- Skillshare art classes\n" | |
"- Google Arts & Culture app\n" | |
"- Local museum virtual tours\n\n") | |
# Learning style based recommendations | |
if "Visual" in learning_style: | |
response += ("**Visual Learning Resources:**\n" | |
"- MindMeister for mind mapping\n" | |
"- Canva for creating visual notes\n" | |
"- YouTube educational channels\n\n") | |
if "Auditory" in learning_style: | |
response += ("**Auditory Learning Resources:**\n" | |
"- Audible for audiobooks\n" | |
"- Podcasts like TED Talks Education\n" | |
"- Text-to-speech tools\n\n") | |
if "Reading/Writing" in learning_style: | |
response += ("**Reading/Writing Resources:**\n" | |
"- Evernote for note-taking\n" | |
"- Project Gutenberg for free books\n" | |
"- Grammarly for writing help\n\n") | |
if "Kinesthetic" in learning_style: | |
response += ("**Kinesthetic Learning Resources:**\n" | |
"- Labster virtual labs\n" | |
"- DIY science experiment kits\n" | |
"- Standing desk or exercise ball chair\n\n") | |
return response | |
def _generate_help_message(self) -> str: | |
"""Generate help message with capabilities""" | |
return ("""I can help you with: | |
1. **Study Strategies** - Get personalized study tips based on your learning style | |
2. **Academic Performance** - Check your GPA and get improvement suggestions | |
3. **Course Planning** - View your course history and get recommendations | |
4. **Goal Setting** - Set and track your academic goals | |
5. **Resource Recommendations** - Get suggested learning materials | |
Try asking: | |
- "How should I study for my math class?" | |
- "What's my current GPA?" | |
- "What courses should I take next year?" | |
- "Can you recommend some science resources?" | |
- "Help me set some academic goals" | |
""") | |
# Initialize teaching assistant | |
assistant = TeachingAssistant() | |
# ========== GRADIO INTERFACE ========== | |
with gr.Blocks(title="Personalized Learning Assistant", theme=gr.themes.Soft()) as app: | |
gr.Markdown("# π Personalized Learning Assistant") | |
gr.Markdown("This tool helps students understand their learning style, track academic progress, and get personalized study recommendations.") | |
with gr.Tab("π Step 1: Upload Transcript"): | |
gr.Markdown("### Upload your academic transcript") | |
gr.Markdown("For best results, upload a PDF of your official transcript.") | |
with gr.Row(): | |
with gr.Column(): | |
transcript_file = gr.File( | |
label="Transcript file", | |
file_types=[".pdf"], | |
info="PDF format recommended" | |
) | |
clear_btn = gr.Button("Clear") | |
with gr.Column(): | |
transcript_output = gr.Textbox( | |
label="Transcript Results", | |
lines=20, | |
interactive=False | |
) | |
transcript_data = gr.State() | |
transcript_file.change( | |
fn=parse_transcript, | |
inputs=transcript_file, | |
outputs=[transcript_output, transcript_data] | |
) | |
clear_btn.click( | |
lambda: [None, "", None], | |
outputs=[transcript_file, transcript_output, transcript_data] | |
) | |
with gr.Tab("π Step 2: Learning Style Quiz"): | |
gr.Markdown("### Discover Your Learning Style") | |
gr.Markdown("Complete this 20-question quiz to understand how you learn best.") | |
with gr.Accordion("About Learning Styles", open=False): | |
gr.Markdown(""" | |
**Visual Learners** prefer using images, diagrams, and spatial understanding. | |
**Auditory Learners** learn best through listening and speaking. | |
**Reading/Writing Learners** prefer information displayed as words. | |
**Kinesthetic Learners** learn through movement and hands-on activities. | |
""") | |
quiz_components = [] | |
with gr.Column(): | |
for i, (question, options) in enumerate(zip(learning_style_questions, learning_style_options)): | |
quiz_components.append( | |
gr.Radio( | |
options, | |
label=f"{i+1}. {question}", | |
interactive=True | |
) | |
) | |
with gr.Row(): | |
submit_quiz = gr.Button("Submit Quiz", variant="primary") | |
reset_quiz = gr.Button("Reset Quiz") | |
learning_output = gr.Textbox( | |
label="Your Learning Style Results", | |
lines=15, | |
interactive=False | |
) | |
submit_quiz.click( | |
fn=learning_style_quiz, | |
inputs=quiz_components, | |
outputs=learning_output | |
) | |
reset_quiz.click( | |
lambda: [None]*len(quiz_components), | |
outputs=quiz_components | |
) | |
with gr.Tab("π€ Step 3: Personal Profile"): | |
gr.Markdown("### Create Your Personal Profile") | |
gr.Markdown("This information helps personalize your learning experience.") | |
with gr.Row(): | |
with gr.Column(): | |
name = gr.Textbox(label="Full Name", placeholder="Enter your name") | |
age = gr.Number(label="Age", precision=0, minimum=10, maximum=25) | |
interests = gr.Textbox( | |
label="Interests/Hobbies", | |
placeholder="e.g., Science, Music, Sports" | |
) | |
goals = gr.Textbox( | |
label="Academic Goals", | |
placeholder="What do you want to achieve?", | |
lines=3 | |
) | |
study_preferences = gr.Textbox( | |
label="Study Preferences", | |
placeholder="When/where/how do you prefer to study?", | |
lines=3 | |
) | |
with gr.Column(): | |
gr.Markdown("#### Favorites") | |
movie = gr.Textbox(label="Favorite Movie") | |
movie_reason = gr.Textbox(label="Why do you like it?") | |
show = gr.Textbox(label="Favorite TV Show") | |
show_reason = gr.Textbox(label="Why do you like it?") | |
book = gr.Textbox(label="Favorite Book") | |
book_reason = gr.Textbox(label="Why do you like it?") | |
character = gr.Textbox(label="Favorite Character (book/movie/show)") | |
character_reason = gr.Textbox(label="Why do you like them?") | |
with gr.Row(): | |
blog_checkbox = gr.Checkbox(label="Include a personal blog/journal entry?", value=False) | |
blog_text = gr.Textbox( | |
label="Your Blog/Journal", | |
visible=False, | |
lines=5, | |
placeholder="Write about your learning experiences, challenges, or thoughts..." | |
) | |
blog_checkbox.change( | |
lambda x: gr.update(visible=x), | |
inputs=blog_checkbox, | |
outputs=blog_text | |
) | |
with gr.Tab("πΎ Step 4: Save & Review"): | |
gr.Markdown("### Review and Save Your Profile") | |
with gr.Row(): | |
profile_selector = gr.Dropdown( | |
label="Select Profile to Load", | |
choices=get_profile_list(), | |
interactive=True, | |
allow_custom_value=False | |
) | |
refresh_profiles = gr.Button("π Refresh List") | |
with gr.Row(): | |
save_btn = gr.Button("πΎ Save Profile", variant="primary") | |
load_btn = gr.Button("π Load Profile") | |
clear_btn = gr.Button("π§Ή Clear Form") | |
output_summary = gr.Markdown() | |
# Profile management functions | |
refresh_profiles.click( | |
lambda: gr.update(choices=get_profile_list()), | |
outputs=profile_selector | |
) | |
save_btn.click( | |
fn=save_profile, | |
inputs=[ | |
name, age, interests, transcript_data, learning_output, | |
movie, movie_reason, show, show_reason, | |
book, book_reason, character, character_reason, | |
blog_text, goals, study_preferences | |
], | |
outputs=output_summary | |
).then( | |
lambda: gr.update(choices=get_profile_list()), | |
outputs=profile_selector | |
) | |
load_btn.click( | |
fn=lambda name: generate_profile_summary(load_profile(name)), | |
inputs=profile_selector, | |
outputs=output_summary | |
) | |
clear_btn.click( | |
lambda: [""]*15 + [None, False, ""], | |
outputs=[ | |
name, age, interests, goals, study_preferences, | |
movie, movie_reason, show, show_reason, | |
book, book_reason, character, character_reason, | |
blog_text, blog_checkbox, output_summary | |
] | |
) | |
with gr.Tab("π€ AI Teaching Assistant"): | |
gr.Markdown("## Your Personalized Learning Assistant") | |
gr.Markdown("Chat with your AI assistant to get personalized learning advice based on your profile.") | |
# Profile selection for assistant | |
with gr.Row(): | |
assistant_profile_selector = gr.Dropdown( | |
label="Select Your Profile", | |
choices=get_profile_list(), | |
interactive=True | |
) | |
load_assistant_profile = gr.Button("Load Profile") | |
refresh_assistant_profiles = gr.Button("π Refresh") | |
# Chat interface | |
chatbot = gr.ChatInterface( | |
fn=assistant.generate_response, | |
examples=[ | |
"How should I study for my next math test?", | |
"What's my current GPA?", | |
"Show me my course history", | |
"Recommend some science resources", | |
"Help me set academic goals" | |
], | |
title="Chat with Your Teaching Assistant", | |
retry_btn=None, | |
undo_btn=None, | |
clear_btn="Clear Chat" | |
) | |
# Profile management for assistant | |
load_assistant_profile.click( | |
fn=lambda name: assistant.load_profile(name) or f"Loaded profile for {name}", | |
inputs=assistant_profile_selector, | |
outputs=chatbot.chatbot | |
) | |
refresh_assistant_profiles.click( | |
lambda: gr.update(choices=get_profile_list()), | |
outputs=assistant_profile_selector | |
) | |
if __name__ == "__main__": | |
app.launch() | |