Dannyar608 commited on
Commit
5e90a64
·
verified ·
1 Parent(s): 1afdb58

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +190 -363
app.py CHANGED
@@ -16,7 +16,7 @@ import secrets
16
  import string
17
  from huggingface_hub import HfApi, HfFolder
18
  import torch
19
- from transformers import AutoTokenizer, AutoModelForCausalLM
20
  import time
21
  import logging
22
  import asyncio
@@ -35,6 +35,7 @@ from dateutil.relativedelta import relativedelta
35
  import numpy as np
36
  import matplotlib.pyplot as plt
37
  from tqdm import tqdm
 
38
 
39
  # Enhanced Configuration
40
  PROFILES_DIR = "student_profiles"
@@ -61,7 +62,7 @@ logging.basicConfig(
61
  logger = logging.getLogger(__name__)
62
 
63
  # Model configuration
64
- MODEL_NAME = "deepseek-ai/deepseek-llm-7b"
65
 
66
  @lru_cache(maxsize=1)
67
  def get_model_and_tokenizer():
@@ -1472,374 +1473,188 @@ class EnhancedProfileManager:
1472
  # Initialize profile manager
1473
  profile_manager = EnhancedProfileManager()
1474
 
1475
- class EnhancedTeachingAssistant:
1476
  def __init__(self):
1477
- self.context_history = []
1478
- self.max_context_length = MAX_CONTEXT_HISTORY
1479
- self.model, self.tokenizer = None, None
1480
- self.last_model_load_attempt = 0
1481
-
1482
- async def initialize_model(self):
1483
- if not self.model or not self.tokenizer:
1484
- if time.time() - self.last_model_load_attempt > 3600:
1485
- self.model, self.tokenizer = get_model_and_tokenizer()
1486
- self.last_model_load_attempt = time.time()
1487
-
1488
- async def generate_response(self, message: str, history: List[List[Union[str, None]]], session_token: str) -> str:
1489
- try:
1490
- await self.initialize_model()
1491
-
1492
- profile = profile_manager.load_profile(session_token=session_token)
1493
- if not profile:
1494
- return "Please complete and save your profile first to get personalized advice."
1495
-
1496
- self._update_context(message, history)
1497
-
1498
- student_name = profile.get('name', 'Student')
1499
- transcript = profile.get('transcript', {})
1500
-
1501
- if transcript.get('format') == 'progress_summary':
1502
- gpa = transcript.get('student_info', {}).get('weighted_gpa', None)
1503
- service_hours = transcript.get('student_info', {}).get('community_service_hours', 0)
1504
- else:
1505
- gpa = transcript.get('academic_summary', {}).get('gpa', {}).get('district', None)
1506
- service_hours = transcript.get('assessments', {}).get('community_service', {}).get('hours', 0)
1507
-
1508
- learning_style = re.search(r"Your primary learning style is\s*\*\*(.*?)\*\*",
1509
- profile.get('learning_style', ''))
1510
- learning_style = learning_style.group(1) if learning_style else None
1511
-
1512
- context = f"You are an AI teaching assistant helping {student_name}. "
1513
- if gpa:
1514
- context += f"{student_name}'s current weighted GPA is {gpa}. "
1515
- if learning_style:
1516
- context += f"They are a {learning_style.lower()} learner. "
1517
- if service_hours:
1518
- context += f"They have completed {service_hours} community service hours. "
1519
-
1520
- if self.context_history:
1521
- context += "Recent conversation:\n"
1522
- for item in self.context_history[-self.max_context_length:]:
1523
- role = "Student" if item['role'] == 'user' else "Assistant"
1524
- context += f"{role}: {item['content']}\n"
1525
-
1526
- query_type = self._classify_query(message)
1527
- response = await self._generate_typed_response(query_type, message, context, profile)
1528
-
1529
- return response
1530
-
1531
- except Exception as e:
1532
- logger.error(f"Error generating response: {str(e)}")
1533
- return "I encountered an error processing your request. Please try again."
1534
-
1535
- def _classify_query(self, message: str) -> str:
1536
- message_lower = message.lower()
1537
-
1538
- if any(word in message_lower for word in ['gpa', 'grade', 'average']):
1539
- return 'gpa'
1540
- elif any(word in message_lower for word in ['study', 'learn', 'exam', 'test']):
1541
- return 'study'
1542
- elif any(word in message_lower for word in ['course', 'class', 'subject']):
1543
- return 'courses'
1544
- elif any(word in message_lower for word in ['college', 'university', 'apply']):
1545
- return 'college'
1546
- elif any(word in message_lower for word in ['plan', 'schedule', 'calendar']):
1547
- return 'planning'
1548
- elif any(word in message_lower for word in ['resource', 'book', 'website']):
1549
- return 'resources'
1550
- else:
1551
- return 'general'
1552
-
1553
- async def _generate_typed_response(self, query_type: str, message: str, context: str, profile: Dict) -> str:
1554
- if query_type == 'gpa':
1555
- return self._generate_gpa_response(profile)
1556
- elif query_type == 'study':
1557
- return self._generate_study_response(profile)
1558
- elif query_type == 'courses':
1559
- return self._generate_courses_response(profile)
1560
- elif query_type == 'college':
1561
- return self._generate_college_response(profile)
1562
- elif query_type == 'planning':
1563
- return self._generate_planning_response(profile)
1564
- elif query_type == 'resources':
1565
- return self._generate_resources_response(profile)
1566
- else:
1567
- return await self._generate_general_response(message, context)
1568
-
1569
- def _generate_gpa_response(self, profile: Dict) -> str:
1570
- transcript = profile.get('transcript', {})
1571
- analysis = academic_analyzer.analyze_gpa(transcript)
1572
- response = [
1573
- f"## 📊 GPA Analysis",
1574
- f"**Rating:** {analysis['rating']}",
1575
- f"{analysis['description']}",
1576
- f"{analysis['comparison']}",
1577
- "",
1578
- f"## 🎓 Graduation Status"
1579
- ]
1580
-
1581
- grad_status = academic_analyzer.analyze_graduation_status(transcript)
1582
- response.append(grad_status['status'])
1583
- response.append(f"**Completion:** {grad_status['completion_percentage']:.1f}%")
1584
-
1585
- if grad_status.get('missing_requirements'):
1586
- response.append("\n**Missing Requirements:**")
1587
- for req in grad_status['missing_requirements'][:3]: # Show top 3 missing
1588
- if transcript.get('format') == 'progress_summary':
1589
- response.append(f"- {req['code']}: {req['description']} ({req['remaining']} credits remaining)")
1590
- else:
1591
- response.append(f"- {req['subject']}: {req['remaining']} credits remaining")
1592
-
1593
- response.append("\n## 🏫 College Recommendations")
1594
- college_recs = academic_analyzer.generate_college_recommendations(transcript)
1595
-
1596
- if college_recs['reach']:
1597
- response.append("\n**Reach Schools:**")
1598
- response.extend([f"- {school}" for school in college_recs['reach'][:3]])
1599
-
1600
- if college_recs['target']:
1601
- response.append("\n**Target Schools:**")
1602
- response.extend([f"- {school}" for school in college_recs['target'][:3]])
1603
-
1604
- if analysis.get('improvement_tips'):
1605
- response.append("\n**Improvement Tips:**")
1606
- response.extend([f"- {tip}" for tip in analysis['improvement_tips']])
1607
-
1608
- return "\n".join(response)
1609
-
1610
- def _generate_study_response(self, profile: Dict) -> str:
1611
- learning_style_match = re.search(r"Your primary learning style is\s*\*\*(.*?)\*\*",
1612
- profile.get('learning_style', ''))
1613
- if not learning_style_match:
1614
- return "Please complete the learning style quiz first to get personalized study advice."
1615
-
1616
- learning_style = learning_style_match.group(1)
1617
- study_plan = profile.get('study_plan', {})
1618
-
1619
- response = [
1620
- f"As a **{learning_style}** learner, here are some study strategies for you:"
1621
- ]
1622
-
1623
- if study_plan.get('study_strategies'):
1624
- response.extend([f"- {strategy}" for strategy in study_plan['study_strategies']])
1625
- else:
1626
- if learning_style.lower() == 'visual':
1627
- response.extend([
1628
- "- Use color coding in your notes",
1629
- "- Create mind maps and diagrams",
1630
- "- Watch educational videos to visualize concepts"
1631
- ])
1632
- elif learning_style.lower() == 'auditory':
1633
- response.extend([
1634
- "- Record lectures and listen to them",
1635
- "- Explain concepts out loud to yourself",
1636
- "- Participate in study groups"
1637
- ])
1638
- elif learning_style.lower() == 'reading/writing':
1639
- response.extend([
1640
- "- Write detailed summaries in your own words",
1641
- "- Create question-answer sets for each topic",
1642
- "- Rewrite your notes to reinforce learning"
1643
- ])
1644
- elif learning_style.lower() == 'kinesthetic':
1645
- response.extend([
1646
- "- Use hands-on activities when possible",
1647
- "- Study while walking or pacing",
1648
- "- Create physical models to represent concepts"
1649
- ])
1650
 
1651
- if study_plan.get('time_management_tips'):
1652
- response.append("\n**Time Management Tips:**")
1653
- response.extend([f"- {tip}" for tip in study_plan['time_management_tips']])
1654
 
1655
- return "\n".join(response)
1656
-
1657
- def _generate_courses_response(self, profile: Dict) -> str:
1658
- transcript = profile.get('transcript', {})
1659
- if not transcript.get('course_history'):
1660
- return "I couldn't find your course information. Please upload your transcript first."
1661
 
1662
- current_courses = [
1663
- course for course in transcript['course_history']
1664
- if (course.get('status', '').lower() == 'in progress' or
1665
- (isinstance(course.get('credit_earned'), float) and course['credit_earned'] == 0))
1666
- ]
1667
 
1668
- completed_courses = [
1669
- course for course in transcript['course_history']
1670
- if (course.get('status', '').lower() == 'completed' or
1671
- (isinstance(course.get('credit_earned'), float) and course['credit_earned'] > 0))
1672
- ]
1673
-
1674
- response = []
 
 
 
 
 
 
 
 
 
 
 
1675
 
1676
- if current_courses:
1677
- response.append("**Your Current Courses:**")
1678
- for course in current_courses[:5]:
1679
- course_name = course.get('description') or course.get('course_title', 'Unknown')
1680
- response.append(
1681
- f"- {course_name} "
1682
- f"({course.get('course_code', '')})"
 
 
 
 
 
 
 
1683
  )
1684
- else:
1685
- response.append("I couldn't find any current courses in your transcript.")
1686
-
1687
- if completed_courses:
1688
- response.append("\n**Recently Completed Courses:**")
1689
- for course in completed_courses[:5]:
1690
- course_name = course.get('description') or course.get('course_title', 'Unknown')
1691
- grade = course.get('grade_earned', '') or course.get('grade', '')
1692
- if grade:
1693
- response.append(
1694
- f"- {course_name} "
1695
- f"(Grade: {grade})"
1696
- )
1697
- else:
1698
- response.append(f"- {course_name}")
1699
-
1700
- rigor = academic_analyzer.analyze_course_rigor(transcript)
1701
- if rigor['rating']:
1702
- response.append(f"\n**Course Rigor Analysis:** {rigor['rating']}")
1703
- if rigor['recommendations']:
1704
- response.append("\n**Recommendations:**")
1705
- response.extend([f"- {rec}" for rec in rigor['recommendations']])
1706
-
1707
- return "\n".join(response)
1708
-
1709
- def _generate_college_response(self, profile: Dict) -> str:
1710
- recommendations = academic_analyzer.generate_college_recommendations(profile.get('transcript', {}))
1711
-
1712
- response = ["**College Recommendations Based on Your Profile:**"]
1713
-
1714
- if recommendations['reach']:
1715
- response.append("\n**Reach Schools (Competitive):**")
1716
- response.extend([f"- {school}" for school in recommendations['reach'][:3]])
1717
-
1718
- if recommendations['target']:
1719
- response.append("\n**Target Schools (Good Match):**")
1720
- response.extend([f"- {school}" for school in recommendations['target'][:3]])
1721
-
1722
- if recommendations['safety']:
1723
- response.append("\n**Safety Schools (Likely Admission):**")
1724
- response.extend([f"- {school}" for school in recommendations['safety'][:3]])
1725
-
1726
- if recommendations['scholarships']:
1727
- response.append("\n**Scholarship Opportunities:**")
1728
- response.extend([f"- {scholarship}" for scholarship in recommendations['scholarships'][:3]])
1729
-
1730
- if recommendations['improvement_areas']:
1731
- response.append("\n**Areas to Improve for College Admissions:**")
1732
- response.extend([f"- {area}" for area in recommendations['improvement_areas']])
1733
-
1734
- return "\n".join(response)
1735
-
1736
- def _generate_planning_response(self, profile: Dict) -> str:
1737
- study_plan = profile.get('study_plan', {})
1738
-
1739
- response = ["**Study Planning Advice:**"]
1740
-
1741
- if study_plan.get('weekly_schedule'):
1742
- response.append("\nHere's a suggested weekly study schedule:")
1743
- for day, activities in study_plan['weekly_schedule'].items():
1744
- if activities:
1745
- response.append(f"\n**{day}:**")
1746
- for activity in activities[:2]:
1747
- response.append(
1748
- f"- {activity.get('course', 'Course')}: "
1749
- f"{activity.get('duration', '45-60 minutes')}"
1750
- )
1751
- else:
1752
- response.append("\nA good study schedule should include:")
1753
- response.append("- 45-60 minute study blocks with short breaks")
1754
- response.append("- Focus on 1-2 subjects per day")
1755
- response.append("- Regular review sessions")
1756
-
1757
- if study_plan.get('time_management_tips'):
1758
- response.append("\n**Time Management Tips:**")
1759
- response.extend([f"- {tip}" for tip in study_plan['time_management_tips'][:3]])
1760
-
1761
- return "\n".join(response)
1762
-
1763
- def _generate_resources_response(self, profile: Dict) -> str:
1764
- study_plan = profile.get('study_plan', {})
1765
- transcript = profile.get('transcript', {})
1766
-
1767
- response = ["**Recommended Learning Resources:**"]
1768
 
1769
- if study_plan.get('resource_recommendations'):
1770
- response.extend([f"- {resource}" for resource in study_plan['resource_recommendations'][:3]])
1771
- else:
1772
- response.extend([
1773
- "- Khan Academy for math and science",
1774
- "- Quizlet for flashcards",
1775
- "- Wolfram Alpha for math help"
1776
- ])
 
1777
 
1778
- current_courses = [
1779
- course for course in transcript.get('course_history', [])
1780
- if (course.get('status', '').lower() == 'in progress' or
1781
- (isinstance(course.get('credit_earned'), float) and course['credit_earned'] == 0))
 
 
 
 
 
 
 
 
 
 
 
1782
  ]
1783
 
1784
- if current_courses:
1785
- response.append("\n**Course-Specific Resources:**")
1786
- for course in current_courses[:2]:
1787
- course_name = course.get('description') or course.get('course_title', 'your course')
1788
- if 'MATH' in course_name.upper():
1789
- response.append(f"- For {course_name}: Desmos Graphing Calculator, Art of Problem Solving")
1790
- elif 'SCIENCE' in course_name.upper():
1791
- response.append(f"- For {course_name}: PhET Simulations, Crash Course Science videos")
1792
- elif 'HISTORY' in course_name.upper():
1793
- response.append(f"- For {course_name}: Crash Course History videos, Library of Congress resources")
1794
 
1795
- return "\n".join(response)
1796
-
1797
- async def _generate_general_response(self, message: str, context: str) -> str:
1798
- if not self.model or not self.tokenizer:
1799
- return "I'm still loading my knowledge base. Please try again in a moment."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1800
 
1801
- try:
1802
- prompt = f"{context}\nStudent: {message}\nAssistant:"
1803
-
1804
- inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
1805
-
1806
- outputs = self.model.generate(
1807
- **inputs,
1808
- max_new_tokens=200,
1809
- temperature=0.7,
1810
- top_p=0.9,
1811
- repetition_penalty=1.1,
1812
- do_sample=True
1813
- )
1814
-
1815
- response = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
1816
-
1817
- response = response[len(prompt):].strip()
1818
-
1819
- if response and response[-1] not in {'.', '!', '?'}:
1820
- last_period = response.rfind('.')
1821
- if last_period > 0:
1822
- response = response[:last_period + 1]
1823
-
1824
- return response if response else "I'm not sure how to respond to that. Could you rephrase your question?"
1825
- except Exception as e:
1826
- logger.error(f"Model generation error: {str(e)}")
1827
- return "I encountered an error generating a response. Please try again."
1828
-
1829
- def _update_context(self, message: str, history: List[List[Union[str, None]]]) -> None:
1830
- self.context_history.append({"role": "user", "content": message})
1831
 
1832
- if history:
1833
- for h in history[-self.max_context_length:]:
1834
- if h[0]:
1835
- self.context_history.append({"role": "user", "content": h[0]})
1836
- if h[1]:
1837
- self.context_history.append({"role": "assistant", "content": h[1]})
 
 
 
 
 
 
 
1838
 
1839
- self.context_history = self.context_history[-(self.max_context_length * 2):]
1840
 
1841
- # Initialize teaching assistant
1842
- teaching_assistant = EnhancedTeachingAssistant()
1843
 
1844
  class StudyCalendar:
1845
  def __init__(self):
@@ -2574,20 +2389,32 @@ def create_enhanced_interface():
2574
  ]
