X commited on
Commit
fc5effb
·
verified ·
1 Parent(s): b65f3c6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +181 -77
app.py CHANGED
@@ -24,8 +24,7 @@ print(f"CUDA доступна: {torch.cuda.is_available()}")
24
  if torch.cuda.is_available():
25
  print(f"GPU: {torch.cuda.get_device_name(0)}")
26
 
27
- # Используем модель, которая точно работает
28
- MODEL_NAME = "sberbank-ai/rugpt3small_based_on_gpt2" # Рабочая модель
29
  EMBEDDING_MODEL = "all-MiniLM-L6-v2"
30
  SCIENCE_DATASET = "RafaelUI/ru_science"
31
  ARTICLE_LIMIT = 50
@@ -52,19 +51,85 @@ st.set_page_config(
52
  )
53
 
54
  # ===================================================================
55
- # 2. ПРОВЕРКА УСТАНОВКИ TRANSFORMERS
56
  # ===================================================================
57
 
58
- try:
59
- from transformers import GPT2LMHeadModel, GPT2Tokenizer
60
- TRANSFORMERS_OK = True
61
- except ImportError:
62
- TRANSFORMERS_OK = False
63
- st.error("❌ Ошибка: transformers не установлен или устарел")
64
- st.info("Установите: pip install transformers --upgrade")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  # ===================================================================
67
- # 3. НАСТОЯЩАЯ НЕЙРОСЕТЬ
68
  # ===================================================================
69
 
70
  class NeuralChatbot:
@@ -75,18 +140,16 @@ class NeuralChatbot:
75
  self.generator = None
76
  self.is_loaded = False
77
 
78
- self.system_prompt = f"""Ты - {AI_NAME}, дружелюбный научный AI-ассистент от компании {COMPANY_NAME}.
79
  Ты создан в {CREATION_DATE} командой {', '.join(CREATORS)}.
80
- Ты всегда отвечаешь на русском языке, тепло и профессионально.
81
- Ты помогаешь с научными вопросами, системным администрированием и технологиями.
82
- Ты генерируешь уникальные ответы каждый раз.
 
83
 
84
- Вот вопрос пользователя: """
85
 
86
  def load_model(self):
87
- if not TRANSFORMERS_OK:
88
- return False
89
-
90
  with st.spinner("🧠 Загружаю нейросеть..."):
91
  try:
92
  from transformers import GPT2LMHeadModel, GPT2Tokenizer
@@ -138,21 +201,84 @@ class NeuralChatbot:
138
 
139
  return response
140
 
141
- except Exception as e:
142
- print(f"Ошибка генерации: {e}")
143
  return self.fallback_response(query)
144
 
145
  def fallback_response(self, query):
146
- return f"""Я {AI_NAME} от {COMPANY_NAME}.
147
 
148
- К сожалению, сейчас нейросеть временно недоступна, но я хочу ответить на ваш вопрос: "{query}"
149
 
150
- Обычно я генерирую уникальные ответы с помощью нейросети GPT. Попробуйте позже, и я смогу дать более развернутый ответ! 🧠
151
 
152
- А пока я могу рассказать, что создан в {CREATION_DATE} командой {', '.join(CREATORS)}. Я помогаю с научными вопросами и технологиями."""
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  # ===================================================================
155
- # 4. ЗАГРУЗКА СТАТЕЙ
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  # ===================================================================
157
 
158
  @st.cache_resource
@@ -179,8 +305,7 @@ def load_science_articles():
179
  with open(ARTICLES_FILE, 'wb') as f:
180
  pickle.dump(articles, f)
181
  return articles
182
- except Exception as e:
183
- st.warning(f"Не удалось загрузить статьи: {e}")
184
  return []
185
 
186
  @st.cache_resource
@@ -218,23 +343,6 @@ def search_articles(query, _articles, _embeddings, _embedder):
218
  except:
219
  return []
220
 
