Files changed (1) hide show
  1. app.py +514 -0
app.py ADDED
@@ -0,0 +1,514 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, AutoConfig
4
+ from fastapi import FastAPI
5
+ from pydantic import BaseModel
6
+ import gradio as gr
7
+ import sounddevice as sd
8
+ import numpy as np
9
+ import wave
10
+ import tempfile
11
+ from gtts import gTTS
12
+ import os
13
+
14
+ # Клонирование репозитория Hugging Face
15
+
16
+ device = "cuda" if torch.cuda.is_available() else "cpu"
17
+
18
+ # Определяем стратегию загрузки модели
19
+ if torch.cuda.is_available():
20
+ vram_total = torch.cuda.get_device_properties(0).total_memory / (1024 ** 3)
21
+ if vram_total >= 16:
22
+ quantization_config = BitsAndBytesConfig(
23
+ load_in_4bit=True,
24
+ bnb_4bit_compute_dtype=torch.float16,
25
+ bnb_4bit_use_double_quant=True,
26
+ bnb_4bit_quant_type="nf4"
27
+ )
28
+ device_map = "auto"
29
+ elif vram_total >= 10:
30
+ quantization_config = BitsAndBytesConfig(load_in_8bit=True)
31
+ device_map = "auto"
32
+ else:
33
+ quantization_config = None
34
+ device_map = {"": "cpu"}
35
+ else:
36
+ quantization_config = None
37
+ device_map = {"": "cpu"}
38
+
39
+ # Загружаем модель FreedomIntelligence/RAG-Instruct-Llama3-3B
40
+ model_name = "FreedomIntelligence/RAG-Instruct-Llama3-3B"
41
+ config = AutoConfig.from_pretrained(model_name)
42
+
43
+ if quantization_config is not None:
44
+ quantization_config.llm_int8_enable_fp32_cpu_offload = True
45
+ quantization_config.offload_folder = "offload_weights"
46
+
47
+ model = AutoModelForCausalLM.from_pretrained(
48
+ model_name,
49
+ config=config,
50
+ quantization_config=quantization_config,
51
+ device_map=device_map,
52
+ )
53
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
54
+
55
+ # FastAPI
56
+ app = FastAPI()
57
+
58
+ class MathQuery(BaseModel):
59
+ topic: str
60
+ difficulty: str = "medium"
61
+
62
+ def generate_math_lesson(topic: str, difficulty: str):
63
+ prompt = f"Create a {difficulty} level math lesson on {topic} in English."
64
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
65
+ outputs = model.generate(**inputs, max_new_tokens=300, temperature=0.7, top_p=0.9)
66
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
67
+
68
+ def generate_english_task():
69
+ prompt = "Generate a random English learning exercise."
70
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
71
+ outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9)
72
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
73
+ def generate_random_task(difficulty):
74
+ """
75
+ This function generates a random English learning exercise using the
76
+ language model. It's similar to generate_english_task but can be
77
+ modified to generate different types of random tasks.
78
+ """
79
+ prompt = f"Generate a random English learning exercise {difficulty}"
80
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
81
+ outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9)
82
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
83
+
84
+
85
+ def answer_help_question(question: str):
86
+ prompt = f"Answer this question: {question}"
87
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
88
+ outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9)
89
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
90
+
91
+
92
+ # Gradio Web UI - Киберпанк стиль
93
+ custom_css = """
94
+ body {
95
+ background-color: #000;
96
+ color: #0ff;
97
+ font-family: 'Orbitron', sans-serif;
98
+ background-image: url('https://wallpaperaccess.com/full/1503811.jpg');
99
+ background-size: cover;
100
+ }
101
+ .container {
102
+ max-width: 900px;
103
+ margin: auto;
104
+ padding: 20px;
105
+ background: rgba(10, 10, 10, 0.9);
106
+ border-radius: 10px;
107
+ box-shadow: 0px 0px 20px cyan;
108
+ }
109
+ button {
110
+ background: linear-gradient(45deg, #ff00ff, #00ffff);
111
+ color: black;
112
+ padding: 10px;
113
+ border: none;
114
+ border-radius: 5px;
115
+ cursor: pointer;
116
+ font-weight: bold;
117
+ }
118
+ button:hover {
119
+ background: linear-gradient(45deg, #ff0000, #00ff00);
120
+ }
121
+ """
122
+
123
+ # Проверяем доступность устройства
124
+ device = "cuda" if torch.cuda.is_available() else "cpu"
125
+
126
+ # Проверяем наличие необходимых библиотек и загружаем модель для распознавания речи
127
+ try:
128
+ model_name = "openai/whisper-small"
129
+ model = AutoModelForSpeechSeq2Seq.from_pretrained(model_name).to(device)
130
+ processor = AutoProcessor.from_pretrained(model_name)
131
+ stt_pipeline = pipeline(
132
+ "automatic-speech-recognition", model=model, tokenizer=processor.tokenizer,
133
+ feature_extractor=processor.feature_extractor, device=0 if torch.cuda.is_available() else -1
134
+ )
135
+ except ModuleNotFoundError as e:
136
+ print(f"Ошибка: {e}. Убедитесь, что все зависимости установлены.")
137
+ exit()
138
+
139
+ def record_audio(duration=5, samplerate=16000):
140
+ print("Recording...")
141
+ audio_data = sd.rec(int(duration * samplerate), samplerate=samplerate, channels=1, dtype='int16')
142
+ sd.wait()
143
+ print("Recording finished")
144
+ return np.squeeze(audio_data)
145
+
146
+ def save_audio(audio_data, samplerate=16000):
147
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_wav:
148
+ with wave.open(temp_wav.name, 'wb') as wf:
149
+ wf.setnchannels(1)
150
+ wf.setsampwidth(2)
151
+ wf.setframerate(samplerate)
152
+ wf.writeframes(audio_data.tobytes())
153
+ return temp_wav.name
154
+
155
+ def transcribe_audio():
156
+ try:
157
+ audio_data = record_audio()
158
+ audio_path = save_audio(audio_data)
159
+ result = stt_pipeline(audio_path)
160
+ return result.get("text", "Ошибка распознавания")
161
+ except Exception as e:
162
+ return f"Ошибка обработки аудио: {e}"
163
+
164
+ def generate_ai_response(user_text):
165
+ return f"Вы сказали: {user_text}. Это тестовый ответ AI."
166
+
167
+ def tts_response(text):
168
+ try:
169
+ tts = gTTS(text, lang='ru')
170
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
171
+ tts.save(temp_file.name)
172
+ return temp_file.name
173
+ except Exception as e:
174
+ print(f"Ошибка генерации речи: {e}")
175
+ return None
176
+
177
+ def voice_interaction():
178
+ greeting_text = "Привет! Я ваш голосовой ассистент. Как я могу помочь?"
179
+ greeting_audio = tts_response(greeting_text)
180
+ recognized_text = transcribe_audio()
181
+ print("User said:", recognized_text)
182
+ response_text = generate_ai_response(recognized_text)
183
+ response_audio = tts_response(response_text)
184
+ return greeting_text, greeting_audio, recognized_text, response_text, response_audio
185
+
186
+
187
+
188
+ with gr.Blocks(css=custom_css) as demo:
189
+ gr.Markdown("""
190
+ <div class='container'>
191
+ <h1>⚡ CyberAI Learning Platform ⚡</h1>
192
+ <h2>🚀 Powered by FreedomIntelligence/RAG-Instruct-Llama3-3B</h2>
193
+ </div>
194
+ """)
195
+
196
+ with gr.Tabs() as tabs:
197
+ with gr.TabItem("Math Lessons"):
198
+ topic_input = gr.Textbox(label="Enter Math Topic")
199
+ difficulty_level = gr.Radio(["Easy", "Medium", "Hard"], label="Select Difficulty", value="Medium")
200
+ generate_button = gr.Button("Generate Lesson")
201
+ lesson_output = gr.Textbox(label="Generated Lesson", interactive=False)
202
+ generate_button.click(generate_math_lesson, inputs=[topic_input, difficulty_level], outputs=lesson_output)
203
+
204
+ with gr.TabItem("English Tasks"):
205
+ task_list = gr.Textbox(label="Generated English Task", interactive=False)
206
+ refresh_button = gr.Button("Get New Task")
207
+ refresh_button.click(generate_english_task, outputs=task_list)
208
+
209
+ with gr.TabItem("English Study Plan"):
210
+ study_plan_text = """<h3>English Tenses Overview</h3>
211
+ <p>There are 12 tenses in English, divided into 4 groups...</p>"""
212
+ import torch
213
+ from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, AutoConfig
214
+ from fastapi import FastAPI
215
+ from pydantic import BaseModel
216
+ import gradio as gr
217
+
218
+ # Определяем устройство
219
+ device = "cuda" if torch.cuda.is_available() else "cpu"
220
+
221
+ # Определяем стратегию загрузки модели
222
+ if torch.cuda.is_available():
223
+ vram_total = torch.cuda.get_device_properties(0).total_memory / (1024 ** 3)
224
+ if vram_total >= 16:
225
+ quantization_config = BitsAndBytesConfig(
226
+ load_in_4bit=True,
227
+ bnb_4bit_compute_dtype=torch.float16,
228
+ bnb_4bit_use_double_quant=True,
229
+ bnb_4bit_quant_type="nf4"
230
+ )
231
+ device_map = "auto"
232
+ elif vram_total >= 10:
233
+ quantization_config = BitsAndBytesConfig(load_in_8bit=True)
234
+ device_map = "auto"
235
+ else:
236
+ quantization_config = None
237
+ device_map = {"": "cpu"}
238
+ else:
239
+ quantization_config = None
240
+ device_map = {"": "cpu"}
241
+
242
+ # Загружаем модель FreedomIntelligence/RAG-Instruct-Llama3-3B
243
+ model_name = "FreedomIntelligence/RAG-Instruct-Llama3-3B"
244
+ config = AutoConfig.from_pretrained(model_name)
245
+
246
+ if quantization_config is not None:
247
+ quantization_config.llm_int8_enable_fp32_cpu_offload = True
248
+ quantization_config.offload_folder = "offload_weights"
249
+
250
+ model = AutoModelForCausalLM.from_pretrained(
251
+ model_name,
252
+ config=config,
253
+ quantization_config=quantization_config,
254
+ device_map=device_map,
255
+ )
256
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
257
+
258
+ # FastAPI
259
+ app = FastAPI()
260
+
261
+ class MathQuery(BaseModel):
262
+ topic: str
263
+ difficulty: str = "medium"
264
+
265
+ def generate_math_lesson(topic: str, difficulty: str):
266
+ prompt = f"Create a {difficulty} level math lesson on {topic} in English."
267
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
268
+ outputs = model.generate(**inputs, max_new_tokens=300, temperature=0.7, top_p=0.9)
269
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
270
+
271
+ def generate_english_task(difficulty):
272
+ prompt = f"Generate a random English learning exercise, {difficulty}"
273
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
274
+ outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9)
275
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
276
+ def generate_task_by_topic(topic: str,difficulty):
277
+ prompt = f"Generate a random English learning {topic} exercise ,{difficulty} "
278
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
279
+ outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9)
280
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
281
+
282
+ def answer_help_question(question: str):
283
+ prompt = f"Answer this question: {question}"
284
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
285
+ outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9)
286
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
287
+
288
+ # Gradio Web UI - Киберпанк стиль
289
+ custom_css = """
290
+ body {
291
+ background-color: #000;
292
+ color: #0ff;
293
+ font-family: 'Orbitron', sans-serif;
294
+ background-image: url('https://wallpaperaccess.com/full/1503811.jpg');
295
+ background-size: cover;
296
+ }
297
+ .container {
298
+ max-width: 900px;
299
+ margin: auto;
300
+ padding: 20px;
301
+ background: rgba(10, 10, 10, 0.9);
302
+ border-radius: 10px;
303
+ box-shadow: 0px 0px 20px cyan;
304
+ }
305
+ button {
306
+ background: linear-gradient(45deg, #ff00ff, #00ffff);
307
+ color: black;
308
+ padding: 10px;
309
+ border: none;
310
+ border-radius: 5px;
311
+ cursor: pointer;
312
+ font-weight: bold;
313
+ }
314
+ button:hover {
315
+ background: linear-gradient(45deg, #ff0000, #00ff00);
316
+ }
317
+ """
318
+
319
+ with gr.Blocks(css=custom_css) as demo:
320
+ gr.Markdown("""
321
+ <div class='container'>
322
+ <h1>⚡ Prosto AI⚡</h1>
323
+ <h2></h2>
324
+ </div>
325
+ """)
326
+
327
+ with gr.Tabs() as tabs:
328
+ with gr.TabItem("Math Lessons"):
329
+ topic_input = gr.Textbox(label="Enter Math Topic")
330
+ difficulty_level = gr.Radio(["Easy", "Medium", "Hard"], label="Select Difficulty", value="Medium")
331
+ generate_button = gr.Button("Generate Lesson")
332
+ lesson_output = gr.Textbox(label="Generated Lesson", interactive=False)
333
+ generate_button.click(generate_math_lesson, inputs=[topic_input, difficulty_level], outputs=lesson_output)
334
+
335
+ with gr.TabItem("English Tasks"):
336
+ difficulty_level = gr.Radio(["Easy", "Medium", "Hard"], label="Select Difficulty", value="Medium")
337
+
338
+
339
+
340
+ gr.Markdown("**Generate a task based on a specific topic or randomly:**")
341
+ task_topic_input = gr.Textbox(label="Enter a topic for the task")
342
+ generate_task_button = gr.Button("Generate Task by Topic")
343
+ generate_random_task_button = gr.Button("Generate Random Task")
344
+ generated_task_output = gr.Textbox(label="Generated Task", interactive=False)
345
+
346
+ generate_task_button.click(generate_task_by_topic, inputs=[task_topic_input, difficulty_level], outputs=generated_task_output)
347
+ generate_random_task_button.click(generate_random_task, inputs=[difficulty_level], outputs=generated_task_output)
348
+
349
+
350
+
351
+ with gr.TabItem("English Study Plan"):
352
+ study_plan_text = """<h3>English Tenses Overview</h3>
353
+ <p>План изучения английских времён
354
+ Изучение времён английского языка лучше всего разбивать на этапы, начиная с самых простых и постепенно переходя к более сложным. Этот план поможет вам постепенно освоить все времена и научиться их применять.
355
+
356
+ 🔹 Этап 1: Введение в систему времён
357
+ 📌 Цель: Ознакомиться с группами времён и их особенностями.
358
+
359
+ Понять, что в английском языке 12 времён, которые делятся на 4 группы:
360
+ Simple (Простые) – действие как факт.
361
+ Continuous (Длительные) – действие в процессе.
362
+ Perfect (Совершенные) – результат.
363
+ Perfect Continuous (Совершенные длительные) – процесс с акцентом на длительность.
364
+ 🔹 Этап 2: Освоение группы Simple (Простые времена)
365
+ 📌 Цель: Научиться выражать действия как факты, повторяющиеся события и события в будущем.
366
+
367
+ Present Simple (Настоящее простое)
368
+
369
+ Используется для регулярных действий, фактов и расписаний.
370
+ Формула: (I/You/We/They + V / He/She/It + V+s/es)
371
+ Пример: I go to school every day.
372
+ Past Simple (Прошедшее простое)
373
+
374
+ Действие, которое произошло в прошлом и закончилось.
375
+ Формула: (V2 или V+ed)
376
+ Пример: She visited Paris last year.
377
+ Future Simple (Будущее простое)
378
+
379
+ Действие, которое произойдёт в будущем.
380
+ Формула: (will + V)
381
+ Пример: They will travel to Japan next summer.
382
+ 📝 Практика: ✔️ Напишите 10 предложений в каждом времени.
383
+ ✔️ Используйте глаголы в разных формах.
384
+ ✔️ Расскажите о своём дне, вчерашнем дне и планах на завтра.
385
+
386
+ 🔹 Этап 3: Изучение группы Continuous (Длительные времена)
387
+ 📌 Цель: Научиться говорить о процессах, которые происходят в конкретный момент времени.
388
+
389
+ Present Continuous (Настоящее длительное)
390
+
391
+ Действие происходит прямо сейчас или в ближайшем будущем.
392
+ Формула: (am/is/are + V-ing)
393
+ Пример: She is reading a book now.
394
+ Past Continuous (Прошедшее длительное)
395
+
396
+ Действие длилось в определённый момент в прошлом.
397
+ Формула: (was/were + V-ing)
398
+ Пример: They were watching TV when I called.
399
+ Future Continuous (Будущее длительное)
400
+
401
+ Действие будет происходить в определённый момент в будущем.
402
+ Формула: (will be + V-ing)
403
+ Пример: This time tomorrow, I will be flying to New York.
404
+ 📝 Практика: ✔️ Опишите, что вы делаете прямо сейчас.
405
+ ✔️ Расскажите о том, что вы делали вчера в определённое время.
406
+ ✔️ Опишите, чем вы будете заниматься в завтрашний вечер.
407
+
408
+ 🔹 Этап 4: Освоение группы Perfect (Совершенные времена)
409
+ 📌 Цель: Научиться говорить о результатах действий.
410
+
411
+ Present Perfect (Настоящее совершенное)
412
+
413
+ Действие произошло в прошлом, но его результат важен сейчас.
414
+ Формула: (have/has + V3)
415
+ Пример: I have just finished my homework.
416
+ Past Perfect (Прошедшее совершенное)
417
+
418
+ Действие произошло до другого действия в прошлом.
419
+ Формула: (had + V3)
420
+ Пример: By the time I arrived, they had left.
421
+ Future Perfect (Будущее совершенное)
422
+
423
+ Действие завершится к определённому моменту в будущем.
424
+ Формула: (will have + V3)
425
+ Пример: I will have finished the report by tomorrow.
426
+ 📝 Практика: ✔️ Опишите, что вы уже сделали сегодня.
427
+ ✔️ Расскажите о событии, которое произошло до другого события в прошлом.
428
+ ✔️ Напишите, что вы завершите к концу следующей недели.
429
+
430
+ 🔹 Этап 5: Совершенные длительные времена (Perfect Continuous)
431
+ 📌 Цель: Использовать времена для описания длительных процессов с акцентом на продолжительность.
432
+
433
+ Present Perfect Continuous (Настоящее совершенное длительное)
434
+
435
+ Действие началось в прошлом и продолжается до сих пор.
436
+ Формула: (have/has been + V-ing)
437
+ Пример: I have been studying English for 5 years.
438
+ Past Perfect Continuous (Прошедшее совершенное длительное)
439
+
440
+ Действие длилось до определённого момента в прошлом.
441
+ Формула: (had been + V-ing)
442
+ Пример: She had been working at that company for 3 years before she quit.
443
+ Future Perfect Continuous (Будущее совершенное длительное)
444
+
445
+ Действие будет продолжаться до определённого момента в будущем.
446
+ Формула: (will have been + V-ing)
447
+ Пример: By next year, I will have been living here for 10 years.
448
+ 📝 Практика: ✔️ Опишите, как долго вы занимаетесь каким-либо хобби.
449
+ ✔️ Напишите, как долго длилось какое-то действие до определённого момента в прошлом.
450
+ ✔️ Составьте предложение о том, как долго вы будете чем-то заниматься в будущем.
451
+
452
+ 🔹 Этап 6: Итоговое повторение и практика
453
+ 📌 Цель: Закрепить знания и научиться использовать времена в речи.
454
+
455
+ ✅ Повторите основные отличия времён.
456
+ �� Составьте сравнительные таблицы, чтобы видеть разницу между временами.
457
+ ✅ Практикуйтесь в устной и письменной речи:
458
+
459
+ Опишите один день из жизни с разными временами.
460
+ Составьте рассказ о себе, используя все времена.
461
+ Потренируйтесь объяснять ситуации с разными временными формами.
462
+ 🔹 Совет: Лучше всего изучать времена постепенно, разбирая примеры и активно используя их в речи! 🚀
463
+
464
+ Такой подход поможет вам поэтапно освоить все времена и научиться использовать их правильно. Если нужна дополнительная практика или примеры — дайте знать! 😊
465
+
466
+
467
+
468
+
469
+
470
+
471
+
472
+ </p>"""
473
+ gr.Markdown(study_plan_text)
474
+ help_button = gr.Button("❓ Need Help?")
475
+ help_button.click(lambda: tabs.select(tabs.value)) #Fixed this line
476
+
477
+ with gr.TabItem("Help"):
478
+ question_input = gr.Textbox(label="Ask a question")
479
+ answer_output = gr.Textbox(label="AI Response", interactive=False)
480
+ ask_button = gr.Button("Ask AI")
481
+ ask_button.click(answer_help_question, inputs=[question_input], outputs=answer_output)
482
+ with gr.TabItem("Talking"):
483
+ record_button = gr.Button("🎙️ Говорить")
484
+ upload_audio = gr.File(label="Upload Audio")
485
+ greeting_output = gr.Audio(label="AI Приветствие", autoplay=True)
486
+ transcription_output = gr.Textbox(label="Распознанный текст")
487
+ response_text_output = gr.Textbox(label="Ответ AI")
488
+ audio_output = gr.Audio(label="Голосовой ответ AI", autoplay=True)
489
+
490
+ record_button.click(voice_interaction, outputs=[greeting_output, transcription_output, response_text_output, audio_output])
491
+ upload_audio.change(transcribe_audio, inputs=[upload_audio], outputs=[transcription_output])
492
+
493
+
494
+ record_button.click(voice_interaction, outputs=[greeting_output, transcription_output, response_text_output, audio_output])
495
+ with gr.TabItem("Resources"): # Nested correctly under tabs
496
+ gr.Markdown("## 📚 Полезные ресурсы для изучения английского")
497
+
498
+ with gr.Row(): # Nested correctly under Resources TabItem
499
+ gr.Markdown("[🎬 Фильмы на английском](https://www.netflix.com/)", label="Фильмы")
500
+ gr.Markdown("[📖 Книги на английском](https://www.gutenberg.org/)", label="Книги")
501
+
502
+ with gr.Row(): # Nested correctly under Resources TabItem
503
+ gr.Markdown("[🎧 Аудиокниги](https://librivox.org/)", label="Аудиокниги")
504
+ gr.Markdown("[📚 Уроки английского](https://www.ef.com/wwen/english-resources/)", label="Уроки английского")
505
+
506
+ with gr.Row(): # Nested correctly under Resources TabItem
507
+ gr.Markdown("[📺 Видео-уроки](https://www.youtube.com/results?search_query=learn+english)", label="Видео-уроки")
508
+ gr.Markdown("[📝 Грамматические упражнения](https://www.englishclub.com/grammar/)", label="Грамматика")
509
+
510
+
511
+
512
+
513
+ demo.launch()
514
+