2575
  )
2576
 
2577
- with gr.Tab("AI Assistant", id=4):
2578
- gr.Markdown("## 💬 Your Personalized Learning Assistant")
2579
- gr.Markdown("Ask me anything about studying, your courses, grades, or learning strategies.")
2580
 
2581
  chatbot = gr.Chatbot(height=500)
2582
- msg = gr.Textbox(label="Your Message")
2583
- clear = gr.Button("Clear")
2584
 
2585
- def respond(message, chat_history):
2586
- bot_message = teaching_assistant.generate_response(message, chat_history, session_token.value)
2587
- chat_history.append((message, bot_message))
 
 
 
 
 
 
 
 
2588
  return "", chat_history
2589
 
2590
- msg.submit(respond, [msg, chatbot], [msg, chatbot])
 
 
 
 
2591
  clear.click(lambda: None, None, chatbot, queue=False)
2592
 
2593
  with gr.Tab("Goals & Planning", id=5):
 
16
  import string
17
  from huggingface_hub import HfApi, HfFolder
18
  import torch
19
+ from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
20
  import time
21
  import logging
22
  import asyncio
 
35
  import numpy as np
36
  import matplotlib.pyplot as plt
37
  from tqdm import tqdm
38
+ import random
39
 
40
  # Enhanced Configuration
