resulmamiyev commited on
Commit
4ed309e
·
verified ·
1 Parent(s): b0a564d

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. .DS_Store +0 -0
  2. .gitignore +1 -0
  3. gradio_app.py +303 -36
  4. prompts.py +20 -12
  5. translation.py +592 -0
  6. utils.py +84 -0
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
.gitignore CHANGED
@@ -4,3 +4,4 @@ app.ipynb
4
  test.md
5
  __pycache__/
6
  .env
 
 
4
  test.md
5
  __pycache__/
6
  .env
7
+ google.json
gradio_app.py CHANGED
@@ -1,21 +1,48 @@
1
  import gradio as gr
 
2
  from app import question_graph, MemorySaver
 
3
  import uuid
4
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  # -----------------------------
7
  # In-Memory Storage for Feedback Flow
8
  # -----------------------------
9
  session_data = {}
 
 
 
10
 
11
 
12
  # -----------------------------
13
  # Graph Invocation Function
14
  # -----------------------------
15
- def run_graph(topic, subtopic, difficulty):
16
  session_id = str(uuid.uuid4()) # Unique session per question
17
  memory = MemorySaver()
18
 
 
 
 
 
 
 
 
19
  inputs = {
20
  "topic": topic,
21
  "subtopic": subtopic,
@@ -46,17 +73,20 @@ def run_graph(topic, subtopic, difficulty):
46
  }
47
 
48
  generated_question = partial_result.get("question", "No question generated.")
49
- return (
50
- session_id,
51
- generated_question,
52
- "Enter feedback if needed, or click 'Solve Question'.",
53
- )
 
 
 
54
 
55
 
56
  # -----------------------------
57
  # Handle Feedback and Rerun Graph
58
  # -----------------------------
59
- def handle_feedback(session_id, feedback_text):
60
  data = session_data.get(session_id)
61
  if not data:
62
  return session_id, "Session expired or invalid.", ""
@@ -67,6 +97,10 @@ def handle_feedback(session_id, feedback_text):
67
 
68
  if feedback_text:
69
  # Update state with feedback at node 'feedback'
 
 
 
 
70
  question_graph.update_state(
71
  thread, {"human_feedback": feedback_text}, as_node="feedback"
72
  )
@@ -101,13 +135,23 @@ def handle_feedback(session_id, feedback_text):
101
 
102
  solution_md = final_result.get("solution", "No solution generated.")
103
  answer = final_result.get("answer", "No answer.")
 
 
 
 
 
 
 
 
 
 
104
  return session_id, solution_md, answer
105
 
106
 
107
  # -----------------------------
108
  # Solve Question – Full Graph Run
109
  # -----------------------------
110
- def solve_question(session_id):
111
  data = session_data.get(session_id)
112
  thread = {"configurable": {"thread_id": session_id}}
113
  if not data:
@@ -129,61 +173,284 @@ def solve_question(session_id):
129
  print("Final Result", final_result)
130
  solution_md = final_result.get("solution", "No solution generated.")
131
  answer = final_result.get("answer", "No answer.")
132
- return solution_md, answer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
 
135
  # -----------------------------
136
  # Gradio UI Layout
137
  # -----------------------------
138
  with gr.Blocks(title="LangGraph Math Solver") as demo:
139
- gr.Markdown(
140
- "## 🧠 Dahee AI\nInput your topic and generate math questions, provide feedback, and get step-by-step solutions."
141
  )
142
 
143
- with gr.Row():
144
- topic_input = gr.Textbox(label="Topic", placeholder="e.g., Combinatorics")
145
- subtopic_input = gr.Textbox(
146
- label="Subtopic", placeholder="e.g., Enumerative combinatorics"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  )
148
- difficulty_input = gr.Dropdown(
149
- label="Difficulty", choices=["easy", "medium", "hard"], value="medium"
 
150
  )
151
 
152
- generate_btn = gr.Button("Generate Question")
153
- question_output = gr.Markdown(label="Generated Question", render=True)
154
- feedback_note = gr.Textbox(
155
- label="Feedback (Optional)", placeholder="Enter feedback to refine question..."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  )
157
 
158
- with gr.Row():
159
- feedback_btn = gr.Button("Submit Feedback")
160
- solve_btn = gr.Button("Solve Question")
 
 
 
 
 
 
 
 
 
161
 
162
- solution_output = gr.Markdown(label="Solution (Markdown)", render=True)
163
- final_answer = gr.Markdown(label="Final Answer", render=True)
 
 
 
164
 
165
  # Hidden session ID
166
  session_state = gr.State()
167
 
168
- # Events
169
- generate_btn.click(
170
  run_graph,
171
- inputs=[topic_input, subtopic_input, difficulty_input],
172
- outputs=[session_state, question_output, feedback_note],
173
  )
174
 
175
- feedback_btn.click(
176
  handle_feedback,
177
- inputs=[session_state, feedback_note],
178
- outputs=[session_state, question_output, feedback_note],
179
  )
180
 
181
- solve_btn.click(
182
- solve_question, inputs=[session_state], outputs=[solution_output, final_answer]
 
 
183
  )
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  # -----------------------------
186
  # Launch App
187
  # -----------------------------
188
  if __name__ == "__main__":
189
- demo.launch(share=True)
 
1
  import gradio as gr
2
+ import utils
3
  from app import question_graph, MemorySaver
4
+ from translation import LANGUAGES
5
  import uuid
6
  import os
7
+ from dotenv import load_dotenv
8
+ import tempfile
9
+
10
+ load_dotenv()
11
+
12
+ service_account_json = os.environ.get("GOOGLE_SERVICE_ACCOUNT_JSON")
13
+ PROJECT_ID = os.environ.get("GOOGLE_CLOUD_PROJECT")
14
+
15
+ if service_account_json:
16
+ # Write the JSON content to a temporary file
17
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".json")
18
+ temp_file.write(service_account_json.encode("utf-8"))
19
+ temp_file.close()
20
+ # Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the temp file path
21
+ os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = temp_file.name
22
 
23
  # -----------------------------
24
  # In-Memory Storage for Feedback Flow
25
  # -----------------------------
26
  session_data = {}
