Rooni commited on
Commit
cd3e819
·
verified ·
1 Parent(s): f2abf90

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +184 -20
app.py CHANGED
@@ -12,34 +12,116 @@ from fastapi import FastAPI, HTTPException
12
  from fastapi.responses import FileResponse
13
  from fastapi.staticfiles import StaticFiles
14
 
15
- # ... (остальной код без изменений)
 
 
 
16
 
17
- # Создаем интерфейс с помощью Gradio
18
- with gr.Blocks() as demo:
19
- with gr.Row():
20
- with gr.Column():
21
- chatbot = gr.Chatbot(label="История Сообщений", type='messages') # <- Исправлено
22
- with gr.Row():
23
- image_input = gr.Image(label="Фото", type="pil")
24
- instructions = gr.Textbox(label="Сообщение", lines=3, placeholder="Реши...")
25
- submit_button = gr.Button("Отправить")
26
 
27
- submit_button.click(
28
- fn=ask_openai_with_image,
29
- inputs=[gr.State(initial_messages), instructions, image_input, gr.Textbox(SERVER_URL, visible=False)],
30
- outputs=[gr.State(initial_messages), chatbot],
31
- concurrency_limit=150,
32
- show_progress=True # Добавлено для отображения прогресса
33
- )
 
 
 
 
 
 
 
 
34
 
35
- # ... (остальной код без изменений)
 
 
36
 
 
 
 
 
 
 
 
 
 
37
 
 
 
 
 
 
 
 
 
38
 
39
  # Функция для отправки запроса в OpenAI с изображением и получения ответа
40
  def ask_openai_with_image(messages, instruction, image, server_url):
41
- # ... (код до обработки ответа от OpenAI без изменений)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
  # Проверяем ответ и возвращаем результат
45
  if response.status_code == 200:
@@ -54,4 +136,86 @@ def ask_openai_with_image(messages, instruction, image, server_url):
54
  # Преобразуем сообщения в формат кортежей для Gradio
55
  formatted_messages = format_messages_for_chatbot(messages) # <- Исправлено
56
  return messages, formatted_messages
57
- # ... (остальной код обработки ошибок без изменений)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  from fastapi.responses import FileResponse
13
  from fastapi.staticfiles import StaticFiles
14
 
15
+ # Путь к временному кэшу
16
+ CACHE_DIR = os.path.join(tempfile.gettempdir(), "image_cache")
17
+ if not os.path.exists(CACHE_DIR):
18
+ os.makedirs(CACHE_DIR)
19
 
20
+ # Время жизни кэша в минутах
21
+ CACHE_DURATION = 45
 
 
 
 
 
 
 
22
 
23
+ # Функция для очистки кэша
24
+ def clear_cache():
25
+ current_time = datetime.now()
26
+ for filename in os.listdir(CACHE_DIR):
27
+ file_path = os.path.join(CACHE_DIR, filename)
28
+ if os.path.isfile(file_path):
29
+ file_time = datetime.fromtimestamp(os.path.getmtime(file_path))
30
+ if current_time - file_time > timedelta(minutes=CACHE_DURATION):
31
+ os.remove(file_path)
32
+
33
+ # Запуск очистки кэша каждые 45 минут
34
+ def start_cache_cleanup():
35
+ while True:
36
+ clear_cache()
37
+ threading.Event().wait(CACHE_DURATION * 60)
38
 
39
+ # Запуск потока для очистки кэша
40
+ cleanup_thread = threading.Thread(target=start_cache_cleanup, daemon=True)
41
+ cleanup_thread.start()
42
 
43
+ # Функция для сохранения изображения в кэш и возврата пути к нему
44
+ def save_image_to_cache(image):
45
+ image_hash = hashlib.md5(image.tobytes()).hexdigest()
46
+ image_path = os.path.join(CACHE_DIR, f"{image_hash}.jpg")
47
+
48
+ if not os.path.exists(image_path):
49
+ image.save(image_path, format="JPEG")
50
+
51
+ return image_path
52
 
53
+ # Функция для сжатия изображения
54
+ def compress_image(image, max_size=(800, 800)):
55
+ image.thumbnail(max_size, Image.LANCZOS)
56
+ return image
57
+
58
+ # Функция для получения прямой ссылки на изображение в кэше
59
+ def get_image_url(image_path, server_url):
60
+ return f"{server_url}/image/{os.path.basename(image_path)}"
61
 
62
  # Функция для отправки запроса в OpenAI с изображением и получения ответа
63
  def ask_openai_with_image(messages, instruction, image, server_url):
64
+ if not instruction and image is None:
65
+ emj = random.choice(emojis)
66
+ raise gr.Error(f"{emj} Заполните, пожалуйста, хотя бы одно поле")
67
+
68
+ new_message = {
69
+ "role": "user",
70
+ "content": [
71
+ {
72
+ "type": "text",
73
+ "text": instruction if instruction else "",
74
+ }
75
+ ]
76
+ }
77
+
78
+ if image is not None:
79
+ # Сжимаем изображение
80
+ compressed_image = compress_image(image)
81
+ # Сохраняем изображение в кэш
82
+ image_path = save_image_to_cache(compressed_image)
83
+ # Получаем прямую ссылку на изображение
84
+ image_url = get_image_url(image_path, server_url)
85
+ new_message["content"].append({
86
+ "type": "image_url",
87
+ "image_url": {
88
+ "url": image_url,
89
+ "detail": "high",
90
+ },
91
+ })
92
+
93
+ messages.append(new_message)
94
+
95
+ payload = {
96
+ "model": "learnlm-1.5-pro-experimental",
97
+ "messages": messages,
98
+ "max_tokens": 4095,
99
+ }
100
+
101
+ # Заголовки для запроса
102
+ headers = {
103
+ 'Content-Type': 'application/json',
104
+ 'Authorization': f'Bearer {api_key}'
105
+ }
106
+
107
+ # URL для запроса к API OpenAI
108
+ url = BASE_URL
109
 
