Rizzhi commited on
Commit
32c4e29
Β·
verified Β·
1 Parent(s): ad87005

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +254 -0
app.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os # Keep os import in case it's used elsewhere, though not for Streamlit env vars now
3
+
4
+ # Import your existing modules
5
+ from modules.wiki_fetcher import fetch_topic_summary, fetch_wikibooks_links, fetch_wikidata_facts, fetch_wikiversity_resources
6
+ from modules.ai_engine import mentor_chat_response, generate_flashcards
7
+
8
+ # --- Gradio Theme and Global Styling ---
9
+ # Gradio handles light/dark mode automatically with its themes.
10
+ # We'll use a theme that generally looks good. You can experiment with others like
11
+ # gr.themes.Default(), gr.themes.Monochrome(), gr.themes.Glass()
12
+ theme = gr.themes.Soft()
13
+
14
+ # Custom CSS for the flashcards to mimic the Streamlit look
15
+ # Gradio's theming will handle the overall app background/text colors.
16
+ custom_css = """
17
+ /* Basic styling for the banner */
18
+ .banner {
19
+ text-align: center;
20
+ padding: 20px;
21
+ background-color: var(--background-fill-primary); /* Gradio's primary background color */
22
+ color: var(--text-color-body); /* Gradio's body text color */
23
+ border-radius: var(--radius-xl);
24
+ margin-bottom: 20px;
25
+ }
26
+ .banner h1 {
27
+ font-size: 2.5em;
28
+ margin-bottom: 0.2em;
29
+ color: var(--text-color-body);
30
+ }
31
+ .banner p {
32
+ font-size: 1.1em;
33
+ color: var(--text-color-subdued);
34
+ }
35
+
36
+ /* Styling for flashcards, adapting to Gradio's theme variables */
37
+ .flashcard {
38
+ background-color: var(--background-fill-secondary); /* Gradio's secondary background color */
39
+ padding: 1em;
40
+ margin-bottom: 1em;
41
+ border-radius: var(--radius-xl);
42
+ border: 1px solid var(--border-color-primary);
43
+ box-shadow: var(--shadow-drop-lg);
44
+ }
45
+ .flashcard h4 {
46
+ color: var(--text-color-body);
47
+ margin-top: 0;
48
+ margin-bottom: 0.5em;
49
+ }
50
+ .flashcard details {
51
+ margin-top: 0.5em;
52
+ }
53
+ .flashcard summary {
54
+ color: var(--text-color-subdued);
55
+ cursor: pointer;
56
+ font-weight: bold;
57
+ }
58
+ .flashcard p {
59
+ color: var(--text-color-subdued);
60
+ padding-top: 0.5em;
61
+ margin-bottom: 0;
62
+ }
63
+ """
64
+
65
+ # --- Functions to handle logic for Gradio UI interactions ---
66
+
67
+ def learn_topic_action(topic):
68
+ """
69
+ Handles the logic for the 'Learn a Topic' tab.
70
+ Fetches summary, links, facts, resources, and generates flashcards.
71
+ Returns multiple outputs for Gradio components.
72
+ """
73
+ summary_output = ""
74
+ books_output = ""
75
+ facts_output = ""
76
+ resources_output = ""
77
+ flashcard_status = ""
78
+ flashcards_data = [] # Data to be stored in session state
79
+
80
+ if not topic:
81
+ # Return empty strings for outputs and a message for status
82
+ return "", "", "", "", "Please enter a topic to learn.", []
83
+
84
+ # Fetch summary
85
+ # Gradio handles loading indicators automatically when functions are running
86
+ summary = fetch_topic_summary(topic)
87
+ if summary:
88
+ summary_output = f"### πŸ“– Topic Summary\n\n{summary}"
89
+ else:
90
+ summary_output = "Couldn't find that topic. Try again with a simpler keyword."
91
+ # If summary fails, no other data can be fetched, so return early
92
+ return summary_output, "", "", "", "", []
93
+
94
+ # Fetch Wikibooks links
95
+ books = fetch_wikibooks_links(topic)
96
+ if books:
97
+ books_output = "### πŸ”— Wikibooks Links\n\n" + "\n".join([f"- πŸ“˜ [{title}]({url})" for title, url in books])
98
+ else:
99
+ books_output = "No related books found on Wikibooks."
100
+
101
+ # Fetch Wikidata facts
102
+ facts = fetch_wikidata_facts(topic)
103
+ if facts:
104
+ facts_output = "### πŸ”¬ Wikidata Facts\n\n" + "\n".join([f"- οΏ½ {fact}" for fact in facts])
105
+ else:
106
+ facts_output = "No structured facts found on Wikidata."
107
+
108
+ # Fetch Wikiversity resources
109
+ resources = fetch_wikiversity_resources(topic)
110
+ if resources:
111
+ resources_output = "### πŸŽ“ Wikiversity Resources\n\n" + "\n".join([f"- πŸŽ“ [{title}]({link})" for title, link in resources])
112
+ else:
113
+ resources_output = "No learning resources found on Wikiversity."
114
+
115
+ # Generate flashcards
116
+ flashcards = generate_flashcards(summary)
117
+ if flashcards:
118
+ flashcards_data = flashcards # Store for session state
119
+ flashcard_status = "βœ… Flashcards generated! Check the Flashcard Review tab."
120
+ else:
121
+ flashcard_status = "⚠️ No flashcards were generated. Try a different topic."
122
+
123
+ return summary_output, books_output, facts_output, resources_output, flashcard_status, flashcards_data
124
+
125
+
126
+ def mentor_chat_action(user_query, chat_history):
127
+ """
128
+ Handles the AI Mentor chat functionality.
129
+ Takes user query and current chat history, generates a response, and updates history.
130
+ """
131
+ if not user_query:
132
+ # If query is empty, return current history without modification
133
+ return chat_history, chat_history
134
+
135
+ reply = mentor_chat_response(user_query)
136
+ chat_history.append([user_query, reply]) # Gradio Chatbot expects list of [user_msg, bot_msg]
137
+ return chat_history, chat_history # Return updated history for display and state
138
+
139
+
140
+ def flashcard_review_display(flashcards_data):
141
+ """
142
+ Generates HTML for displaying flashcards based on the session state data.
143
+ """
144
+ if not flashcards_data:
145
+ return "<p style='text-align: center; color: var(--text-color-subdued);'>Flashcards will appear here after learning a topic.</p>"
146
+
147
+ flashcard_html = ""
148
+ for idx, fc in enumerate(flashcards_data):
149
+ # Apply inline styles for the flashcard to match the Streamlit look
150
+ # These styles are derived from the custom_css block
151
+ flashcard_html += f"""
152
+ <div class='flashcard'>
153
+ <h4>Q{idx+1}: {fc['question']}</h4>
154
+ <details>
155
+ <summary>Show Answer</summary>
156
+ <p>{fc['answer']}</p>
157
+ </details>
158
+ </div>
159
+ """
160
+ return flashcard_html
161
+
162
+ # --- Gradio UI Layout ---
163
+ # Use gr.Blocks for a multi-tab application
164
+ with gr.Blocks(theme=theme, title="WikiMentor", css=custom_css) as demo:
165
+ # App Title and Description (mimicking Streamlit's banner)
166
+ gr.HTML("""
167
+ <div class="banner">
168
+ <h1>πŸŽ“ WikiMentor</h1>
169
+ <p>Your AI-Powered Smart Learning Companion</p>
170
+ </div>
171
+ """)
172
+
173
+ # Persistent state variables for chat history and flashcards
174
+ # These will maintain their values across different tab interactions within a session
175
+ chat_history_state = gr.State([])
176
+ flashcards_state = gr.State([])
177
+
178
+ # Main navigation using Gradio Tabs
179
+ with gr.Tabs() as tabs:
180
+ # --- Learn a Topic Tab ---
181
+ with gr.TabItem("🏫 Learn a Topic", id=0):
182
+ gr.Markdown("## πŸ“˜ Learn a New Topic")
183
+ topic_input = gr.Textbox(label="πŸ” Enter a topic to learn:", placeholder="e.g., Quantum Physics", scale=4)
184
+ learn_button = gr.Button("πŸ“š Fetch Topic Info", scale=1)
185
+
186
+ # Output components for the fetched information
187
+ summary_output = gr.Markdown(label="Topic Summary", show_label=False)
188
+ books_output = gr.Markdown(label="Wikibooks Links", show_label=False)
189
+ facts_output = gr.Markdown(label="Wikidata Facts", show_label=False)
190
+ resources_output = gr.Markdown(label="Wikiversity Resources", show_label=False)
191
+ flashcard_status_output = gr.Markdown(label="Flashcard Generation Status", show_label=False)
192
+
193
+ # Connect the button click to the learning function
194
+ learn_button.click(
195
+ fn=learn_topic_action,
196
+ inputs=[topic_input],
197
+ outputs=[
198
+ summary_output,
199
+ books_output,
200
+ facts_output,
201
+ resources_output,
202
+ flashcard_status_output,
203
+ flashcards_state # Update the flashcards_state with new data
204
+ ]
205
+ )
206
+
207
+ # --- Mentor Chat Tab ---
208
+ with gr.TabItem("πŸ’¬ Mentor Chat", id=1):
209
+ gr.Markdown("## πŸ’¬ Ask Your AI Mentor")
210
+ # Gradio's Chatbot component handles displaying messages
211
+ chatbot = gr.Chatbot(label="Mentor Chat")
212
+ user_query_input = gr.Textbox(label="Type your question:", placeholder="Ask me anything about your topic...")
213
+ send_button = gr.Button("🧠 Get Answer")
214
+
215
+ # Connect the send button to the chat function
216
+ # The .then() method is used to clear the input box after sending
217
+ send_button.click(
218
+ fn=mentor_chat_action,
219
+ inputs=[user_query_input, chat_history_state], # Pass user query and current history
220
+ outputs=[chatbot, chat_history_state] # Update chatbot display and history state
221
+ ).then(
222
+ lambda: "", # Function to clear the input
223
+ outputs=[user_query_input]
224
+ )
225
+
226
+ # --- Flashcard Review Tab ---
227
+ with gr.TabItem("πŸ—‚οΈ Flashcard Review", id=2):
228
+ gr.Markdown("## πŸ—‚οΈ Flashcard Review Mode")
229
+ gr.Markdown("Use these flashcards to revise and reinforce your memory.")
230
+ flashcard_display_area = gr.HTML(label="Your Flashcards")
231
+
232
+ # This function will be called when the tab is selected to display flashcards
233
+ # The `load` event of the `Blocks` interface can trigger this when the tab changes
234
+ tabs.select(
235
+ fn=flashcard_review_display,
236
+ inputs=[flashcards_state], # Pass the current flashcards data
237
+ outputs=[flashcard_display_area],
238
+ # This ensures the flashcards are updated when the tab is switched to
239
+ # only if the selected tab is the flashcard review tab
240
+ # condition=lambda selected_tab: selected_tab == 2 # This condition can be tricky with tabs.select
241
+ )
242
+ # A simpler way to ensure flashcards are loaded when the tab is first viewed
243
+ # or when the app loads:
244
+ demo.load(
245
+ fn=flashcard_review_display,
246
+ inputs=[flashcards_state],
247
+ outputs=[flashcard_display_area]
248
+ )
249
+
250
+
251
+ # Launch the Gradio application
252
+ # server_name="0.0.0.0" and server_port=7860 are crucial for Hugging Face Spaces deployment
253
+ demo.launch(server_name="0.0.0.0", server_port=7860)
254
+ οΏ½