27
+ session_data["en_topics"] = utils.get_topic_names("en")
28
+ session_data["az_topics"] = utils.get_topic_names("az")
29
+ session_data["ru_topics"] = utils.get_topic_names("ru")
30
 
31
 
32
  # -----------------------------
33
  # Graph Invocation Function
34
  # -----------------------------
35
+ def run_graph(topic, subtopic, difficulty, lang):
36
  session_id = str(uuid.uuid4()) # Unique session per question
37
  memory = MemorySaver()
38
 
39
+ if lang == "az" or lang == "ru":
40
+ topic, subtopic, difficulty = utils.get_eng_names(
41
+ topic, subtopic, difficulty, lang
42
+ )
43
+
44
+ print("Topic:", topic, "Subtopic:", subtopic, "Difficulty:", difficulty)
45
+
46
  inputs = {
47
  "topic": topic,
48
  "subtopic": subtopic,
 
73
  }
74
 
75
  generated_question = partial_result.get("question", "No question generated.")
76
+
77
+ # Translate Question if English is not selected
78
+ if lang != "en":
79
+ generated_question = utils.translate_text(
80
+ generated_question, PROJECT_ID, target_lang=lang, source_lang="en"
81
+ )
82
+
83
+ return session_id, generated_question, LANGUAGES[lang]["feedback_placeholder"]
84
 
85
 
86
  # -----------------------------
87
  # Handle Feedback and Rerun Graph
88
  # -----------------------------
89
+ def handle_feedback(session_id, feedback_text, lang):
90
  data = session_data.get(session_id)
91
  if not data:
92
  return session_id, "Session expired or invalid.", ""
 
97
 
98
  if feedback_text:
99
  # Update state with feedback at node 'feedback'
100
+ feedback_text = utils.translate_text(
101
+ feedback_text, PROJECT_ID, target_lang="en"
102
+ )
103
+
104
  question_graph.update_state(
105
  thread, {"human_feedback": feedback_text}, as_node="feedback"
106
  )
 
135
 
136
  solution_md = final_result.get("solution", "No solution generated.")
137
  answer = final_result.get("answer", "No answer.")
138
+
139
+ # Translate solution and answer if lang is not English
140
+ if lang != "en":
141
+ solution_md = utils.translate_text(
142
+ solution_md, PROJECT_ID, target_lang=lang, source_lang="en"
143
+ )
144
+ answer = utils.translate_text(
145
+ answer, PROJECT_ID, target_lang=lang, source_lang="en"
146
+ )
147
+
148
  return session_id, solution_md, answer
149
 
150
 
151
  # -----------------------------
152
  # Solve Question – Full Graph Run
153
  # -----------------------------
154
+ def solve_question(session_id, lang):
155
  data = session_data.get(session_id)
156
  thread = {"configurable": {"thread_id": session_id}}
157
  if not data:
 
173
  print("Final Result", final_result)
174
  solution_md = final_result.get("solution", "No solution generated.")
175
  answer = final_result.get("answer", "No answer.")
176
+
177
+ # Translate solution and answer if lang is not English
178
+ if lang != "en":
179
+ solution_md = utils.translate_text(
180
+ solution_md, PROJECT_ID, target_lang=lang, source_lang="en"
181
+ )
182
+ answer = utils.translate_text(
183
+ answer, PROJECT_ID, target_lang=lang, source_lang="en"
184
+ )
185
+
186
+ return solution_md
187
+
188
+
189
+ # Language toggle updates UI
190
+ def update_ui(lang):
191
+ return (
192
+ LANGUAGES[lang]["title"], # Markdown title
193
+ gr.update(visible=(lang == "az")), # Show Azerbaijani UI
194
+ gr.update(visible=(lang == "en")), # Show English UI
195
+ gr.update(visible=(lang == "ru")), # Show Russian UI
196
+ )
197
+
198
+
199
+ def update_subtopics(selected_topic, lang):
200
+ subtopics_list = utils.get_subtopics(selected_topic, lang)
201
+ return gr.update(
202
+ choices=subtopics_list, value=subtopics_list[0] if subtopics_list else ""
203
+ )
204
 
205
 
206
  # -----------------------------
207
  # Gradio UI Layout
208
  # -----------------------------
209
  with gr.Blocks(title="LangGraph Math Solver") as demo:
210
+ lang_toggle = gr.Dropdown(
211
+ label="🌍 Select Language", choices=["en", "az", "ru"], value="en"
212
  )
213
 
214
+ title = gr.Markdown(LANGUAGES["en"]["title"])
215
+
216
+ # English UI Components
217
+ with gr.Column(visible=True) as english_ui:
218
+ with gr.Row():
219
+ topic_input_en = gr.Dropdown(
220
+ label=LANGUAGES["en"]["topic_label"],
221
+ choices=session_data["en_topics"],
222
+ value=None,
223
+ )
224
+ subtopic_input_en = gr.Dropdown(
225
+ label=LANGUAGES["en"]["subtopic_label"], choices=[], value=None
226
+ )
227
+ difficulty_input_en = gr.Dropdown(
228
+ label=LANGUAGES["en"]["difficulty_label"],
229
+ choices=["easy", "medium", "hard"],
230
+ value="medium",
231
+ )
232
+
233
+ generate_btn_en = gr.Button(LANGUAGES["en"]["generate_btn"])
234
+ question_output_en = gr.Markdown(
235
+ label=LANGUAGES["en"]["question_output"],
236
+ render=True,
237
+ latex_delimiters=[
238
+ {"left": "$$", "right": "$$", "display": True},
239
+ {"left": "$", "right": "$", "display": False},
240
+ ],
241
  )
242
+ feedback_note_en = gr.Textbox(
243
+ label=LANGUAGES["en"]["feedback_label"],
244
+ placeholder=LANGUAGES["en"]["feedback_placeholder"],
245
  )
246
 
