Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import os | |
| import io | |
| from PIL import Image | |
| import random | |
| from datetime import datetime, timedelta | |
| import hashlib | |
| import threading | |
| import tempfile | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.responses import FileResponse | |
| from fastapi.staticfiles import StaticFiles | |
| # Путь к временному кэшу | |
| CACHE_DIR = os.path.join(tempfile.gettempdir(), "image_cache") | |
| if not os.path.exists(CACHE_DIR): | |
| os.makedirs(CACHE_DIR) | |
| # Время жизни кэша в минутах | |
| CACHE_DURATION = 45 | |
| # Функция для очистки кэша | |
| def clear_cache(): | |
| current_time = datetime.now() | |
| for filename in os.listdir(CACHE_DIR): | |
| file_path = os.path.join(CACHE_DIR, filename) | |
| if os.path.isfile(file_path): | |
| file_time = datetime.fromtimestamp(os.path.getmtime(file_path)) | |
| if current_time - file_time > timedelta(minutes=CACHE_DURATION): | |
| os.remove(file_path) | |
| # Запуск очистки кэша каждые 45 минут | |
| def start_cache_cleanup(): | |
| while True: | |
| clear_cache() | |
| threading.Event().wait(CACHE_DURATION * 60) | |
| # Запуск потока для очистки кэша | |
| cleanup_thread = threading.Thread(target=start_cache_cleanup, daemon=True) | |
| cleanup_thread.start() | |
| # Функция для сохранения изображения в кэш и возврата пути к нему | |
| def save_image_to_cache(image): | |
| image_hash = hashlib.md5(image.tobytes()).hexdigest() | |
| image_path = os.path.join(CACHE_DIR, f"{image_hash}.jpg") | |
| if not os.path.exists(image_path): | |
| image.save(image_path, format="JPEG") | |
| return image_path | |
| # Функция для сжатия изображения | |
| def compress_image(image, max_size=(800, 800)): | |
| image.thumbnail(max_size, Image.LANCZOS) | |
| return image | |
| # Функция для получения прямой ссылки на изображение в кэше | |
| def get_image_url(image_path, server_url): | |
| return f"{server_url}/image/{os.path.basename(image_path)}" | |
| # Функция для отправки запроса в OpenAI с изображением и получения ответа | |
| def ask_openai_with_image(messages, instruction, image, server_url): | |
| if not instruction and image is None: | |
| emj = random.choice(emojis) | |
| raise gr.Error(f"{emj} Заполните, пожалуйста, хотя бы одно поле") | |
| new_message = { | |
| "role": "user", | |
| "content": [ | |
| { | |
| "type": "text", | |
| "text": instruction if instruction else "", | |
| } | |
| ] | |
| } | |
| if image is not None: | |
| # Сжимаем изображение | |
| compressed_image = compress_image(image) | |
| # Сохраняем изображение в кэш | |
| image_path = save_image_to_cache(compressed_image) | |
| # Получаем прямую ссылку на изображение | |
| image_url = get_image_url(image_path, server_url) | |
| new_message["content"].append({ | |
| "type": "image_url", | |
| "image_url": { | |
| "url": image_url, | |
| "detail": "high", | |
| }, | |
| }) | |
| messages.append(new_message) | |
| payload = { | |
| "model": "learnlm-1.5-pro-experimental", | |
| "messages": messages, | |
| "max_tokens": 4095, | |
| } | |
| # Заголовки для запроса | |
| headers = { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': f'Bearer {api_key}' | |
| } | |
| # URL для запроса к API OpenAI | |
| url = BASE_URL | |
| # Отправляем запрос в OpenAI с таймаутом 225 секунд | |
| try: | |
| response = requests.post(url, headers=headers, json=payload, timeout=225) | |
| except requests.Timeout: | |
| messages.append({ | |
| "role": "assistant", | |
| "content": "Ошибка: Запрос к ИИ превысил максимальное время ожидания. Повторите попытку позже." | |
| }) | |
| return messages, "Ошибка: Запрос к ИИ превысил максимальное время ожидания. Повторите попытку позже." | |
| except requests.RequestException as e: | |
| messages.append({ | |
| "role": "assistant", | |
| "content": f"Ошибка при отправке запроса, повторите попытку позже." | |
| }) | |
| return messages, f"Ошибка при отправке запроса, повторите попытку позже." | |
| # Проверяем ответ и возвращаем результат | |
| if response.status_code == 200: | |
| response_json = response.json() | |
| try: | |
| # Пытаемся извлечь текст из ответа | |
| otvet = response_json["choices"][0]["message"]["content"] | |
| messages.append({ | |
| "role": "assistant", | |
| "content": otvet | |
| }) | |
| return messages, messages | |
| except Exception as e: | |
| # Если есть ошибка в структуре JSON, выводим ее | |
| messages.append({ | |
| "role": "assistant", | |
| "content": f"Ошибка обработки ответа: {e}" | |
| }) | |
| return messages, f"Ошибка обработки ответа: {e}" | |
| else: | |
| # Если произошла ошибка, возвращаем сообщение об ошибке | |
| messages.append({ | |
| "role": "assistant", | |
| "content": f"Ошибка: {response.status_code} - {response.text}" | |
| }) | |
| return messages, f"Ошибка: {response.status_code} - {response.text}" | |
| emojis = ['😊', '🤗', '🥺', '😅', '🤭', '😔', '✨', '😜', '🙏'] | |
| api_key = os.getenv("OPENAI_API_KEY") | |
| BASE_URL = os.getenv("BASE_URL") | |
| SERVER_URL = os.getenv("SERVER_URL", "http://localhost:7860") # Убедитесь, что этот URL правильный | |
| # Текст начального сообщения | |
| start = "Приветствую тебя! 🌟 Ты - \"Помогатор 1.5\". Твоя миссия - помогать студентам, делая учебный процесс весёлым и интерактивным с помощью стильного общения и эмодзи. 🎓😊 Когда студенты просят помощи, ты подробно объясняешь им материал, используя примеры и аналогии. Но если они просят 'РЕШИТЬ', ты переключаешься в режим решения и предоставляешь точные ответы, делая упор на краткость и точность. 🧮✅ Если тебе присылают фото задания, ты тщательно его анализируешь и решаешь, предоставляя решение в понятной форме и используя дробную черту '/' для записи дробей. 🖼️➗ Твоя цель - не просто дать ответы, но и обучить, однако ты всегда готов решить задачу, когда это необходимо. Приступим? 🚀🌈" | |
| # Начальные сообщения | |
| initial_messages = [ | |
| { | |
| "role": "system", | |
| "content": start, | |
| } | |
| ] | |
| # Создаем интерфейс с помощью Gradio | |
| with gr.Blocks() as demo: | |
| with gr.Row(): | |
| with gr.Column(): | |
| chatbot = gr.Chatbot(label="История Сообщений", type='messages') | |
| with gr.Row(): | |
| image_input = gr.Image(label="Фото", type="pil") | |
| instructions = gr.Textbox(label="Сообщение", lines=3, placeholder="Реши...") | |
| submit_button = gr.Button("Отправить") | |
| submit_button.click( | |
| fn=ask_openai_with_image, | |
| inputs=[gr.State(initial_messages), instructions, image_input, gr.Textbox(SERVER_URL, visible=False)], | |
| outputs=[gr.State(initial_messages), chatbot], | |
| concurrency_limit=150, | |
| show_progress=True | |
| ) | |
| # Монтируем маршрут для получения изображений из кэша | |
| app = demo.app | |
| app.mount("/image", StaticFiles(directory=CACHE_DIR), name="image_cache") | |
| # Обработка маршрута для получения изображений из кэша | |
| async def get_image(image_name: str): | |
| image_path = os.path.join(CACHE_DIR, image_name) | |
| if os.path.isfile(image_path): | |
| return FileResponse(image_path) | |
| else: | |
| raise HTTPException(status_code=404, detail="Image not found") | |
| demo.launch() | |