221
- # ===================================================================
222
- # 5. ОЧИСТКА ЗАПРОСОВ
223
- # ===================================================================
224
-
225
- def clean_query(query):
226
- query = re.sub(r'http[s]?://\S+', '', query)
227
- query = re.sub(r'\S+@\S+', '', query)
228
- query = re.sub(r'\+7\s*\(?\d{3}\)?\s*\d{3}\s*\d{2}\s*\d{2}', '', query)
229
- query = re.sub(r'[^\w\s\.\?\!,;:]', ' ', query)
230
- query = ' '.join(query.split())
231
-
232
- if len(query) > 300:
233
- sentences = re.split(r'[.!?]', query)
234
- query = '. '.join(sentences[:2]) + '.' if sentences else query[:200]
235
-
236
- return query.strip()
237
-
238
  # ===================================================================
239
  # 6. ОСНОВНОЙ КЛАСС
240
  # ===================================================================
@@ -252,32 +360,50 @@ class OpenAirAI:
252
  return self.is_ready
253
 
254
  def generate_answer(self, query):
 
255
  clean_q = clean_query(query)
256
- return self.chatbot.generate(clean_q)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
 
258
  # ===================================================================
259
  # 7. ИНТЕРФЕЙС
260
  # ===================================================================
261
 
262
- # Загрузка данных
263
  articles = load_science_articles()
264
  embedder = load_embedder()
265
  embeddings = create_embeddings(articles, embedder)
266
 
267
- # Инициализация AI
268
  if 'ai' not in st.session_state:
269
  st.session_state.ai = OpenAirAI()
270
  st.session_state.ai.initialize()
271
 
272
  ai = st.session_state.ai
273
 
274
- # История чата
275
  if "messages" not in st.session_state:
276
  st.session_state.messages = []
277
- greeting = ai.generate_answer("Привет! Представься и расскажи о себе кратко")
278
  st.session_state.messages.append({"role": "assistant", "content": greeting})
279
 
280
- # --- БОКОВАЯ ПАНЕЛЬ ---
281
  with st.sidebar:
282
  st.image("https://cdn-icons-png.flaticon.com/512/4248/4248455.png", width=80)
283
  st.title(f"🧠 {AI_NAME}")
@@ -297,55 +423,33 @@ with st.sidebar:
297
  **📊 Статистика:**
298
  - Статей: {len(articles)}
299
  - Сообщений: {len(st.session_state.messages)}
