vlasdadsda commited on
Commit
4fb8f72
·
verified ·
1 Parent(s): a4a1f3b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +404 -131
app.py CHANGED
@@ -1,20 +1,9 @@
1
- import asyncio
2
- import sys
3
-
4
- if sys.platform.startswith('win'):
5
- # Используем более стабильную политику событий для Windows
6
- asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
7
-
8
- # Создаем новый цикл событий
9
- loop = asyncio.new_event_loop()
10
- asyncio.set_event_loop(loop)
11
-
12
  import g4f
13
  import gradio as gr
14
  import tempfile
15
  import os
16
  from pathlib import Path
17
- from g4f.client import Client, AsyncClient
18
  from PIL import Image
19
  import io
20
  import requests
@@ -25,7 +14,7 @@ import sys
25
  import time
26
  from typing import Dict, Any, Optional
27
  import easyocr
28
- import asyncio
29
 
30
  AVAILABLE_MODELS = {
31
  "GPT-4": "gpt-4",
@@ -37,16 +26,19 @@ AVAILABLE_MODELS = {
37
  SYSTEM_PROMPT = """
38
  1. Всегда используйте кодировку UTF-8
39
  2. Используйте обработку ошибок
40
- 3. Если пользователь отправляет изображение или пишет чтото на подобие 'посмотри на изображение':
41
  - Автоматически проанализируйте изображение
42
  - Опишите что вы видите на русском языке
43
  - Тебе дается текстовая информация, которая может быть полезна для анализа
44
- 4. Если пользователь просит нарисовать или сгенерировать изображение:
 
 
 
45
  - Начните ответ с [GENERATE_IMAGE]
46
- - Напишите детальный промпт на ангийском языке
47
  - Завершите промпт строкой [/GENERATE_IMAGE]
48
  - Продолжите обычный ответ на русском языке
49
- 5. В режиме размышления:
50
  - Используйте [THINKING_STEP] для обозначения шага размышления
51
  - Используйте [FINAL_ANSWER] для итогового ответа
52
  - Старайтесь подробно описывать ход мыслей
@@ -102,7 +94,7 @@ def process_file(file):
102
  return None
103
 
104
  try:
105
- # Получаем расширение файл��
106
  file_extension = file.name.lower().split('.')[-1] if hasattr(file, 'name') else ''
107
 
108
  # Список поддерживаемых форматов изображений
@@ -154,11 +146,34 @@ def generate_image(prompt: str) -> str:
154
  try:
155
  client = Client()
156
  response = client.images.generate(
157
- model="flux",
158
  prompt=prompt,
159
- response_format="url"
 
160
  )
161
- return response.data[0].url
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  except Exception as e:
163
  return f"Ошибка при генерации изобраения: {str(e)}"
164
 
@@ -211,7 +226,7 @@ def process_image(image_input) -> str:
211
  if not detected_objects and not detected_text:
212
  return """
213
  <div class="image-analysis-animation">
214
- <div class="analysis-text">К сожалению, я не смог распознать объекты на этом изображении</div>
215
  </div>
216
  """
217
 
@@ -256,105 +271,291 @@ def process_image(image_input) -> str:
256
  if 'tmp' in locals():
257
  Path(tmp.name).unlink(missing_ok=True)
258
 
259
- async def chat_response(message, history, model_name, direct_mode, thinking_depth=1.0, uploaded_file=None):
260
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
261
  history = history or []
262
  history.append({"role": "user", "content": message})
263
  history.append({"role": "assistant", "content": ""})
264
-
265
  try:
266
- if model_name == "GPT-4o THINK":
267
- client = AsyncClient()
268
- min_steps = 3
269
- max_steps = 20
270
- num_steps = int(min_steps + (max_steps - min_steps) * (thinking_depth / 10.0))
 
271
 
272
- thinking_prompt = f"""Ты - система глубокого анализа.
273
- СТРОГО СОБЛЮДАЙ ФОРМАТ:
274
- 1. Каждый шаг должен быть в отдельных тегах [THINKING_STEP]текст шага[/THINKING_STEP]
275
- 2. После ВСЕХ шагов размышления пиши [FINAL_ANSWER]итоговый ответ[/FINAL_ANSWER]
276
- 3. Не пиши ничего между тегами
277
- 4. Не используй теги внутри других тегов
278
- 5. Обязательно сделай {num_steps} шагов, не больше и не меньше
279
 
280
- Глубина анализа: {thinking_depth:.1f}/10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
 
282
- Вопрос для анализа: {message}
283
- """
 
 
 
284
 
285
- thinking_html = f"""
286
- <div class="thinking-animation">
287
- <div class="thinking-step">🤔 Начинаю анализ (глубина: {thinking_depth:.1f}, шагов: {num_steps})</div>
288
- </div>
289
- """
290
- history[-1]["content"] = thinking_html
291
  yield history, *[gr.update(visible=False) for _ in range(6)]
 
 
 
 
 
 
 
 
 
 
 
 
 
292
 
293
- try:
294
- stream = await client.chat.completions.create(
295
- model="gpt-4o",
296
- messages=[{"role": "user", "content": thinking_prompt}],
297
- stream=True
298
- )
299
-
300
- thinking_steps = []
301
- current_text = ""
302
-
303
- async for chunk in stream:
304
- if chunk.choices and chunk.choices[0].delta.content:
305
- current_text += chunk.choices[0].delta.content
306
-
307
- while "[THINKING_STEP]" in current_text and "[/THINKING_STEP]" in current_text:
308
- start = current_text.find("[THINKING_STEP]")
309
- end = current_text.find("[/THINKING_STEP]")
310
- if start != -1 and end != -1:
311
- step = current_text[start + len("[THINKING_STEP]"):end].strip()
312
- if step and step not in thinking_steps:
313
- thinking_steps.append(step)
314
- thinking_html = f"""
315
- <div class="thinking-animation">
316
- <div class="thinking-step">🤔 Процесс размышления ({len(thinking_steps)}/{num_steps}):</div>
317
- """
318
- for i, s in enumerate(thinking_steps, 1):
319
- thinking_html += f'<div class="thinking-step">Шаг {i}: {s}</div>'
320
- thinking_html += '</div>'
321
- history[-1]["content"] = thinking_html
322
- yield history, *[gr.update(visible=False) for _ in range(6)]
323
- current_text = current_text[end + len("[/THINKING_STEP]"):]
324
-
325
- if "[FINAL_ANSWER]" in current_text and "[/FINAL_ANSWER]" in current_text:
326
- start = current_text.find("[FINAL_ANSWER]")
327
- end = current_text.find("[/FINAL_ANSWER]")
328
- final_answer = current_text[start + len("[FINAL_ANSWER]"):end].strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
330
- thinking_html = f"""
331
- <div class="thinking-animation">
332
- <div class="thinking-step">✨ Результат анализа (выполнено шагов: {len(thinking_steps)}/{num_steps}):</div>
333
- """
334
- for i, step in enumerate(thinking_steps, 1):
335
- thinking_html += f'<div class="thinking-step">Шаг {i}: {step}</div>'
336
- thinking_html += f'<div class="thinking-conclusion">{final_answer}</div>'
337
- thinking_html += '</div>'
338
- history[-1]["content"] = thinking_html
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  yield history, *[gr.update(visible=False) for _ in range(6)]
340
- break
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
 
342
- except Exception as e:
343
- history[-1]["content"] = f"❌ Ошибка при анализе: {str(e)}"
344
- yield history, *[gr.update(visible=False) for _ in range(6)]
345
- # finally:
346
- # await client.close()
347
-
348
- return
349
-
350
  else:
351
  # Обычный режим работы
352
  if direct_mode:
353
  # Прямая отправка в нейронку для генерации изображения
354
  image_url = generate_image(message)
355
  if not image_url.startswith("Ошибка"):
356
- image_analysis = process_image(image_url)
357
- history[-1]["content"] = f"![Generated Image]({image_url})\n\n{image_analysis}"
358
  else:
359
  history[-1]["content"] = f"❌ {image_url}"
360
  yield history, *[gr.update(visible=False) for _ in range(6)]
@@ -376,7 +577,7 @@ async def chat_response(message, history, model_name, direct_mode, thinking_dept
376
  if file_content:
377
  message = f"Файл содержит:\n```\n{file_content}\n```\n\n{message}"
378
 
379
- # Формируем историю сообщений
380
  for msg in history[:-2]:
381
  messages.append({"role": msg["role"], "content": msg["content"]})
382
  messages.append({"role": "user", "content": str(message)})
@@ -401,22 +602,22 @@ async def chat_response(message, history, model_name, direct_mode, thinking_dept
401
  end_idx = partial_message.find("[/GENERATE_IMAGE]")
402
  image_prompt = partial_message[start_idx:end_idx].strip()
403
 
404
- # Показываем статус ге��ерации
405
  history[-1]["content"] = """
406
- <div class="generating-animation">
407
- <div class="generating-text">Генерация изображения...</div>
408
- </div>
409
- """
410
  yield history, *[gr.update(visible=False) for _ in range(6)]
411
 
412
  # Генерируем изображение
413
  image_url = generate_image(image_prompt)
414
 
415
  if not image_url.startswith("Ошибка"):
416
- # Анализируем изображение на наличие текста
417
- image_analysis = process_image(image_url)
418
  explanation_text = partial_message[end_idx + len("[/GENERATE_IMAGE]"):].strip()
419
- partial_message = f"![Generated Image]({image_url})\n\n{image_analysis}\n\n{explanation_text}"
420
  else:
421
  partial_message = f"❌ {image_url}"
422
 
@@ -430,9 +631,13 @@ async def chat_response(message, history, model_name, direct_mode, thinking_dept
430
  if code_end != -1:
431
  code_block = partial_message[code_start:code_end].strip()
432
 
433
- # В конце убираем курсор
434
  history[-1]["content"] = partial_message
435
- yield history, *[gr.update(visible=True if code_block else False) for _ in range(6)]
 
 
 
 
436
 
437
  except Exception as e:
438
  print(f"Error: {e}")
@@ -446,7 +651,7 @@ async def chat_response(message, history, model_name, direct_mode, thinking_dept
446
  gr.update(visible=True),
447
  "",
448
  gr.update(visible=False),
449
- gr.update(visible=False)
450
  )
451
 
452
  def analyze_code(code):
@@ -476,7 +681,7 @@ def analyze_code(code):
476
  return [{"role": "assistant", "content": f"❌ Ошибка при анализе: {str(e)}"}]
477
 
478
  def create_interface():
479
- # Обновляем тему на темную
480
  theme = gr.themes.Soft(
481
  primary_hue="slate",
482
  secondary_hue="gray",
@@ -491,7 +696,7 @@ def create_interface():
491
  input_background_fill="#2d2d2d",
492
  )
493
 
494
- # Обновляем CSS стили для управлен��я цветом кода
495
  css = """
496
  .gradio-container {
497
  background-color: #1a1a1a !important;
@@ -513,7 +718,7 @@ def create_interface():
513
  position: relative;
514
  transition: all 0.3s ease;
515
  }
516
- /* Добавляем стиль для блоков кода */
517
  .message.bot pre {
518
  background-color: #1a1a1a !important;
519
  border-radius: 8px;
@@ -745,6 +950,69 @@ def create_interface():
745
  margin-bottom: 10px;
746
  font-style: italic;
747
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
748
  """
749
 
750
  # Добавте этот скрипт в create_interface()
@@ -768,7 +1036,7 @@ def create_interface():
768
  render_markdown=True
769
  )
770
 
771
- # Добавляем омпоненты для вывода
772
  output_text = gr.Textbox(
773
  label="Вывод",
774
  interactive=False,
@@ -810,16 +1078,16 @@ def create_interface():
810
 
811
  # Добавляем слайдер глубины размышления (изначально скрытый)
812
  thinking_depth = gr.Slider(
813
- minimum=0.1,
814
- maximum=10.0,
815
- value=1.0,
816
- step=0.1,
817
- label="Глубина размышления",
818
  visible=False
819
  )
820
 
821
  direct_mode = gr.Checkbox(
822
- label="Прямая генерация (без обрботки прмпта)",
823
  value=False
824
  )
825
  file_output = gr.File(label="Загрузить файл")
@@ -931,12 +1199,17 @@ def create_interface():
931
 
932
  if __name__ == "__main__":
933
  demo = create_interface()
 
 
 
 
934
 
935
- try:
936
- demo.launch(
937
- show_api=False,
938
- show_error=True,
939
- debug=True
940
- )
941
- except Exception as e:
942
- print(f"Ошибка запуска: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
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
 
14
  import time
15
  from typing import Dict, Any, Optional
16
  import easyocr
17
+ from web_engine import search_info, get_page_text # Импортируем функции из web_engine.py
18
 
19
  AVAILABLE_MODELS = {
20
  "GPT-4": "gpt-4",
 
26
  SYSTEM_PROMPT = """
27
  1. Всегда используйте кодировку UTF-8
28
  2. Используйте обработку ошибок
29
+ 3. Если пользователь отправляет изображение или пишет что-то на подобие 'посмотри на изображение':
30
  - Автоматически проанализируйте изображение
31
  - Опишите что вы видите на русском языке
32
  - Тебе дается текстовая информация, которая может быть полезна для анализа
33
+ 4. Если пользователь просит найти информацию, например, "найди что-то про Адольфа Гитлера":
34
+ - Ответь с текстом [SEARCH: {prompt}]
35
+ - Затем используй полученную информацию для ответа на вопрос
36
+ 5. Если пользователь просит нарисовать или сгенерировать изображение:
37
  - Начните ответ с [GENERATE_IMAGE]
38
+ - Напишите детальный промпт на английском языке
39
  - Завершите промпт строкой [/GENERATE_IMAGE]
40
  - Продолжите обычный ответ на русском языке
41
+ 6. В режиме размышления:
42
  - Используйте [THINKING_STEP] для обозначения шага размышления
43
  - Используйте [FINAL_ANSWER] для итогового ответа
44
  - Старайтесь подробно описывать ход мыслей
 
94
  return None
95
 
96
  try:
97
+ # Получаем расширение файла
98
  file_extension = file.name.lower().split('.')[-1] if hasattr(file, 'name') else ''
99
 
100
  # Список поддерживаемых форматов изображений
 
146
  try:
147
  client = Client()
148
  response = client.images.generate(
149
+ model="flux-1.1-pro",
150
  prompt=prompt,
151
+ response_format="url",
152
+ provider=g4f.Provider.Airforce
153
  )
154
+
155
+ image_url = response.data[0].url
156
+
157
+ # Проверяем доступность изображения
158
+ timeout = 30 # Максимальное время ожидания в секундах
159
+ interval = 0.1 # Интервал между проверками в секундах
160
+ elapsed_time = 0
161
+
162
+ while elapsed_time < timeout:
163
+ # Проверяем доступность изображения
164
+ head_response = requests.head(image_url)
165
+ if head_response.status_code == 200:
166
+ # Дополнительная проверка на наличие изображения
167
+ get_response = requests.get(image_url)
168
+ if get_response.status_code == 200:
169
+ return image_url # Изображение доступно
170
+ else:
171
+ return "❌ Ошибка: изображение недоступно."
172
+ time.sleep(interval)
173
+ elapsed_time += interval
174
+
175
+ return "❌ Ошибка: время ожидания изображения истекло." # Время ожидания истекло
176
+
177
  except Exception as e:
178
  return f"Ошибка при генерации изобраения: {str(e)}"
179
 
 
226
  if not detected_objects and not detected_text:
227
  return """
228
  <div class="image-analysis-animation">
229
+ <div class="analysis-text">К сожалению, я не смог распознать объекты на этом изобраении</div>
230
  </div>
231
  """
232
 
 
271
  if 'tmp' in locals():
272
  Path(tmp.name).unlink(missing_ok=True)
273
 
274
+ def chat_response(message, history, model_name, direct_mode, thinking_depth=1.0, uploaded_file=None):
275
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
276
  history = history or []
277
  history.append({"role": "user", "content": message})
278
  history.append({"role": "assistant", "content": ""})
279
+
280
  try:
281
+ # Проверяем, содержит ли сообщение [SEARCH:]
282
+ if "[SEARCH:" in message:
283
+ print("Поиск информации...") # Отладочное сообщение
284
+ prompt = message.split("[SEARCH:")[1].strip(" ]") # Извлекаем текст запроса
285
+ response_text = f"[SEARCH: {prompt}]\n" # Форматируем ответ
286
+ history[-1]["content"] = response_text # Обновляем историю с запросом поиска
287
 
288
+ # Выполняем поиск информации
289
+ results = search_info(prompt) # Ищем информацию
290
+ if not results:
291
+ history.append({"role": "assistant", "content": "Не удалось найти информацию."})
292
+ yield history, *[gr.update(visible=False) for _ in range(6)]
293
+ return
 
294
 
295
+ info_text = ""
296
+ for link in results:
297
+ info_text += f"Ссылка: {link}\n"
298
+ text = get_page_text(link)
299
+ info_text += f"Текст: {text}\n\n" # Добавляем текст страницы
300
+ print(f"Вот информация по запросу '{prompt}':\n\n{info_text}\nСделай краткий ответ на основе этой информации.")
301
+ # Формируем запрос для GPT
302
+ web_search = f"Вот информация по запросу '{prompt}':\n\n{info_text}\nСделай краткий ответ на основе этой информации."
303
+ print("Отправка запроса к GPT...") # Отладочное сообщение
304
+ response = g4f.ChatCompletion.create(
305
+ model="gpt-4o",
306
+ messages=[
307
+ {"role": "system", "content": "Сделай краткий ответ на основе следующей информации:"},
308
+ {"role": "user", "content": web_search}
309
+ ],
310
+ stream=True,
311
+ )
312
 
313
+ # Получаем ответ от GPT
314
+ if isinstance(response, str):
315
+ final_response = response
316
+ else:
317
+ final_response = "Не удалось получить ответ."
318
 
319
+ history.append({"role": "assistant", "content": final_response}) # Добавляе�� ответ ИИ
 
 
 
 
 
320
  yield history, *[gr.update(visible=False) for _ in range(6)]
321
+ return
322
+
323
+ if model_name == "GPT-4o THINK":
324
+ max_retries = 5
325
+ retry_count = 0
326
+
327
+ # Формируем thinking_prompt
328
+ min_steps = 2
329
+ max_steps = 25
330
+ thinking_depth = float(thinking_depth)
331
+ num_steps = max(min_steps, int(thinking_depth))
332
+
333
+ thinking_prompt = f"""Ты - система глубокого анализа. Твоя задача - максимально подробно проанализировать вопрос.
334
 
335
+ Глубина анализа: {thinking_depth:.1f}/10
336
+ Количество шагов размышления: {num_steps}
337
+
338
+ ВАЖНО: Строго соблюдай формат ответа. Каждый тег должен быть на новой строке:
339
+
340
+ [THINKING_STEP]
341
+ Текст первого шага...
342
+ [/THINKING_STEP]
343
+
344
+ [THINKING_STEP]
345
+ Текст второго шага...
346
+ [/THINKING_STEP]
347
+
348
+ [FINAL_ANSWER]
349
+ Итоговый ответ...
350
+ [/FINAL_ANSWER]
351
+
352
+ Вопрос: {message}
353
+ """
354
+
355
+ while retry_count < max_retries:
356
+ try:
357
+ # Показываем статус попытки
358
+ thinking_html = f"""
359
+ <div class="thinking-animation">
360
+ <div class="thinking-step">🤔 Думаю...</div>
361
+ </div>
362
+ """
363
+ history[-1]["content"] = thinking_html
364
+ yield history, *[gr.update(visible=False) for _ in range(6)]
365
+ print('Обработка запроса')
366
+ # Создаем запрос с таймаутом только для первого чанка
367
+ response = g4f.ChatCompletion.create(
368
+ model="gpt-4o",
369
+ messages=[{"role": "system", "content": thinking_prompt}],
370
+ stream=True,
371
+ # timeout=30
372
+ )
373
+
374
+ # Флаг для отслеживания получения первого чанка
375
+ received_first_chunk = False
376
+ partial_message = ""
377
+ current_block = ""
378
+ in_thinking_step = False
379
+ in_final_answer = False
380
+
381
+ for chunk in response:
382
+ if chunk and isinstance(chunk, str):
383
+ received_first_chunk = True
384
+ current_block += chunk
385
+
386
+ # Исправляем неправильно закрытые теги
387
+ # ... существующий код ...
388
+ current_block = (current_block
389
+ .replace("[/THINKING_STEP\n", "[/THINKING_STEP]\n") # Исправляем закрывающий тег THINKING_STEP
390
+ .replace("[/FINAL_ANSWER\n", "[/FINAL_ANSWER]\n") # Исправляем закрывающий тег FINAL_ANSWER
391
+ .replace("\n[/THINKING_STEP", "\n[/THINKING_STEP]") # Исправляем порядок закрывающего тега THINKING_STEP
392
+ .replace("\n[/FINAL_ANSWER", "\n[/FINAL_ANSWER]") # Исправляем порядок закрывающего тега FINAL_ANSWER
393
+ .replace("]]]]]]", "") # Убираем лишние закрывающие скобки
394
+ .replace("]]", "") # Убираем лишние закрывающие скобки
395
+ .replace("]", "") # Исправляем закрывающий тег THINKING_STEP с учетом закрывающей скобки
396
+ )
397
+ # ... существующий код ...
398
+
399
+ # Проверяем начало блоков
400
+ if "[THINKING_STEP]" in current_block:
401
+ in_thinking_step = True
402
+ current_block = current_block.replace("[THINKING_STEP]", "")
403
+
404
+ if "[THINKING_STEP" in current_block:
405
+ in_thinking_step = True
406
+ current_block = current_block.replace("[THINKING_STEP", "")
407
+
408
+ if "[FINAL_ANSWER]" in current_block:
409
+ in_final_answer = True
410
+ current_block = current_block.replace("[FINAL_ANSWER]", "")
411
+
412
+ # Проверяем завершение блоков
413
+ if "[/THINKING_STEP]" in current_block and in_thinking_step:
414
+ block_content = current_block[:current_block.find("[/THINKING_STEP]")]
415
+ formatted_block = f'<div class="thinking-step-block">{block_content}</div>'
416
+ partial_message += formatted_block
417
+ current_block = current_block[current_block.find("[/THINKING_STEP]") + len("[/THINKING_STEP]"):]
418
+ in_thinking_step = False
419
+
420
+ if "[/THINKING_STEP" in current_block and in_thinking_step:
421
+ block_content = current_block[:current_block.find("[/THINKING_STEP")]
422
+ formatted_block = f'<div class="thinking-step-block">{block_content}</div>'
423
+ partial_message += formatted_block
424
+ current_block = current_block[current_block.find("[/THINKING_STEP") + len("[/THINKING_STEP"):]
425
+ in_thinking_step = False
426
+
427
+ if "[/FINAL_ANSWER]" in current_block and in_final_answer:
428
+ block_content = current_block[:current_block.find("[/FINAL_ANSWER]")]
429
+ formatted_block = f'<div class="final-answer-block">{block_content}</div>'
430
+ partial_message += formatted_block
431
+ current_block = current_block[current_block.find("[/FINAL_ANSWER]") + len("[/FINAL_ANSWER]"):]
432
+ in_final_answer = False
433
+
434
+ if "[/FINAL_ANSWER" in current_block and in_final_answer:
435
+ block_content = current_block[:current_block.find("[/FINAL_ANSWER")]
436
+ formatted_block = f'<div class="final-answer-block">{block_content}</div>'
437
+ partial_message += formatted_block
438
+ current_block = current_block[current_block.find("[/FINAL_ANSWER") + len("[/FINAL_ANSWER"):]
439
+ in_final_answer = False
440
+
441
+ # Убираем лишние пробелы и переносы строк
442
+ display_message = partial_message + current_block.strip()
443
+ history[-1]["content"] = display_message
444
+ yield history, *[gr.update(visible=False) for _ in range(6)]
445
+
446
+ # # Если получили первый чанк, создаем новый стрим без таймаута
447
+ # if received_first_chunk:
448
+ # response = g4f.ChatCompletion.create(
449
+ # model="gpt-4o",
450
+ # messages=[{"role": "system", "content": thinking_prompt}],
451
+ # stream=True,
452
+ # provider=g4f.Provider.Airforce
453
+ # )
454
+ # break
455
+
456
+ # Продолжаем обработку без таймаута
457
+ if received_first_chunk:
458
+ for chunk in response:
459
+ if chunk and isinstance(chunk, str):
460
+ current_block += chunk
461
+
462
+ # Исправляем неправильно закрытые теги
463
+ # ... существующий код ...
464
+ current_block = (current_block
465
+ .replace("[/THINKING_STEP\n", "[/THINKING_STEP]\n") # Исправляем закрывающий тег THINKING_STEP
466
+ .replace("[/THINKING_STEP", "[/THINKING_STEP]\n") # Исправляем закрывающий тег THINKING_STEP
467
+ # .replace("[/THINKING_STEP]", "[/THINKING_STEP]\n") # Исправляем закрывающий тег THINKING_STEP с учетом закрывающей скобки
468
+
469
+ .replace("[/FINAL_ANSWER\n", "[/FINAL_ANSWER]\n") # Исправляем закрывающий тег FINAL_ANSWER
470
+ .replace("[/FINAL_ANSWER]", "[/FINAL_ANSWER]\n") # Исправляем закрывающий тег FINAL_ANSWER с учетом закрывающей скобки
471
+ .replace("\n[/THINKING_STEP", "\n[/THINKING_STEP]") # Исправляем порядок закрывающего тега THINKING_STEP
472
+ .replace("\n[/FINAL_ANSWER", "\n[/FINAL_ANSWER]") # Исправляем порядок закрывающего тега FINAL_ANSWER
473
+ .replace("]]]]]]", "") # Убираем лишние закрывающие скобки
474
+ .replace("]]", "") # Убираем лишние закрывающие скобки
475
+ .replace("]", "") # Убираем лишние закрывающие скобки
476
+
477
+ )
478
+
479
 
480
+ # Проверяем начало блоков
481
+ if "[THINKING_STEP]" in current_block:
482
+ in_thinking_step = True
483
+ current_block = current_block.replace("[THINKING_STEP]", "")
484
+ if "[THINKING_STEP" in current_block:
485
+ in_thinking_step = True
486
+ current_block = current_block.replace("[THINKING_STEP", "")
487
+
488
+ if "[FINAL_ANSWER]" in current_block:
489
+ in_final_answer = True
490
+ current_block = current_block.replace("[FINAL_ANSWER]", "")
491
+ if "[FINAL_ANSWER" in current_block:
492
+ in_final_answer = True
493
+ current_block = current_block.replace("[FINAL_ANSWER", "")
494
+
495
+ # Проверяем завершение блоков
496
+ if "[/THINKING_STEP]" in current_block and in_thinking_step:
497
+ block_content = current_block[:current_block.find("[/THINKING_STEP]")]
498
+ formatted_block = f'<div class="thinking-step-block">{block_content}</div>'
499
+ partial_message += formatted_block
500
+ current_block = current_block[current_block.find("[/THINKING_STEP]") + len("[/THINKING_STEP]"):]
501
+ in_thinking_step = False
502
+ if "[/THINKING_STEP" in current_block and in_thinking_step:
503
+ block_content = current_block[:current_block.find("[/THINKING_STEP")]
504
+ formatted_block = f'<div class="thinking-step-block">{block_content}</div>'
505
+ partial_message += formatted_block
506
+ current_block = current_block[current_block.find("[/THINKING_STEP") + len("[/THINKING_STEP"):]
507
+ in_thinking_step = False
508
+
509
+ elif "[/FINAL_ANSWER]" in current_block and in_final_answer:
510
+ block_content = current_block[:current_block.find("[/FINAL_ANSWER]")]
511
+ formatted_block = f'<div class="final-answer-block">{block_content}</div>'
512
+ partial_message += formatted_block
513
+ current_block = current_block[current_block.find("[/FINAL_ANSWER") + len("[/FINAL_ANSWER]"):]
514
+ in_final_answer = False
515
+ elif "[/FINAL_ANSWER" in current_block and in_final_answer:
516
+ block_content = current_block[:current_block.find("[/FINAL_ANSWER")]
517
+ formatted_block = f'<div class="final-answer-block">{block_content}</div>'
518
+ partial_message += formatted_block
519
+ current_block = current_block[current_block.find("[/FINAL_ANSWER") + len("[/FINAL_ANSWER"):]
520
+ in_final_answer = False
521
+
522
+ # Убираем лишние пробелы и переносы строк
523
+ display_message = partial_message + current_block.strip()
524
+ history[-1]["content"] = display_message
525
  yield history, *[gr.update(visible=False) for _ in range(6)]
526
+ break
527
+
528
+ retry_count += 1
529
+ if retry_count == max_retries:
530
+ error_message = f"""
531
+ <div class="error-animation">
532
+ <div class="error-text">❌ Не удалось получить ответ после {max_retries} попыток.
533
+ Попробуйте использовать обычный режим или повторите запрос позже.</div>
534
+ </div>
535
+ """
536
+ history[-1]["content"] = error_message
537
+ yield history, *[gr.update(visible=False) for _ in range(6)]
538
+ return
539
+
540
+ except Exception as e:
541
+ retry_count += 1
542
+ if retry_count == max_retries:
543
+ error_message = f"""
544
+ <div class="error-animation">
545
+ <div class="error-text">❌ Ошибка при анализе: {str(e)}</div>
546
+ </div>
547
+ """
548
+ history[-1]["content"] = error_message
549
+ yield history, *[gr.update(visible=False) for _ in range(6)]
550
+ return
551
 
 
 
 
 
 
 
 
 
552
  else:
553
  # Обычный режим работы
554
  if direct_mode:
555
  # Прямая отправка в нейронку для генерации изображения
556
  image_url = generate_image(message)
557
  if not image_url.startswith("Ошибка"):
558
+ history[-1]["content"] = f"![Generated Image]({image_url})"
 
559
  else:
560
  history[-1]["content"] = f"❌ {image_url}"
561
  yield history, *[gr.update(visible=False) for _ in range(6)]
 
577
  if file_content:
578
  message = f"Файл содержит:\n```\n{file_content}\n```\n\n{message}"
579
 
580
+ # ормируем историю сообщений
581
  for msg in history[:-2]:
582
  messages.append({"role": msg["role"], "content": msg["content"]})
583
  messages.append({"role": "user", "content": str(message)})
 
602
  end_idx = partial_message.find("[/GENERATE_IMAGE]")
603
  image_prompt = partial_message[start_idx:end_idx].strip()
604
 
605
+ # Показываем статус генерации
606
  history[-1]["content"] = """
607
+ <div class="generating-animation">
608
+ <div class="generating-text">Генерация изображения...</div>
609
+ </div>
610
+ """
611
  yield history, *[gr.update(visible=False) for _ in range(6)]
612
 
613
  # Генерируем изображение
614
  image_url = generate_image(image_prompt)
615
 
616
  if not image_url.startswith("Ошибка"):
617
+ # Анализируем изображение
618
+ # image_analysis = process_image(image_url)
619
  explanation_text = partial_message[end_idx + len("[/GENERATE_IMAGE]"):].strip()
620
+ partial_message = f"![Generated Image]({image_url})\n\n{explanation_text}"
621
  else:
622
  partial_message = f"❌ {image_url}"
623
 
 
631
  if code_end != -1:
632
  code_block = partial_message[code_start:code_end].strip()
633
 
634
+ # В конце убирае курсор и сбрасываем файл
635
  history[-1]["content"] = partial_message
636
+ yield (
637
+ history,
638
+ *[gr.update(visible=True if code_block else False) for _ in range(5)],
639
+ gr.update(value=None) # Сбрасываем файл после ответа
640
+ )
641
 
642
  except Exception as e:
643
  print(f"Error: {e}")
 
651
  gr.update(visible=True),
652
  "",
653
  gr.update(visible=False),
654
+ gr.update(value=None) # Сбрасываем файл в случае ошибки
655
  )
656
 
657
  def analyze_code(code):
 
681
  return [{"role": "assistant", "content": f"❌ Ошибка при анализе: {str(e)}"}]
682
 
683
  def create_interface():
684
+ # Обновляем тему на темую
685
  theme = gr.themes.Soft(
686
  primary_hue="slate",
687
  secondary_hue="gray",
 
696
  input_background_fill="#2d2d2d",
697
  )
698
 
699
+ # Обновляем CSS стили для управления цветом кода
700
  css = """
701
  .gradio-container {
702
  background-color: #1a1a1a !important;
 
718
  position: relative;
719
  transition: all 0.3s ease;
720
  }
721
+ /* Добавляем стиль ля блоков кода */
722
  .message.bot pre {
723
  background-color: #1a1a1a !important;
724
  border-radius: 8px;
 
950
  margin-bottom: 10px;
951
  font-style: italic;
952
  }
953
+
954
+ .error-animation {
955
+ position: relative;
956
+ width: 100%;
957
+ min-height: 80px;
958
+ background: linear-gradient(45deg, #2d1a1a, #2d2d2d);
959
+ border-radius: 15px;
960
+ overflow: hidden;
961
+ display: flex;
962
+ align-items: center;
963
+ justify-content: center;
964
+ border-left: 4px solid #e24a4a;
965
+ padding: 15px;
966
+ margin: 10px 0;
967
+ }
968
+
969
+ .error-text {
970
+ color: #ff9999;
971
+ font-size: 16px;
972
+ z-index: 2;
973
+ text-align: center;
974
+ }
975
+
976
+ .thinking-step-block {
977
+ background: linear-gradient(45deg, #1a1a1a, #2d2d2d);
978
+ border-left: 4px solid #4a90e2;
979
+ margin: 15px 0;
980
+ padding: 15px;
981
+ border-radius: 8px;
982
+ animation: fadeIn 0.5s ease-in-out;
983
+ }
984
+
985
+ .final-answer-block {
986
+ background: linear-gradient(45deg, #1a2a3a, #2d3d4d);
987
+ border-left: 4px solid #50c878;
988
+ margin: 20px 0;
989
+ padding: 20px;
990
+ border-radius: 8px;
991
+ font-weight: bold;
992
+ animation: slideIn 0.5s ease-in-out;
993
+ }
994
+
995
+ @keyframes fadeIn {
996
+ from {
997
+ opacity: 0;
998
+ transform: translateY(10px);
999
+ }
1000
+ to {
1001
+ opacity: 1;
1002
+ transform: translateY(0);
1003
+ }
1004
+ }
1005
+
1006
+ @keyframes slideIn {
1007
+ from {
1008
+ opacity: 0;
1009
+ transform: translateX(-10px);
1010
+ }
1011
+ to {
1012
+ opacity: 1;
1013
+ transform: translateX(0);
1014
+ }
1015
+ }
1016
  """
1017
 
1018
  # Добавте этот скрипт в create_interface()
 
1036
  render_markdown=True
1037
  )
1038
 
1039
+ # Добавляем компоненты для вывода
1040
  output_text = gr.Textbox(
1041
  label="Вывод",
1042
  interactive=False,
 
1078
 
1079
  # Добавляем слайдер глубины размышления (изначально скрытый)
1080
  thinking_depth = gr.Slider(
1081
+ minimum=2.0, # Минимум 3 шага
1082
+ maximum=25.0,
1083
+ value=3.0,
1084
+ step=1.0, # Шаг целочисленный
1085
+ label="Глубина размышления (количество шагов анализа)",
1086
  visible=False
1087
  )
1088
 
1089
  direct_mode = gr.Checkbox(
1090
+ label="Прямая нерация (без обрботки прмпта)",
1091
  value=False
1092
  )
1093
  file_output = gr.File(label="Загрузить файл")
 
1199
 
1200
  if __name__ == "__main__":
1201
  demo = create_interface()
1202
+
1203
+
1204
+ # Запускем мониторинг изменений в тдельном потоке
1205
+
1206
 
1207
+ demo.launch(
1208
+ show_api=False,
1209
+ show_error=True,
1210
+ favicon_path=None,
1211
+ auth=None,
1212
+ # quiet=True, # Добавим этот параметр
1213
+
1214
+
1215
+ )