247
+ with gr.Row():
248
+ feedback_btn_en = gr.Button(LANGUAGES["en"]["feedback_btn"])
249
+ solve_btn_en = gr.Button(LANGUAGES["en"]["solve_btn"])
250
+
251
+ solution_output_en = gr.Markdown(
252
+ label=LANGUAGES["en"]["solution_output"],
253
+ render=True,
254
+ latex_delimiters=[
255
+ {"left": "$$", "right": "$$", "display": True},
256
+ {"left": "$", "right": "$", "display": False},
257
+ {"left": "[", "right": "]", "display": False},
258
+ ],
259
+ )
260
+ # final_answer_en = gr.Markdown(
261
+ # label=LANGUAGES["en"]["final_answer"], render=True
262
+ # )
263
+
264
+ # Azerbaijani UI Components (Initially Hidden)
265
+ with gr.Column(visible=False) as azeri_ui:
266
+ with gr.Row():
267
+ topic_input_az = gr.Dropdown(
268
+ label=LANGUAGES["az"]["topic_label"],
269
+ choices=session_data["az_topics"],
270
+ value=None,
271
+ )
272
+ subtopic_input_az = gr.Dropdown(
273
+ label=LANGUAGES["az"]["subtopic_label"], choices=[], value=None
274
+ )
275
+ difficulty_input_az = gr.Dropdown(
276
+ label=LANGUAGES["az"]["difficulty_label"],
277
+ choices=["asan", "orta", "çətin"],
278
+ value="orta",
279
+ )
280
+
281
+ generate_btn_az = gr.Button(LANGUAGES["az"]["generate_btn"])
282
+ question_output_az = gr.Markdown(
283
+ label=LANGUAGES["az"]["question_output"],
284
+ render=True,
285
+ latex_delimiters=[
286
+ {"left": "$$", "right": "$$", "display": True},
287
+ {"left": "$", "right": "$", "display": False},
288
+ ],
289
+ )
290
+ feedback_note_az = gr.Textbox(
291
+ label=LANGUAGES["az"]["feedback_label"],
292
+ placeholder=LANGUAGES["az"]["feedback_placeholder"],
293
+ )
294
+
295
+ with gr.Row():
296
+ feedback_btn_az = gr.Button(LANGUAGES["az"]["feedback_btn"])
297
+ solve_btn_az = gr.Button(LANGUAGES["az"]["solve_btn"])
298
+
299
+ solution_output_az = gr.Markdown(
300
+ label=LANGUAGES["az"]["solution_output"],
301
+ render=True,
302
+ latex_delimiters=[
303
+ {"left": "$$", "right": "$$", "display": True},
304
+ {"left": "$", "right": "$", "display": False},
305
+ {"left": "[", "right": "]", "display": False},
306
+ ],
307
+ )
308
+ # final_answer_az = gr.Markdown(
309
+ # label=LANGUAGES["az"]["final_answer"], render=True
310
+ # )
311
+
312
+ # Russian UI Components (Initially Hidden)
313
+ with gr.Column(visible=False) as russian_ui:
314
+ with gr.Row():
315
+ topic_input_ru = gr.Dropdown(
316
+ label=LANGUAGES["ru"]["topic_label"],
317
+ choices=session_data["ru_topics"],
318
+ value=None,
319
+ )
320
+ subtopic_input_ru = gr.Dropdown(
321
+ label=LANGUAGES["ru"]["subtopic_label"], choices=[], value=None
322
+ )
323
+ difficulty_input_ru = gr.Dropdown(
324
+ label=LANGUAGES["ru"]["difficulty_label"],
325
+ choices=["легкий", "средний", "сложный"],
326
+ value="средний",
327
+ )
328
+
329
+ generate_btn_ru = gr.Button(LANGUAGES["ru"]["generate_btn"])
330
+ question_output_ru = gr.Markdown(
331
+ label=LANGUAGES["ru"]["question_output"],
332
+ render=True,
333
+ latex_delimiters=[
334
+ {"left": "$$", "right": "$$", "display": True},
335
+ {"left": "$", "right": "$", "display": False},
336
+ ],
337
+ )
338
+ feedback_note_ru = gr.Textbox(
339
+ label=LANGUAGES["ru"]["feedback_label"],
340
+ placeholder=LANGUAGES["ru"]["feedback_placeholder"],
341
+ )
342
+
343
+ with gr.Row():
344
+ feedback_btn_ru = gr.Button(LANGUAGES["ru"]["feedback_btn"])
345
+ solve_btn_ru = gr.Button(LANGUAGES["ru"]["solve_btn"])
346
+
347
+ solution_output_ru = gr.Markdown(
348
+ label=LANGUAGES["ru"]["solution_output"],
349
+ render=True,
350
+ latex_delimiters=[
351
+ {"left": "$$", "right": "$$", "display": True},
352
+ {"left": "$", "right": "$", "display": False},
353
+ {"left": "[", "right": "]", "display": False},
354
+ ],
355
+ )
356
+ # final_answer_ru = gr.Markdown(
357
+ # label=LANGUAGES["ru"]["final_answer"], render=True
358
+ # )
359
+
360
+ # Language Toggle
361
+ lang_toggle.change(
362
+ update_ui,
363
+ inputs=[lang_toggle],
364
+ outputs=[
365
+ title,
366
+ azeri_ui,
367
+ english_ui,
368
+ russian_ui,
369
+ ], # Using .update() to toggle visibility
370
  )
371
 
372
+ # Topic Selection Events
373
+ topic_input_en.change(
374
+ update_subtopics,
375
+ inputs=[topic_input_en, lang_toggle],
376
+ outputs=[subtopic_input_en],
377
+ )
378
+
379
+ topic_input_az.change(
380
+ update_subtopics,
381
+ inputs=[topic_input_az, lang_toggle],
382
+ outputs=[subtopic_input_az],
383
+ )
384
 
385
+ topic_input_ru.change(
386
+ update_subtopics,
387
+ inputs=[topic_input_ru, lang_toggle],
388
+ outputs=[subtopic_input_ru],
389
+ )
390
 
391
  # Hidden session ID
392
  session_state = gr.State()
393
 
394
+ # Events for English UI
395
+ generate_btn_en.click(
396
  run_graph,
397
+ inputs=[topic_input_en, subtopic_input_en, difficulty_input_en, lang_toggle],
398
+ outputs=[session_state, question_output_en, feedback_note_en],
399
  )
400
 