300
- - Модель: {MODEL_NAME.split("/")[-1]}
301
  """)
302
 
303
  if st.button("🗑️ Очистить чат"):
304
  st.session_state.messages = []
305
- greeting = ai.generate_answer("Привет! Представься и расскажи о себе кратко")
306
  st.session_state.messages.append({"role": "assistant", "content": greeting})
307
  st.rerun()
308
-
309
- if st.button("🔄 Сгенерировать новое приветствие"):
310
- new_greeting = ai.generate_answer("Привет! Представься заново")
311
- if st.session_state.messages:
312
- st.session_state.messages[0] = {"role": "assistant", "content": new_greeting}
313
- st.rerun()
314
 
315
- # --- ОСНОВНАЯ ЧАСТЬ ---
316
  st.title(f"🧠 {AI_NAME} - Нейросетевой AI-ассистент")
317
- st.markdown(f"**{AI_NAME}** от **{COMPANY_NAME}** | Ответы генерируются нейросетью")
318
 
319
- # Отображение сообщений
320
  for message in st.session_state.messages:
321
  with st.chat_message(message["role"]):
322
  st.markdown(message["content"])
323
 
324
- # Поле ввода
325
  if prompt := st.chat_input("Задайте вопрос..."):
326
  st.session_state.messages.append({"role": "user", "content": prompt})
327
  with st.chat_message("user"):
328
  st.markdown(prompt)
329
 
330
  with st.chat_message("assistant"):
331
- with st.spinner("🧠 Нейросеть генерирует ответ..."):
332
- # Ищем релевантные статьи
333
- articles_context = search_articles(prompt, articles, embeddings, embedder)
334
-
335
- # Генерируем ответ
336
  response = ai.generate_answer(prompt)
337
-
338
- # Добавляем статьи в ответ
339
- if articles_context and len(response) < 50:
340
- response += "\n\n📄 Я нашел релевантные научные статьи:\n"
341
- for i, art in enumerate(articles_context, 1):
342
- response += f"{i}. {art['title']}\n"
343
-
344
  st.markdown(response)
345
  st.session_state.messages.append({"role": "assistant", "content": response})
346
 
347
  st.rerun()
348
 
349
- # --- ПОДВАЛ ---
350
  st.divider()
351
- st.caption(f"🧠 {AI_NAME} от {COMPANY_NAME} | Создан в {CREATION_DATE} | Генеративная нейросеть")
 
24
  if torch.cuda.is_available():
25
  print(f"GPU: {torch.cuda.get_device_name(0)}")
26
 
27
+ MODEL_NAME = "sberbank-ai/rugpt3small_based_on_gpt2"
 
28
  EMBEDDING_MODEL = "all-MiniLM-L6-v2"
29
  SCIENCE_DATASET = "RafaelUI/ru_science"
30
  ARTICLE_LIMIT = 50
 
51
  )
52
 
53
  # ===================================================================
54
+ # 2. БАЗА ЗНАНИЙ ДЛЯ КОРРЕКТНЫХ ОТВЕТОВ
55
  # ===================================================================
56
 
57
+ KNOWLEDGE = {
58
+ "education": """
59
+ ### Образование и специальность
60
+
61
+ Я, OpenAirAI, не учусь в традиционном смысле, но постоянно обучаюсь на новых данных.
62
+
63
+ **Моя "специальность":**
64
+ - Обработка естественного языка
65
+ - Поиск информации в научных статьях
66
+ - Анализ данных
67
+
68
+ **Что я умею:**
69
+ - Отвечать на научные вопросы
70
+ - Находить информацию в статьях ru_science
71
+ - Помогать с системным администрированием
72
+ - Генерировать уникальные ответы
73
+
74
+ **Что я не умею:**
75
+ - Не имею личного опыта
76
+ - Не могу принимать решения за людей
77
+ - Не имею физического воплощения
78
+ """,
79
+ "mission": """
80
+ ### Моя миссия
81
+
82
+ Я создан для того, чтобы:
83
+ 1. Делать знания доступными
84
+ 2. Помогать в научных исследованиях
85
+ 3. Популяризировать науку
86
+
87
+ **Как я помогаю людям:**
88
+ - Отвечаю на вопросы
89
+ - Нахожу релевантные статьи
90
+ - Объясняю сложные концепции простым языком
91
+
92
+ **Почему это важно:**
93
+ Наука должна быть доступна каждому, а я помогаю убрать барьеры между человеком и знаниями.
94
+ """,
95
+ "internet": """
96
+ ### О существовании интернета
97
+
98
+ Интернет существует как глобальная сеть, объединяющая миллиарды устройств.
99
+
100
+ **Что такое интернет:**
101
+ - Физическая инфраструктура (кабели, серверы)
102
+ - Протоколы передачи данных (TCP/IP)
103
+ - Миллионы веб-сайтов и сервисов
104
+
105
+ **Интернет - это:**
106
+ - Инструмент для обмена информацией
107
+ - Платформа для общения
108
+ - Источник знаний
109
+
110
+ Я существую в интернете, поэтому могу с уверенностью сказать, что он реален.
111
+ """,
112
+ "projects": """
113
+ ### О проектах и сотрудничестве
114
+
115
+ OpenRussianAI - открытый проект.
116
+
117
+ **Как присоединиться:**
118
+ 1. Посетите наш сайт: https://sites.google.com/view/opruai/home
119
+ 2. Подпишитесь на Hugging Face: https://huggingface.co/OpenRussianAI
120
+ 3. Свяжитесь с нами: info@openrussianai.ru
121
+
122
+ **Что мы делаем:**
123
+ - Разрабатываем AI-помощников
124
+ - Исследуем NLP
125
+ - Популяризируем науку
126
+
127
+ **Присоединяйтесь к сообществу!**
128
+ """
129
+ }
130
 
131
  # ===================================================================
132
+ # 3. НЕЙРОСЕТЬ
133
  # ===================================================================
134
 
135
  class NeuralChatbot:
 
140
  self.generator = None
141
  self.is_loaded = False
142
 
143
+ self.system_prompt = f"""Ты - {AI_NAME}, научный AI-ассистент от компании {COMPANY_NAME}.
144
  Ты создан в {CREATION_DATE} командой {', '.join(CREATORS)}.
