X commited on
Commit
7934afb
·
verified ·
1 Parent(s): 4d0b581

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -80
app.py CHANGED
@@ -5,6 +5,7 @@ import json
5
  from pathlib import Path
6
  from datetime import datetime
7
  import requests
 
8
 
9
  # === ЗАГРУЗКА МОДЕЛИ ===
10
  print("🚀 Загрузка модели...")
@@ -20,7 +21,9 @@ HISTORY_DIR = Path("chat_history")
20
  HISTORY_DIR.mkdir(exist_ok=True)
21
 
22
  def get_history_path(username):
23
- return HISTORY_DIR / f"{username}.json"
 
 
24
 
25
  def load_history(username):
26
  path = get_history_path(username)
@@ -35,7 +38,7 @@ def save_history(username, history_data):
35
  json.dump(history_data, f, ensure_ascii=False, indent=2)
36
 
37
  def check_if_pro(token):
38
- if not token:
39
  return False
40
  try:
41
  response = requests.get(
@@ -53,16 +56,14 @@ def check_if_pro(token):
53
  # === ГЕНЕРАЦИЯ ОТВЕТА ===
54
  def generate_response(message, history, username, current_chat_id):
55
  if not username:
56
- gr.Warning("Пожалуйста, войдите через Hugging Face")
57
  return history, gr.update(), current_chat_id
58
 
59
  if not message.strip():
60
  return history, gr.update(), current_chat_id
61
 
62
- # Добавляем сообщение пользователя
63
  history = history + [{"role": "user", "content": message}]
64
 
65
- # Формируем промпт из всей истории
66
  prompt = ""
67
  for msg in history:
68
  if msg["role"] == "user":
@@ -87,7 +88,6 @@ def generate_response(message, history, username, current_chat_id):
87
 
88
  history = history + [{"role": "assistant", "content": ai_response}]
89
 
90
- # Сохраняем в хранилище
91
  if username and current_chat_id:
92
  history_data = load_history(username)
93
  if current_chat_id not in history_data:
@@ -179,8 +179,6 @@ CUSTOM_CSS = """
179
 
180
  # === ИНТЕРФЕЙС ===
181
  with gr.Blocks(title="OpenAirAI-X Chat") as demo:
182
-
183
- # Состояния
184
  username_state = gr.State("")
185
  history_state = gr.State({})
186
  current_chat_id_state = gr.State(None)
@@ -194,96 +192,77 @@ with gr.Blocks(title="OpenAirAI-X Chat") as demo:
194
  """)
195
 
196
  with gr.Row():
197
- # Боковая панель
198
  with gr.Column(scale=1, min_width=250):
199
- user_info = gr.Textbox(
200
- label="Пользователь",
201
- value="Не авторизован",
202
- interactive=False,
203
- elem_classes="user-info"
204
- )
205
  pro_badge = gr.HTML('<div class="pro-badge">👑 PRO</div>', visible=False)
206
  new_chat_btn = gr.Button("➕ Новый чат", variant="primary")
207
  gr.Markdown("### 📚 История чатов")
208
- chat_list = gr.Radio(
209
- choices=[],
210
- label="Ваши чаты",
211
- interactive=True
212
- )
213
  delete_chat_btn = gr.Button("🗑️ Удалить выбранный чат", variant="stop", size="sm")
214
  logout_btn = gr.Button("🚪 Выйти", size="sm")
215
 
216
- # Основная область чата
217
  with gr.Column(scale=3):
218
- chatbot = gr.Chatbot(
219
- label="Диалог",
220
- height=500
221
- )
222
  with gr.Row():
223
- msg_input = gr.Textbox(
224
- placeholder="Напишите сообщение...",
225
- lines=2,
226
- scale=5,
227
- show_label=False
228
- )
229
  send_btn = gr.Button("📤 Отправить", variant="primary", scale=1)
230
 
231
- # Экран входа
232
  with gr.Column(visible=True) as login_screen:
233
  gr.HTML("""
234
  <div class="main-header">
235
  <h1>🤖 OpenAirAI-X Chat</h1>
236
- <p>Войдите через Hugging Face, чтобы начать</p>
237
  </div>
238
  """)
239
  gr.Markdown("""
240
  ### 🔐 Вход в систему
241
 
242
- Для использования чата необходимо войти через аккаунт Hugging Face.
243
-
244
- **Преимущества входа:**
245
- - 💾 Сохранение истории чатов
246
- - 👑 PRO-статус для подписчиков
247
- - 🔄 Доступ к предыдущим диалогам
248
  """)
