Update app.py
Browse files
app.py
CHANGED
|
@@ -46,15 +46,18 @@ def predict(message, history, subject_id, file_input):
|
|
| 46 |
system_instruction = f"You are an expert AI Tutor specializing in {subj}. Help the student understand concepts clearly."
|
| 47 |
|
| 48 |
formatted_contents = []
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
current_parts = [types.Part.from_text(message)]
|
| 54 |
|
| 55 |
if file_input is not None:
|
| 56 |
try:
|
| 57 |
-
with open(file_input
|
| 58 |
pdf_bytes = f.read()
|
| 59 |
current_parts.append(
|
| 60 |
types.Part.from_bytes(
|
|
@@ -88,25 +91,34 @@ def predict(message, history, subject_id, file_input):
|
|
| 88 |
|
| 89 |
# ── Dynamic Features Generators ──
|
| 90 |
def generate_quiz(subject_id):
|
| 91 |
-
subj = next((s["label"] for s in SUBJECTS if s["id"] == subject_id), "General Studies")
|
| 92 |
if not client: return "API key missing."
|
|
|
|
| 93 |
prompt = f"Generate a 3-question multiple choice quiz about {subj} with answers at the bottom. Format beautifully with markdown."
|
| 94 |
-
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
def generate_notes(history, subject_id):
|
| 98 |
-
subj = next((s["label"] for s in SUBJECTS if s["id"] == subject_id), "General Studies")
|
| 99 |
if not client: return "API key missing."
|
|
|
|
| 100 |
prompt = f"Based on this study history for {subj}: {str(history)}. Create highly structured, clean summary revision notes with key bullet points."
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
def generate_flashcards(history, subject_id):
|
| 105 |
-
subj = next((s["label"] for s in SUBJECTS if s["id"] == subject_id), "General Studies")
|
| 106 |
if not client: return "API key missing."
|
|
|
|
| 107 |
prompt = f"Based on this study history for {subj}: {str(history)}. Generate 4 interactive flashcards formatted as 'Question: [Text] | Answer: [Text]'."
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
# ── Gradio UI Construction ──
|
| 112 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate")) as demo:
|
|
@@ -141,7 +153,8 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate")
|
|
| 141 |
new_todo = gr.Textbox(placeholder="+ Add custom task & press Enter", show_label=False)
|
| 142 |
|
| 143 |
def add_todo(task, current_todos):
|
| 144 |
-
if task.strip():
|
|
|
|
| 145 |
return gr.update(choices=current_todos, value=current_todos), ""
|
| 146 |
new_todo.submit(add_todo, [new_todo, todo_list], [todo_list, new_todo])
|
| 147 |
|
|
@@ -170,7 +183,8 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate")
|
|
| 170 |
def update_subject_view(sub_id):
|
| 171 |
subj_obj = next((s for s in SUBJECTS if s["id"] == sub_id), SUBJECTS[0])
|
| 172 |
banner_text = f"### {subj_obj['emoji']} {subj_obj['label']} \n*{subj_obj['description']}*"
|
| 173 |
-
|
|
|
|
| 174 |
|
| 175 |
subject_dropdown.change(
|
| 176 |
update_subject_view,
|
|
@@ -178,18 +192,32 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate")
|
|
| 178 |
outputs=[subject_info_banner, suggestion_box, current_subject_id, chatbot]
|
| 179 |
)
|
| 180 |
|
| 181 |
-
|
|
|
|
| 182 |
|
| 183 |
def handle_audio(audio_path):
|
| 184 |
-
if audio_path:
|
|
|
|
| 185 |
return ""
|
| 186 |
audio_input.change(handle_audio, inputs=[audio_input], outputs=[msg_input])
|
| 187 |
|
| 188 |
def respond(message, chat_history, sub_id, pdf_file):
|
| 189 |
-
if not message.strip():
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
yield "", chat_history
|
| 194 |
|
| 195 |
submit_btn.click(respond, [msg_input, chatbot, current_subject_id, file_upload], [msg_input, chatbot])
|
|
|
|
| 46 |
system_instruction = f"You are an expert AI Tutor specializing in {subj}. Help the student understand concepts clearly."
|
| 47 |
|
| 48 |
formatted_contents = []
|
| 49 |
+
if history:
|
| 50 |
+
for turn in history:
|
| 51 |
+
if turn[0] is not None:
|
| 52 |
+
formatted_contents.append(types.Content(role="user", parts=[types.Part.from_text(str(turn[0]))]))
|
| 53 |
+
if turn[1] is not None:
|
| 54 |
+
formatted_contents.append(types.Content(role="model", parts=[types.Part.from_text(str(turn[1]))]))
|
| 55 |
|
| 56 |
current_parts = [types.Part.from_text(message)]
|
| 57 |
|
| 58 |
if file_input is not None:
|
| 59 |
try:
|
| 60 |
+
with open(file_input, "rb") as f:
|
| 61 |
pdf_bytes = f.read()
|
| 62 |
current_parts.append(
|
| 63 |
types.Part.from_bytes(
|
|
|
|
| 91 |
|
| 92 |
# ── Dynamic Features Generators ──
|
| 93 |
def generate_quiz(subject_id):
|
|
|
|
| 94 |
if not client: return "API key missing."
|
| 95 |
+
subj = next((s["label"] for s in SUBJECTS if s["id"] == subject_id), "General Studies")
|
| 96 |
prompt = f"Generate a 3-question multiple choice quiz about {subj} with answers at the bottom. Format beautifully with markdown."
|
| 97 |
+
try:
|
| 98 |
+
response = client.models.generate_content(model='gemini-2.5-flash', contents=prompt)
|
| 99 |
+
return response.text
|
| 100 |
+
except Exception as e:
|
| 101 |
+
return f"Error generating quiz: {str(e)}"
|
| 102 |
|
| 103 |
def generate_notes(history, subject_id):
|
|
|
|
| 104 |
if not client: return "API key missing."
|
| 105 |
+
subj = next((s["label"] for s in SUBJECTS if s["id"] == subject_id), "General Studies")
|
| 106 |
prompt = f"Based on this study history for {subj}: {str(history)}. Create highly structured, clean summary revision notes with key bullet points."
|
| 107 |
+
try:
|
| 108 |
+
response = client.models.generate_content(model='gemini-2.5-flash', contents=prompt)
|
| 109 |
+
return response.text
|
| 110 |
+
except Exception as e:
|
| 111 |
+
return f"Error generating notes: {str(e)}"
|
| 112 |
|
| 113 |
def generate_flashcards(history, subject_id):
|
|
|
|
| 114 |
if not client: return "API key missing."
|
| 115 |
+
subj = next((s["label"] for s in SUBJECTS if s["id"] == subject_id), "General Studies")
|
| 116 |
prompt = f"Based on this study history for {subj}: {str(history)}. Generate 4 interactive flashcards formatted as 'Question: [Text] | Answer: [Text]'."
|
| 117 |
+
try:
|
| 118 |
+
response = client.models.generate_content(model='gemini-2.5-flash', contents=prompt)
|
| 119 |
+
return response.text
|
| 120 |
+
except Exception as e:
|
| 121 |
+
return f"Error generating flashcards: {str(e)}"
|
| 122 |
|
| 123 |
# ── Gradio UI Construction ──
|
| 124 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate")) as demo:
|
|
|
|
| 153 |
new_todo = gr.Textbox(placeholder="+ Add custom task & press Enter", show_label=False)
|
| 154 |
|
| 155 |
def add_todo(task, current_todos):
|
| 156 |
+
if task and task.strip():
|
| 157 |
+
current_todos.append(task.strip())
|
| 158 |
return gr.update(choices=current_todos, value=current_todos), ""
|
| 159 |
new_todo.submit(add_todo, [new_todo, todo_list], [todo_list, new_todo])
|
| 160 |
|
|
|
|
| 183 |
def update_subject_view(sub_id):
|
| 184 |
subj_obj = next((s for s in SUBJECTS if s["id"] == sub_id), SUBJECTS[0])
|
| 185 |
banner_text = f"### {subj_obj['emoji']} {subj_obj['label']} \n*{subj_obj['description']}*"
|
| 186 |
+
new_radio_choices = SUGGESTIONS.get(sub_id, [])
|
| 187 |
+
return banner_text, gr.update(choices=new_radio_choices, value=None), sub_id, []
|
| 188 |
|
| 189 |
subject_dropdown.change(
|
| 190 |
update_subject_view,
|
|
|
|
| 192 |
outputs=[subject_info_banner, suggestion_box, current_subject_id, chatbot]
|
| 193 |
)
|
| 194 |
|
| 195 |
+
# Direct text box binding
|
| 196 |
+
suggestion_box.select(lambda x: x.value, inputs=[suggestion_box], outputs=[msg_input])
|
| 197 |
|
| 198 |
def handle_audio(audio_path):
|
| 199 |
+
if audio_path:
|
| 200 |
+
return "[Voice Note Uploaded: Analyzing audio content]"
|
| 201 |
return ""
|
| 202 |
audio_input.change(handle_audio, inputs=[audio_input], outputs=[msg_input])
|
| 203 |
|
| 204 |
def respond(message, chat_history, sub_id, pdf_file):
|
| 205 |
+
if not message or not message.strip():
|
| 206 |
+
return "", chat_history
|
| 207 |
+
|
| 208 |
+
# Gradio 6 style history list append
|
| 209 |
+
chat_history = chat_history or []
|
| 210 |
+
chat_history.append({"role": "user", "metadata": {"title": ""}, "content": message})
|
| 211 |
+
chat_history.append({"role": "assistant", "metadata": {"title": ""}, "content": ""})
|
| 212 |
+
|
| 213 |
+
# Convert gradio history items for raw loop standard if needed
|
| 214 |
+
raw_history = []
|
| 215 |
+
for i in range(0, len(chat_history)-2, 2):
|
| 216 |
+
if i+1 < len(chat_history):
|
| 217 |
+
raw_history.append((chat_history[i]["content"], chat_history[i+1]["content"]))
|
| 218 |
+
|
| 219 |
+
for chunk in predict(message, raw_history, sub_id, pdf_file):
|
| 220 |
+
chat_history[-1]["content"] = chunk
|
| 221 |
yield "", chat_history
|
| 222 |
|
| 223 |
submit_btn.click(respond, [msg_input, chatbot, current_subject_id, file_upload], [msg_input, chatbot])
|