krish-ai-dev commited on
Commit
a73dfcc
·
verified ·
1 Parent(s): b6b8b15

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -0
app.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import json
4
+ import base64
5
+ from datetime import datetime
6
+ import gradio as gr
7
+ from google import genai
8
+ from google.genai import types
9
+
10
+ # ── Gemini Client Setup ──
11
+ api_key = os.environ.get("GEMINI_API_KEY", "")
12
+ client = genai.Client(api_key=api_key) if api_key else None
13
+
14
+ # ── Mock Data & Configuration ──
15
+ SUBJECTS = [
16
+ {"id": "math", "label": "Mathematics", "emoji": "📐", "description": "Algebra, Calculus, Geometry & more"},
17
+ {"id": "science", "label": "Science", "emoji": "🔬", "description": "Physics, Chemistry, Biology & more"},
18
+ {"id": "history", "label": "History", "emoji": "🏛️", "description": "World events, civilizations & culture"},
19
+ {"id": "literature", "label": "Literature", "emoji": "📖", "description": "Essays, poetry, novels & analysis"},
20
+ {"id": "geography", "label": "Geography", "emoji": "🌍", "description": "Maps, climate, human geography"},
21
+ {"id": "cs", "label": "Computer Science", "emoji": "💻", "description": "Algorithms, data structures & coding"},
22
+ ]
23
+
24
+ SUGGESTIONS = {
25
+ "math": ["Explain the quadratic formula", "What is a derivative?", "How do matrices work?"],
26
+ "science": ["Explain Newton's third law", "What is DNA replication?", "How does nuclear fusion work?"],
27
+ "history": ["What caused WWI?", "Explain the French Revolution", "Who was Genghis Khan?"],
28
+ "literature": ["Analyse Hamlet's soliloquy", "What is a metaphor?", "Explain stream of consciousness"],
29
+ "geography": ["What causes earthquakes?", "Explain plate tectonics", "What is the water cycle?"],
30
+ "cs": ["Explain Big O notation", "What is recursion?", "How does a hash table work?"],
31
+ }
32
+
33
+ def get_greeting():
34
+ h = datetime.now().hour
35
+ if h < 12: return "Good morning 👋"
36
+ elif h < 17: return "Good afternoon 👋"
37
+ else: return "Good evening 👋"
38
+
39
+ # ── Gemini Stream & Logic Functions ──
40
+ def predict(message, history, subject_id, file_input):
41
+ if not client:
42
+ yield "⚠️ Please configure GEMINI_API_KEY in your Hugging Face Space secrets."
43
+ return
44
+
45
+ subj = next((s["label"] for s in SUBJECTS if s["id"] == subject_id), "General Studies")
46
+ system_instruction = f"You are an expert AI Tutor specializing in {subj}. Help the student understand concepts clearly."
47
+
48
+ formatted_contents = []
49
+ for turn in history:
50
+ formatted_contents.append(types.Content(role="user", parts=[types.Part.from_text(turn[0])]))
51
+ formatted_contents.append(types.Content(role="model", parts=[types.Part.from_text(turn[1])]))
52
+
53
+ current_parts = [types.Part.from_text(message)]
54
+
55
+ if file_input is not None:
56
+ try:
57
+ with open(file_input.name, "rb") as f:
58
+ pdf_bytes = f.read()
59
+ current_parts.append(
60
+ types.Part.from_bytes(
61
+ data=pdf_bytes,
62
+ mime_type="application/pdf"
63
+ )
64
+ )
65
+ except Exception as e:
66
+ yield f"Error reading PDF file: {str(e)}"
67
+ return
68
+
69
+ formatted_contents.append(types.Content(role="user", parts=current_parts))
70
+
71
+ try:
72
+ response_stream = client.models.generate_content_stream(
73
+ model='gemini-2.5-flash',
74
+ contents=formatted_contents,
75
+ config=types.GenerateContentConfig(
76
+ system_instruction=system_instruction,
77
+ temperature=0.7,
78
+ )
79
+ )
80
+
81
+ partial_message = ""
82
+ for chunk in response_stream:
83
+ if chunk.text:
84
+ partial_message += chunk.text
85
+ yield partial_message
86
+ except Exception as e:
87
+ yield f"An error occurred: {str(e)}"
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
+ response = client.models.generate_content(model='gemini-2.5-flash', contents=prompt)
95
+ return response.text
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
+ response = client.models.generate_content(model='gemini-2.5-flash', contents=prompt)
102
+ return response.text
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
+ response = client.models.generate_content(model='gemini-2.5-flash', contents=prompt)
109
+ return response.text
110
+
111
+ # ── Gradio UI Construction ──
112
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="slate")) as demo:
113
+ current_subject_id = gr.State(value="math")
114
+
115
+ with gr.Row():
116
+ # SIDEBAR
117
+ with gr.Column(scale=1, min_width=280):
118
+ gr.Markdown("## ⚡ StudyAI Dashboard")
119
+ greeting_md = gr.Markdown(f"*{get_greeting()}*")
120
+
121
+ subject_dropdown = gr.Dropdown(
122
+ choices=[(s["label"] + " " + s["emoji"], s["id"]) for s in SUBJECTS],
123
+ value="math",
124
+ label="📚 Select Active Subject",
125
+ interactive=True
126
+ )
127
+
128
+ gr.Markdown("---")
129
+ gr.Markdown("⏱️ **Focus Pomodoro Timer**")
130
+ gr.HTML("<div style='font-size:24px; font-weight:bold; text-align:center;'>25:00</div>")
131
+ with gr.Row():
132
+ gr.Button("▶️ Start", size="sm")
133
+ gr.Button("⏹️ Reset", size="sm")
134
+
135
+ gr.Markdown("---")
136
+ gr.Markdown("📝 **Todo Checklist**")
137
+ todo_list = gr.CheckboxGroup(
138
+ choices=["Read textbook chapters", "Complete AI Quiz assignment", "Review Generated Notes"],
139
+ label="Tasks for Session"
140
+ )
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(): current_todos.append(task)
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
+
148
+ # MAIN WORKSPACE
149
+ with gr.Column(scale=4):
150
+ with gr.Tabs() as main_tabs:
151
+
152
+ # TAB 1: Chat
153
+ with gr.Tab("💬 AI Chat Workspace", id="chat_tab"):
154
+ subject_info_banner = gr.Markdown("### 📐 Mathematics \n*Algebra, Calculus, Geometry & more*")
155
+
156
+ suggestion_box = gr.Radio(
157
+ choices=SUGGESTIONS["math"],
158
+ label="💡 Instant Suggestions (Click to choose, then type or send)",
159
+ interactive=True
160
+ )
161
+
162
+ file_upload = gr.File(label="📂 Upload Study Material (PDF up to 50MB)", file_types=[".pdf"])
163
+ chatbot = gr.Chatbot(height=400, show_copy_button=True)
164
+
165
+ with gr.Row():
166
+ msg_input = gr.Textbox(placeholder="Ask anything...", scale=4, show_label=False)
167
+ audio_input = gr.Audio(sources=["microphone"], type="filepath", label="🎙️ Voice", scale=1)
168
+ submit_btn = gr.Button("Send 🚀", variant="primary", scale=1)
169
+
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
+ return banner_text, gr.update(choices=SUGGESTIONS.get(sub_id, [])), sub_id, []
174
+
175
+ subject_dropdown.change(
176
+ update_subject_view,
177
+ inputs=[subject_dropdown],
178
+ outputs=[subject_info_banner, suggestion_box, current_subject_id, chatbot]
179
+ )
180
+
181
+ suggestion_box.change(lambda x: x, inputs=[suggestion_box], outputs=[msg_input])
182
+
183
+ def handle_audio(audio_path):
184
+ if audio_path: return f"[Voice Note Uploaded: Analyzing audio content]"
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(): return "", chat_history
190
+ chat_history.append((message, ""))
191
+ for chunk in predict(message, chat_history[:-1], sub_id, pdf_file):
192
+ chat_history[-1] = (message, chunk)
193
+ yield "", chat_history
194
+
195
+ submit_btn.click(respond, [msg_input, chatbot, current_subject_id, file_upload], [msg_input, chatbot])
196
+ msg_input.submit(respond, [msg_input, chatbot, current_subject_id, file_upload], [msg_input, chatbot])
197
+
198
+ # TAB 2: Quiz
199
+ with gr.Tab("🎯 AI Quiz Mode", id="quiz_tab"):
200
+ quiz_generate_btn = gr.Button("✨ Generate New Custom Quiz via Gemini", variant="secondary")
201
+ quiz_output = gr.Markdown("*Click the button above to dynamically render an AI quiz.*")
202
+ quiz_generate_btn.click(generate_quiz, inputs=[current_subject_id], outputs=[quiz_output])
203
+
204
+ # TAB 3: Notes
205
+ with gr.Tab("📝 Summary Study Notes", id="notes_tab"):
206
+ notes_generate_btn = gr.Button("📖 Compile Revision Notes from Chat History", variant="secondary")
207
+ notes_output = gr.Markdown("*Click above to transform chat threads into notes.*")
208
+ notes_generate_btn.click(generate_notes, inputs=[chatbot, current_subject_id], outputs=[notes_output])
209
+
210
+ # TAB 4: Flashcards
211
+ with gr.Tab("🃏 Active Flashcards", id="flashcards_tab"):
212
+ flash_generate_btn = gr.Button("🔄 Formulate Flashcards from Chat History", variant="secondary")
213
+ flash_output = gr.Markdown("*Click above to extract flashcards.*")
214
+ flash_generate_btn.click(generate_flashcards, inputs=[chatbot, current_subject_id], outputs=[flash_output])
215
+
216
+ gr.Markdown("⚡ *Powered by Gemini 2.5 Flash API.*")
217
+
218
+ if __name__ == "__main__":
219
+ demo.queue()
220
+ demo.launch()