249
- gr.LoginButton(value="🔑 Войти через Hugging Face", variant="primary")
 
 
 
 
250
 
251
  # === ОБРАБОТЧИКИ ===
252
 
253
- def handle_login(request: gr.Request):
254
- if request.username:
255
- username = request.username
256
- token = request.oauth_token.get("access_token") if request.oauth_token else None
257
- is_pro = check_if_pro(token)
258
- history_data = load_history(username)
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  chat_list_choices = get_chat_list(username)
260
-
261
- current_chat_id = None
262
- if not history_data:
263
- chat_id = datetime.now().strftime("%Y%m%d_%H%M%S")
264
- history_data[chat_id] = {
265
- "title": "Новый чат",
266
- "created": datetime.now().isoformat(),
267
- "messages": []
268
- }
269
- save_history(username, history_data)
270
- current_chat_id = chat_id
271
- chat_list_choices = get_chat_list(username)
272
-
273
- pro_badge_html = '<div class="pro-badge">👑 PRO</div>'
274
- display_name = f"👤 {username}"
275
-
276
- return (
277
- gr.update(visible=True),
278
- gr.update(visible=False),
279
- display_name,
280
- username,
281
- history_data,
282
- current_chat_id,
283
- chat_list_choices,
284
- gr.update(visible=is_pro, value=pro_badge_html)
285
- )
286
- return (gr.update(), gr.update(), gr.update(), "", {}, None, [], gr.update())
287
 
288
  def handle_logout():
289
  return (
@@ -297,11 +276,10 @@ with gr.Blocks(title="OpenAirAI-X Chat") as demo:
297
  gr.update(visible=False)
298
  )
299
 
300
- demo.load(
301
  fn=handle_login,
302
- inputs=None,
303
- outputs=[main_interface, login_screen, user_info, username_state,
304
- history_state, current_chat_id_state, chat_list, pro_badge]
305
  )
306
 