41
  PROFILES_DIR = "student_profiles"
 
62
  logger = logging.getLogger(__name__)
63
 
64
  # Model configuration
65
+ MODEL_NAME = "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5"
66
 
67
  @lru_cache(maxsize=1)
68
  def get_model_and_tokenizer():
 
1473
  # Initialize profile manager
1474
  profile_manager = EnhancedProfileManager()
1475
 
1476
+ class EducationalChatbot:
1477
  def __init__(self):
1478
+ self.model_name = "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5"
1479
+ self.tokenizer = None
1480
+ self.model = None
1481
+ self.educational_topics = {
1482
+ 'math': ['algebra', 'calculus', 'geometry', 'trigonometry'],
1483
+ 'science': ['biology', 'chemistry', 'physics', 'astronomy'],
1484
+ 'humanities': ['history', 'literature', 'philosophy'],
1485
+ 'languages': ['english', 'spanish', 'french', 'grammar'],
1486
+ 'arts': ['music', 'art', 'drama'],
1487
+ 'technology': ['programming', 'computer science']
1488
+ }
1489
+ self.load_model()
1490
+
1491
+ def load_model(self):
1492
+ """Load the HuggingFace model"""
1493
+ self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
1494
+ self.model = AutoModelForCausalLM.from_pretrained(
1495
+ self.model_name,
1496
+ torch_dtype=torch.float16,
1497
+ device_map="auto"
1498
+ )
1499
+ logger.info("Educational chatbot model loaded")
1500
+
1501
+ def is_educational(self, question: str) -> bool:
1502
+ """Check if question is educational"""
1503
+ question_lower = question.lower()
1504
+ for category, topics in self.educational_topics.items():
1505
+ if any(topic in question_lower for topic in topics):
1506
+ return True
1507
+ return False
1508
+
1509
+ def generate_response(self, question: str, profile: Dict) -> Tuple[str, List[Dict]]:
1510
+ """Generate a personalized educational response"""
1511
+ if not self.is_educational(question):
1512
+ return (
1513
+ "I specialize in educational topics only. Please ask about subjects like math, "
1514
+ "science, history, or literature. I can help with concepts, problem-solving methods, "
1515
+ "and learning strategies.",
1516
+ []
1517
+ )
1518
+
1519
+ # Get learning style from profile
1520
+ learning_style = self._get_learning_style(profile)
1521
+
1522
+ # Generate base response using the model
1523
+ prompt = self._build_prompt(question, profile)
1524
+ inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
1525
+
1526
+ outputs = self.model.generate(
1527
+ **inputs,
1528
+ max_new_tokens=300,
1529
+ temperature=0.7,
1530
+ top_p=0.9,
1531
+ repetition_penalty=1.2,
1532
+ do_sample=True
1533
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1534
 
1535
+ raw_response = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
 
 
1536
 
1537
+ # Process the response to be more pedagogical
1538
+ processed_response = self._make_response_pedagogical(raw_response)
 
 
 
 
1539
 
1540
+ # Add multimedia based on learning style
1541
+ multimedia = self._get_multimedia_suggestions(processed_response, learning_style)
 
 
 
1542
 
1543
+ return processed_response, multimedia
1544
+
1545
+ def _get_learning_style(self, profile: Dict) -> str:
1546
+ """Extract learning style from profile"""
1547
+ if not profile or 'learning_style' not in profile:
1548
+ return 'balanced'
1549
+
1550
+ style_match = re.search(r"Your primary learning style is\s*\*\*(.*?)\*\*",
1551
+ profile['learning_style'])
1552
+ return style_match.group(1).lower() if style_match else 'balanced'
1553
+
1554
+ def _build_prompt(self, question: str, profile: Dict) -> str:
1555
+ """Build a personalized prompt for the model"""
1556
+ base_prompt = (
1557
+ "You are an expert teaching assistant helping a student. Your role is to guide them "
1558
+ "to discover answers themselves, not provide direct solutions. Use the Socratic method "
1559
+ "by asking guiding questions and explaining concepts step-by-step.\n\n"
1560
+ )
1561
 
1562
+ if profile:
1563
+ # Add academic context if available
1564
+ if 'transcript' in profile:
1565
+ courses = [c['course_title'] for c in profile['transcript'].get('course_history', [])]
1566
+ base_prompt += (
1567
+ f"The student has taken these courses: {', '.join(courses[:5])}. "
1568
+ "Consider their academic background when responding.\n\n"
1569
+ )
1570
+
1571
+ # Add learning style
1572
+ learning_style = self._get_learning_style(profile)
1573
+ if learning_style != 'balanced':
1574
+ base_prompt += (
1575
+ f"The student is a {learning_style} learner. Adapt your teaching approach accordingly.\n\n"
1576
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1577
 
1578
+ base_prompt += (
1579
+ f"Student Question: {question}\n\n"
1580
+ "Teaching Assistant Response:\n"
1581
+ "1. First, let's understand the key concepts involved...\n"
1582
+ "2. What do you think would be the first step in solving this?\n"
1583
+ "3. Consider this approach...\n"
1584
+ "4. Here's how we might break this down...\n"
1585
+ "Remember, the goal is understanding, not just the answer."
1586
+ )
1587
 
1588
+ return base_prompt
1589
+
1590
+ def _make_response_pedagogical(self, response: str) -> str:
1591
+ """Process the raw response to be more teaching-oriented"""
1592
+ # Remove direct answers if present
1593
+ response = re.sub(r"(the answer is|it is|direct solution:) .*?(\n|$)", "", response, flags=re.I)
1594
+
1595
+ # Add more guiding language
1596
+ guiding_phrases = [
1597
+ "What do you think about...",
1598
+ "Have you considered...",
1599
+ "Let's break this down...",
1600
+ "One approach might be...",
1601
+ "Think about how you would...",
1602
+ "What steps would you take to..."
1603
  ]
1604
 
1605
+ # Ensure response has at least 2 guiding questions
1606
+ if sum(1 for phrase in guiding_phrases if phrase.lower() in response.lower()) < 2:
1607
+ response += "\n\n" + "\n".join(guiding_phrases[:2])
 
 
 
 
 
 
 
1608
 
1609
+ return response
1610
+
1611
+ def _get_multimedia_suggestions(self, response: str, learning_style: str) -> List[Dict]:
1612
+ """Generate multimedia suggestions based on learning style and content"""
1613
+ suggestions = []
1614
+
1615
+ # Common educational platforms
1616
+ resources = {
1617
+ 'visual': [
1618
+ {"type": "video", "source": "Khan Academy", "url": "https://www.khanacademy.org"},
1619
+ {"type": "diagram", "source": "Math is Fun", "url": "https://www.mathsisfun.com"},
1620
+ {"type": "infographic", "source": "InfoGram", "url": "https://infogram.com"}
1621
+ ],
1622
+ 'auditory': [
1623
+ {"type": "podcast", "source": "Stuff You Should Know", "url": "https://www.iheart.com/podcast/stuff-you-should-know-26940277"},
1624
+ {"type": "audio_lecture", "source": "The Great Courses", "url": "https://www.thegreatcourses.com"}
1625
+ ],
1626
+ 'reading/writing': [
1627
+ {"type": "article", "source": "Britannica", "url": "https://www.britannica.com"},
1628
+ {"type": "textbook", "source": "OpenStax", "url": "https://openstax.org"}
1629
+ ],
1630
+ 'kinesthetic': [
1631
+ {"type": "interactive", "source": "PhET Simulations", "url": "https://phet.colorado.edu"},
1632
+ {"type": "hands-on", "source": "Science Buddies", "url": "https://www.sciencebuddies.org"}
1633
+ ]
1634
+ }
1635
 
1636
+ # Add general suggestions based on learning style
1637
+ if learning_style in resources:
1638
+ suggestions.extend(resources[learning_style][:2])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1639
 
1640
+ # Add specific content based on response
1641
+ if "math" in response.lower():
1642
+ suggestions.append({
1643
+ "type": "practice_problems",
1644
+ "source": "Art of Problem Solving",
1645
+ "url": "https://artofproblemsolving.com"
1646
+ })
1647
+ elif "science" in response.lower():
1648
+ suggestions.append({
1649
+ "type": "experiment",
1650
+ "source": "Science Journal",
1651
+ "url": "https://sciencejournal.withgoogle.com"
1652
+ })
1653
 
1654
+ return suggestions
1655
 
1656
+ # Initialize the chatbot
1657
+ educational_chatbot = EducationalChatbot()
1658
 
1659
  class StudyCalendar:
1660
  def __init__(self):
 
2389
  ]
2390
  )
