Dannyar608 commited on
Commit
32164a9
·
verified ·
1 Parent(s): 9d2362d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -165
app.py CHANGED
@@ -2,15 +2,14 @@
2
  import sys
3
  import subprocess
4
  import importlib
 
5
 
6
- # List of required packages
7
  required_packages = {
8
  'gradio': 'gradio>=3.0',
9
  'pandas': 'pandas',
10
  'PyPDF2': 'PyPDF2',
11
  'transformers': 'transformers',
12
- 'pdfplumber': 'pdfplumber',
13
- 'typing_extensions': 'typing_extensions'
14
  }
15
 
16
  def check_and_install_packages():
@@ -23,12 +22,7 @@ def check_and_install_packages():
23
 
24
  if missing_packages:
25
  print(f"Missing packages: {', '.join(missing_packages)}")
26
- print("Attempting to install...")
27
- try:
28
- subprocess.check_call([sys.executable, "-m", "pip", "install", *missing_packages])
29
- print("Installation successful.")
30
- except subprocess.CalledProcessError as e:
31
- print(f"Failed to install packages. Error: {e}")
32
 
33
  check_and_install_packages()
34
 
@@ -59,6 +53,7 @@ class UniversalTranscriptParser:
59
  }
60
 
61
  def parse_transcript(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
 
62
  transcript_type = self._identify_transcript_type(text)
63
 
64
  if transcript_type == 'homeschool':
@@ -69,6 +64,7 @@ class UniversalTranscriptParser:
69
  return self._parse_miami_dade(text)
70
 
71
  def _identify_transcript_type(self, text: str) -> str:
 
72
  if re.search(r'Sample OFFICIAL HIGH SCHOOL TRANSCRIPT', text):
73
  return 'homeschool'
74
  elif re.search(r'DORAL ACADEMY HIGH SCHOOL', text):
@@ -76,22 +72,27 @@ class UniversalTranscriptParser:
76
  return 'miami_dade'
77
 
78
  def _parse_homeschool(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
 
79
  courses = []
80
  current_grade = None
81
  current_year = None
82
 
 
83
  student_info = {}
84
  name_match = re.search(r'Student Name:\s*(.+)\s*SSN:', text)
85
  if name_match:
86
  student_info['name'] = name_match.group(1).strip()
87
 
 
88
  for line in text.split('\n'):
 
89
  grade_match = re.match(r'^\|?\s*(\d+th Grade)\s*\|.*(\d{4}-\d{4})', line)
90
  if grade_match:
91
  current_grade = grade_match.group(1)
92
  current_year = grade_match.group(2)
93
  continue
94
 
 
95
  course_match = re.match(
96
  r'^\|?\s*([^\|]+?)\s*\|\s*([A-Z][+*]?)\s*\|\s*([^\|]+)\s*\|\s*(\d+\.?\d*)\s*\|\s*(\d+)',
97
  line
@@ -99,6 +100,7 @@ class UniversalTranscriptParser:
99
 
100
  if course_match and current_grade:
101
  course_name = course_match.group(1).strip()
 
102
  course_name = re.sub(r'^\|?\s*', '', course_name)
103
 
104
  courses.append({
@@ -112,33 +114,40 @@ class UniversalTranscriptParser:
112
  'transcript_type': 'homeschool'
113
  })
114
 
 
115
  gpa_data = {}
116
  gpa_match = re.search(r'Cum\. GPA\s*\|\s*([\d\.]+)', text)
117
  if gpa_match:
118
  gpa_data['unweighted'] = gpa_match.group(1)
119
- gpa_data['weighted'] = gpa_match.group(1)
120
 
121
  return {
122
  'student_info': student_info,
123
- 'courses': {'All': courses},
124
  'gpa': gpa_data,
125
  'grade_level': current_grade.replace('th Grade', '') if current_grade else "Unknown"
126
  }
127
 
128
  def _parse_doral_academy(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
 
129
  courses = []
 
 
130
  student_info = {}
131
  name_match = re.search(r'LEGAL NAME:\s*([^\n]+)', text)
132
  if name_match:
133
  student_info['name'] = name_match.group(1).strip()
134
 
 
135
  year_pattern = re.compile(r'YEAR:\s*(\d{4}-\d{4})\s*GRADE LEVEL:\s*(\d{2})', re.MULTILINE)
136
  year_matches = year_pattern.finditer(text)
137
 
 
138
  grade_year_map = {}
139
  for match in year_matches:
140
  grade_year_map[match.group(2)] = match.group(1)
141
 
 
142
  course_pattern = re.compile(
143
  r'(\d)\s+(\d{7})\s+([^\n]+?)\s+([A-Z]{2})\s+([A-Z])\s+([A-Z])\s+([A-Z])\s+(\d\.\d{2})\s+(\d\.\d{2})',
144
  re.MULTILINE
@@ -166,6 +175,7 @@ class UniversalTranscriptParser:
166
 
167
  courses_by_grade[grade_level_num].append(course_info)
168
 
 
169
  gpa_data = {}
170
  unweighted_match = re.search(r'Un-weighted GPA\s*([\d\.]+)', text)
171
  weighted_match = re.search(r'Weighted GPA\s*([\d\.]+)', text)
@@ -175,6 +185,7 @@ class UniversalTranscriptParser:
175
  if weighted_match:
176
  gpa_data['weighted'] = weighted_match.group(1)
177
 
 
178
  grade_level = "12" if re.search(r'GRADE LEVEL:\s*12', text) else "Unknown"
179
 
180
  return {
@@ -185,14 +196,17 @@ class UniversalTranscriptParser:
185
  }
186
 
187
  def _parse_miami_dade(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
 
188
  courses = []
189
  courses_by_grade = defaultdict(list)
190
 
 
191
  student_info = {}
192
  name_match = re.search(r'0783977 - ([^,]+),\s*([^\n]+)', text)
193
  if name_match:
194
  student_info['name'] = f"{name_match.group(2)} {name_match.group(1)}"
195
 
 
196
  course_pattern = re.compile(
197
  r'([A-Z]-[A-Za-z\s&]+)\s*\|\s*(\d{4}-\d{4})\s*\|\s*(\d{2})\s*\|\s*([A-Z0-9]+)\s*\|\s*([^\|]+)\s*\|\s*([^\|]+)\s*\|\s*([^\|]+)\s*\|\s*([A-Z]?)\s*\|\s*([A-Z]?)\s*\|\s*([^\|]+)',
198
  re.MULTILINE
@@ -218,11 +232,13 @@ class UniversalTranscriptParser:
218
 
219
  courses_by_grade[match.group(3)].append(course_info)
220
 
 
221
  gpa_data = {
222
  'weighted': extract_gpa(text, 'Weighted GPA'),
223
  'unweighted': extract_gpa(text, 'Un-weighted GPA')
224
  }
225
 
 
226
  grade_level = re.search(r'Current Grade:\s*(\d+)', text).group(1) if re.search(r'Current Grade:\s*(\d+)', text) else "Unknown"
227
 
228
  return {
@@ -274,85 +290,16 @@ def parse_transcript(file):
274
 
275
  parsed_data = parser.parse_transcript(text)
276
 
277
- output_text = f"Student Transcript Summary\n{'='*40}\n"
278
-
279
- if 'student_info' in parsed_data and 'name' in parsed_data['student_info']:
280
- output_text += f"Student: {parsed_data['student_info']['name']}\n"
281
-
282
- output_text += f"Current Grade Level: {parsed_data.get('grade_level', 'Unknown')}\n"
283
-
284
- if 'gpa' in parsed_data:
285
- gpa = parsed_data['gpa']
286
- output_text += f"Weighted GPA: {gpa.get('weighted', 'N/A')}\n"
287
- output_text += f"Unweighted GPA: {gpa.get('unweighted', 'N/A')}\n\n"
288
-
289
- output_text += "Course History:\n{'='*40}\n"
290
-
291
- if 'courses' in parsed_data:
292
- courses_by_grade = parsed_data['courses']
293
-
294
- def grade_sort_key(grade):
295
- try:
296
- num = int(re.search(r'\d+', grade).group())
297
- return num
298
- except (AttributeError, ValueError):
299
- return float('inf')
300
-
301
- grades_sorted = sorted(courses_by_grade.keys(), key=grade_sort_key)
302
-
303
- for grade in grades_sorted:
304
- output_text += f"\nGrade {grade}:\n{'-'*30}\n"
305
- for course in courses_by_grade[grade]:
306
- output_text += f"- {course.get('name', 'Unnamed Course')}"
307
- if 'grade' in course and course['grade']:
308
- output_text += f" (Grade: {course['grade']})"
309
- if 'credits' in course:
310
- output_text += f" | Credits: {course['credits']}"
311
- if 'school_year' in course:
312
- output_text += f" | Year: {course['school_year']}"
313
- output_text += "\n"
314
 
315
  return output_text, parsed_data
316
  else:
317
  return "Unsupported file format (PDF only for transcript parsing)", None
318
 
319
- def transcript_display(transcript_dict):
320
- if not transcript_dict or "courses" not in transcript_dict:
321
- return "No course information available"
322
-
323
- display = "### Detailed Course History\n"
324
- courses_by_grade = transcript_dict["courses"]
325
-
326
- if isinstance(courses_by_grade, dict):
327
- def grade_sort_key(grade):
328
- try:
329
- num = int(re.search(r'\d+', grade).group())
330
- return num
331
- except (AttributeError, ValueError):
332
- return float('inf')
333
-
334
- grades_sorted = sorted(courses_by_grade.keys(), key=grade_sort_key)
335
-
336
- for grade in grades_sorted:
337
- display += f"\n**Grade {grade}**\n"
338
- for course in courses_by_grade[grade]:
339
- display += f"- {course.get('name', 'Unnamed Course')}"
340
- if 'grade' in course and course['grade']:
341
- display += f" (Grade: {course['grade']})"
342
- if 'credits' in course:
343
- display += f" | Credits: {course['credits']}"
344
- if 'school_year' in course:
345
- display += f" | Year: {course['school_year']}"
346
- display += "\n"
347
-
348
- if 'gpa' in transcript_dict:
349
- gpa = transcript_dict['gpa']
350
- display += "\n**GPA Information**\n"
351
- display += f"- Unweighted: {gpa.get('unweighted', 'N/A')}\n"
352
- display += f"- Weighted: {gpa.get('weighted', 'N/A')}\n"
353
-
354
- return display
355
-
356
  # ========== LEARNING STYLE QUIZ ==========
357
  learning_style_questions = [
358
  "When you study for a test, you prefer to:",
@@ -421,16 +368,20 @@ def learning_style_quiz(*answers):
421
  max_score = max(scores.values())
422
  total_questions = len(learning_style_questions)
423
 
 
424
  percentages = {style: (score/total_questions)*100 for style, score in scores.items()}
425
 
 
426
  sorted_styles = sorted(scores.items(), key=lambda x: x[1], reverse=True)
427
 
 
428
  result = "Your Learning Style Results:\n\n"
429
  for style, score in sorted_styles:
430
  result += f"{style}: {score}/{total_questions} ({percentages[style]:.1f}%)\n"
431
 
432
  result += "\n"
433
 
 
434
  primary_styles = [style for style, score in scores.items() if score == max_score]
435
 
436
  if len(primary_styles) == 1:
@@ -453,7 +404,7 @@ def learning_style_quiz(*answers):
453
  result += "- Create summaries in your own words\n"
454
  result += "- Read textbooks and articles\n"
455
  result += "- Make lists to organize information\n"
456
- else:
457
  result += "Tips for Kinesthetic Learners:\n"
458
  result += "- Use hands-on activities\n"
459
  result += "- Take frequent movement breaks\n"
@@ -469,6 +420,7 @@ def learning_style_quiz(*answers):
469
  def save_profile(name, age, interests, transcript, learning_style,
470
  movie, movie_reason, show, show_reason,
471
  book, book_reason, character, character_reason, blog):
 
472
  age = int(age) if age else 0
473
 
474
  favorites = {
@@ -501,8 +453,9 @@ def save_profile(name, age, interests, transcript, learning_style,
501
  **Age:** {age}
502
  **Interests:** {interests}
503
  **Learning Style:** {learning_style}
504
- #### Transcript:
505
- {transcript_display(transcript)}
 
506
  #### Favorites:
507
  - Movie: {favorites['movie']} ({favorites['movie_reason']})
508
  - Show: {favorites['show']} ({favorites['show_reason']})
@@ -528,107 +481,96 @@ def generate_response(message, history):
528
  if not profile:
529
  return "Please complete and save your profile first using the previous tabs."
530
 
 
531
  learning_style = profile.get("learning_style", "")
532
- grade_level = profile.get("transcript", {}).get("grade_level", "unknown")
533
- gpa = profile.get("transcript", {}).get("gpa", {})
534
- interests = profile.get("interests", "")
535
- courses = profile.get("transcript", {}).get("courses", {})
536
 
 
 
 
 
 
 
 
 
 
537
  greetings = ["hi", "hello", "hey"]
538
  study_help = ["study", "learn", "prepare", "exam"]
539
- grade_help = ["grade", "gpa", "score"]
540
- interest_help = ["interest", "hobby", "passion"]
541
- course_help = ["courses", "classes", "transcript", "schedule"]
542
 
543
  if any(greet in message.lower() for greet in greetings):
544
  return f"Hello {profile.get('name', 'there')}! How can I help you today?"
545
 
 
 
 
 
 
546
  elif any(word in message.lower() for word in study_help):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  if "Visual" in learning_style:
548
- response = ("Based on your visual learning style, I recommend:\n"
549
- "- Creating mind maps or diagrams\n"
550
- "- Using color-coded notes\n"
551
- "- Watching educational videos")
552
  elif "Auditory" in learning_style:
553
- response = ("Based on your auditory learning style, I recommend:\n"
554
- "- Recording lectures and listening to them\n"
555
- "- Participating in study groups\n"
556
- "- Explaining concepts out loud")
557
  elif "Reading/Writing" in learning_style:
558
- response = ("Based on your reading/writing learning style, I recommend:\n"
559
- "- Writing detailed notes\n"
560
- "- Creating summaries in your own words\n"
561
- "- Reading textbooks and articles")
562
  elif "Kinesthetic" in learning_style:
563
- response = ("Based on your kinesthetic learning style, I recommend:\n"
564
- "- Hands-on practice\n"
565
- "- Creating physical models\n"
566
- "- Taking frequent movement breaks")
567
- else:
568
- response = ("Here are some general study tips:\n"
569
- "- Break study sessions into 25-minute chunks\n"
570
- "- Review material regularly\n"
571
- "- Teach concepts to someone else")
572
 
573
  return response
574
 
575
- elif any(word in message.lower() for word in grade_help):
576
- return (f"Your GPA information:\n"
577
- f"- Unweighted: {gpa.get('unweighted', 'N/A')}\n"
578
- f"- Weighted: {gpa.get('weighted', 'N/A')}\n\n"
579
- "To improve your grades, try:\n"
580
- "- Setting specific goals\n"
581
- "- Meeting with teachers\n"
582
- "- Developing a study schedule")
583
-
584
- elif any(word in message.lower() for word in interest_help):
585
- return (f"I see you're interested in: {interests}\n\n"
586
- "You might want to:\n"
587
- "- Find clubs or activities related to these interests\n"
588
- "- Explore career paths that align with them")
589
-
590
  elif any(word in message.lower() for word in course_help):
591
- response = "Here's a summary of your courses:\n"
592
- if isinstance(courses, dict):
593
- def grade_sort_key(grade):
594
- try:
595
- num = int(re.search(r'\d+', grade).group())
596
- return num
597
- except (AttributeError, ValueError):
598
- return float('inf')
599
-
600
- grades_sorted = sorted(courses.keys(), key=grade_sort_key)
601
-
602
- for grade in grades_sorted:
603
- response += f"\nGrade {grade}:\n"
604
- for course in courses[grade]:
605
- response += f"- {course.get('name', 'Unnamed Course')}"
606
- if 'grade' in course:
607
- response += f" (Grade: {course['grade']})"
608
- response += "\n"
609
- else:
610
- response += "No detailed course information available."
611
  return response
612
 
613
  elif "help" in message.lower():
614
  return ("I can help with:\n"
615
- "- Study tips based on your learning style\n"
616
- "- GPA and grade information\n"
617
- "- Course history and schedules\n"
618
- "- General academic advice\n\n"
619
- "Try asking about study strategies or your grades!")
620
 
621
  else:
622
  return ("I'm your personalized teaching assistant. "
623
- "I can help with study tips, grade information, and academic advice. "
624
- "Try asking about how to study for your classes!")
625
 
626
  # ========== GRADIO INTERFACE ==========
627
  with gr.Blocks() as app:
628
  with gr.Tab("Step 1: Upload Transcript"):
629
  gr.Markdown("### Upload your transcript (PDF recommended)")
630
  transcript_file = gr.File(label="Transcript file", file_types=[".pdf"])
631
- transcript_output = gr.Textbox(label="Transcript Results", lines=20)
632
  transcript_data = gr.State()
633
  transcript_file.change(
634
  fn=parse_transcript,
@@ -681,13 +623,12 @@ with gr.Blocks() as app:
681
  chatbot = gr.ChatInterface(
682
  fn=generate_response,
683
  examples=[
684
- "How should I study for my next test?",
685
- "What's my GPA information?",
686
- "Show me my course history",
687
- "How can I improve my grades?"
688
  ]
689
  )
690
 
691
- # ========== RUN APPLICATION ==========
692
  if __name__ == "__main__":
693
- app.launch()
 
 
2
  import sys
3
  import subprocess
4
  import importlib
5
+ from datetime import datetime
6
 
 
7
  required_packages = {
8
  'gradio': 'gradio>=3.0',
9
  'pandas': 'pandas',
10
  'PyPDF2': 'PyPDF2',
11
  'transformers': 'transformers',
12
+ 'pdfplumber': 'pdfplumber'
 
13
  }
14
 
15
  def check_and_install_packages():
 
22
 
23
  if missing_packages:
24
  print(f"Missing packages: {', '.join(missing_packages)}")
25
+ subprocess.check_call([sys.executable, "-m", "pip", "install", *missing_packages])
 
 
 
 
 
26
 
27
  check_and_install_packages()
28
 
 
53
  }
54
 
55
  def parse_transcript(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
56
+ """Determine transcript type and parse accordingly"""
57
  transcript_type = self._identify_transcript_type(text)
58
 
59
  if transcript_type == 'homeschool':
 
64
  return self._parse_miami_dade(text)
65
 
66
  def _identify_transcript_type(self, text: str) -> str:
67
+ """Identify which type of transcript we're processing"""
68
  if re.search(r'Sample OFFICIAL HIGH SCHOOL TRANSCRIPT', text):
69
  return 'homeschool'
70
  elif re.search(r'DORAL ACADEMY HIGH SCHOOL', text):
 
72
  return 'miami_dade'
73
 
74
  def _parse_homeschool(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
75
+ """Parse homeschool transcript format"""
76
  courses = []
77
  current_grade = None
78
  current_year = None
79
 
80
+ # Extract student info
81
  student_info = {}
82
  name_match = re.search(r'Student Name:\s*(.+)\s*SSN:', text)
83
  if name_match:
84
  student_info['name'] = name_match.group(1).strip()
85
 
86
+ # Process each line
87
  for line in text.split('\n'):
88
+ # Check for grade level header
89
  grade_match = re.match(r'^\|?\s*(\d+th Grade)\s*\|.*(\d{4}-\d{4})', line)
90
  if grade_match:
91
  current_grade = grade_match.group(1)
92
  current_year = grade_match.group(2)
93
  continue
94
 
95
+ # Course line pattern
96
  course_match = re.match(
97
  r'^\|?\s*([^\|]+?)\s*\|\s*([A-Z][+*]?)\s*\|\s*([^\|]+)\s*\|\s*(\d+\.?\d*)\s*\|\s*(\d+)',
98
  line
 
100
 
101
  if course_match and current_grade:
102
  course_name = course_match.group(1).strip()
103
+ # Clean course names that start with | or have extra spaces
104
  course_name = re.sub(r'^\|?\s*', '', course_name)
105
 
106
  courses.append({
 
114
  'transcript_type': 'homeschool'
115
  })
116
 
117
+ # Extract GPA information from homeschool transcript
118
  gpa_data = {}
119
  gpa_match = re.search(r'Cum\. GPA\s*\|\s*([\d\.]+)', text)
120
  if gpa_match:
121
  gpa_data['unweighted'] = gpa_match.group(1)
122
+ gpa_data['weighted'] = gpa_match.group(1) # Homeschool often has same weighted/unweighted
123
 
124
  return {
125
  'student_info': student_info,
126
+ 'courses': {'All': courses}, # Homeschool doesn't separate by grade in same way
127
  'gpa': gpa_data,
128
  'grade_level': current_grade.replace('th Grade', '') if current_grade else "Unknown"
129
  }
130
 
131
  def _parse_doral_academy(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
132
+ """Parse Doral Academy specific format"""
133
  courses = []
134
+
135
+ # Extract student info
136
  student_info = {}
137
  name_match = re.search(r'LEGAL NAME:\s*([^\n]+)', text)
138
  if name_match:
139
  student_info['name'] = name_match.group(1).strip()
140
 
141
+ # Extract school year information
142
  year_pattern = re.compile(r'YEAR:\s*(\d{4}-\d{4})\s*GRADE LEVEL:\s*(\d{2})', re.MULTILINE)
143
  year_matches = year_pattern.finditer(text)
144
 
145
+ # Create mapping of grade levels to years
146
  grade_year_map = {}
147
  for match in year_matches:
148
  grade_year_map[match.group(2)] = match.group(1)
149
 
150
+ # Course pattern for Doral Academy
151
  course_pattern = re.compile(
152
  r'(\d)\s+(\d{7})\s+([^\n]+?)\s+([A-Z]{2})\s+([A-Z])\s+([A-Z])\s+([A-Z])\s+(\d\.\d{2})\s+(\d\.\d{2})',
153
  re.MULTILINE
 
175
 
176
  courses_by_grade[grade_level_num].append(course_info)
177
 
178
+ # Extract GPA information from Doral Academy transcript
179
  gpa_data = {}
180
  unweighted_match = re.search(r'Un-weighted GPA\s*([\d\.]+)', text)
181
  weighted_match = re.search(r'Weighted GPA\s*([\d\.]+)', text)
 
185
  if weighted_match:
186
  gpa_data['weighted'] = weighted_match.group(1)
187
 
188
+ # Extract current grade level
189
  grade_level = "12" if re.search(r'GRADE LEVEL:\s*12', text) else "Unknown"
190
 
191
  return {
 
196
  }
197
 
198
  def _parse_miami_dade(self, text: str) -> Dict[str, Union[Dict, List[Dict]]]:
199
+ """Parse standard Miami-Dade format"""
200
  courses = []
201
  courses_by_grade = defaultdict(list)
202
 
203
+ # Extract student info
204
  student_info = {}
205
  name_match = re.search(r'0783977 - ([^,]+),\s*([^\n]+)', text)
206
  if name_match:
207
  student_info['name'] = f"{name_match.group(2)} {name_match.group(1)}"
208
 
209
+ # Course pattern for Miami-Dade
210
  course_pattern = re.compile(
211
  r'([A-Z]-[A-Za-z\s&]+)\s*\|\s*(\d{4}-\d{4})\s*\|\s*(\d{2})\s*\|\s*([A-Z0-9]+)\s*\|\s*([^\|]+)\s*\|\s*([^\|]+)\s*\|\s*([^\|]+)\s*\|\s*([A-Z]?)\s*\|\s*([A-Z]?)\s*\|\s*([^\|]+)',
212
  re.MULTILINE
 
232
 
233
  courses_by_grade[match.group(3)].append(course_info)
234
 
235
+ # Extract GPA information
236
  gpa_data = {
237
  'weighted': extract_gpa(text, 'Weighted GPA'),
238
  'unweighted': extract_gpa(text, 'Un-weighted GPA')
239
  }
240
 
241
+ # Extract current grade level
242
  grade_level = re.search(r'Current Grade:\s*(\d+)', text).group(1) if re.search(r'Current Grade:\s*(\d+)', text) else "Unknown"
243
 
244
  return {
 
290
 
291
  parsed_data = parser.parse_transcript(text)
292
 
293
+ # Only show GPA in the output
294
+ output_text = f"Transcript Processed Successfully!\n\n"
295
+ output_text += f"GPA Information:\n"
296
+ output_text += f"- Weighted: {parsed_data['gpa'].get('weighted', 'N/A')}\n"
297
+ output_text += f"- Unweighted: {parsed_data['gpa'].get('unweighted', 'N/A')}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
 
299
  return output_text, parsed_data
300
  else:
301
  return "Unsupported file format (PDF only for transcript parsing)", None
302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  # ========== LEARNING STYLE QUIZ ==========
304
  learning_style_questions = [
305
  "When you study for a test, you prefer to:",
 
368
  max_score = max(scores.values())
369
  total_questions = len(learning_style_questions)
370
 
371
+ # Calculate percentages
372
  percentages = {style: (score/total_questions)*100 for style, score in scores.items()}
373
 
374
+ # Sort styles by score (descending)
375
  sorted_styles = sorted(scores.items(), key=lambda x: x[1], reverse=True)
376
 
377
+ # Prepare detailed results
378
  result = "Your Learning Style Results:\n\n"
379
  for style, score in sorted_styles:
380
  result += f"{style}: {score}/{total_questions} ({percentages[style]:.1f}%)\n"
381
 
382
  result += "\n"
383
 
384
+ # Determine primary and secondary styles
385
  primary_styles = [style for style, score in scores.items() if score == max_score]
386
 
387
  if len(primary_styles) == 1:
 
404
  result += "- Create summaries in your own words\n"
405
  result += "- Read textbooks and articles\n"
406
  result += "- Make lists to organize information\n"
407
+ else: # Kinesthetic
408
  result += "Tips for Kinesthetic Learners:\n"
409
  result += "- Use hands-on activities\n"
410
  result += "- Take frequent movement breaks\n"
 
420
  def save_profile(name, age, interests, transcript, learning_style,
421
  movie, movie_reason, show, show_reason,
422
  book, book_reason, character, character_reason, blog):
423
+ # Convert age to int if it's a numpy number (from gradio Number input)
424
  age = int(age) if age else 0
425
 
426
  favorites = {
 
453
  **Age:** {age}
454
  **Interests:** {interests}
455
  **Learning Style:** {learning_style}
456
+ #### GPA Information:
457
+ - Weighted: {transcript['gpa'].get('weighted', 'N/A')}
458
+ - Unweighted: {transcript['gpa'].get('unweighted', 'N/A')}
459
  #### Favorites:
460
  - Movie: {favorites['movie']} ({favorites['movie_reason']})
461
  - Show: {favorites['show']} ({favorites['show_reason']})
 
481
  if not profile:
482
  return "Please complete and save your profile first using the previous tabs."
483
 
484
+ # Get profile data
485
  learning_style = profile.get("learning_style", "")
486
+ transcript = profile.get("transcript", {})
487
+ gpa = transcript.get("gpa", {})
488
+ courses = []
 
489
 
490
+ # Flatten all courses from all grades
491
+ if 'courses' in transcript:
492
+ if isinstance(transcript['courses'], dict):
493
+ for grade_courses in transcript['courses'].values():
494
+ courses.extend(grade_courses)
495
+ elif isinstance(transcript['courses'], list):
496
+ courses = transcript['courses']
497
+
498
+ # Common responses
499
  greetings = ["hi", "hello", "hey"]
500
  study_help = ["study", "learn", "prepare", "exam"]
501
+ grade_help = ["gpa", "grade point average", "grades"]
502
+ course_help = ["courses", "classes", "subjects"]
 
503
 
504
  if any(greet in message.lower() for greet in greetings):
505
  return f"Hello {profile.get('name', 'there')}! How can I help you today?"
506
 
507
+ elif any(word in message.lower() for word in grade_help):
508
+ return (f"Your GPA information:\n"
509
+ f"- Weighted: {gpa.get('weighted', 'N/A')}\n"
510
+ f"- Unweighted: {gpa.get('unweighted', 'N/A')}")
511
+
512
  elif any(word in message.lower() for word in study_help):
513
+ # Analyze course performance to give personalized advice
514
+ strong_subjects = [c['name'] for c in courses if 'grade' in c and c['grade'] in ['A', 'A+', 'B+']]
515
+ weak_subjects = [c['name'] for c in courses if 'grade' in c and c['grade'] in ['D', 'F']]
516
+
517
+ response = "Here are some personalized study tips:\n"
518
+
519
+ if strong_subjects:
520
+ response += f"\nYou're doing well in: {', '.join(strong_subjects[:3])}\n"
521
+ response += "→ Keep up the good work in these areas!\n"
522
+
523
+ if weak_subjects:
524
+ response += f"\nYou might want to focus more on: {', '.join(weak_subjects[:3])}\n"
525
+ response += "→ Consider getting extra help or tutoring\n"
526
+
527
+ # Add learning style specific tips
528
  if "Visual" in learning_style:
529
+ response += "\nVisual Learner Tip: Try creating diagrams or mind maps\n"
 
 
 
530
  elif "Auditory" in learning_style:
531
+ response += "\nAuditory Learner Tip: Record yourself explaining concepts\n"
 
 
 
532
  elif "Reading/Writing" in learning_style:
533
+ response += "\nReading/Writing Tip: Write summaries in your own words\n"
 
 
 
534
  elif "Kinesthetic" in learning_style:
535
+ response += "\nKinesthetic Tip: Use physical objects to demonstrate concepts\n"
 
 
 
 
 
 
 
 
536
 
537
  return response
538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  elif any(word in message.lower() for word in course_help):
540
+ if not courses:
541
+ return "No course information available."
542
+
543
+ # Group by subject area
544
+ subjects = defaultdict(list)
545
+ for course in courses:
546
+ if 'name' in course:
547
+ # Extract first word as subject area
548
+ subject = course['name'].split()[0]
549
+ subjects[subject].append(course)
550
+
551
+ response = "Your course subjects:\n"
552
+ for subject, subject_courses in subjects.items():
553
+ response += f"\n{subject} ({len(subject_courses)} courses)"
554
+
 
 
 
 
 
555
  return response
556
 
557
  elif "help" in message.lower():
558
  return ("I can help with:\n"
559
+ "- Your GPA information\n"
560
+ "- Personalized study tips\n"
561
+ "- Course information\n"
562
+ "- Learning style recommendations")
 
563
 
564
  else:
565
  return ("I'm your personalized teaching assistant. "
566
+ "Ask me about your GPA, courses, or study tips!")
 
567
 
568
  # ========== GRADIO INTERFACE ==========
569
  with gr.Blocks() as app:
570
  with gr.Tab("Step 1: Upload Transcript"):
571
  gr.Markdown("### Upload your transcript (PDF recommended)")
572
  transcript_file = gr.File(label="Transcript file", file_types=[".pdf"])
573
+ transcript_output = gr.Textbox(label="Transcript Results", lines=5)
574
  transcript_data = gr.State()
575
  transcript_file.change(
576
  fn=parse_transcript,
 
623
  chatbot = gr.ChatInterface(
624
  fn=generate_response,
625
  examples=[
626
+ "What's my GPA?",
627
+ "How should I study for my classes?",
628
+ "What subjects am I taking?"
 
629
  ]
630
  )
631
 
 
632
  if __name__ == "__main__":
633
+ app.launch()
634
+