145
+ Ты отвечаешь на русском языке, четко и по делу.
146
+ Если вопрос про образование, миссию или интернет - используй знания из базы.
147
+ Если вопрос про науку - ищи в статьях.
148
+ Всегда давай структурированный ответ.
149
 
150
+ Вопрос: """
151
 
152
  def load_model(self):
 
 
 
153
  with st.spinner("🧠 Загружаю нейросеть..."):
154
  try:
155
  from transformers import GPT2LMHeadModel, GPT2Tokenizer
 
201
 
202
  return response
203
 
204
+ except:
 
205
  return self.fallback_response(query)
206
 
207
  def fallback_response(self, query):
208
+ return f"""Я {AI_NAME} от {COMPANY_NAME}.
209
 
210
+ Извините, нейросеть временно недоступна. Вот что я знаю по вашему вопросу:
211
 
212
+ {self.get_knowledge(query)}
213
 
214
+ Если нужна более подробная информация, попробуйте позже. 🧠"""
215
+
216
+ def get_knowledge(self, query):
217
+ q = query.lower()
218
+ if any(w in q for w in ["образован", "специальн", "учусь", "умею"]):
219
+ return KNOWLEDGE["education"]
220
+ elif any(w in q for w in ["мисси", "цель", "помога", "задача"]):
221
+ return KNOWLEDGE["mission"]
222
+ elif any(w in q for w in ["интернет", "существу"]):
223
+ return KNOWLEDGE["internet"]
224
+ elif any(w in q for w in ["проект", "сотруднич", "присоедин"]):
225
+ return KNOWLEDGE["projects"]
226
+ else:
227
+ return "Я помогаю с научными вопросами. Что именно вас интересует?"
228
 
229
  # ===================================================================
230
+ # 4. ОЧИСТКА ЗАПРОСОВ ОТ СПАМА
231
+ # ===================================================================
232
+
233
+ def clean_query(query):
234
+ """Очищает запрос от спама и мусора"""
235
+ # Удаляем ссылки
236
+ query = re.sub(r'http[s]?://\S+', '', query)
237
+ query = re.sub(r'www\.\S+', '', query)
238
+
239
+ # Удаляем email
240
+ query = re.sub(r'\S+@\S+', '', query)
241
+
242
+ # Удаляем телефоны
243
+ query = re.sub(r'\+7\s*\(?\d{3}\)?\s*\d{3}\s*\d{2}\s*\d{2}', '', query)
244
+ query = re.sub(r'8\s*\(?\d{3}\)?\s*\d{3}\s*\d{2}\s*\d{2}', '', query)
245
+
246
+ # Удаляем странные символы
247
+ query = re.sub(r'[^\w\s\.\?\!,;:]', ' ', query)
248
+
249
+ # Удаляем множественные пробелы
250
+ query = ' '.join(query.split())
251
+
252
+ # Если запрос слишком длинный - берем первое осмысленное предложение
253
+ if len(query) > 300:
254
+ sentences = re.split(r'[.!?]', query)
255
+ query = '. '.join([s for s in sentences[:3] if len(s) > 10]) + '.'
256
+
257
+ return query.strip()
258
+
259
+ def extract_main_question(query):
260
+ """Извлекает основной вопрос из спама"""
261
+ q = query.lower()
262
+
263
+ # Ключевые слова вопросов
264
+ question_keywords = ['что', 'как', 'почему', 'где', 'когда', 'кто', 'зачем', 'какой']
265
+
266
+ # Ищем предложения с вопросительными словами
267
+ sentences = re.split(r'[.!?]', q)
268
+ questions = []
269
+
270
+ for s in sentences:
271
+ if any(keyword in s for keyword in question_keywords):
272
+ questions.append(s.strip())
273
+
274
+ if questions:
275
+ return '. '.join(questions[:2]) + '?'
276
+
277
+ # Если вопросов нет, берем первые 100 символов
278
+ return query[:150] + ('...' if len(query) > 150 else '')
279
+
280
+ # ===================================================================
281
+ # 5. ЗАГРУЗКА СТАТЕЙ
282
  # ===================================================================
283
 
284
  @st.cache_resource
 
305
  with open(ARTICLES_FILE, 'wb') as f:
306
  pickle.dump(articles, f)
307
  return articles
308
+ except:
 
309
  return []
310
 
311
  @st.cache_resource
 
343
  except:
344
  return []
345
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  # ===================================================================
347
  # 6. ОСНОВНОЙ КЛАСС
348
  # ===================================================================
 
360
  return self.is_ready
361
 
362
  def generate_answer(self, query):
363
+ # Очищаем запрос
364
  clean_q = clean_query(query)
365
+
366
+ # Если запрос стал пустым
367
+ if not clean_q or len(clean_q) < 3:
368
+ return f"Я {self.name} от {self.company}. Чем могу помочь? Задайте конкретный вопрос. 🧠"
369
+
370
+ # Извлекаем основной вопрос
371
+ main_q = extract_main_question(clean_q)
372
+
373
+ # Ищем статьи
374
+ articles_context = search_articles(main_q, articles, embeddings, embedder)
375
+
376
+ # Если есть статьи и вопрос научный
377
+ if articles_context and any(w in main_q.lower() for w in ["науч", "исслед", "стать", "эксперимент"]):
378
+ response = self.chatbot.generate(main_q)
379
+ if articles_context:
380
+ response += "\n\n📄 **Релевантные статьи:**\n"
381
+ for i, art in enumerate(articles_context, 1):
382
+ response += f"{i}. {art['title']}\n"
383
+ return response
384
+
385
+ # Генерируем ответ через нейросеть
386
+ return self.chatbot.generate(main_q)
387
 
388
  # ===================================================================
389
  # 7. ИНТЕРФЕЙС
390
  # ===================================================================
391
 
 
392
  articles = load_science_articles()
393
  embedder = load_embedder()
394
  embeddings = create_embeddings(articles, embedder)
395
 
 
396
  if 'ai' not in st.session_state:
397
  st.session_state.ai = OpenAirAI()
398
  st.session_state.ai.initialize()
399
 
400
  ai = st.session_state.ai
401
 
 
402
  if "messages" not in st.session_state:
403
  st.session_state.messages = []
404
+ greeting = ai.generate_answer("Привет! Представься")
405
  st.session_state.messages.append({"role": "assistant", "content": greeting})
406
 
 
407
  with st.sidebar:
408
  st.image("https://cdn-icons-png.flaticon.com/512/4248/4248455.png", width=80)
409
  st.title(f"🧠 {AI_NAME}")
 
423
  **📊 Статистика:**
424
  - Статей: {len(articles)}
425
  - Сообщений: {len(st.session_state.messages)}
 
426
  """)