2391
 
2392
+ with gr.Tab("AI Teaching Assistant", id=4):
2393
+ gr.Markdown("## 💬 Your Personalized Teaching Assistant")
2394
+ gr.Markdown("Ask educational questions about any subject. I'll guide you to discover the answers yourself.")
2395
 
2396
  chatbot = gr.Chatbot(height=500)
2397
+ msg = gr.Textbox(label="Your Educational Question")
2398
+ clear = gr.Button("Clear Chat")
2399
 
2400
+ def respond(message: str, chat_history: List, profile: Dict) -> Tuple[str, List]:
2401
+ """Handle chat responses with multimedia"""
2402
+ response, multimedia = educational_chatbot.generate_response(message, profile)
2403
+
2404
+ # Format multimedia suggestions
2405
+ if multimedia:
2406
+ response += "\n\n**Suggested Resources:**\n"
2407
+ for item in multimedia:
2408
+ response += f"- [{item['type'].title()}] {item['source']}: {item['url']}\n"
2409
+
2410
+ chat_history.append((message, response))
2411
  return "", chat_history
2412
 
2413
+ msg.submit(
2414
+ respond,
2415
+ inputs=[msg, chatbot, gr.State(profile_manager.load_profile(session_token.value))],
2416
+ outputs=[msg, chatbot]
2417
+ )
2418
  clear.click(lambda: None, None, chatbot, queue=False)
2419
 
2420
  with gr.Tab("Goals & Planning", id=5):