prasai-ap commited on
Commit
78b7b40
·
verified ·
1 Parent(s): 8739715

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +264 -0
app.py ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import Any
3
+
4
+ from dotenv import load_dotenv
5
+ import gradio as gr
6
+ import requests
7
+
8
+
9
+ load_dotenv()
10
+
11
+ BACKEND_URL = os.getenv("BACKEND_URL", "").rstrip("/")
12
+ EXAMPLE_QUESTION = "soil erosion vaneko ke ho"
13
+ EXAMPLE_CONTEXT = (
14
+ "Soil erosion is the removal of topsoil by wind, water, or other natural forces. "
15
+ "It can make farmland less fertile and can be reduced by planting trees and grass."
16
+ )
17
+
18
+
19
+ def ask_tutor(question: str, textbook_context: str) -> tuple[str, str, str]:
20
+ question = question.strip()
21
+ textbook_context = textbook_context.strip()
22
+
23
+ if not question:
24
+ return (
25
+ "Please type a student question.",
26
+ "कृपया विद्यार्थीको प्रश्न लेख्नुहोस्।",
27
+ "1. Add a question first.\n2. Then try again.\n3. Use a textbook topic.",
28
+ )
29
+
30
+ if BACKEND_URL:
31
+ backend_result = ask_backend(question)
32
+
33
+ if backend_result:
34
+ return backend_result
35
+
36
+ return mock_response(question=question, textbook_context=textbook_context)
37
+
38
+
39
+ def ask_backend(question: str) -> tuple[str, str, str] | None:
40
+ try:
41
+ response = requests.post(
42
+ f"{BACKEND_URL}/ask",
43
+ json={
44
+ "question": question,
45
+ "student_id": "hf-space-demo",
46
+ "language_support": "English and Nepali",
47
+ },
48
+ timeout=60,
49
+ )
50
+ response.raise_for_status()
51
+ data = response.json()
52
+ except requests.RequestException:
53
+ return None
54
+ except ValueError:
55
+ return None
56
+
57
+ return format_backend_response(data)
58
+
59
+
60
+ def format_backend_response(data: dict[str, Any]) -> tuple[str, str, str]:
61
+ quiz_questions = data.get("quiz_questions", [])
62
+ english_answer = data.get("answer_english", "No English answer returned.")
63
+ normalized_question = str(data.get("normalized_question") or "").strip()
64
+
65
+ if normalized_question:
66
+ english_answer = f"Interpreted question: {normalized_question}\n\n{english_answer}"
67
+
68
+ return (
69
+ english_answer,
70
+ data.get("answer_nepali", "नेपाली उत्तर प्राप्त भएन।"),
71
+ format_quiz(quiz_questions),
72
+ )
73
+
74
+
75
+ def mock_response(question: str, textbook_context: str) -> tuple[str, str, str]:
76
+ context = textbook_context or EXAMPLE_CONTEXT
77
+ simple_context = truncate(context, max_length=450)
78
+ normalized_question = normalize_question_mock(question)
79
+
80
+ english = (
81
+ f"Interpreted question: {normalized_question}\n\n"
82
+ "Mock demo answer: I am using the textbook context only. "
83
+ f"A simple explanation is: {simple_context}"
84
+ )
85
+ nepali = (
86
+ "मक डेमो उत्तर: म पाठ्यपुस्तकको सन्दर्भ मात्र प्रयोग गर्दैछु। "
87
+ "यो विषयलाई सरल रूपमा बुझ्दा, माटोको माथिल्लो उपयोगी भाग हावा वा पानीले "
88
+ "बगाएर लैजान सक्छ। यस्तो हुँदा खेतीका लागि माटो कमजोर हुन सक्छ।"
89
+ )
90
+ quiz = format_quiz(
91
+ [
92
+ "What is the main idea from the explanation?",
93
+ "Can you give one simple example?",
94
+ "Can you explain it in your own words?",
95
+ ]
96
+ )
97
+
98
+ return english, nepali, quiz
99
+
100
+
101
+ def normalize_question_mock(question: str) -> str:
102
+ text = question.lower()
103
+
104
+ if "soil erosion" in text or ("mato" in text and "katan" in text):
105
+ return "What is soil erosion?"
106
+
107
+ if "photosynthesis" in text or ("prakash" in text and "sansleshan" in text):
108
+ return "What is photosynthesis?"
109
+
110
+ if "fraction" in text or "bhinn" in text:
111
+ return "What is a fraction?"
112
+
113
+ if "oxygen" in text or "aksijan" in text:
114
+ return "What is oxygen?"
115
+
116
+ mixed_topic = extract_mixed_language_topic(text)
117
+
118
+ if mixed_topic:
119
+ return f"What is {mixed_topic}?"
120
+
121
+ return question
122
+
123
+
124
+ def extract_mixed_language_topic(text: str) -> str:
125
+ markers = [
126
+ " vaneko ",
127
+ " bhaneko ",
128
+ " vanya ",
129
+ " bhanya ",
130
+ " vanne ",
131
+ " bhanne ",
132
+ ]
133
+
134
+ if not any(marker in f" {text} " for marker in markers):
135
+ return ""
136
+
137
+ topic = f" {text} "
138
+ removable_phrases = [
139
+ " vaneko ",
140
+ " bhaneko ",
141
+ " vanya ",
142
+ " bhanya ",
143
+ " vanne ",
144
+ " bhanne ",
145
+ " ke ho ",
146
+ " k ho ",
147
+ " kya ho ",
148
+ " vana ",
149
+ " bhana ",
150
+ " ho ",
151
+ " ? ",
152
+ ]
153
+
154
+ for phrase in removable_phrases:
155
+ topic = topic.replace(phrase, " ")
156
+
157
+ topic = " ".join(topic.split()).strip(" ?.,")
158
+
159
+ if not topic or len(topic) > 80:
160
+ return ""
161
+
162
+ return topic
163
+
164
+
165
+ def format_quiz(quiz_questions: list[Any]) -> str:
166
+ questions = [
167
+ str(question).strip()
168
+ for question in quiz_questions
169
+ if str(question).strip()
170
+ ]
171
+
172
+ if not questions:
173
+ questions = [
174
+ "What did you learn from the explanation?",
175
+ "Can you give one example?",
176
+ "Can you explain it to a friend?",
177
+ ]
178
+
179
+ return "\n".join(
180
+ f"{index}. {question}"
181
+ for index, question in enumerate(questions[:3], start=1)
182
+ )
183
+
184
+
185
+ def truncate(text: str, max_length: int) -> str:
186
+ if len(text) <= max_length:
187
+ return text
188
+
189
+ return f"{text[: max_length - 3]}..."
190
+
191
+
192
+ with gr.Blocks(title="Pathshala AI", theme=gr.themes.Soft()) as demo:
193
+ gr.Markdown(
194
+ """
195
+ # Pathshala AI
196
+ Bilingual AI tutor for rural primary students in Nepal. Try English, Nepali,
197
+ or romanized Nepali questions like `soil erosion vaneko ke ho`.
198
+ """
199
+ )
200
+
201
+ with gr.Row():
202
+ with gr.Column(scale=1):
203
+ question_input = gr.Textbox(
204
+ label="Student question",
205
+ placeholder=EXAMPLE_QUESTION,
206
+ value=EXAMPLE_QUESTION,
207
+ lines=2,
208
+ )
209
+ context_input = gr.Textbox(
210
+ label="Optional textbook context",
211
+ placeholder="Paste a short textbook paragraph here.",
212
+ value=EXAMPLE_CONTEXT,
213
+ lines=5,
214
+ )
215
+ ask_button = gr.Button("Ask Tutor", variant="primary")
216
+
217
+ with gr.Column(scale=1):
218
+ english_output = gr.Textbox(
219
+ label="English explanation",
220
+ lines=6,
221
+ )
222
+ nepali_output = gr.Textbox(
223
+ label="Nepali explanation",
224
+ lines=6,
225
+ )
226
+ quiz_output = gr.Textbox(
227
+ label="3 quiz questions",
228
+ lines=5,
229
+ )
230
+
231
+ gr.Examples(
232
+ examples=[
233
+ [EXAMPLE_QUESTION, EXAMPLE_CONTEXT],
234
+ [
235
+ "What is a fraction?",
236
+ (
237
+ "A fraction shows a part of a whole. The top number tells how many "
238
+ "parts we have. The bottom number tells how many equal parts the "
239
+ "whole is divided into."
240
+ ),
241
+ ],
242
+ [
243
+ "photosynthesis vaneko ke ho vana",
244
+ (
245
+ "Photosynthesis is the process by which green plants use sunlight, "
246
+ "water, and carbon dioxide to make food."
247
+ ),
248
+ ],
249
+ ],
250
+ inputs=[question_input, context_input],
251
+ outputs=[english_output, nepali_output, quiz_output],
252
+ fn=ask_tutor,
253
+ cache_examples=False,
254
+ )
255
+
256
+ ask_button.click(
257
+ fn=ask_tutor,
258
+ inputs=[question_input, context_input],
259
+ outputs=[english_output, nepali_output, quiz_output],
260
+ )
261
+
262
+
263
+ if __name__ == "__main__":
264
+ demo.launch()