Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -75,6 +75,77 @@ if HF_TOKEN:
|
|
| 75 |
logger.error(f"Attempt {attempt + 1} failed to initialize Hugging Face API: {str(e)}")
|
| 76 |
time.sleep(2 ** attempt)
|
| 77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
# ========== LEARNING STYLE QUIZ ==========
|
| 79 |
class LearningStyleQuiz:
|
| 80 |
def __init__(self):
|
|
@@ -1582,77 +1653,6 @@ class EnhancedTeachingAssistant:
|
|
| 1582 |
# Initialize teaching assistant
|
| 1583 |
teaching_assistant = EnhancedTeachingAssistant()
|
| 1584 |
|
| 1585 |
-
# ========== UTILITY FUNCTIONS ==========
|
| 1586 |
-
class DataEncryptor:
|
| 1587 |
-
def __init__(self, key: str):
|
| 1588 |
-
self.cipher = Fernet(key.encode())
|
| 1589 |
-
|
| 1590 |
-
def encrypt(self, data: str) -> str:
|
| 1591 |
-
return self.cipher.encrypt(data.encode()).decode()
|
| 1592 |
-
|
| 1593 |
-
def decrypt(self, encrypted_data: str) -> str:
|
| 1594 |
-
return self.cipher.decrypt(encrypted_data.encode()).decode()
|
| 1595 |
-
|
| 1596 |
-
encryptor = DataEncryptor(ENCRYPTION_KEY)
|
| 1597 |
-
|
| 1598 |
-
def generate_session_token() -> str:
|
| 1599 |
-
alphabet = string.ascii_letters + string.digits
|
| 1600 |
-
return ''.join(secrets.choice(alphabet) for _ in range(SESSION_TOKEN_LENGTH))
|
| 1601 |
-
|
| 1602 |
-
def sanitize_input(text: str) -> str:
|
| 1603 |
-
if not text:
|
| 1604 |
-
return ""
|
| 1605 |
-
text = html.escape(text.strip())
|
| 1606 |
-
text = re.sub(r'<[^>]*>', '', text)
|
| 1607 |
-
text = re.sub(r'[^\w\s\-.,!?@#\$%^&*()+=]', '', text)
|
| 1608 |
-
return text
|
| 1609 |
-
|
| 1610 |
-
def validate_name(name: str) -> str:
|
| 1611 |
-
name = name.strip()
|
| 1612 |
-
if not name:
|
| 1613 |
-
raise ValueError("Name cannot be empty.")
|
| 1614 |
-
if len(name) > 100:
|
| 1615 |
-
raise ValueError("Name is too long (maximum 100 characters).")
|
| 1616 |
-
if any(c.isdigit() for c in name):
|
| 1617 |
-
raise ValueError("Name cannot contain numbers.")
|
| 1618 |
-
return name
|
| 1619 |
-
|
| 1620 |
-
def validate_age(age: Union[int, float, str]) -> int:
|
| 1621 |
-
try:
|
| 1622 |
-
age_int = int(age)
|
| 1623 |
-
if not MIN_AGE <= age_int <= MAX_AGE:
|
| 1624 |
-
raise ValueError(f"Age must be between {MIN_AGE} and {MAX_AGE}.")
|
| 1625 |
-
return age_int
|
| 1626 |
-
except (ValueError, TypeError):
|
| 1627 |
-
raise ValueError("Please enter a valid age number.")
|
| 1628 |
-
|
| 1629 |
-
def validate_file(file_obj) -> None:
|
| 1630 |
-
if not file_obj:
|
| 1631 |
-
raise ValueError("Please upload a file first")
|
| 1632 |
-
|
| 1633 |
-
file_ext = os.path.splitext(file_obj.name)[1].lower()
|
| 1634 |
-
if file_ext not in ALLOWED_FILE_TYPES:
|
| 1635 |
-
raise ValueError(f"Invalid file type. Allowed types: {', '.join(ALLOWED_FILE_TYPES)}")
|
| 1636 |
-
|
| 1637 |
-
file_size = os.path.getsize(file_obj.name) / (1024 * 1024)
|
| 1638 |
-
if file_size > MAX_FILE_SIZE_MB:
|
| 1639 |
-
raise ValueError(f"File too large. Maximum size is {MAX_FILE_SIZE_MB}MB.")
|
| 1640 |
-
|
| 1641 |
-
def remove_sensitive_info(text: str) -> str:
|
| 1642 |
-
patterns = [
|
| 1643 |
-
(r'\b\d{3}-\d{2}-\d{4}\b', '[REDACTED-SSN]'),
|
| 1644 |
-
(r'\b\d{6,9}\b', '[ID]'),
|
| 1645 |
-
(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', '[EMAIL]'),
|
| 1646 |
-
(r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b', '[IP]'),
|
| 1647 |
-
(r'\b[A-Z][a-z]+ [A-Z][a-z]+\b', '[NAME]'),
|
| 1648 |
-
(r'\b\d{3}\) \d{3}-\d{4}\b', '[PHONE]'),
|
| 1649 |
-
(r'\b\d{1,5} [A-Z][a-z]+ [A-Z][a-z]+, [A-Z]{2} \d{5}\b', '[ADDRESS]')
|
| 1650 |
-
]
|
| 1651 |
-
|
| 1652 |
-
for pattern, replacement in patterns:
|
| 1653 |
-
text = re.sub(pattern, replacement, text)
|
| 1654 |
-
return text
|
| 1655 |
-
|
| 1656 |
# ========== GRADIO INTERFACE ==========
|
| 1657 |
def create_enhanced_interface():
|
| 1658 |
with gr.Blocks(theme=gr.themes.Soft(), title="Student Learning Assistant") as app:
|
|
|
|
| 75 |
logger.error(f"Attempt {attempt + 1} failed to initialize Hugging Face API: {str(e)}")
|
| 76 |
time.sleep(2 ** attempt)
|
| 77 |
|
| 78 |
+
# ========== UTILITY FUNCTIONS ==========
|
| 79 |
+
class DataEncryptor:
|
| 80 |
+
def __init__(self, key: str):
|
| 81 |
+
self.cipher = Fernet(key.encode())
|
| 82 |
+
|
| 83 |
+
def encrypt(self, data: str) -> str:
|
| 84 |
+
return self.cipher.encrypt(data.encode()).decode()
|
| 85 |
+
|
| 86 |
+
def decrypt(self, encrypted_data: str) -> str:
|
| 87 |
+
return self.cipher.decrypt(encrypted_data.encode()).decode()
|
| 88 |
+
|
| 89 |
+
encryptor = DataEncryptor(ENCRYPTION_KEY)
|
| 90 |
+
|
| 91 |
+
def generate_session_token() -> str:
|
| 92 |
+
alphabet = string.ascii_letters + string.digits
|
| 93 |
+
return ''.join(secrets.choice(alphabet) for _ in range(SESSION_TOKEN_LENGTH))
|
| 94 |
+
|
| 95 |
+
def sanitize_input(text: str) -> str:
|
| 96 |
+
if not text:
|
| 97 |
+
return ""
|
| 98 |
+
text = html.escape(text.strip())
|
| 99 |
+
text = re.sub(r'<[^>]*>', '', text)
|
| 100 |
+
text = re.sub(r'[^\w\s\-.,!?@#\$%^&*()+=]', '', text)
|
| 101 |
+
return text
|
| 102 |
+
|
| 103 |
+
def validate_name(name: str) -> str:
|
| 104 |
+
name = name.strip()
|
| 105 |
+
if not name:
|
| 106 |
+
raise ValueError("Name cannot be empty.")
|
| 107 |
+
if len(name) > 100:
|
| 108 |
+
raise ValueError("Name is too long (maximum 100 characters).")
|
| 109 |
+
if any(c.isdigit() for c in name):
|
| 110 |
+
raise ValueError("Name cannot contain numbers.")
|
| 111 |
+
return name
|
| 112 |
+
|
| 113 |
+
def validate_age(age: Union[int, float, str]) -> int:
|
| 114 |
+
try:
|
| 115 |
+
age_int = int(age)
|
| 116 |
+
if not MIN_AGE <= age_int <= MAX_AGE:
|
| 117 |
+
raise ValueError(f"Age must be between {MIN_AGE} and {MAX_AGE}.")
|
| 118 |
+
return age_int
|
| 119 |
+
except (ValueError, TypeError):
|
| 120 |
+
raise ValueError("Please enter a valid age number.")
|
| 121 |
+
|
| 122 |
+
def validate_file(file_obj) -> None:
|
| 123 |
+
if not file_obj:
|
| 124 |
+
raise ValueError("Please upload a file first")
|
| 125 |
+
|
| 126 |
+
file_ext = os.path.splitext(file_obj.name)[1].lower()
|
| 127 |
+
if file_ext not in ALLOWED_FILE_TYPES:
|
| 128 |
+
raise ValueError(f"Invalid file type. Allowed types: {', '.join(ALLOWED_FILE_TYPES)}")
|
| 129 |
+
|
| 130 |
+
file_size = os.path.getsize(file_obj.name) / (1024 * 1024)
|
| 131 |
+
if file_size > MAX_FILE_SIZE_MB:
|
| 132 |
+
raise ValueError(f"File too large. Maximum size is {MAX_FILE_SIZE_MB}MB.")
|
| 133 |
+
|
| 134 |
+
def remove_sensitive_info(text: str) -> str:
|
| 135 |
+
patterns = [
|
| 136 |
+
(r'\b\d{3}-\d{2}-\d{4}\b', '[REDACTED-SSN]'),
|
| 137 |
+
(r'\b\d{6,9}\b', '[ID]'),
|
| 138 |
+
(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', '[EMAIL]'),
|
| 139 |
+
(r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b', '[IP]'),
|
| 140 |
+
(r'\b[A-Z][a-z]+ [A-Z][a-z]+\b', '[NAME]'),
|
| 141 |
+
(r'\b\d{3}\) \d{3}-\d{4}\b', '[PHONE]'),
|
| 142 |
+
(r'\b\d{1,5} [A-Z][a-z]+ [A-Z][a-z]+, [A-Z]{2} \d{5}\b', '[ADDRESS]')
|
| 143 |
+
]
|
| 144 |
+
|
| 145 |
+
for pattern, replacement in patterns:
|
| 146 |
+
text = re.sub(pattern, replacement, text)
|
| 147 |
+
return text
|
| 148 |
+
|
| 149 |
# ========== LEARNING STYLE QUIZ ==========
|
| 150 |
class LearningStyleQuiz:
|
| 151 |
def __init__(self):
|
|
|
|
| 1653 |
# Initialize teaching assistant
|
| 1654 |
teaching_assistant = EnhancedTeachingAssistant()
|
| 1655 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1656 |
# ========== GRADIO INTERFACE ==========
|
| 1657 |
def create_enhanced_interface():
|
| 1658 |
with gr.Blocks(theme=gr.themes.Soft(), title="Student Learning Assistant") as app:
|