ngwakomadikwe commited on
Commit
3c1c8e8
·
verified ·
1 Parent(s): fea03bf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +12 -141
app.py CHANGED
@@ -1,6 +1,14 @@
1
  """
2
- SmartMate - AI Student Assistant (Gradio Version)
3
  For Hugging Face Spaces
 
 
 
 
 
 
 
 
4
  """
5
 
6
  import os
@@ -72,7 +80,7 @@ class SchoolService:
72
 
73
  class AdminService:
74
  def __init__(self):
75
- self.admins = {"teacher@smartmate.edu": "password123"}
76
 
77
  def authenticate(self, username: str, password: str) -> bool:
78
  return self.admins.get(username) == password
@@ -99,7 +107,7 @@ else:
99
  def ai_chat(message: str, history: List) -> str:
100
  if USE_OPENAI:
101
  try:
102
- system_prompt = f"""You are SmartMate, an AI assistant for students.
103
  Use this context to answer accurately:
104
  {school_service.get_school_context_for_ai()}
105
 
@@ -110,141 +118,4 @@ Be helpful, encouraging, and accurate. If unsure, say so."""
110
  {"role": "system", "content": system_prompt},
111
  {"role": "user", "content": message}
112
  ],
113
- temperature=0.7,
114
- max_tokens=500
115
- )
116
- reply = response.choices[0].message.content.strip()
117
-
118
- # Add related announcements
119
- keywords = ["exam", "test", "due", "assignment"]
120
- if any(kw in message.lower() for kw in keywords):
121
- matches = school_service.get_announcements()
122
- relevant = [a for a in matches if any(kw in a["title"].lower() or kw in a["content"].lower() for kw in keywords)]
123
- if relevant:
124
- reply += "\n\n📌 **Relevant Announcements:**"
125
- for ann in relevant[:2]:
126
- reply += f"\n- {ann['title']} ({ann['course']}) → {ann['content'][:70]}..."
127
-
128
- return reply
129
- except Exception as e:
130
- return f"⚠️ AI Error: {str(e)}"
131
- else:
132
- return f"👋 Hi! I'm SmartMate. You asked: '{message}'. *(Set OPENAI_API_KEY in HF Secrets for real AI.)*"
133
-
134
-
135
- # ==================== GRADIO INTERFACE ====================
136
-
137
- def render_announcements(course: str) -> str:
138
- announcements = school_service.get_announcements(course)
139
- if not announcements:
140
- return "<p style='color: #6c757d; text-align: center;'>No announcements.</p>"
141
- html = ""
142
- for ann in announcements:
143
- color = "red" if ann["priority"] == "high" else "orange" if ann["priority"] == "normal" else "gray"
144
- html += f"""
145
- <div style="
146
- border: 1px solid #e0e0e0;
147
- border-radius: 8px;
148
- padding: 12px;
149
- margin: 8px 0;
150
- background: white;
151
- ">
152
- <div style="display: flex; justify-content: space-between;">
153
- <strong>{ann['title']}</strong>
154
- <span style="background: {color}; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.7em;">{ann['priority'].upper()}</span>
155
- </div>
156
- <div style="margin-top: 4px; color: #555;">{ann['content']}</div>
157
- <div style="font-size: 0.8em; color: #999;">{ann['course']} • {ann['date']}</div>
158
- </div>
159
- """
160
- return html
161
-
162
-
163
- # State for admin login
164
- IS_ADMIN = False
165
-
166
- def admin_login(username: str, password: str) -> tuple:
167
- global IS_ADMIN
168
- if admin_service.authenticate(username, password):
169
- IS_ADMIN = True
170
- return (
171
- gr.update(visible=False),
172
- gr.update(visible=True),
173
- "✅ Login successful!",
174
- gr.update(visible=True)
175
- )
176
- return (
177
- gr.update(visible=True),
178
- gr.update(visible=False),
179
- "❌ Invalid credentials",
180
- gr.update(visible=False)
181
- )
182
-
183
- def admin_logout():
184
- global IS_ADMIN
185
- IS_ADMIN = False
186
- return (
187
- gr.update(visible=True),
188
- gr.update(visible=False),
189
- "",
190
- gr.update(visible=False)
191
- )
192
-
193
- def post_announcement(title: str, content: str, course: str, priority: str) -> str:
194
- if not IS_ADMIN:
195
- return "🔒 Only admins can post."
196
- if not title or not content:
197
- return "⚠️ Title and content required."
198
- school_service.add_announcement(title, content, course, priority)
199
- return "✅ Posted!"
200
-
201
- # ==================== BUILD UI ====================
202
-
203
- with gr.Blocks(css="""
204
- .gradio-container {
205
- font-family: 'Inter', sans-serif;
206
- }
207
- """) as demo:
208
- gr.Markdown("# 🎓 SmartMate - AI Student Assistant")
209
-
210
- with gr.Tab("📢 Announcements"):
211
- course_filter = gr.Dropdown(choices=school_service.courses, value="All", label="Filter by Course")
212
- announcements_html = gr.HTML()
213
- course_filter.change(fn=render_announcements, inputs=course_filter, outputs=announcements_html)
214
- demo.load(fn=render_announcements, inputs=course_filter, outputs=announcements_html)
215
-
216
- with gr.Tab("💬 Chat"):
217
- chatbot = gr.Chatbot(height=400)
218
- msg = gr.Textbox(label="Ask me anything...")
219
- clear = gr.Button("Clear")
220
- msg.submit(fn=ai_chat, inputs=[msg, chatbot], outputs=[msg, chatbot])
221
- clear.click(lambda: None, None, chatbot)
222
-
223
- with gr.Tab("📂 Upload Files"):
224
- file_input = gr.File(label="Upload PDF/Notes")
225
- upload_btn = gr.Button("Upload")
226
- status = gr.Textbox(label="Status")
227
- upload_btn.click(fn=school_service.upload_file, inputs=file_input, outputs=status)
228
-
229
- with gr.Tab("🔐 Admin"):
230
- with gr.Group() as login_group:
231
- username = gr.Textbox(label="Username")
232
- password = gr.Textbox(label="Password", type="password")
233
- login_btn = gr.Button("Login")
234
- login_status = gr.Textbox(label="Status")
235
- with gr.Group(visible=False) as dashboard:
236
- title = gr.Textbox(label="Title")
237
- content = gr.Textbox(label="Content", lines=3)
238
- course = gr.Dropdown(choices=school_service.courses[1:], label="Course")
239
- priority = gr.Radio(["low", "normal", "high"], label="Priority")
240
- post_btn = gr.Button("Post")
241
- post_result = gr.Textbox(label="Result")
242
- logout_btn = gr.Button("Logout")
243
-
244
- login_btn.click(fn=admin_login, inputs=[username, password], outputs=[login_group, dashboard, login_status, post_btn])
245
- logout_btn.click(fn=admin_logout, inputs=None, outputs=[login_group, dashboard, login_status, post_result])
246
- post_btn.click(fn=post_announcement, inputs=[title, content, course, priority], outputs=post_result)
247
-
248
-
249
- if __name__ == "__main__":
250
- demo.launch()
 
1
  """
2
+ ThutoAI - AI Student Assistant (Gradio Version)
3
  For Hugging Face Spaces
4
+ Meaning: "Thuto" = Learning/Education (Setswana)
5
+
6
+ Features:
7
+ - Course-filtered announcements
8
+ - AI chatbot with school context
9
+ - File uploads
10
+ - Admin panel for teachers
11
+ - Mobile-friendly UI
12
  """
13
 
14
  import os
 
80
 
81
  class AdminService:
82
  def __init__(self):
83
+ self.admins = {"teacher@thutoai.edu": "password123"}
84
 
85
  def authenticate(self, username: str, password: str) -> bool:
86
  return self.admins.get(username) == password
 
107
  def ai_chat(message: str, history: List) -> str:
108
  if USE_OPENAI:
109
  try:
110
+ system_prompt = f"""You are ThutoAI, an AI assistant for students.
111
  Use this context to answer accurately:
112
  {school_service.get_school_context_for_ai()}
113
 
 
118
  {"role": "system", "content": system_prompt},
119
  {"role": "user", "content": message}
120
  ],
121
+