Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- .DS_Store +0 -0
- .gitignore +1 -0
- gradio_app.py +303 -36
- prompts.py +20 -12
- translation.py +592 -0
- 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 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
|
| 134 |
|
| 135 |
# -----------------------------
|
| 136 |
# Gradio UI Layout
|
| 137 |
# -----------------------------
|
| 138 |
with gr.Blocks(title="LangGraph Math Solver") as demo:
|
| 139 |
-
gr.
|
| 140 |
-
"
|
| 141 |
)
|
| 142 |
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
)
|
| 148 |
-
|
| 149 |
-
label="
|
|
|
|
| 150 |
)
|
| 151 |
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
)
|
| 157 |
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
-
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
| 164 |
|
| 165 |
# Hidden session ID
|
| 166 |
session_state = gr.State()
|
| 167 |
|
| 168 |
-
# Events
|
| 169 |
-
|
| 170 |
run_graph,
|
| 171 |
-
inputs=[
|
| 172 |
-
outputs=[session_state,
|
| 173 |
)
|
| 174 |
|
| 175 |
-
|
| 176 |
handle_feedback,
|
| 177 |
-
inputs=[session_state,
|
| 178 |
-
outputs=[session_state,
|
| 179 |
)
|
| 180 |
|
| 181 |
-
|
| 182 |
-
solve_question,
|
|
|
|
|
|
|
| 183 |
)
|
| 184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
# -----------------------------
|
| 186 |
# Launch App
|
| 187 |
# -----------------------------
|
| 188 |
if __name__ == "__main__":
|
| 189 |
-
demo.launch(
|
|
|
|
| 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
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|