307
  send_btn.click(
@@ -345,9 +323,8 @@ with gr.Blocks(title="OpenAirAI-X Chat") as demo:
345
  logout_btn.click(
346
  fn=handle_logout,
347
  inputs=None,
348
- outputs=[main_interface, login_screen, user_info, username_state,
349
- history_state, current_chat_id_state, chat_list, pro_badge]
350
  )
351
 
352
- # Запуск с CSS в launch()
353
  demo.launch(server_name="0.0.0.0", server_port=7860, css=CUSTOM_CSS)
 
5
  from pathlib import Path
6
  from datetime import datetime
7
  import requests
8
+ import os
9
 
10
  # === ЗАГРУЗКА МОДЕЛИ ===
11
  print("🚀 Загрузка модели...")
 
21
  HISTORY_DIR.mkdir(exist_ok=True)
22
 
23
  def get_history_path(username):
24
+ # Очищаем имя пользователя от недопустимых символов для имени файла
25
+ safe_name = "".join(c for c in username if c.isalnum() or c in ('-', '_')).lower()
26
+ return HISTORY_DIR / f"{safe_name}.json"
27
 
28
  def load_history(username):
29
  path = get_history_path(username)
 
38
  json.dump(history_data, f, ensure_ascii=False, indent=2)
39
 
40
  def check_if_pro(token):
41
+ if not token or not token.startswith("hf_"):
42
  return False
43
  try:
44
  response = requests.get(
 
56
  # === ГЕНЕРАЦИЯ ОТВЕТА ===
57
  def generate_response(message, history, username, current_chat_id):
58
  if not username:
59
+ gr.Warning("Сначала введите имя пользователя на экране входа!")
60
  return history, gr.update(), current_chat_id
61
 
62
  if not message.strip():
63
  return history, gr.update(), current_chat_id
64
 
 
65
  history = history + [{"role": "user", "content": message}]
66
 
 
67
  prompt = ""
68
  for msg in history:
69
  if msg["role"] == "user":
 
88
 
89
  history = history + [{"role": "assistant", "content": ai_response}]
90
 
 
91
  if username and current_chat_id:
92
  history_data = load_history(username)
93
  if current_chat_id not in history_data:
 
179
 
180
  # === ИНТЕРФЕЙС ===
181
  with gr.Blocks(title="OpenAirAI-X Chat") as demo:
 
 
182
  username_state = gr.State("")
183
  history_state = gr.State({})
184
  current_chat_id_state = gr.State(None)
 
192
  """)
193
 
194
  with gr.Row():
 
195
  with gr.Column(scale=1, min_width=250):
196
+ user_info = gr.Textbox(label="Пользователь", value="Не авторизован", interactive=False, elem_classes="user-info")
 
 
 
 
 
197
  pro_badge = gr.HTML('<div class="pro-badge">👑 PRO</div>', visible=False)
198
  new_chat_btn = gr.Button("➕ Новый чат", variant="primary")
199
  gr.Markdown("### 📚 История чатов")
200
+ chat_list = gr.Radio(choices=[], label="Ваши чаты", interactive=True)
 
 
 
 
201
  delete_chat_btn = gr.Button("🗑️ Удалить выбранный чат", variant="stop", size="sm")
202
  logout_btn = gr.Button("🚪 Выйти", size="sm")
203
 
 
204
  with gr.Column(scale=3):
205
+ # Исправлено для Gradio 6.0: убраны type и show_copy_button
206
+ chatbot = gr.Chatbot(label="Диалог", height=500)
 
 
207
  with gr.Row():
208
+ msg_input = gr.Textbox(placeholder="Напишите сообщение...", lines=2, scale=5, show_label=False)
 
 
 
 
 
209
  send_btn = gr.Button("📤 Отправить", variant="primary", scale=1)
210
 
211
+ # Экран входа (без gr.LoginButton, чтобы избежать ошибок в Docker)
212
  with gr.Column(visible=True) as login_screen:
213
  gr.HTML("""
214
  <div class="main-header">
215
  <h1>🤖 OpenAirAI-X Chat</h1>
216
+ <p>Введите данные для входа</p>
217
  </div>
218
  """)
219
  gr.Markdown("""
220
  ### 🔐 Вход в систему
221
 
222
+ Введите ваше имя пользователя Hugging Face. История чатов будет привязана к этому имени.
 
 
 
 
 
223
  """)
224
+ with gr.Column(max_width=400):
225
+ username_input = gr.Textbox(label="Имя пользователя (HF Username)", placeholder="Например: RootLinux21")
226
+ token_input = gr.Textbox(label="HF Token (необязательно, только для проверки PRO)", type="password", placeholder="hf_...")
227
+ login_btn = gr.Button("🔑 Войти", variant="primary")
228
+ gr.Markdown("*Если у вас есть PRO-подписка, вставьте ваш токен (Settings -> Access Tokens), чтобы увидеть значок 👑*, токен не передаётся OpenRussianAI!")
229
 
230
  # === ОБРАБОТЧИКИ ===
231
 
232
+ def handle_login(username, token):
233
+ if not username.strip():
234
+ gr.Warning("Введите имя пользователя!")
235
+ return gr.update(), gr.update(), "Не авторизован", "", {}, None, [], gr.update(visible=False)
236
+
237
+ is_pro = check_if_pro(token)
238
+ history_data = load_history(username)
239
+ chat_list_choices = get_chat_list(username)
240
+
241
+ current_chat_id = None
242
+ if not history_data:
243
+ chat_id = datetime.now().strftime("%Y%m%d_%H%M%S")
244
+ history_data[chat_id] = {
245
+ "title": "Новый чат",
246
+ "created": datetime.now().isoformat(),
247
+ "messages": []
248
+ }
249
+ save_history(username, history_data)
250
+ current_chat_id = chat_id
251
  chat_list_choices = get_chat_list(username)
252
+
253
+ pro_badge_html = '<div class="pro-badge">👑 PRO</div>'
254
+ display_name = f"👤 {username}"
255
+
256
+ return (
257
+ gr.update(visible=True), # main_interface
258
+ gr.update(visible=False), # login_screen
259
+ display_name, # user_info
260
+ username, # username_state
261
+ history_data, # history_state
262
+ current_chat_id, # current_chat_id_state
263
+ chat_list_choices, # chat_list
264
+ gr.update(visible=is_pro, value=pro_badge_html) # pro_badge
265
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
  def handle_logout():
268
  return (
 
276
  gr.update(visible=False)
277
  )
278
 
279
+ login_btn.click(
280
  fn=handle_login,
281
+ inputs=[username_input, token_input],
282
+ outputs=[main_interface, login_screen, user_info, username_state, history_state, current_chat_id_state, chat_list, pro_badge]
 
283
  )
284
 
285
  send_btn.click(
 
323
  logout_btn.click(
324
  fn=handle_logout,
325
  inputs=None,
326
+ outputs=[main_interface, login_screen, user_info, username_state, history_state, current_chat_id_state, chat_list, pro_badge]
 
327
  )
328
 
329
+ # Запуск: css передается в launch(), как требует Gradio 6.0
330
  demo.launch(server_name="0.0.0.0", server_port=7860, css=CUSTOM_CSS)