vlasdadsda commited on
Commit
99fb93e
·
1 Parent(s): 6e62792

Add application file

Browse files
Files changed (1) hide show
  1. app.py +726 -0
app.py ADDED
@@ -0,0 +1,726 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import g4f
2
+ import gradio as gr
3
+ import tempfile
4
+ import os
5
+ from pathlib import Path
6
+ from g4f.client import Client
7
+ from PIL import Image
8
+ import io
9
+ import requests
10
+ import numpy as np
11
+ from ultralytics import YOLO
12
+ import subprocess
13
+ import sys
14
+ import time
15
+ from typing import Dict, Any, Optional
16
+
17
+ AVAILABLE_MODELS = {
18
+ "GPT-4": "gpt-4",
19
+ "GPT-4 Turbo": "gpt-4-turbo",
20
+ "GPT-4o": "gpt-4o",
21
+ }
22
+
23
+ SYSTEM_PROMPT = """
24
+ 1. Всегда используйте кодировку UTF-8
25
+ 2. Используйте обработку ошибок
26
+ 3. Если пользователь просит нарисовать или сгенерировать изображение:
27
+ - Начните ответ с [GENERATE_IMAGE]
28
+ - Напишите детальный промпт на английском языке
29
+ - Завершите промпт строкой [/GENERATE_IMAGE]
30
+ - Продолжите обычный ответ на русском языке
31
+ """
32
+
33
+ def test_code(code: str, file_type: str = ".py") -> Dict[str, Any]:
34
+ """Тестирование кода в безопасной среде"""
35
+ start_time = time.time()
36
+ result = {
37
+ "success": False,
38
+ "output": "",
39
+ "error": "",
40
+ "execution_time": 0
41
+ }
42
+
43
+ try:
44
+ code = "# -*- coding: utf-8 -*-\n" + code
45
+
46
+ with tempfile.NamedTemporaryFile(suffix=file_type, mode='w', encoding='utf-8', delete=False) as tmp:
47
+ tmp.write(code)
48
+ tmp_path = tmp.name
49
+
50
+ process = subprocess.Popen(
51
+ [sys.executable, tmp_path],
52
+ stdout=subprocess.PIPE,
53
+ stderr=subprocess.PIPE,
54
+ text=True,
55
+ encoding='utf-8'
56
+ )
57
+
58
+ try:
59
+ stdout, stderr = process.communicate(timeout=10)
60
+ result["success"] = process.returncode == 0
61
+ result["output"] = stdout
62
+ result["error"] = stderr
63
+
64
+ except subprocess.TimeoutExpired:
65
+ process.kill()
66
+ result["error"] = "Превышено время выполнения (10 сек)"
67
+
68
+ finally:
69
+ os.unlink(tmp_path)
70
+
71
+ except Exception as e:
72
+ result["error"] = str(e)
73
+
74
+ result["execution_time"] = time.time() - start_time
75
+ return result
76
+
77
+ def process_file(file):
78
+ """Обработка загруженного файла"""
79
+ if not file:
80
+ return None
81
+
82
+ try:
83
+ # Получаем расширение файла
84
+ file_extension = file.name.lower().split('.')[-1] if hasattr(file, 'name') else ''
85
+
86
+ # Список поддерживаемых форматов изображений
87
+ image_extensions = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'}
88
+
89
+ # Если это изображение
90
+ if file_extension in image_extensions:
91
+ try:
92
+ # Открываем изображение
93
+ if isinstance(file, str):
94
+ image = Image.open(file)
95
+ else:
96
+ image = Image.open(io.BytesIO(file.read()))
97
+
98
+ # Анализируем изображение
99
+ return process_image(image)
100
+ except Exception as e:
101
+ return f"[Ошибка обработки изображения: {str(e)}]"
102
+
103
+ # Если это текстовый файл
104
+ if isinstance(file, str):
105
+ with open(file, 'r', encoding='utf-8') as f:
106
+ return f.read()
107
+ else:
108
+ return file.read().decode('utf-8')
109
+
110
+ except UnicodeDecodeError:
111
+ return "[Бинарный файл]"
112
+ except Exception as e:
113
+ return f"[Ошибка чтения файла: {str(e)}]"
114
+ def process_audio(file_path: str, operation: str) -> Optional[str]:
115
+ """Обработка аудио файлов"""
116
+ try:
117
+ from pydub import AudioSegment
118
+ audio = AudioSegment.from_file(file_path)
119
+
120
+ if "громкость" in operation.lower():
121
+ audio = audio + 10
122
+
123
+ output_path = os.path.join(tempfile.gettempdir(), f"processed_{int(time.time())}.mp3")
124
+ audio.export(output_path, format="mp3")
125
+ return output_path
126
+
127
+ except Exception as e:
128
+ return f"Ошибка обработки аудио: {str(e)}"
129
+
130
+ def generate_image(prompt: str) -> str:
131
+ """Генерация изображения через g4f"""
132
+ try:
133
+ client = Client()
134
+ response = client.images.generate(
135
+ model="flux",
136
+ prompt=prompt,
137
+ response_format="url"
138
+ )
139
+ return response.data[0].url
140
+ except Exception as e:
141
+ return f"Ошибка при генерации изобраения: {str(e)}"
142
+
143
+ def process_image(image_input) -> str:
144
+ """Обработка изображения и распознавание объектов через YOLOv8"""
145
+ try:
146
+ # Загружаем модель YOLOv8n
147
+ model = YOLO('yolov8n.pt')
148
+
149
+ # Если передан URL
150
+ if isinstance(image_input, str):
151
+ response = requests.get(image_input)
152
+ image = Image.open(io.BytesIO(response.content))
153
+ # Если передан объект изображения
154
+ elif isinstance(image_input, Image.Image):
155
+ image = image_input
156
+ else:
157
+ return "❌ Неподдерживаемый формат изображения"
158
+
159
+ # Конвертируем изображение в RGB если оно в RGBA
160
+ if image.mode == 'RGBA':
161
+ image = image.convert('RGB')
162
+
163
+ # Сохраняем изображение во временный файл для обработки
164
+ with tempfile.NamedTemporaryFile(suffix='.jpg', delete=False) as tmp:
165
+ image.save(tmp.name, format='JPEG')
166
+ # Запускаем распознавание
167
+ results = model(tmp.name)
168
+
169
+ # Собираем найденные объекты
170
+ detected_objects = []
171
+ for r in results:
172
+ for box in r.boxes:
173
+ class_id = int(box.cls)
174
+ class_name = model.names[class_id]
175
+ detected_objects.append(class_name)
176
+
177
+ # Если объектов нет
178
+ if not detected_objects:
179
+ return "Я ничего не вижу на этом изображении."
180
+
181
+ # Формируем список объектов для анализа
182
+ analysis = ", ".join(detected_objects)
183
+
184
+ response = g4f.ChatCompletion.create(
185
+ model="gpt-4o",
186
+ messages=[
187
+ {"role": "system", "content": """Ты - помощник по описанию изображений.
188
+ Твоя задача - описывать найденные объекты простым языком.
189
+ Всегда начинай ответ со слов "Я на этом изображении вижу..."
190
+ Не используй технические термины или проценты.
191
+ Не добавляй никаких пояснений или вводных фраз.
192
+ Если объектов нет, отвечай только "Я ничего не вижу на этом изображении."
193
+ """},
194
+ {"role": "assistant", "content": "Я готов описывать объекты на изображениях простым языком."},
195
+ {"role": "user", "content": f"На изображении найдены: {analysis}"}
196
+ ],
197
+ stream=False
198
+ )
199
+
200
+ return f"{response}"
201
+
202
+ except Exception as e:
203
+ return f"❌ Ошибка при обработке изображения: {str(e)}"
204
+ finally:
205
+ if 'tmp' in locals():
206
+ Path(tmp.name).unlink(missing_ok=True)
207
+
208
+ def chat_response(message, history, model_name, direct_mode, uploaded_file=None):
209
+ messages = [{"role": "system", "content": SYSTEM_PROMPT}]
210
+ history = history or []
211
+ history.append({"role": "user", "content": message})
212
+ history.append({"role": "assistant", "content": ""})
213
+ print(f"Получено сообщение: {message}")
214
+ print(f"Модель: {model_name}")
215
+ print(f"Прямая генерация: {direct_mode}")
216
+ print(f"Загруженный файл: {uploaded_file}")
217
+ try:
218
+ if direct_mode:
219
+ # Прямая отправка в нейронку для генерации изображения
220
+ image_url = generate_image(message)
221
+ if not image_url.startswith("Ошибка"):
222
+ # Анализируем изображение на наличие текста
223
+ image_analysis = process_image(image_url)
224
+ history[-1]["content"] = f"![Generated Image]({image_url})\n\n{image_analysis}"
225
+ else:
226
+ history[-1]["content"] = f"❌ {image_url}"
227
+ yield history, *[gr.update(visible=False) for _ in range(6)]
228
+ return
229
+
230
+ # Начальные значения
231
+ yield (
232
+ history,
233
+ gr.update(visible=False),
234
+ gr.update(visible=False),
235
+ gr.update(visible=False),
236
+ "",
237
+ gr.update(visible=False),
238
+ gr.update(visible=False)
239
+ )
240
+
241
+ if uploaded_file:
242
+ file_content = process_file(uploaded_file)
243
+ if file_content:
244
+ message = f"Файл содержит:\n```\n{file_content}\n```\n\n{message}"
245
+
246
+ # Формируем историю сообщений
247
+ for msg in history[:-2]:
248
+ messages.append({"role": msg["role"], "content": msg["content"]})
249
+ messages.append({"role": "user", "content": str(message)})
250
+
251
+ partial_message = ""
252
+ code_block = None
253
+
254
+ response = g4f.ChatCompletion.create(
255
+ model=AVAILABLE_MODELS.get(model_name, "gpt-4o"),
256
+ messages=messages,
257
+ stream=True,
258
+ provider=g4f.Provider.Airforce
259
+ )
260
+
261
+ for chunk in response:
262
+ if chunk:
263
+ if isinstance(chunk, str):
264
+ partial_message += chunk
265
+
266
+ # Проверяем на запрос генерации изображения
267
+ if "[GENERATE_IMAGE]" in partial_message and "[/GENERATE_IMAGE]" in partial_message:
268
+ start_idx = partial_message.find("[GENERATE_IMAGE]") + len("[GENERATE_IMAGE]")
269
+ end_idx = partial_message.find("[/GENERATE_IMAGE]")
270
+ image_prompt = partial_message[start_idx:end_idx].strip()
271
+
272
+ # Показываем статус генерации
273
+ history[-1]["content"] = """
274
+ <div class="generating-animation">
275
+ <div class="generating-text">Генерация изображения...</div>
276
+ </div>
277
+ """
278
+ yield history, *[gr.update(visible=False) for _ in range(6)]
279
+
280
+ # Генерируем изображение
281
+ image_url = generate_image(image_prompt)
282
+
283
+ if not image_url.startswith("Ошибка"):
284
+ # Анализируем изображение на наличие текста
285
+ image_analysis = process_image(image_url)
286
+ explanation_text = partial_message[end_idx + len("[/GENERATE_IMAGE]"):].strip()
287
+ partial_message = f"![Generated Image]({image_url})\n\n{image_analysis}\n\n{explanation_text}"
288
+ else:
289
+ partial_message = f"❌ {image_url}"
290
+
291
+ history[-1]["content"] = partial_message + "▓"
292
+ yield history, *[gr.update(visible=False) for _ in range(6)]
293
+
294
+ # Проверяем наличие кода
295
+ if "```" in partial_message:
296
+ code_start = partial_message.rfind("```") + 3
297
+ code_end = partial_message.find("```", code_start)
298
+ if code_end != -1:
299
+ code_block = partial_message[code_start:code_end].strip()
300
+
301
+ # В конце убираем курсор
302
+ history[-1]["content"] = partial_message
303
+ yield history, *[gr.update(visible=True if code_block else False) for _ in range(6)]
304
+
305
+ except Exception as e:
306
+ print(f"Error: {e}")
307
+ history[-1]["content"] = f"❌ Произошла ошибка: {str(e)}"
308
+ yield (
309
+ history,
310
+ gr.update(visible=False),
311
+ gr.update(visible=True, value=str(e)),
312
+ gr.update(visible=True),
313
+ "",
314
+ gr.update(visible=False),
315
+ gr.update(visible=False)
316
+ )
317
+
318
+ def analyze_code(code):
319
+ """Анализ кода и получение объяснения"""
320
+ if not code:
321
+ return [{"role": "assistant", "content": "❌ Нет кода для анализа"}]
322
+
323
+ prompt = f"""Проанализируй этот код и объясни:
324
+ 1. Что он делает
325
+ 2. Возможные проблемы или ошибки
326
+ 3. Как можно улучшить
327
+ 4. Примеры использования
328
+
329
+ Код:
330
+ ```
331
+ {code}
332
+ ```"""
333
+
334
+ try:
335
+ response = g4f.ChatCompletion.create(
336
+ model="gpt-4o",
337
+ messages=[{"role": "user", "content": prompt}],
338
+ stream=False
339
+ )
340
+ return [{"role": "assistant", "content": response if isinstance(response, str) else "Не удалось получить анализ"}]
341
+ except Exception as e:
342
+ return [{"role": "assistant", "content": f"❌ Ошибка при анализе: {str(e)}"}]
343
+
344
+ def create_interface():
345
+ # Обновляем тему на темную
346
+ theme = gr.themes.Soft(
347
+ primary_hue="slate",
348
+ secondary_hue="gray",
349
+ ).set(
350
+ body_background_fill="#1a1a1a",
351
+ body_text_color="#ffffff",
352
+ button_primary_background_fill="#2d2d2d",
353
+ button_primary_background_fill_hover="#3d3d3d",
354
+ button_primary_text_color="white",
355
+ block_label_background_fill="#2d2d2d",
356
+ block_title_text_color="#ffffff",
357
+ input_background_fill="#2d2d2d",
358
+ )
359
+
360
+ # Обновляем CSS стили для управления цветом кода
361
+ css = """
362
+ .gradio-container {
363
+ background-color: #1a1a1a !important;
364
+ }
365
+ .chatbot {
366
+ background-color: #2d2d2d !important;
367
+ border-radius: 10px;
368
+ box-shadow: 0 2px 6px rgba(0,0,0,0.15);
369
+ }
370
+ .message.user {
371
+ background-color: #3d3d3d !important;
372
+ color: white !important;
373
+ border-radius: 15px;
374
+ }
375
+ .message.bot {
376
+ background-color: #2d2d2d !important;
377
+ color: white !important;
378
+ border-radius: 15px;
379
+ position: relative;
380
+ transition: all 0.3s ease;
381
+ }
382
+ /* Добавляем стиль для блоков кода */
383
+ .message.bot pre {
384
+ background-color: #1a1a1a !important;
385
+ border-radius: 8px;
386
+ padding: 10px;
387
+ }
388
+ .message.bot.typing::after {
389
+ content: '|';
390
+ animation: cursor 1s infinite;
391
+ }
392
+ @keyframes cursor {
393
+ 0% { opacity: 0; }
394
+ 50% { opacity: 1; }
395
+ 100% { opacity: 0; }
396
+ }
397
+
398
+ .message.bot:last-child {
399
+ animation: fadeIn 0.3s ease-in-out;
400
+ }
401
+
402
+ /* Убираем дублирующиеся стили курсора */
403
+ .message.bot:last-child:not(:empty)::after {
404
+ content: '';
405
+ }
406
+
407
+ /* Анимация появления текста */
408
+ @keyframes fadeIn {
409
+ from {
410
+ opacity: 0;
411
+ transform: translateY(10px);
412
+ }
413
+ to {
414
+ opacity: 1;
415
+ transform: translateY(0);
416
+ }
417
+ }
418
+
419
+ @keyframes cursor {
420
+ 0% { opacity: 0; }
421
+ 50% { opacity: 1; }
422
+ 100% { opacity: 0; }
423
+ }
424
+ .footer {
425
+ display: none !important;
426
+ }
427
+
428
+ .generating-animation {
429
+ position: relative;
430
+ width: 100%;
431
+ height: 120px;
432
+ background: linear-gradient(45deg, #1a1a1a, #2d2d2d);
433
+ border-radius: 15px;
434
+ overflow: hidden;
435
+ display: flex;
436
+ align-items: center;
437
+ justify-content: center;
438
+ }
439
+
440
+ .generating-text {
441
+ color: white;
442
+ font-size: 16px;
443
+ z-index: 2;
444
+ animation: pulse 1.5s infinite;
445
+ }
446
+
447
+ .generating-animation::before {
448
+ content: '';
449
+ position: absolute;
450
+ width: 200%;
451
+ height: 200%;
452
+ top: -50%;
453
+ left: -50%;
454
+ background:
455
+ radial-gradient(2px 2px at 20% 30%, rgba(255,255,255,0.8), rgba(0,0,0,0)),
456
+ radial-gradient(2px 2px at 40% 70%, rgba(255,255,255,0.8), rgba(0,0,0,0)),
457
+ radial-gradient(2px 2px at 50% 40%, rgba(255,255,255,0.8), rgba(0,0,0,0)),
458
+ radial-gradient(2px 2px at 60% 60%, rgba(255,255,255,0.8), rgba(0,0,0,0));
459
+ background-repeat: repeat;
460
+ animation: rotate 8s linear infinite;
461
+ }
462
+
463
+ @keyframes rotate {
464
+ from {
465
+ transform: rotate(0deg);
466
+ }
467
+ to {
468
+ transform: rotate(360deg);
469
+ }
470
+ }
471
+
472
+ @keyframes pulse {
473
+ 0% { opacity: 0.6; }
474
+ 50% { opacity: 1; }
475
+ 100% { opacity: 0.6; }
476
+ }
477
+
478
+ .submit-btn {
479
+ min-width: 100px !important;
480
+ cursor: pointer !important;
481
+ background-color: #4a4a4a !important;
482
+ transition: all 0.2s ease;
483
+ }
484
+
485
+ .submit-btn:hover {
486
+ background-color: #5a5a5a !important;
487
+ }
488
+
489
+ .input-row {
490
+ gap: 8px;
491
+ padding: 8px;
492
+ background: #2d2d2d;
493
+ border-radius: 8px;
494
+ margin-top: 8px;
495
+ }
496
+
497
+ .footer {
498
+ display: none !important;
499
+ }
500
+ """
501
+
502
+ # Обновляем JavaScript, уберем проблемный код
503
+ js = """
504
+ document.addEventListener('DOMContentLoaded', function() {
505
+ // Добавляем стили
506
+ var style = document.createElement('style');
507
+ style.textContent = '.particle { position: absolute; background: white; width: 3px; height: 3px; border-radius: 50%; pointer-events: none; }';
508
+ document.head.appendChild(style);
509
+
510
+ // Функция для создания частиц
511
+ function addParticles(event) {
512
+ var btn = event.currentTarget;
513
+ for(var i = 0; i < 8; i++) {
514
+ var p = document.createElement('div');
515
+ p.className = 'particle';
516
+ p.style.left = event.offsetX + 'px';
517
+ p.style.top = event.offsetY + 'px';
518
+
519
+ // Случайное движение
520
+ var x = (Math.random() - 0.5) * 50;
521
+ var y = (Math.random() - 0.5) * 50;
522
+
523
+ p.animate([
524
+ { transform: 'translate(0, 0)', opacity: 1 },
525
+ { transform: 'translate(' + x + 'px, ' + y + 'px)', opacity: 0 }
526
+ ], {
527
+ duration: 500,
528
+ easing: 'ease-out'
529
+ }).onfinish = function() { p.remove(); };
530
+
531
+ btn.appendChild(p);
532
+ }
533
+ }
534
+
535
+ // Добвляем обработчики на кнопки
536
+ var buttons = document.querySelectorAll('.submit-btn, .analyze-btn, .run-btn');
537
+ buttons.forEach(function(btn) {
538
+ btn.style.position = 'relative';
539
+ btn.style.overflow = 'hidden';
540
+ btn.addEventListener('click', addParticles);
541
+ });
542
+ });
543
+ """
544
+
545
+ with gr.Blocks(theme=theme, css=css) as demo:
546
+ # gr.Markdown("# 💬 AI Chat Assistant")
547
+
548
+ current_code = gr.State("")
549
+
550
+ with gr.Row():
551
+ with gr.Column(scale=4):
552
+ chatbot = gr.Chatbot(
553
+ height="600px",
554
+ show_label=False,
555
+ container=True,
556
+ show_copy_button=True,
557
+ elem_classes="chatbot",
558
+ type="messages",
559
+ render_markdown=True
560
+ )
561
+
562
+ # Добавляем компоненты для вывода
563
+ output_text = gr.Textbox(
564
+ label="Вывод",
565
+ interactive=False,
566
+ visible=False
567
+ )
568
+ error_text = gr.Textbox(
569
+ label="⚠️ Ошибки",
570
+ interactive=False,
571
+ visible=False
572
+ )
573
+ ask_help_btn = gr.Button(
574
+ "❓ Спросить почему возникла ошибка",
575
+ visible=False
576
+ )
577
+
578
+ with gr.Row(elem_classes="input-row"):
579
+ msg = gr.Textbox(
580
+ placeholder="Спросите что-нибудь...",
581
+ container=False,
582
+ scale=4,
583
+ show_label=False,
584
+ lines=1, # Явно указываем одну строку
585
+ elem_classes="input-textbox"
586
+ )
587
+ submit = gr.Button(
588
+ "Отправить",
589
+ variant="primary",
590
+ scale=1,
591
+ elem_classes="submit-btn"
592
+ )
593
+ clear = gr.Button("Очистить", scale=1)
594
+
595
+ with gr.Column(scale=1, visible=True) as sidebar:
596
+ model = gr.Dropdown(
597
+ choices=list(AVAILABLE_MODELS.keys()),
598
+ value="GPT-4o",
599
+ label="Модель"
600
+ )
601
+ direct_mode = gr.Checkbox(
602
+ label="Прямая генерация (без обрботки прмпта)",
603
+ value=False
604
+ )
605
+ file_output = gr.File(label="Загрузить файл")
606
+
607
+ # Добавляем примеры ипользования в виде кнопок
608
+
609
+
610
+ # Добавляем кнопки анализа и запуска кода
611
+ analyze_btn = gr.Button(
612
+ "Анализировать",
613
+ visible=False,
614
+ elem_classes="analyze-btn"
615
+ )
616
+
617
+ run_btn = gr.Button(
618
+ "▶️ Запустить код",
619
+ visible=False,
620
+ elem_classes="run-btn"
621
+ )
622
+
623
+ def run_code(code):
624
+ if not code:
625
+ return {
626
+ output_text: gr.update(value=" Нет кода для выполнения", visible=True),
627
+ error_text: gr.update(visible=False),
628
+ ask_help_btn: gr.update(visible=False)
629
+ }
630
+
631
+ result = test_code(code)
632
+
633
+ return {
634
+ output_text: gr.update(value=result["output"] if result["success"] else "", visible=True),
635
+ error_text: gr.update(value=result["error"], visible=bool(result["error"])),
636
+ # ask_help_btn: gr.update(visible=bool(result["error"]))
637
+ }
638
+
639
+ def handle_error_question(error_message, code_block):
640
+ """Обработчик кнопки помощи с ошибкой"""
641
+ error_prompt = f"""Объясните ошибку и как её исправить:
642
+
643
+ Код:
644
+ ```
645
+ {code_block}
646
+ ```
647
+
648
+ Ошибка:
649
+ {error_message}"""
650
+
651
+ try:
652
+ response = g4f.ChatCompletion.create(
653
+ model="gpt-3.5-turbo",
654
+ messages=[{"role": "user", "content": error_prompt}],
655
+ stream=False
656
+ )
657
+ return [{"role": "assistant", "content": response if isinstance(response, str) else "Не удалось получиь ответ"}]
658
+ except Exception as e:
659
+ return [{"role": "assistant", "content": f"Ошибка при получнии объяснения: {str(e)}"}]
660
+
661
+ # Обработчики событий
662
+ msg.submit(
663
+ fn=chat_response,
664
+ inputs=[msg, chatbot, model, direct_mode, file_output],
665
+ outputs=[chatbot, output_text, error_text, ask_help_btn, current_code, analyze_btn, run_btn],
666
+ api_name=None, # Изменим с False на None
667
+ show_progress=True
668
+ ).then(
669
+ fn=lambda: gr.update(value=""),
670
+ outputs=[msg]
671
+ )
672
+
673
+ submit.click(
674
+ fn=chat_response,
675
+ inputs=[msg, chatbot, model, direct_mode, file_output],
676
+ outputs=[chatbot, output_text, error_text, ask_help_btn, current_code, analyze_btn, run_btn],
677
+ api_name=None, # Изменим с False на None
678
+ show_progress=True
679
+ ).then(
680
+ fn=lambda: gr.update(value=""),
681
+ outputs=[msg]
682
+ )
683
+
684
+ ask_help_btn.click(
685
+ fn=handle_error_question,
686
+ inputs=[error_text, current_code],
687
+ outputs=chatbot
688
+ )
689
+
690
+ analyze_btn.click(
691
+ fn=analyze_code,
692
+ inputs=[current_code],
693
+ outputs=[chatbot]
694
+ )
695
+
696
+ run_btn.click(
697
+ fn=run_code,
698
+ inputs=[current_code],
699
+ outputs=[output_text, error_text, ask_help_btn]
700
+ )
701
+
702
+ clear.click(
703
+ fn=lambda: (None, "", "", False, ""),
704
+ outputs=[chatbot, output_text, error_text, ask_help_btn, current_code]
705
+ )
706
+
707
+ return demo
708
+
709
+
710
+ if __name__ == "__main__":
711
+ demo = create_interface()
712
+ demo.queue() # Добавим параметр concurrency_count
713
+
714
+ # Запускаем мониторинг изменений в тдельном потоке
715
+
716
+
717
+ demo.launch(
718
+ show_api=False,
719
+ show_error=True,
720
+ server_name="127.0.0.1",
721
+ server_port=7860,
722
+ favicon_path=None,
723
+ auth=None,
724
+ # quiet=True, # Добавим этот параметр
725
+ share=True
726
+ )