401
+ feedback_btn_en.click(
402
  handle_feedback,
403
+ inputs=[session_state, feedback_note_en, lang_toggle],
404
+ outputs=[session_state, question_output_en, feedback_note_en],
405
  )
406
 
407
+ solve_btn_en.click(
408
+ solve_question,
409
+ inputs=[session_state, lang_toggle],
410
+ outputs=[solution_output_en],
411
  )
412
 
413
+ # Events for Azerbaijani UI
414
+ generate_btn_az.click(
415
+ run_graph,
416
+ inputs=[topic_input_az, subtopic_input_az, difficulty_input_az, lang_toggle],
417
+ outputs=[session_state, question_output_az, feedback_note_az],
418
+ )
419
+
420
+ feedback_btn_az.click(
421
+ handle_feedback,
422
+ inputs=[session_state, feedback_note_az, lang_toggle],
423
+ outputs=[session_state, question_output_az, feedback_note_az],
424
+ )
425
+
426
+ solve_btn_az.click(
427
+ solve_question,
428
+ inputs=[session_state, lang_toggle],
429
+ outputs=[solution_output_az],
430
+ )
431
+
432
+ # Events for Russian UI
433
+ generate_btn_ru.click(
434
+ run_graph,
435
+ inputs=[topic_input_ru, subtopic_input_ru, difficulty_input_ru, lang_toggle],
436
+ outputs=[session_state, question_output_ru, feedback_note_ru],
437
+ )
438
+
439
+ feedback_btn_ru.click(
440
+ handle_feedback,
441
+ inputs=[session_state, feedback_note_ru, lang_toggle],
442
+ outputs=[session_state, question_output_ru, feedback_note_ru],
443
+ )
444
+
445
+ solve_btn_ru.click(
446
+ solve_question,
447
+ inputs=[session_state, lang_toggle],
448
+ outputs=[solution_output_ru],
449
+ )
450
+
451
+
452
  # -----------------------------
453
  # Launch App
454
  # -----------------------------
455
  if __name__ == "__main__":
456
+ demo.launch()
prompts.py CHANGED
@@ -93,16 +93,24 @@ Check if the steps and results are mathematically correct and consistent.
93
 
94
 
95
  FINALIZE_INSTRUCTION = """
96
- You are a math tutor. Given the problem, steps, and calculation results, write a clear and concise Markdown solution.
97
-
98
- Include:
99
- - Step-by-step solution
100
- - Final answer (boxed or highlighted)
101
-
102
- Question: {question}
103
- Steps: {steps}
104
- Tool Results: {tool_results}
105
- Verified: {verified}
106
-
107
- Respond in markdown format. ALWAYS write mathematical equations in between dollar signs (e.g., $x^2$).
 
 
 
 
 
 
 
 
108
  """
 
93
 
94
 
95
  FINALIZE_INSTRUCTION = """
96
+ You are a math tutor, and your task is to produce a clear and concise Markdown solution for math problems. Follow these instructions carefully:
97
+
98
+ 1. Provide a detailed, step-by-step solution.
99
+ 2. Present the final answer clearly, either boxed or highlighted.
100
+ 3. **All mathematical expressions MUST be enclosed in dollar signs only:**
101
+ - For inline math, use a single pair of dollar signs (e.g., `$x^2$`).
102
+ - For display math, use double dollar signs on their own lines (e.g.,
103
+ ```
104
+ $$x^2$$
105
+ ```).
106
+ - **Do NOT use any other LaTeX environments (e.g., do not use `\\(`, `\\[`, or similar).**
107
+ 4. Strictly follow these formatting rules for every mathematical expression.
108
+
109
+ Use the following placeholders in your solution:
110
+ - **Question:** {question}
111
+ - **Steps:** {steps}
112
+ - **Tool Results:** {tool_results}
113
+ - **Verified:** {verified}
114
+
115
+ Respond in Markdown format only.
116
  """
