import gradio as gr import pandas as pd import PyPDF2 import json import re # Parse uploaded transcript file def parse_transcript(file): if file.name.endswith('.csv'): df = pd.read_csv(file.name) elif file.name.endswith(('.xls', '.xlsx')): df = pd.read_excel(file.name) elif file.name.endswith('.pdf'): reader = PyPDF2.PdfReader(file) text = "" for page in reader.pages: text += page.extract_text() or "" df = pd.DataFrame({'Transcript_Text': [text]}) else: raise ValueError("Unsupported file format. Use .csv, .xlsx, or .pdf") return df # Extract student info def extract_transcript_info(df): transcript_text = df['Transcript_Text'].iloc[0] if 'Transcript_Text' in df.columns else '' info = {} name_match = re.search(r"Name[:\s]+([A-Z][a-z]+\s[A-Z][a-z]+)", transcript_text) if name_match: info['Name'] = name_match.group(1) gpa_match = re.findall(r'(GPA|Grade Point Average)[^\d]*(\d+\.\d+)', transcript_text, re.IGNORECASE) if gpa_match: if len(gpa_match) == 1: info['GPA'] = gpa_match[0][1] elif len(gpa_match) >= 2: info['Unweighted_GPA'] = gpa_match[0][1] info['Weighted_GPA'] = gpa_match[1][1] grade_match = re.search(r'Grade:?[\s]*(\d{1,2})', transcript_text, re.IGNORECASE) if grade_match: info['Grade_Level'] = grade_match.group(1) courses = re.findall(r'(?i)\b([A-Z][a-zA-Z\s&/]+)\s+(\d{1,3})\b', transcript_text) if courses: info['Courses'] = list(set([c[0].strip() for c in courses])) return info # Learning style questions - from educationplanner.org learning_style_questions = [ "When you are learning something new, you prefer to:", "When you are at home, you like to:", "When you spell a word, you remember it by:", "When you read, you:", "When you write, you:", "When you listen to music, you:", "When you work at solving a problem, you:", "When you give someone directions, you:", "When you are concentrating, you:", "When you meet someone new, you remember them by:" ] learning_style_answers = [ ["Watch someone do it", "Listen to someone explain it", "Read about it"], ["Watch TV or play video games", "Listen to music or talk to people", "Read books or write stories"], ["Seeing the word in your mind", "Saying the word out loud", "Writing the word down"], ["See the action in your mind", "Hear the characters talk", "Focus on the written words"], ["Use diagrams or doodles", "Talk about ideas", "Write detailed notes"], ["Appreciate the rhythm and melodies", "Easily remember lyrics", "Analyze the lyrics"], ["Visualize the solution", "Discuss the problem", "Write out the steps"], ["Draw a map", "Give spoken directions", "Write directions"], ["Picture things", "Say things out loud", "Write or read quietly"], ["Remember faces", "Remember names or voices", "Remember what you wrote about them"] ] style_count_map = {0: "visual", 1: "auditory", 2: "reading/writing"} def learning_style_quiz(*answers): scores = {'visual': 0, 'auditory': 0, 'reading/writing': 0} for i, ans in enumerate(answers): if i < len(learning_style_answers): options = learning_style_answers[i] if ans in options: index = options.index(ans) style = style_count_map[index] scores[style] += 1 max_score = max(scores.values()) best_styles = [style.capitalize() for style, score in scores.items() if score == max_score] return ", ".join(best_styles) # PanoramaEd categories and multiple choice questions get_to_know_categories = { "All About Me": [ ("What’s your favorite way to spend a day off?", []), ("If you could only eat one food for the rest of your life, what would it be?", []), ("Do you have any pets? If so, what are their names?", []), ("If you could travel anywhere in the world, where would you go?", []), ("What’s your favorite holiday or tradition?", []), ("What are some of your favorite movies or shows?", []), ("Do you have a favorite book or book series? Why?", []), ("Who is a character from a show, book, or movie that you relate to? Why?", []), ("If you could be any fictional character, who would you be and why?", []) ], "Hopes and Dreams": [ ("What do you want to be when you grow up?", []), ("What’s something you hope to achieve this year?", []), ("If you could change the world in one way, what would you do?", []), ("What are you most proud of?", []), ("What’s a big dream you have for your future?", []) ], "School Life": [ ("What’s your favorite subject in school?", []), ("What’s something that makes learning easier for you?", []), ("Do you prefer working alone or in groups?", []), ("What helps you feel confident in class?", []), ("What’s something you’re good at in school?", []) ], "Relationships": [ ("Who do you look up to and why?", []), ("Who is someone that makes you feel safe and supported?", []), ("Do you have a best friend? What do you like to do together?", []), ("What’s one thing you wish people knew about you?", []), ("What’s something kind you’ve done for someone else?", []) ] } def generate_learning_plan(info): level = info.get("Grade_Level", "unknown") courses = info.get("Courses", []) gpa = info.get("GPA", info.get("Unweighted_GPA", "N/A")) return f""" 📘 **Personalized Learning Plan** - Grade Level: {level} - GPA: {gpa} - Suggested Focus Areas: {', '.join(courses[:3]) if courses else 'N/A'} - Goals: Strengthen key subjects, explore interests, and build study habits. """ def generate_learning_style_summary(style): return f""" 🧠 **Learning Style Summary** You are a **{style}** learner. That means you learn best through {"visual aids like charts and images" if "Visual" in style else "listening and verbal instruction" if "Auditory" in style else "reading and writing-based methods"}. """ def generate_motivation_section(responses): hopes = [ans for q, ans in responses.items() if "hope" in q.lower() or "dream" in q.lower()] return f""" 💡 **Motivational Summary** Your dreams are powerful: {'; '.join(hopes) if hopes else 'You are filled with potential!'}. Believe in yourself and keep moving forward. """ def save_profile(file, *inputs): try: if not file: return "⚠️ Please upload your transcript." quiz_answers = inputs[:len(learning_style_questions)] if any(ans is None for ans in quiz_answers): return "⚠️ Please answer all the learning style questions." blog_checkbox = inputs[len(learning_style_questions)] blog_text = inputs[len(learning_style_questions)+1] category_answers = inputs[len(learning_style_questions)+2:] if any(ans.strip() == "" for ans in category_answers): return "⚠️ Please complete all 'Get to Know You' sections before saving." if blog_checkbox and blog_text.strip() == "": return "⚠️ You checked the blog option but didn’t write anything. Please write your mini blog or uncheck the option." df = parse_transcript(file) transcript_info = extract_transcript_info(df) learning_type = learning_style_quiz(*quiz_answers) question_texts = [q for cat in get_to_know_categories.values() for q, _ in cat] responses = dict(zip(question_texts, category_answers)) profile = { "transcript": df.to_dict(orient='records'), "transcript_info": transcript_info, "learning_style": learning_type, "get_to_know_answers": responses, "blog": blog_text if blog_checkbox else "[User chose to skip this section]" } summary = { "Learning_Plan": generate_learning_plan(transcript_info), "Style_Summary": generate_learning_style_summary(learning_type), "Motivation": generate_motivation_section(responses) } with open("student_profile.json", "w") as f: json.dump(profile, f, indent=4) with open("student_summary.md", "w") as f: f.write(summary["Learning_Plan"] + '\n' + summary["Style_Summary"] + '\n' + summary["Motivation"]) return f"✅ Profile saved! Your learning style is: {learning_type}" except Exception as e: return f"❌ Error: {str(e)}" # Build Gradio UI with gr.Blocks() as demo: gr.Markdown("## 🎓 Personalized AI Student Assistant") with gr.Row(): file = gr.File(label="📄 Upload Your Transcript (.csv, .xlsx, .pdf)") with gr.Column(): gr.Markdown("### 🧠 Learning Style Discovery") quiz_components = [] for i, (question, options) in enumerate(zip(learning_style_questions, learning_style_answers)): quiz_components.append(gr.Radio( choices=options, label=f"{i+1}. {question}" )) category_inputs = [] for category, questions in get_to_know_categories.items(): gr.Markdown(f"### 📘 {category}") for q_text, _ in questions: category_inputs.append(gr.Textbox(label=q_text)) blog_checkbox = gr.Checkbox(label="📝 I'd like to write a mini blog about myself") blog_text = gr.Textbox(lines=5, label="✍️ Mini Blog", visible=False) blog_checkbox.change(fn=lambda x: gr.update(visible=x), inputs=blog_checkbox, outputs=blog_text) submit = gr.Button("🗕️ Save My Profile") output = gr.Textbox(label="Status") submit.click(fn=save_profile, inputs=[file, *quiz_components, blog_checkbox, blog_text, *category_inputs], outputs=[output]) if __name__ == '__main__': demo.launch()