427
 
428
  if st.button("🗑️ Очистить чат"):
429
  st.session_state.messages = []
430
+ greeting = ai.generate_answer("Привет! Представься")
431
  st.session_state.messages.append({"role": "assistant", "content": greeting})
432
  st.rerun()
 
 
 
 
 
 
433
 
 
434
  st.title(f"🧠 {AI_NAME} - Нейросетевой AI-ассистент")
435
+ st.markdown(f"**{AI_NAME}** от **{COMPANY_NAME}** | Очищает запросы от спа��а")
436
 
 
437
  for message in st.session_state.messages:
438
  with st.chat_message(message["role"]):
439
  st.markdown(message["content"])
440
 
 
441
  if prompt := st.chat_input("Задайте вопрос..."):
442
  st.session_state.messages.append({"role": "user", "content": prompt})
443
  with st.chat_message("user"):
444
  st.markdown(prompt)
445
 
446
  with st.chat_message("assistant"):
447
+ with st.spinner("🧠 Думаю..."):
 
 
 
 
448
  response = ai.generate_answer(prompt)
 
 
 
 
 
 
 
449
  st.markdown(response)
450
  st.session_state.messages.append({"role": "assistant", "content": response})
451
 
452
  st.rerun()
453
 
 
454
  st.divider()
455
+ st.caption(f"🧠 {AI_NAME} от {COMPANY_NAME} | Создан в {CREATION_DATE}")