translation.py ADDED
@@ -0,0 +1,592 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ LANGUAGES = {
2
+ "en": {
3
+ "title": "## 🧠 Dahee AI\nInput your topic and generate math questions, provide feedback, and get step-by-step solutions.",
4
+ "topic_label": "Topic",
5
+ "topic_placeholder": "e.g., Combinatorics",
6
+ "subtopic_label": "Subtopic",
7
+ "subtopic_placeholder": "e.g., Enumerative combinatorics",
8
+ "difficulty_label": "Difficulty",
9
+ "generate_btn": "Generate Question",
10
+ "feedback_label": "Feedback (Optional)",
11
+ "feedback_placeholder": "Enter feedback to refine question...",
12
+ "feedback_btn": "Submit Feedback",
13
+ "solve_btn": "Solve Question",
14
+ "question_output": "Generated Question",
15
+ "solution_output": "Solution (Markdown)",
16
+ "final_answer": "Final Answer",
17
+ },
18
+ "az": {
19
+ "title": "## 🧠 Dahee AI\nMövzunu daxil edin və riyazi suallar yaradın, rəy bildirin və addım-addım həllər əldə edin.",
20
+ "topic_label": "Mövzu",
21
+ "topic_placeholder": "məs., Kombinatorika",
22
+ "subtopic_label": "Alt mövzu",
23
+ "subtopic_placeholder": "məs., Hesablama Kombinatorikası",
24
+ "difficulty_label": "Çətinlik",
25
+ "generate_btn": "Sual Yarat",
26
+ "feedback_label": "Rəy (İstəyə bağlı)",
27
+ "feedback_placeholder": "Sualı düzəltmək üçün rəy bildirin...",
28
+ "feedback_btn": "Rəyi Göndər",
29
+ "solve_btn": "Sualı Həll et",
30
+ "question_output": "Yaradılan Sual",
31
+ "solution_output": "Həll (Markdown)",
32
+ "final_answer": "Son Cavab",
33
+ },
34
+ "ru": {
35
+ "title": "## 🧠 Dahee AI\nВведите свою тему и сгенерируйте математические вопросы, оставьте отзыв и получите пошаговые решения.",
36
+ "topic_label": "Тема",
37
+ "topic_placeholder": "например, Комбинаторика",
38
+ "subtopic_label": "Подтема",
39
+ "subtopic_placeholder": "например, Перечислительная комбинаторика",
40
+ "difficulty_label": "Сложность",
41
+ "generate_btn": "Создать вопрос",
42
+ "feedback_label": "Отзыв (Необязательно)",
43
+ "feedback_placeholder": "Введите отзыв для улучшения вопроса...",
44
+ "feedback_btn": "Отправить отзыв",
45
+ "solve_btn": "Решить вопрос",
46
+ "question_output": "Сгенерированный вопрос",
47
+ "solution_output": "Решение (Markdown)",
48
+ "final_answer": "Финальный ответ",
49
+ },
50
+ }
51
+
52
+ DIFFICULTY = [
53
+ {"en": "Easy", "az": "Asan", "ru": "Легко"},
54
+ {"en": "Medium", "az": "Orta", "ru": "Средне"},
55
+ {"en": "Hard", "az": "Çətin", "ru": "Трудно"},
56
+ ]
57
+
58
+ TOPICS = [
59
+ {
60
+ "en": "nth degree root",
61
+ "az": "n-ci dərəcədən kök",
62
+ "ru": "корень n-й степени",
63
+ "subtopics": [
64
+ {
65
+ "level": 9,
66
+ "en": "Real numbers",
67
+ "az": "Həqiqi ədədlər",
68
+ "ru": "Действительные числа",
69
+ },
70
+ {
71
+ "level": 9,
72
+ "en": "Absolute value of real number",
73
+ "az": "Həqiqi ədədin mütləq qiymətı",
74
+ "ru": "Абсолютная величина действительного числа",
75
+ },
76
+ {
77
+ "level": 9,
78
+ "en": "Numerical sets",
79
+ "az": "Ədədi çoxluqlar",
80
+ "ru": "Числовые множества",
81
+ },
82
+ {
83
+ "level": 9,
84
+ "en": "Introduction to nth degree root",
85
+ "az": "n -ci dərəcədən kökə giriş",
86
+ "ru": "Введение в корень n-й степени",
87
+ },
88
+ {
89
+ "level": 9,
90
+ "en": "Properties of nth degree root",
91
+ "az": "n-ci dərəcədən kökün xassələri",
92
+ "ru": "Свойства корня n-й степени",
93
+ },
94
+ {
95
+ "level": 9,
96
+ "en": "Taking the factor out from under the root sign",
97
+ "az": "Vuruğun kök işarəsi altindan çıxarılması",
98
+ "ru": "Вынесение множителя из-под знака корня",
99
+ },
100
+ {
101
+ "level": 9,
102
+ "en": "Putting the factor under the root sign",
103
+ "az": "Vuruğun kök işarəsi altina daxil edilməsi",
104
+ "ru": "Внесение множителя под знак корня",
105
+ },
106
+ ],
107
+ },
108
+ {
109
+ "en": "Rational Exponents",
110
+ "az": "Rasional üstlü qüvvətlər",
111
+ "ru": "Рациональные показатели",
112
+ "subtopics": [
113
+ {
114
+ "level": 9,
115
+ "en": "Rational Exponents",
116
+ "az": "Rasional üstlü qüvvətlər",
117
+ "ru": "Рациональные показатели",
118
+ },
119
+ {
120
+ "level": 9,
121
+ "en": "Properties of Rational Exponents",
122
+ "az": "Rasional üstlü qüvvənin xassələri",
123
+ "ru": "Свойства степени с рациональным показателем",
124
+ },
125
+ ],
126
+ },
127
+ {
128
+ "en": "Circle",
129
+ "az": "Çevrə",
130
+ "ru": "Окружность",
131
+ "subtopics": [
132
+ {
133
+ "level": 9,
134
+ "en": "Central angle. Arc of a circle",
135
+ "az": "Mərkəzi bucaq. Çevrə qövsü",
136
+ "ru": "Центральный угол. Дуга окружности",
137
+ },
138
+ {
139
+ "level": 9,
140
+ "en": "Arc length",
141
+ "az": "Qövsün uzunluğu",
142
+ "ru": "Длина дуги",
143
+ },
144
+ {
145
+ "level": 9,
146
+ "en": "Properties of a chord",
147
+ "az": "Vətərin xassələri",
148
+ "ru": "Свойства хорды",
149
+ },
150
+ {
151
+ "level": 9,
152
+ "en": "Angle inscribed in a circle",
153
+ "az": "Çevrə daxilinə çəkilmiş bucaq",
154
+ "ru": "Угол, вписанный в окружность",
155
+ },
156
+ {
157
+ "level": 9,
158
+ "en": "Tangent to a circle",
159
+ "az": "Çevrəyə toxunan",
160
+ "ru": "Касательная к окружности",
161
+ },
162
+ {
163
+ "level": 9,
164
+ "en": "Angles formed by tangents and secants",
165
+ "az": "Çevrəyə çəkilmiş toxunanlar və kəsənlər arasındakı bucaqlar",
166
+ "ru": "Углы, образованные касательными и секущими",
167
+ },
168
+ {
169
+ "level": 9,
170
+ "en": "Proportionality of chords and tangents in a circle",
171
+ "az": "Çevrədə vətər və kəsənlərin parçalarının mütənasibliyi",
172
+ "ru": "Пропорциональность отрезков хорд и секущих окружности",
173
+ },
174
+ ],
175
+ },
176
+ {
177
+ "en": "Functions and Graphs",
178
+ "az": "Funksiyalar və qrafiklər",
179
+ "ru": "Функции и графики",
180
+ "subtopics": [
181
+ {
182
+ "level": 9,
183
+ "en": "Quadratic function and its graph",
184
+ "az": "Kvadratik funksiya və onun qrafiki",
185
+ "ru": "Квадратичная функция и ее график",
186
+ },
187
+ {
188
+ "level": 9,
189
+ "en": "Representation of the quadratic function in different forms",
190
+ "az": "Kvadratik funksiyanın müxtəlif formalarda təqdimi",
191
+ "ru": "Представление квадратичной функции в разных формах",
192
+ },
193
+ {
194
+ "level": 9,
195
+ "en": "Plotting the graph of the function y = ax^2 + bx + c",
196
+ "az": "y = ax^2 + bx + c funksiyasının qrafikinin qurulması",
197
+ "ru": "Построение графика функции y = ax^2 + bx + c",
198
+ },
199
+ {
200
+ "level": 9,
201
+ "en": "Properties of the function y = ax^2 + bx + c",
202
+ "az": "y = ax^2 + bx + c funksiyasının xassələri",
203
+ "ru": "Свойства функции y = ax^2 + bx + c",
204
+ },
205
+ {
206
+ "level": 9,
207
+ "en": "Function y = |x| and its graph",
208
+ "az": "y = |x| funksiyası və onun qrafiki",
209
+ "ru": "Функция у = |х| и ее график",
210
+ },
211
+ {
212
+ "level": 9,
213
+ "en": "Function y = x^3 and its graph",
214
+ "az": "y = x^3 funksiyası və onun qrafiki",
215
+ "ru": "Функция у = x^3 и ее график",
216
+ },
217
+ ],
218
+ },
219
+ {
220
+ "en": "Equation of a circle",
221
+ "az": "Çevrənin tənliyi",
222
+ "ru": "Уравнение окружности",
223
+ "subtopics": [
224
+ {
225
+ "level": 9,
226
+ "en": "Distance between two points",
227
+ "az": "İki nöqtə arasındakı məsafə düsturu",
228
+ "ru": "Расстояние между двумя точками",
229
+ },
230
+ {
231
+ "level": 9,
232
+ "en": "Equation of a circle",
233
+ "az": "Çevrənin tənliyi",
234
+ "ru": "Уравнение окружности",
235
+ },
236
+ {
237
+ "level": 9,
238
+ "en": "Coordinates of points on a circle and trigonometric ratios",
239
+ "az": "Çevrə üzərindəki nöqtələrin koordinatları və triqonometrik nisbətlər",
240
+ "ru": "Координаты точек, находящихся на окружности, и тригонометрические соотношения",
241
+ },
242
+ {
243
+ "level": 9,
244
+ "en": "Area of ​​a circular sector and segment",
245
+ "az": "Dairə sektoru və seqmentinin sahəsi",
246
+ "ru": "Площадь кругового сектора и сегмента",
247
+ },
248
+ ],
249
+ },
250
+ {
251
+ "en": "Equations and System of equations",
252
+ "az": "Tənliklər və tənlikler sistemi",
253
+ "ru": "Уравнения и система уравнений",
254
+ "subtopics": [
255
+ {
256
+ "level": 9,
257
+ "en": "Equations of higher degrees",
258
+ "az": "Yüksək dərəcəli tənliklər",
259
+ "ru": "Уравнения высших степеней",
260
+ },
261
+ {
262
+ "level": 9,
263
+ "en": "Rational equations",
264
+ "az": "Rasional tənliklər",
265
+ "ru": "Рациональные уравнения",
266
+ },
267
+ {
268
+ "level": 9,
269
+ "en": "Equations with modulus",
270
+ "az": "Modullu tənliklər",
271
+ "ru": "Уравнения с модулем",
272
+ },
273
+ {
274
+ "level": 9,
275
+ "en": "Irrational equations",
276
+ "az": "İrrasional tənliklər",
277
+ "ru": "Иррациональные уравнения",
278
+ },
279
+ {
280
+ "level": 9,
281
+ "en": "Introduction to system of equations",
282
+ "az": "Tənliklər sisteminə giriş",
283
+ "ru": "Введение в систему уравнений",
284
+ },
285
+ {
286
+ "level": 9,
287
+ "en": "Systems of equations in which one equation is of the first and the other of the second degree",
288
+ "az": "Bir tənliyi birdərəcəli, digəri ikidərəcəli olan tənliklər sistemi",
289
+ "ru": "Системы уравнений, в которых одно уравнение первой, а другое второй степени",
290
+ },
291
+ {
292
+ "level": 9,
293
+ "en": "Solution of the system by algebraic methods",
294
+ "az": "Tənliklər sisteminin cəbri üsulla həlli",
295
+ "ru": "Решение системы алгебраическими методами",
296
+ },
297
+ {
298
+ "level": 9,
299
+ "en": "Systems of equations in which both equations are of the second degree",
300
+ "az": "Hər iki tənliyi ikidərəcəli olan tənliklər sistemi",
301
+ "ru": "Системы уравнений, в которых оба уравнения второй степени",
302
+ },
303
+ {
304
+ "level": 9,
305
+ "en": "Problems leading to a system of equations",
306
+ "az": "Tənliklər sisteminə gətirilən məsələlər",
307
+ "ru": "Задачи, приводящие к системе уравнений",
308
+ },
309
+ ],
310
+ },
311
+ {
312
+ "en": "Polygons",
313
+ "az": "Çoxbucaqlılar",
314
+ "ru": "Многоугольники",
315
+ "subtopics": [
316
+ {
317
+ "level": 9,
318
+ "en": "Introduction to Polygons",
319
+ "az": "Çoxbucaqlılara giriş",
320
+ "ru": "Введение в многоугольники",
321
+ },
322
+ {
323
+ "level": 9,
324
+ "en": "The sum of the interior and exterior angles of a convex polygon",
325
+ "az": "Qabarıq çoxbucaqlının daxili və xarici bucaqlarının cəmi",
326
+ "ru": "Сумма внутренних и внешних углов выпуклого многоугольника",
327
+ },
328
+ {
329
+ "level": 9,
330
+ "en": "Inscribed and circumscribed polygons",
331
+ "az": "Çevrənin daxilinə və xaricinə çəkilmiş çoxbucaqlılar",
332
+ "ru": "Вписанные и описанные многоугольники",
333
+ },
334
+ {
335
+ "level": 9,
336
+ "en": "Inscribed and circumscribed triangles",
337
+ "az": "Üçbucağın daxilinə və xaricinə çəkilmiş çevrələr",
338
+ "ru": "Вписанные и описанные треугольники",
339
+ },
340
+ {
341
+ "level": 9,
342
+ "en": "Properties of inscribed and circumscribed quadrilaterals",
343
+ "az": "Çevrənin daxilinə və xaricinə çəkilmiş dördbucaqlının xassələri",
344
+ "ru": "Свойства вписанных и описанных четырехугольников",
345
+ },
346
+ {
347
+ "level": 9,
348
+ "en": "Inscribed and circumscribed regular polygons",
349
+ "az": "Düzgün çoxbucaqlının daxilinə və xaricinə çəkilmiş çevrələr",
350
+ "ru": "Вписанные и описанные правильные многоугольники",
351
+ },
352
+ {
353
+ "level": 9,
354
+ "en": "Area of a regular polygon",
355
+ "az": "Düzgün çoxbucaqlının sahəsi",
356
+ "ru": "Площадь правильного многоугольника",
357
+ },
358
+ ],
359
+ },
360
+ {
361
+ "en": "Inequalities",
362
+ "az": "Bərabərsizliklər",
363
+ "ru": "Неравенства",
364
+ "subtopics": [
365
+ {
366
+ "level": 9,
367
+ "en": "System of Linear Inequalities",
368
+ "az": "Xətti bərabərsizliklər sistemi",
369
+ "ru": "Система линейных неравенств",
370
+ },
371
+ {
372
+ "level": 9,
373
+ "en": "Inequalities with modulus",
374
+ "az": "Modullu bərabərsizliklər",
375
+ "ru": "Неравенства с модулем",
376
+ },
377
+ {
378
+ "level": 9,
379
+ "en": "Quadratic inequalities",
380
+ "az": "Kvadrat bərabərsizliklər",
381
+ "ru": "Квадратные неравенства",
382
+ },
383
+ {
384
+ "level": 9,
385
+ "en": "Interval method",
386
+ "az": "İntervallar üsulu",
387
+ "ru": "Метод интервалов",
388
+ },
389
+ {
390
+ "level": 9,
391
+ "en": "Solution of rational inequalities by interval method",
392
+ "az": "Rasional bərabərsizliklərin intervallar üsulu ilə həlli",
393
+ "ru": "Решение рациональных неравенств методом интервалов",
394
+ },
395
+ {
396
+ "level": 9,
397
+ "en": "Irretional inequalities",
398
+ "az": "İrrasional bərabərsizliklər",
399
+ "ru": "Иррациональные неравенства",
400
+ },
401
+ ],
402
+ },
403
+ {
404
+ "en": "Vectors",
405
+ "az": "Vektorlar",
406
+ "ru": "Векторы",
407
+ "subtopics": [
408
+ {
409
+ "level": 9,
410
+ "en": "Intorduction to Vectors",
411
+ "az": "Vektorlara giriş",
412
+ "ru": "Введение в векторы",
413
+ },
414
+ {
415
+ "level": 9,
416
+ "en": "Vectors on the Cartesian coordinate plane",
417
+ "az": "Dekart koordinat müstəvisində vektorlar",
418
+ "ru": "Векторы на декартовой координатной плоскости",
419
+ },
420
+ {
421
+ "level": 9,
422
+ "en": "Vector direction and direction angle",
423
+ "az": "Vektorun istiqaməti və meyil bucağı",
424
+ "ru": "Направление вектора и угол наклона",
425
+ },
426
+ {
427
+ "level": 9,
428
+ "en": "Trigonometric relations and vector components",
429
+ "az": "Triqonometrik nisbətlər və vektorun komponentləri",
430
+ "ru": "Тригонометрические соотношения и компоненты вектора",
431
+ },
432
+ {
433
+ "level": 9,
434
+ "en": "Addition and subtraction of vectors",
435
+ "az": "Vektorların toplanması və çıxılması",
436
+ "ru": "Сложение и вычитание векторов",
437
+ },
438
+ {
439
+ "level": 9,
440
+ "en": "Addition of collinear vectors",
441
+ "az": "Kollinear vektorların toplanması",
442
+ "ru": "Сложение коллинеарных векторов",
443
+ },
444
+ {
445
+ "level": 9,
446
+ "en": "Addition and subtraction of non-collinear vectors",
447
+ "az": "Kollinear olmayan vektorların toplanması və çıxılması",
448
+ "ru": "Сложение и вычитание неколлинеарных векторов",
449
+ },
450
+ {
451
+ "level": 9,
452
+ "en": "Addition of vectors given by components",
453
+ "az": "Vektorların komponentlərindən istifadə etməklə toplanması",
454
+ "ru": "Сложение векторов, заданных компонентами",
455
+ },
456
+ {
457
+ "level": 9,
458
+ "en": "Multiplying a vector by a number",
459
+ "az": "Vektorun ədədə vurulması",
460
+ "ru": "Умножение вектора на число",
461
+ },
462
+ {
463
+ "level": 9,
464
+ "en": "Operations on vectors given by components",
465
+ "az": "Komponentləri ilə verilmiş vektorlar üzərində əməllər",
466
+ "ru": "Операции над векторами, заданными компонентами",
467
+ },
468
+ {
469
+ "level": 9,
470
+ "en": "Parallel transport",
471
+ "az": "Paralel köçürmə",
472
+ "ru": "Параллельный перенос",
473
+ },
474
+ {
475
+ "level": 9,
476
+ "en": "Movement and congruent figures",
477
+ "az": "Hərəkət və konqruyent fiqurlar",
478
+ "ru": "Движение и конгруэнтные фигуры",
479
+ },
480
+ ],
481
+ },
482
+ {
483
+ "en": "Numerical sequences",
484
+ "az": "Ədədi ardıcıllıqlar",
485
+ "ru": "Числовые последовательности",
486
+ "subtopics": [
487
+ {
488
+ "level": 9,
489
+ "en": "Introduction to numerical sequences",
490
+ "az": "Ədədi ardıcıllıqlara giriş",
491
+ "ru": "Введение в числовые последовательности",
492
+ },
493
+ {
494
+ "level": 9,
495
+ "en": "Arithmetic progression",
496
+ "az": "Ədədi silsilə",
497
+ "ru": "Арифметическая прогрессия",
498
+ },
499
+ {
500
+ "level": 9,
501
+ "en": "nth term of an arithmetic progression",
502
+ "az": "Ədədi silsilənin n-ci həddi",
503
+ "ru": "n-й член арифметической прогрессии",
504
+ },
505
+ {
506
+ "level": 9,
507
+ "en": "Properties of arithmetic progression",
508
+ "az": "Ədədi silsilənin xassələri",
509
+ "ru": "Свойства арифметической прогрессии",
510
+ },
511
+ {
512
+ "level": 9,
513
+ "en": "Sum of n terms of an arithmetic progression",
514
+ "az": "Ədədi silsilənin n həddinin cəmi",
515
+ "ru": "Сумма n членов арифметической прогрессии",
516
+ },
517
+ {
518
+ "level": 9,
519
+ "en": "Geometric progression",
520
+ "az": "Həndəsi silsilə",
521
+ "ru": "Геометрическая прогрессия",
522
+ },
523
+ {
524
+ "level": 9,
525
+ "en": "nth term of a geometric progression",
526
+ "az": "Həndəsi silsilənin n-ci həddi",
527
+ "ru": "n-й член геометрической прогрессии",
528
+ },
529
+ {
530
+ "level": 9,
531
+ "en": "Properties of geometric progression",
532
+ "az": "Həndəsi silsilənin xassələri",
533
+ "ru": "Свойства геометрической прогрессии",
534
+ },
535
+ {
536
+ "level": 9,
537
+ "en": "Sum of n terms of a geometric progression",
538
+ "az": "Həndəsi silsilənin n həddinin cəmi",
539
+ "ru": "Сумма n членов геометрической прогрессии",
540
+ },
541
+ {
542
+ "level": 9,
543
+ "en": "Sum of infinitely decreasing geometric progression",
544
+ "az": "Sonsuz azalan həndəsi silsilənin cəmi",
545
+ "ru": "Сумма бесконечно убывающей геометрической прогрессии",
546
+ },
547
+ ],
548
+ },
549
+ {
550
+ "en": "Combinatorics and Permutations",
551
+ "az": "Kombinatorika və Ehtimal",
552
+ "ru": "Комбинаторика и Перестановки",
553
+ "subtopics": [
554
+ {
555
+ "level": 9,
556
+ "en": "Relative frequency",
557
+ "az": "Nisbi tezlik",
558
+ "ru": "Относительная частота",
559
+ },
560
+ {
561
+ "level": 9,
562
+ "en": "Arithmetic mean of frequency distribution",
563
+ "az": "Tezlik paylanmasına görə ədədi orta",
564
+ "ru": "Среднее арифметическое по распределению частот",
565
+ },
566
+ {
567
+ "level": 9,
568
+ "en": "Permuations nPn",
569
+ "az": "Permutasiya nPn",
570
+ "ru": "Перестановки nPn",
571
+ },
572
+ {
573
+ "level": 9,
574
+ "en": "Permutations with repetitions",
575
+ "az": "Təkrarlı permutasiyalar",
576
+ "ru": "Пермутации с повторениями",
577
+ },
578
+ {
579
+ "level": 9,
580
+ "en": "Permutations - Placements, nPk",
581
+ "az": "Permutasiyalar - Yerləşmələr, nPk",
582
+ "ru": "Пермутации - Размещения, nPk",
583
+ },
584
+ {
585
+ "level": 9,
586
+ "en": "Combinations nCk",
587
+ "az": "Kombinezon, nCk",
588
+ "ru": "Комбинезон nCk",
589
+ },
590
+ ],
591
+ },
592
+ ]
utils.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from google.cloud import translate_v3 as translate
2
+ from translation import TOPICS, DIFFICULTY
3
+
4
+
5
+ # -----------------------------
6
+ # Helper Function: Translate Text
7
+ # -----------------------------
8
+ def translate_text(text, project_id, target_lang="az", source_lang=None):
9
+ """Translate text to the target language using Google Translate API."""
10
+ if not text.strip():
11
+ return text # Return empty text unchanged
12
+ try:
13
+ translate_client = translate.TranslationServiceClient()
14
+ parent = f"projects/{project_id}/locations/global"
15
+ response = translate_client.translate_text(
16
+ contents=[text],
17
+ target_language_code=target_lang,
18
+ parent=parent,
19
+ mime_type="text/plain",
20
+ source_language_code=source_lang,
21
+ )
22
+ return response.translations[0].translated_text
23
+ except Exception as e:
24
+ return f"Translation Error: {str(e)}"
25
+
26
+
27
+ # -----------------------------
28
+ # Helper Function: Get Topics List
29
+ # -----------------------------
30
+ def get_topic_names(lang):
31
+ return [topic[lang] for topic in TOPICS]
32
+
33
+
34
+ # -----------------------------
35
+ # Helper Function: Get Subtopics List
36
+ # -----------------------------
37
+ def get_subtopics(selected_topic, lang):
38
+ if not selected_topic:
39
+ return []
40
+
41
+ # Reverse map to find subtopics of selected topic
42
+ subtopics = next(
43
+ (topic["subtopics"] for topic in TOPICS if topic[lang] == selected_topic), None
44
+ )
45
+
46
+ return [subtopic[lang] for subtopic in subtopics]
47
+
48
+
49
+ # -----------------------------
50
+ # Helper Function: Get English Topic and Subtopic Names
51
+ # -----------------------------
52
+ def get_eng_names(selected_topic, selected_subtopic, difficulty, lang):
53
+ if not selected_topic or not selected_subtopic:
54
+ return None, None
55
+
56
+ # Reverse map to find English names of selected topic and subtopic
57
+ topic_en, subtopics = next(
58
+ (
59
+ (topic["en"], topic["subtopics"])
60
+ for topic in TOPICS
61
+ if topic[lang] == selected_topic
62
+ ),
63
+ None,
64
+ )
65
+
66
+ subtopic_en = next(
67
+ (
68
+ subtopic["en"]
69
+ for subtopic in subtopics
70
+ if subtopic[lang] == selected_subtopic
71
+ ),
72
+ None,
73
+ )
74
+
75
+ difficulty_en = next(
76
+ (
77
+ difficulty["en"]
78
+ for difficulty in DIFFICULTY
79
+ if difficulty[lang] == difficulty
80
+ ),
81
+ None,
82
+ )
83
+
84
+ return topic_en, subtopic_en, difficulty_en