import g4f import gradio as gr import tempfile import os from pathlib import Path from g4f.client import Client from PIL import Image import io import requests import numpy as np from ultralytics import YOLO import subprocess import sys import time from typing import Dict, Any, Optional import easyocr from web_engine import search_info, get_page_text # Импортируем функции из web_engine.py AVAILABLE_MODELS = { # "GPT-4": "gpt-4", "O3 (NEW)": "openai", } SYSTEM_PROMPT = """ 1. Всегда используйте кодировку UTF-8 2. Используйте обработку ошибок 3. Если пользователь отправляет изображение или пишет что-то на подобие 'посмотри на изображение': - Автоматически проанализируйте изображение - Опишите что вы видите на русском языке - Тебе дается текстовая информация, которая может быть полезна для анализа 4. Если пользователь просит найти информацию, например, "найди что-то про Адольфа Гитлера": - Ответь с текстом [SEARCH: {prompt}] - Затем используй полученную информацию для ответа на вопрос 4.1 Если ты не знаешь информации которая пользователь запрашивает то напиши: [SEARCH: {PROMPT}] 5. Если пользователь просит нарисовать или сгенерировать изображение: - Начните ответ с [GENERATE_IMAGE] - Напишите детальный промпт на английском языке - Завершите промпт строкой [/GENERATE_IMAGE] - Продолжите обычный ответ на русском языке 6. В режиме размышления: - Используйте [THINKING_STEP] для обозначения шага размышления - Используйте [FINAL_ANSWER] для итогового ответа - Старайтесь подробно описывать ход мыслей """ def test_code(code: str, file_type: str = ".py") -> Dict[str, Any]: """Тестирование кода в безопасной среде""" start_time = time.time() result = { "success": False, "output": "", "error": "", "execution_time": 0 } try: code = "# -*- coding: utf-8 -*-\n" + code with tempfile.NamedTemporaryFile(suffix=file_type, mode='w', encoding='utf-8', delete=False) as tmp: tmp.write(code) tmp_path = tmp.name process = subprocess.Popen( [sys.executable, tmp_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='utf-8' ) try: stdout, stderr = process.communicate(timeout=10) result["success"] = process.returncode == 0 result["output"] = stdout result["error"] = stderr except subprocess.TimeoutExpired: process.kill() result["error"] = "Превышено время выполнения (10 сек)" finally: os.unlink(tmp_path) except Exception as e: result["error"] = str(e) result["execution_time"] = time.time() - start_time return result def process_file(file): """Обработка загруженного файла""" if not file: return None try: # print() # Получаем расширение файла file_extension = file.name.lower().split('.')[-1] if hasattr(file, 'name') else '' print(file_extension) # Список поддерживаемых форматов изображений image_extensions = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'} # Если это изображение if file_extension in image_extensions: try: # Открываем изображение if isinstance(file, str): image = Image.open(file) else: image = Image.open(io.BytesIO(file.read())) # Анализируем изображение return process_image(image) except Exception as e: return f"[Ошибка обработки изображения: {str(e)}]" # Если это текстовый файл if isinstance(file, str): with open(file, 'r', encoding='utf-8') as f: return f.read() else: return file.read().decode('utf-8') except UnicodeDecodeError: return "[Бинарный файл]" except Exception as e: return f"[Ошибка чтения файла: {str(e)}]" def process_audio(file_path: str, operation: str) -> Optional[str]: """Обработка аудио файлов""" try: from pydub import AudioSegment audio = AudioSegment.from_file(file_path) if "громкость" in operation.lower(): audio = audio + 10 output_path = os.path.join(tempfile.gettempdir(), f"processed_{int(time.time())}.mp3") audio.export(output_path, format="mp3") return output_path except Exception as e: return f"Ошибка обработки аудио: {str(e)}" def generate_image(prompt: str) -> str: """Генерация изображения через g4f""" try: client = Client() response = client.images.generate( model="flux-pro", prompt=prompt, response_format="url", provider='PollinationsAI' ) image_url = response.data[0].url # Проверяем доступность изображения timeout = 30 # Максимальное время ожидания в секундах interval = 0.1 # Интервал между проверками в секундах elapsed_time = 0 while elapsed_time < timeout: # Проверяем доступность изображения head_response = requests.head(image_url) if head_response.status_code == 200: # Дополнительная проверка на наличие изображения get_response = requests.get(image_url) if get_response.status_code == 200: return image_url # Изображение доступно else: return "❌ Ошибка: изображение недоступно." time.sleep(interval) elapsed_time += interval return "❌ Ошибка: время ожидания изображения истекло." # Время ожидания истекло except Exception as e: return f"Ошибка при генерации изобраения: {str(e)}" def process_image(image_input) -> str: """Обработка изображения через провайдера Blackbox.""" try: # Инициализация клиента GPT с провайдером Blackbox client = Client() # Определяем, как было передано изображение (URL или объект PIL.Image) if isinstance(image_input, str): # Если передан URL изображения response = requests.get(image_input, stream=True) if response.status_code == 200: image = Image.open(response.raw) # Преобразуем поток в объект PIL.Image else: return "❌ Ошибка загрузки изображения по URL." elif isinstance(image_input, Image.Image): # Если передано изображение PIL image = image_input else: return "❌ Неподдерживаемый формат изображения." # Конвертируем изображение в режим RGB, если оно в RGBA или другом формате if image.mode != 'RGB': image = image.convert('RGB') # Сохраняем изображение во временный файл with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: image.save(tmp.name, format="JPEG") # Сохраняем изображение как JPEG image_file = open(tmp.name, "rb") # Открываем файл для передачи в запрос # Запрос на анализ изображения через Blackbox response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Опишите, что изображено на этом изображении."}], image=image_file, provider="Blackbox" ) print("MADEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE") print(response) # Закрываем временный файл image_file.close() # Возвращаем результат анализа return response except Exception as e: return f"❌ Ошибка при обработке изображения: {str(e)}" finally: # Удаляем временный файл после использования if "tmp" in locals(): Path(tmp.name).unlink(missing_ok=True) def chat_response(message, history, model_name, direct_mode, thinking_depth=1.0, uploaded_file=None): messages = [{"role": "system", "content": SYSTEM_PROMPT}] partial_message = "" # Инициализация переменной history = history or [] history.append({"role": "user", "content": message}) history.append({"role": "assistant", "content": ""}) try: # Обычный поток обработки сообщений for msg in history[:-2]: messages.append({"role": msg["role"], "content": msg["content"]}) messages.append({"role": "user", "content": str(message)}) partial_message = "" response = None # Инициализация переменной response response = g4f.ChatCompletion.create( model=AVAILABLE_MODELS.get(model_name, "O3"), messages=messages, stream=False, provider="PollinationsAI" ) if response and isinstance(response, str): partial_message += response history[-1]["content"] = f"""
{partial_message}
""" yield history, *[gr.update(visible=False) for _ in range(6)] # Если в ответе от модели есть [SEARCH:], выполняем поиск if "[SEARCH:" in partial_message: history[-1]["content"] = """
🔍 Выполняется поиск...
""" yield history, *[gr.update(visible=False) for _ in range(6)] prompt = partial_message.split("[SEARCH:")[1].split("]")[0].strip() # Выполняем поиск results = search_info(prompt) if not results: history[-1]["content"] = "Не удалось найти информацию." yield history, *[gr.update(visible=False) for _ in range(6)] return info_text = "" for link in results: info_text += f"Ссылка: {link}\n" page_text = get_page_text(link) info_text += f"Текст: {page_text[:500]}...\n\n" search_response_prompt = f"""Вот информация по запросу "{prompt}": {info_text} На основе этой информации сформируй краткий и понятный ответ на русском языке. """ search_response = g4f.ChatCompletion.create( model="gpt-4", messages=[{"role": "user", "content": search_response_prompt}], stream=False, provider="Mhystical" ) final_response = search_response if isinstance(search_response, str) else "Не удалось получить ответ." final_response = final_response.replace(f"[SEARCH: {prompt}]", "").strip() history.append({"role": "assistant", "content": final_response}) yield history, *[gr.update(visible=False) for _ in range(6)] if response and isinstance(response, str): steps = response.split("[THINKING_STEP]") final_answer = "" for i, step in enumerate(steps): if "[FINAL_ANSWER]" in step: final_answer = step.split("[FINAL_ANSWER]")[1].strip() step = step.split("[FINAL_ANSWER]")[0] step_html = f"""
Шаг {i + 1}: {step.strip()}
""" history[-1]["content"] += step_html yield history, gr.update(visible=False) # Добавляем финальный блок с заключением final_html = f"""
Ответ: {final_answer}
""" history[-1]["content"] += final_html yield history, gr.update(visible=True) return history[-1]["content"] = partial_message.strip() yield history, *[gr.update(visible=True) for _ in range(6)] except Exception as e: history[-1]["content"] = f"❌ Произошла ошибка: {str(e)}" yield ( history, gr.update(visible=False), gr.update(visible=True, value=str(e)), gr.update(visible=True), "", gr.update(visible=False), gr.update(value=None) ) if direct_mode: image_url = generate_image(message) if not image_url.startswith("Ошибка"): history[-1]["content"] = f"![Generated Image]({image_url})" else: history[-1]["content"] = f"❌ {image_url}" yield history, *[gr.update(visible=False) for _ in range(6)] return yield ( history, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), "", gr.update(visible=False), gr.update(visible=False) ) if uploaded_file: file_content = process_file(uploaded_file) if file_content: message = f"Файл содержит:\n```\n{file_content}\n```\n\n{message}" for msg in history[:-2]: messages.append({"role": msg["role"], "content": msg["content"]}) messages.append({"role": "user", "content": str(message)}) partial_message = "" code_block = None # response = g4f.ChatCompletion.create( # model=AVAILABLE_MODELS.get(model_name, "O3"), # messages=messages, # stream=False, # provider="PollinationsAI" # ) if response and isinstance(response, str): partial_message += response if "[GENERATE_IMAGE]" in partial_message: history[-1]["content"] = """
Генерация изображения...
""" if "[GENERATE_IMAGE]" in partial_message and "[/GENERATE_IMAGE]" in partial_message: start_idx = partial_message.find("[GENERATE_IMAGE]") + len("[GENERATE_IMAGE]") end_idx = partial_message.find("[/GENERATE_IMAGE]") image_prompt = partial_message[start_idx:end_idx].strip() yield history, *[gr.update(visible=False) for _ in range(6)] image_url = generate_image(image_prompt) if not image_url.startswith("Ошибка"): explanation_text = partial_message[end_idx + len("[/GENERATE_IMAGE]"):].strip() partial_message = f"![Generated Image]({image_url})\n\n{explanation_text}" else: partial_message = f"❌ {image_url}" history[-1]["content"] = partial_message + "|" yield history, *[gr.update(visible=False) for _ in range(6)] if "```" in partial_message: code_start = partial_message.rfind("```") + 3 code_end = partial_message.find("```", code_start) if code_end != -1: code_block = partial_message[code_start:code_end].strip() history[-1]["content"] = partial_message yield ( history, *[gr.update(visible=True if code_block else False) for _ in range(5)], gr.update(value=None) ) def analyze_code(code): """Анализ кода и получение объяснения""" if not code: return [{"role": "assistant", "content": "❌ Нет кода для анализа"}] prompt = f"""Проанализируй этот код и объясни: 1. Что он делает 2. Возможные проблемы или ошибки 3. Как можно улучшить 4. Примеры использования Код: ``` {code} ```""" try: response = g4f.ChatCompletion.create( model="gpt-4o", messages=[{"role": "user", "content": prompt}], stream=False ) return [{"role": "assistant", "content": response if isinstance(response, str) else "Не удалось получить анализ"}] except Exception as e: return [{"role": "assistant", "content": f"❌ Ошибка при анализе: {str(e)}"}] def create_interface(): # Обновляем тему на темую theme = gr.themes.Soft( primary_hue="slate", secondary_hue="gray", ).set( body_background_fill="#1a1a1a", body_text_color="#ffffff", button_primary_background_fill="#2d2d2d", button_primary_background_fill_hover="#3d3d3d", button_primary_text_color="white", block_label_background_fill="#2d2d2d", block_title_text_color="#ffffff", input_background_fill="#2d2d2d", ) # Обновляем CSS стили для управления цветом кода css = """ .gradio-container { background-color: #1a1a1a !important; } .chatbot { background-color: #2d2d2d !important; border-radius: 10px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .text-fade-in { opacity: 0; /* Исходная прозрачность */ transform: translateY(10px); /* Исходное смещение */ animation: fadeInText 1s ease-in-out forwards; /* Анимация при показе */ } @keyframes fadeInText { 0% { opacity: 0; transform: translateY(10px); /* Немного ниже */ } 100% { opacity: 1; transform: translateY(0); /* Возвращается на место */ } } .message.user { background-color: #3d3d3d !important; color: white !important; border-radius: 15px; } .search-animation { position: relative; width: 100%; min-height: 80px; background: linear-gradient(45deg, #2d2d2d, #3d3d3d); border-radius: 15px; overflow: hidden; display: flex; align-items: center; justify-content: center; } .search-text { color: white; font-size: 18px; z-index: 2; animation: search-pulse 1.5s infinite; } .search-animation::before { content: ''; position: absolute; width: 200%; height: 200%; top: -50%; left: -50%; background: radial-gradient(2px 2px at 20% 30%, rgba(255,255,255,0.3), rgba(0,0,0,0)), radial-gradient(2px 2px at 40% 70%, rgba(255,255,255,0.3), rgba(0,0,0,0)); background-repeat: repeat; animation: search-rotate 6s linear infinite; } @keyframes search-pulse { 0% { opacity: 0.6; } 50% { opacity: 1; } 100% { opacity: 0.6; } } @keyframes search-rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .message.bot { background-color: #2d2d2d !important; color: white !important; border-radius: 15px; position: relative; transition: all 0.3s ease; } /* Добавляем стиль ля блоков кода */ .message.bot pre { background-color: #1a1a1a !important; border-radius: 8px; padding: 10px; } .message.bot.typing::after { content: '|'; animation: cursor 1s infinite; } @keyframes cursor { 0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0; } } .message.bot:last-child { animation: fadeIn 0.3s ease-in-out; } /* Убираем дублирующиеся стили курсора */ .message.bot:last-child:not(:empty)::after { content: ''; } /* Анимация появления текста */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes cursor { 0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0; } } .footer { display: none !important; } .generating-animation { position: relative; width: 100%; height: 120px; background: linear-gradient(45deg, #1a1a1a, #2d2d2d); border-radius: 15px; overflow: hidden; display: flex; align-items: center; justify-content: center; } .generating-text { color: white; font-size: 16px; z-index: 2; animation: pulse 1.5s infinite; } .generating-animation::before { content: ''; position: absolute; width: 200%; height: 200%; top: -50%; left: -50%; background: radial-gradient(2px 2px at 20% 30%, rgba(255,255,255,0.8), rgba(0,0,0,0)), radial-gradient(2px 2px at 40% 70%, rgba(255,255,255,0.8), rgba(0,0,0,0)), radial-gradient(2px 2px at 50% 40%, rgba(255,255,255,0.8), rgba(0,0,0,0)), radial-gradient(2px 2px at 60% 60%, rgba(255,255,255,0.8), rgba(0,0,0,0)); background-repeat: repeat; animation: rotate 8s linear infinite; } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes pulse { 0% { opacity: 0.6; } 50% { opacity: 1; } 100% { opacity: 0.6; } } .submit-btn { min-width: 100px !important; cursor: pointer !important; background-color: #4a4a4a !important; transition: all 0.2s ease; } .submit-btn:hover { background-color: #5a5a5a !important; } .input-row { gap: 8px; padding: 8px; background: #2d2d2d; border-radius: 8px; margin-top: 8px; } .footer { display: none !important; } /* Добавляем анимацию для просмотра изображения */ .image-analysis-animation { position: relative; width: 100%; min-height: 100px; background: linear-gradient(45deg, #2d2d2d, #3d3d3d); border-radius: 15px; overflow: hidden; display: flex; align-items: center; justify-content: center; margin: 10px 0; } .analysis-text { color: white; font-size: 16px; z-index: 2; text-align: center; animation: pulse 1.5s infinite; } .image-analysis-animation::before { content: ''; position: absolute; width: 100%; height: 100%; background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%); animation: scanning 2s linear infinite; } @keyframes scanning { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } .thinking-animation { position: relative; width: 100%; min-height: 100px; background: linear-gradient(45deg, #1a1a1a, #2d2d2d); border-radius: 15px; overflow: hidden; margin: 10px 0; padding: 20px; border-left: 4px solid #4a90e2; transition: all 0.3s ease; } .thinking-animation:hover { background: linear-gradient(45deg, #202020, #333333); } .thinking-step { color: #b0b0b0; font-style: italic; margin-bottom: 10px; padding-left: 20px; border-left: 2px solid #4a90e2; opacity: 0; transform: translateY(10px); animation: fadeInStep 0.5s ease-in-out forwards; } .thinking-conclusion { color: white; font-weight: bold; margin-top: 15px; padding: 10px; background: rgba(74, 144, 226, 0.1); border-radius: 8px; border-left: 4px solid #4a90e2; } @keyframes fadeInStep { to { opacity: 1; transform: translateY(0); } } .typing-cursor { display: inline-block; width: 2px; height: 15px; background: #4a90e2; margin-left: 5px; animation: blink 1s infinite; } @keyframes blink { 50% { opacity: 0; } } /* Стили для слайдера глубины размышления */ .thinking-depth-slider { margin-top: 10px; padding: 8px; background: rgba(74, 144, 226, 0.1); border-radius: 8px; border-left: 4px solid #4a90e2; } /* Индикатор глубины размышления в сообщении */ .thinking-depth-indicator { font-size: 0.9em; color: #4a90e2; margin-bottom: 10px; font-style: italic; } .error-animation { position: relative; width: 100%; min-height: 80px; background: linear-gradient(45deg, #2d1a1a, #2d2d2d); border-radius: 15px; overflow: hidden; display: flex; align-items: center; justify-content: center; border-left: 4px solid #e24a4a; padding: 15px; margin: 10px 0; } .error-text { color: #ff9999; font-size: 16px; z-index: 2; text-align: center; } .thinking-step-block { background: linear-gradient(45deg, #1a1a1a, #2d2d2d); border-left: 4px solid #4a90e2; margin: 15px 0; padding: 15px; border-radius: 8px; animation: fadeIn 0.5s ease-in-out; } .final-answer-block { background: linear-gradient(45deg, #1a2a3a, #2d3d4d); border-left: 4px solid #50c878; margin: 20px 0; padding: 20px; border-radius: 8px; font-weight: bold; animation: slideIn 0.5s ease-in-out; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideIn { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: translateX(0); } } .thinking-animation { position: relative; width: 100%; min-height: 100px; background: linear-gradient(45deg, #1a1a1a, #2d2d2d); border-radius: 15px; overflow: hidden; margin: 10px 0; padding: 20px; border-left: 4px solid #4a90e2; transition: all 0.3s ease; } .thinking-step { color: #b0b0b0; font-style: italic; margin-bottom: 10px; padding-left: 20px; border-left: 2px solid #4a90e2; opacity: 0; transform: translateY(10px); animation: fadeInStep 0.5s ease-in-out forwards; } .thinking-conclusion { color: white; font-weight: bold; margin-top: 15px; padding: 10px; background: rgba(74, 144, 226, 0.1); border-radius: 8px; border-left: 4px solid #4a90e2; } @keyframes fadeInStep { to { opacity: 1; transform: translateY(0); } } """ # Добавте этот скрипт в create_interface() with gr.Blocks(theme=theme, css=css) as demo: # gr.Markdown("# 💬 AI Chat Assistant") current_code = gr.State("") with gr.Row(): with gr.Column(scale=4): chatbot = gr.Chatbot( height="600px", show_label=False, container=True, show_copy_button=True, elem_classes="chatbot", type="messages", render_markdown=True ) with gr.Row(elem_classes="input-row"): msg = gr.Textbox( placeholder="Спросите что-нибудь...", container=False, scale=4, show_label=False, lines=1, # Явно указываем одну строку elem_classes="input-textbox" ) submit = gr.Button( "Отправить", variant="primary", scale=1, elem_classes="submit-btn" ) # clear = gr.Button("Очистить", scale=1) with gr.Column(scale=1, visible=True) as sidebar: model = gr.Dropdown( choices=list(AVAILABLE_MODELS.keys()), value="O3 (NEW)", label="Модель" ) # Добавляем слайдер глубины размышления (изначально скрытый) thinking_depth = gr.Slider( minimum=2.0, # Минимум 3 шага maximum=25.0, value=3.0, step=1.0, # Шаг целочисленный label="Глубина размышления (количество шагов анализа)", visible=False ) direct_mode = gr.Checkbox( label="Прямая нерация (без обрботки прмпта)", value=False ) file_output = gr.File(label="Загрузить файл") # Добавляем примеры ипользования в виде кнопок # Добавляем кнопки анализа и запуска кода analyze_btn = gr.Button( "Анализировать", visible=False, elem_classes="analyze-btn" ) run_btn = gr.Button( "▶️ Запустить код", visible=False, elem_classes="run-btn" ) # Обработчики событий msg.submit( fn=chat_response, inputs=[msg, chatbot, model, direct_mode, thinking_depth, file_output], outputs=[chatbot, current_code], api_name=None ) submit.click( fn=chat_response, inputs=[msg, chatbot, model, direct_mode, thinking_depth, file_output], outputs=[chatbot, current_code], api_name=None ) analyze_btn.click( fn=analyze_code, inputs=[current_code], outputs=[chatbot] ) # clear.click( # fn=lambda: (None, ""), # outputs=[chatbot, current_code] # ) # Добавляем обработчик изменения модели def update_thinking_depth_visibility(model_name): return gr.update(visible=model_name == "GPT-4o THINK") model.change( fn=update_thinking_depth_visibility, inputs=[model], outputs=[thinking_depth] ) return demo if __name__ == "__main__": demo = create_interface() # Запускем мониторинг изменений в тдельном потоке demo.launch( show_api=False, show_error=True, favicon_path=None, auth=None, # quiet=True, # Добавим этот параметр )