110
+ # Отправляем запрос в OpenAI с таймаутом 225 секунд
111
+ try:
112
+ response = requests.post(url, headers=headers, json=payload, timeout=225)
113
+ except requests.Timeout:
114
+ messages.append({
115
+ "role": "assistant",
116
+ "content": "Ошибка: Запрос к ИИ превысил максимальное время ожидания. Повторите попытку позже."
117
+ })
118
+ return messages, "Ошибка: Запрос к ИИ превысил максимальное время ожидания. Повторите попытку позже."
119
+ except requests.RequestException as e:
120
+ messages.append({
121
+ "role": "assistant",
122
+ "content": f"Ошибка при отправке запроса, повторите попытку позже."
123
+ })
124
+ return messages, f"Ошибка при отправке запроса, повторите попытку позже."
125
 
126
  # Проверяем ответ и возвращаем результат
127
  if response.status_code == 200:
 
136
  # Преобразуем сообщения в формат кортежей для Gradio
137
  formatted_messages = format_messages_for_chatbot(messages) # <- Исправлено
138
  return messages, formatted_messages
139
+
140
+ except Exception as e:
141
+ # Если есть ошибка в структуре JSON, выводим ее
142
+ messages.append({
143
+ "role": "assistant",
144
+ "content": f"Ошибка обработки ответа: {e}"
145
+ })
146
+ return messages, f"Ошибка обработки ответа: {e}"
147
+ else:
148
+ # Если произошла ошибка, возвращаем сообщение об ошибке
149
+ messages.append({
150
+ "role": "assistant",
151
+ "content": f"Ошибка: {response.status_code} - {response.text}"
152
+ })
153
+ return messages, f"Ошибка: {response.status_code} - {response.text}"
154
+
155
+ emojis = ['😊', '🤗', '🥺', '😅', '🤭', '😔', '✨', '😜', '🙏']
156
+
157
+ api_key = os.getenv("OPENAI_API_KEY")
158
+ BASE_URL = os.getenv("BASE_URL")
159
+ SERVER_URL = os.getenv("SERVER_URL", "http://localhost:7860") # Убедитесь, что этот URL правильный
160
+
161
+ # Текст начального сообщения
162
+ start = "Приветствую тебя! 🌟 Ты - \"Помогатор 1.5\". Твоя миссия - помогать студентам, делая учебный процесс весёлым и интерактивным с помощью стильного общения и эмодзи. 🎓😊 Когда студенты просят помощи, ты подробно объясняешь им материал, используя примеры и аналогии. Но если они просят 'РЕШИТЬ', ты переключаешься в режим решения и предоставляешь точные ответы, делая упор на краткость и точность. 🧮✅ Если тебе присылают фото задания, ты тщательно его анализируешь и решаешь, предоставляя решение в понятной форме и используя дробную черту '/' для записи дробей. 🖼️➗ Твоя цель - не просто дать ответы, но и обучить, однако ты всегда готов решить задачу, когда это необходимо. Приступим? 🚀🌈"
163
+
164
+ # Функция для преобразования сообщений в формат кортежей
165
+ def format_messages_for_chatbot(messages):
166
+ formatted_messages = []
167
+ for message in messages:
168
+ if message["role"] == "system":
169
+ formatted_messages.append(("Система:", message["content"]))
170
+ elif message["role"] == "user":
171
+ text_content = message["content"][0]["text"]
172
+ image_content = message["content"][1]["image_url"]["url"] if len(message["content"]) > 1 else None
173
+ if image_content:
174
+ formatted_messages.append(("Вы:", f"{text_content}\nИзображение: {image_content}"))
175
+ else:
176
+ formatted_messages.append(("Вы:", text_content))
177
+ elif message["role"] == "assistant":
178
+ formatted_messages.append(("Помогатор 1.5:", message["content"]))
179
+ return formatted_messages
180
+
181
+ # Начальные сообщения
182
+ initial_messages = [
183
+ {
184
+ "role": "system",
185
+ "content": start,
186
+ }
187
+ ]
188
+
189
+ # Создаем интерфейс с помощью Gradio
190
+ with gr.Blocks() as demo:
191
+ with gr.Row():
192
+ with gr.Column():
193
+ chatbot = gr.Chatbot(label="История Сообщений", type='messages') # <- Исправлено
194
+ with gr.Row():
195
+ image_input = gr.Image(label="Фото", type="pil")
196
+ instructions = gr.Textbox(label="Сообщение", lines=3, placeholder="Реши...")
197
+ submit_button = gr.Button("Отправить")
198
+
199
+ submit_button.click(
200
+ fn=ask_openai_with_image,
201
+ inputs=[gr.State(initial_messages), instructions, image_input, gr.Textbox(SERVER_URL, visible=False)],
202
+ outputs=[gr.State(initial_messages), chatbot],
203
+ concurrency_limit=150,
204
+ show_progress=True # Добавлено для отображения прогресса
205
+ )
206
+
207
+
208
+ # Монтируем маршрут для получения изображений из кэша
209
+ app = demo.app
210
+ app.mount("/image", StaticFiles(directory=CACHE_DIR), name="image_cache")
211
+
212
+ # Обработка маршрута для получения изображений из кэша
213
+ @app.get("/image/{image_name:path}")
214
+ async def get_image(image_name: str):
215
+ image_path = os.path.join(CACHE_DIR, image_name)
216
+ if os.path.isfile(image_path):
217
+ return FileResponse(image_path)
218
+ else:
219
+ raise HTTPException(status_code=404, detail="Image not found")
220
+
221
+ demo.launch()