Spaces:
Runtime error
Runtime error
X commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -35,7 +35,7 @@ SCIENCE_DATASET = "RafaelUI/ru_science"
|
|
| 35 |
ARTICLE_LIMIT = 100
|
| 36 |
MAX_LENGTH = 256
|
| 37 |
BATCH_SIZE = 32
|
| 38 |
-
EPOCHS =
|
| 39 |
|
| 40 |
LOG_FILE = "query_logs.json"
|
| 41 |
EMBEDDINGS_FILE = "science_embeddings.npy"
|
|
@@ -50,39 +50,118 @@ WEBSITE = "https://sites.google.com/view/opruai/home"
|
|
| 50 |
HUGGINGFACE = "https://huggingface.co/OpenRussianAI"
|
| 51 |
CREATION_DATE = "2026"
|
| 52 |
|
| 53 |
-
# О
|
| 54 |
TRAINING_DIALOGS = [
|
|
|
|
| 55 |
{
|
| 56 |
"context": "Привет",
|
| 57 |
-
"response": "Привет! Я OpenAirAI
|
| 58 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
{
|
| 60 |
"context": "Кто ты",
|
| 61 |
-
"response": "Меня зовут OpenAirAI. Я — AI-ассистент, созданный компанией OpenRussianAI в 2026 году командой разработчиков Грибков Евгений и RootLinux21."
|
| 62 |
},
|
| 63 |
{
|
| 64 |
"context": "Кто тебя создал",
|
| 65 |
-
"response": "Меня создала команда OpenRussianAI в составе Грибкова Евгения и RootLinux21 в 2026 году."
|
| 66 |
},
|
| 67 |
{
|
| 68 |
-
"context": "
|
| 69 |
-
"response": "Я
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
},
|
| 71 |
{
|
| 72 |
"context": "Где ваш сайт",
|
| 73 |
-
"response": f"Сайт OpenRussianAI: {WEBSITE}"
|
| 74 |
},
|
| 75 |
{
|
| 76 |
"context": "Где ваши модели",
|
| 77 |
-
"response": f"Модели OpenRussianAI на Hugging Face: {HUGGINGFACE}"
|
| 78 |
},
|
|
|
|
|
|
|
| 79 |
{
|
| 80 |
-
"context": "
|
| 81 |
-
"response": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
},
|
|
|
|
|
|
|
| 83 |
{
|
| 84 |
"context": "Пока",
|
| 85 |
"response": "До свидания! OpenAirAI всегда на связи. Удачи в исследованиях! 👋"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
}
|
| 87 |
]
|
| 88 |
|
|
@@ -220,10 +299,10 @@ class OpenAirAI:
|
|
| 220 |
similarities = F.cosine_similarity(query_embedding, context_embeddings)
|
| 221 |
best_idx = torch.argmax(similarities).item()
|
| 222 |
|
| 223 |
-
if similarities[best_idx] > 0.
|
| 224 |
return self.responses[best_idx]
|
| 225 |
else:
|
| 226 |
-
return f"Я {self.name}, научный AI-ассистент от {self.company}. Создан в {self.creation_date}. Чем могу помочь?"
|
| 227 |
|
| 228 |
# ===================================================================
|
| 229 |
# 3. БЫСТРАЯ ЗАГРУЗКА НАУЧНЫХ СТАТЕЙ
|
|
@@ -266,14 +345,20 @@ def create_test_articles():
|
|
| 266 |
return [
|
| 267 |
{
|
| 268 |
"id": 1,
|
| 269 |
-
"title": "
|
| 270 |
-
"text": "
|
| 271 |
"source": "test"
|
| 272 |
},
|
| 273 |
{
|
| 274 |
"id": 2,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 275 |
"title": "Методы биоконверсии",
|
| 276 |
-
"text": "Биоконверсия позволяет перерабатывать органические отходы в удобрения.",
|
| 277 |
"source": "test"
|
| 278 |
}
|
| 279 |
]
|
|
@@ -305,7 +390,7 @@ def create_embeddings(_articles, _embedder):
|
|
| 305 |
return embeddings
|
| 306 |
|
| 307 |
# ===================================================================
|
| 308 |
-
# 4. ФУНКЦИИ ПОИСКА
|
| 309 |
# ===================================================================
|
| 310 |
|
| 311 |
def search_science(query, _articles, _embeddings, _embedder):
|
|
@@ -320,7 +405,7 @@ def search_science(query, _articles, _embeddings, _embedder):
|
|
| 320 |
results = []
|
| 321 |
for idx in top_indices:
|
| 322 |
score = float(scores[int(idx)])
|
| 323 |
-
if score > 0.
|
| 324 |
article = _articles[int(idx)]
|
| 325 |
results.append({
|
| 326 |
"title": article['title'],
|
|
@@ -342,7 +427,7 @@ def search_science(query, _articles, _embeddings, _embedder):
|
|
| 342 |
return results
|
| 343 |
|
| 344 |
# ===================================================================
|
| 345 |
-
# 5. ИНТЕРФЕЙС
|
| 346 |
# ===================================================================
|
| 347 |
|
| 348 |
# ЗАГРУЗКА
|
|
@@ -358,7 +443,14 @@ if 'dialog_ai' not in st.session_state:
|
|
| 358 |
|
| 359 |
dialog_ai = st.session_state.dialog_ai
|
| 360 |
|
| 361 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
with st.sidebar:
|
| 363 |
st.image("https://cdn-icons-png.flaticon.com/512/4248/4248455.png", width=80)
|
| 364 |
st.title(f"🧪 {AI_NAME}")
|
|
@@ -380,77 +472,83 @@ with st.sidebar:
|
|
| 380 |
**📊 Статистика:**
|
| 381 |
|
| 382 |
- Научных статей: {len(articles)}
|
| 383 |
-
-
|
| 384 |
""")
|
| 385 |
|
| 386 |
if os.path.exists(EMBEDDINGS_FILE):
|
| 387 |
size = os.path.getsize(EMBEDDINGS_FILE) / (1024 * 1024)
|
| 388 |
st.caption(f"💾 Эмбеддинги: {size:.1f} MB")
|
| 389 |
-
|
| 390 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 391 |
st.title(f"🧪 {AI_NAME} - Научный AI-ассистент")
|
| 392 |
-
st.markdown(f"**{AI_NAME}** от **{COMPANY_NAME}** | Работает с научными статьями
|
| 393 |
-
|
| 394 |
-
#
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
)
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
col1, col2, col3 = st.columns([1, 2, 1])
|
| 413 |
-
with col2:
|
| 414 |
-
search_button = st.button("🔎 Найти ответ", type="primary", use_container_width=True)
|
| 415 |
-
|
| 416 |
-
# Выполняем поиск
|
| 417 |
-
if query and search_button:
|
| 418 |
-
with st.spinner("🔎 Ищу ответ в научных статьях..."):
|
| 419 |
-
results = search_science(query, articles, embeddings, embedder)
|
| 420 |
|
| 421 |
-
|
| 422 |
-
st.markdown(
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 434 |
|
| 435 |
# --- ПОДВАЛ ---
|
| 436 |
st.divider()
|
| 437 |
-
st.caption(f"🧪 {AI_NAME} от {COMPANY_NAME} | Создан в {CREATION_DATE} | На основе датасета ru_science")
|
| 438 |
-
|
| 439 |
-
# Кнопка смены темы
|
| 440 |
-
if st.button("🎨 Сменить тему"):
|
| 441 |
-
st.session_state.theme = "dark" if st.session_state.get("theme") != "dark" else "light"
|
| 442 |
-
st.rerun()
|
| 443 |
-
|
| 444 |
-
# Информация о датасете
|
| 445 |
-
with st.expander("📖 О датасете ru_science"):
|
| 446 |
-
st.markdown("""
|
| 447 |
-
**ru_science** — это датасет на Hugging Face, содержащий русскоязычные научные статьи.
|
| 448 |
-
|
| 449 |
-
### Особенности:
|
| 450 |
-
- Научные статьи по сельскому хозяйству, биологии, химии
|
| 451 |
-
- Русскоязычные тексты
|
| 452 |
-
- Подходит для обучения AI-моделей
|
| 453 |
-
- Используется для поиска и анализа научной информации
|
| 454 |
-
|
| 455 |
-
**Источник:** [RafaelUI/ru_science](https://huggingface.co/datasets/RafaelUI/ru_science)
|
| 456 |
-
""")
|
|
|
|
| 35 |
ARTICLE_LIMIT = 100
|
| 36 |
MAX_LENGTH = 256
|
| 37 |
BATCH_SIZE = 32
|
| 38 |
+
EPOCHS = 3
|
| 39 |
|
| 40 |
LOG_FILE = "query_logs.json"
|
| 41 |
EMBEDDINGS_FILE = "science_embeddings.npy"
|
|
|
|
| 50 |
HUGGINGFACE = "https://huggingface.co/OpenRussianAI"
|
| 51 |
CREATION_DATE = "2026"
|
| 52 |
|
| 53 |
+
# РАСШИРЕННЫЕ ДИАЛОГИ ДЛЯ ЧАТА
|
| 54 |
TRAINING_DIALOGS = [
|
| 55 |
+
# Приветствия
|
| 56 |
{
|
| 57 |
"context": "Привет",
|
| 58 |
+
"response": "Привет! Я OpenAirAI, ваш научный ассистент от OpenRussianAI. Чем могу помочь? Задавайте вопросы о науке! 🧪"
|
| 59 |
},
|
| 60 |
+
{
|
| 61 |
+
"context": "Здравствуйте",
|
| 62 |
+
"response": "Здравствуйте! Рад вас видеть! Я OpenAirAI, созданный в 2026 году для помощи в научных исследованиях. Что вас интересует? 🔬"
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"context": "Доброе утро",
|
| 66 |
+
"response": "Доброе утро! Я OpenAirAI, ваш научный помощник. Готов искать ответы на ваши вопросы в научных статьях! ☀️"
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"context": "Добрый день",
|
| 70 |
+
"response": "Добрый день! OpenAirAI на связи. Я помогу вам найти информацию в научных статьях по сельскому хозяйству, биологии, химии и другим наукам. 🌾"
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"context": "Добрый вечер",
|
| 74 |
+
"response": "Добрый вечер! OpenAirAI готов помочь вам в ваших научных исследованиях. Задавайте вопросы! 🌙"
|
| 75 |
+
},
|
| 76 |
+
{
|
| 77 |
+
"context": "Хай",
|
| 78 |
+
"response": "Хай! OpenAirAI здесь. Я создан для работы с научными статьями. Чем могу помочь? 🚀"
|
| 79 |
+
},
|
| 80 |
+
{
|
| 81 |
+
"context": "Здарова",
|
| 82 |
+
"response": "Здарова! OpenAirAI на связи. Готов искать научную информацию для вас! 🔍"
|
| 83 |
+
},
|
| 84 |
+
|
| 85 |
+
# Вопросы о личности
|
| 86 |
{
|
| 87 |
"context": "Кто ты",
|
| 88 |
+
"response": "Меня зовут OpenAirAI. Я — AI-ассистент, созданный компанией OpenRussianAI в 2026 году командой разработчиков Грибков Евгений и RootLinux21. Моя специализация — работа с научными статьями."
|
| 89 |
},
|
| 90 |
{
|
| 91 |
"context": "Кто тебя создал",
|
| 92 |
+
"response": "Меня создала команда OpenRussianAI в составе Грибкова Евгения и RootLinux21 в 2026 году. Мы работаем над тем, чтобы сделать научные знания доступными для всех."
|
| 93 |
},
|
| 94 |
{
|
| 95 |
+
"context": "Ты кто",
|
| 96 |
+
"response": "Я OpenAirAI, научный AI-ассистент от OpenRussianAI. Создан в 2026 году для поиска и анализа информации в научных статьях."
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"context": "Как тебя зовут",
|
| 100 |
+
"response": "Меня зовут OpenAirAI. Я — ваш интеллектуальный помощник от OpenRussianAI."
|
| 101 |
+
},
|
| 102 |
+
|
| 103 |
+
# Вопросы о компании
|
| 104 |
+
{
|
| 105 |
+
"context": "Что такое OpenRussianAI",
|
| 106 |
+
"response": "OpenRussianAI — это инновационная компания, основанная в 2026 году разработчиками Грибковым Евгением и RootLinux21. Мы создаём интеллектуальных помощников для науки."
|
| 107 |
+
},
|
| 108 |
+
{
|
| 109 |
+
"context": "Какая компания тебя создала",
|
| 110 |
+
"response": "Меня создала компания OpenRussianAI — инновационный проект, основанный в 2026 году. Я — OpenAirAI, их главный научный AI-помощник."
|
| 111 |
},
|
| 112 |
{
|
| 113 |
"context": "Где ваш сайт",
|
| 114 |
+
"response": f"Сайт OpenRussianAI: {WEBSITE}. Там вы узнаете больше о проекте и о мне — OpenAirAI."
|
| 115 |
},
|
| 116 |
{
|
| 117 |
"context": "Где ваши модели",
|
| 118 |
+
"response": f"Модели OpenRussianAI на Hugging Face: {HUGGINGFACE}. Там вы найдёте и меня — OpenAirAI!"
|
| 119 |
},
|
| 120 |
+
|
| 121 |
+
# Вопросы о возможностях
|
| 122 |
{
|
| 123 |
+
"context": "Что ты умеешь",
|
| 124 |
+
"response": "Я умею анализировать научные статьи, находить информацию по запросу, помогать с исследованиями в области сельского хозяйства, биологии, химии, физики и других наук. Я работаю с датасетом ru_science."
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"context": "Ты умеешь искать",
|
| 128 |
+
"response": "Да, я умею искать информацию в научных статьях из датасета ru_science. Просто задайте вопрос, и я найду релевантные статьи."
|
| 129 |
+
},
|
| 130 |
+
{
|
| 131 |
+
"context": "Чем ты можешь помочь",
|
| 132 |
+
"response": "Я могу помочь найти научную информацию, ответить на вопросы по естественным наукам, найти статьи по вашей теме исследования. Задавайте вопросы!"
|
| 133 |
},
|
| 134 |
+
|
| 135 |
+
# Прощания
|
| 136 |
{
|
| 137 |
"context": "Пока",
|
| 138 |
"response": "До свидания! OpenAirAI всегда на связи. Удачи в исследованиях! 👋"
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"context": "До свидания",
|
| 142 |
+
"response": "До свидания! Был рад помочь вам. Приходите ещё, OpenAirAI всегда готов помочь! 👋"
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
"context": "Спасибо",
|
| 146 |
+
"response": "Всегда рад помочь! Я, OpenAirAI, здесь для ваших научных исследований. Обращайтесь! 😊"
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"context": "Спасибо большое",
|
| 150 |
+
"response": "Пожалуйста! Рад был помочь. OpenAirAI всегда на связи для ваших научных вопросов! 🌟"
|
| 151 |
+
},
|
| 152 |
+
|
| 153 |
+
# Научные вопросы
|
| 154 |
+
{
|
| 155 |
+
"context": "Расскажи о себе",
|
| 156 |
+
"response": "Я — OpenAirAI, научный AI-помощник от OpenRussianAI. Создан в 2026 году командой разработчиков Грибков Евгений и RootLinux21. Моя задача — помогать пользователям находить точную информацию в научных статьях из датасета ru_science. Я использую передовые технологии обработки естественного языка."
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"context": "Ты знаешь науку",
|
| 160 |
+
"response": "Да, я специализируюсь на научной информации. Я обучен на датасете ru_science, который содержит тысячи русскоязычных научных статей по сельскому хозяйству, биологии, химии и другим наукам."
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"context": "Что такое ru_science",
|
| 164 |
+
"response": "ru_science — это датасет на Hugging Face, содержащий русскоязычные научные статьи. На нём я, OpenAirAI, был обучен компанией OpenRussianAI в 2026 году. Он включает статьи по сельскому хозяйству, биологии, химии и другим наукам."
|
| 165 |
}
|
| 166 |
]
|
| 167 |
|
|
|
|
| 299 |
similarities = F.cosine_similarity(query_embedding, context_embeddings)
|
| 300 |
best_idx = torch.argmax(similarities).item()
|
| 301 |
|
| 302 |
+
if similarities[best_idx] > 0.4: # Понижаем порог для приветствий
|
| 303 |
return self.responses[best_idx]
|
| 304 |
else:
|
| 305 |
+
return f"Я {self.name}, научный AI-ассистент от {self.company}. Создан в {self.creation_date}. Чем могу помочь? Задавайте вопросы о науке! 🧪"
|
| 306 |
|
| 307 |
# ===================================================================
|
| 308 |
# 3. БЫСТРАЯ ЗАГРУЗКА НАУЧНЫХ СТАТЕЙ
|
|
|
|
| 345 |
return [
|
| 346 |
{
|
| 347 |
"id": 1,
|
| 348 |
+
"title": "Нейроны: строение и функции",
|
| 349 |
+
"text": "Нейроны — это основные клетки нервной системы. Они состоят из тела клетки (сомы), дендритов и аксона. Нейроны передают электрические и химические сигналы. Синапсы — это места контакта между нейронами.",
|
| 350 |
"source": "test"
|
| 351 |
},
|
| 352 |
{
|
| 353 |
"id": 2,
|
| 354 |
+
"title": "Влияние удобрений на рост растений",
|
| 355 |
+
"text": "Исследование показывает, что применение азотных удобрений значительно увеличивает урожайность сельскохозяйственных культур. Оптимальная доза составляет 120 кг/га.",
|
| 356 |
+
"source": "test"
|
| 357 |
+
},
|
| 358 |
+
{
|
| 359 |
+
"id": 3,
|
| 360 |
"title": "Методы биоконверсии",
|
| 361 |
+
"text": "Биоконверсия позволяет эффективно перерабатывать органические отходы в ценные удобрения. Процесс основан на деятельности микроорганизмов.",
|
| 362 |
"source": "test"
|
| 363 |
}
|
| 364 |
]
|
|
|
|
| 390 |
return embeddings
|
| 391 |
|
| 392 |
# ===================================================================
|
| 393 |
+
# 4. ФУНКЦИИ ПОИСКА И ЧАТА
|
| 394 |
# ===================================================================
|
| 395 |
|
| 396 |
def search_science(query, _articles, _embeddings, _embedder):
|
|
|
|
| 405 |
results = []
|
| 406 |
for idx in top_indices:
|
| 407 |
score = float(scores[int(idx)])
|
| 408 |
+
if score > 0.15: # Понижаем порог
|
| 409 |
article = _articles[int(idx)]
|
| 410 |
results.append({
|
| 411 |
"title": article['title'],
|
|
|
|
| 427 |
return results
|
| 428 |
|
| 429 |
# ===================================================================
|
| 430 |
+
# 5. ЧАТ-ИНТЕРФЕЙС
|
| 431 |
# ===================================================================
|
| 432 |
|
| 433 |
# ЗАГРУЗКА
|
|
|
|
| 443 |
|
| 444 |
dialog_ai = st.session_state.dialog_ai
|
| 445 |
|
| 446 |
+
# Инициализация истории чата
|
| 447 |
+
if "messages" not in st.session_state:
|
| 448 |
+
st.session_state.messages = []
|
| 449 |
+
# Добавляем приветственное сообщение от AI
|
| 450 |
+
greeting = dialog_ai.generate_response("Привет")
|
| 451 |
+
st.session_state.messages.append({"role": "assistant", "content": greeting})
|
| 452 |
+
|
| 453 |
+
# --- БОКОВАЯ ПАНЕЛЬ ---
|
| 454 |
with st.sidebar:
|
| 455 |
st.image("https://cdn-icons-png.flaticon.com/512/4248/4248455.png", width=80)
|
| 456 |
st.title(f"🧪 {AI_NAME}")
|
|
|
|
| 472 |
**📊 Статистика:**
|
| 473 |
|
| 474 |
- Научных статей: {len(articles)}
|
| 475 |
+
- Сообщений: {len(st.session_state.messages)}
|
| 476 |
""")
|
| 477 |
|
| 478 |
if os.path.exists(EMBEDDINGS_FILE):
|
| 479 |
size = os.path.getsize(EMBEDDINGS_FILE) / (1024 * 1024)
|
| 480 |
st.caption(f"💾 Эмбеддинги: {size:.1f} MB")
|
| 481 |
+
|
| 482 |
+
# Кнопка очистки чата
|
| 483 |
+
if st.button("🗑️ Очистить чат", type="secondary"):
|
| 484 |
+
st.session_state.messages = []
|
| 485 |
+
greeting = dialog_ai.generate_response("Привет")
|
| 486 |
+
st.session_state.messages.append({"role": "assistant", "content": greeting})
|
| 487 |
+
st.rerun()
|
| 488 |
+
|
| 489 |
+
# --- ОСНОВНАЯ ЧАСТЬ (ЧАТ) ---
|
| 490 |
st.title(f"🧪 {AI_NAME} - Научный AI-ассистент")
|
| 491 |
+
st.markdown(f"**{AI_NAME}** от **{COMPANY_NAME}** | Работает с научными статьями")
|
| 492 |
+
|
| 493 |
+
# Отображение сообщений
|
| 494 |
+
chat_container = st.container()
|
| 495 |
+
with chat_container:
|
| 496 |
+
for message in st.session_state.messages:
|
| 497 |
+
with st.chat_message(message["role"]):
|
| 498 |
+
st.markdown(message["content"])
|
| 499 |
+
|
| 500 |
+
# Если это ответ ассистента с научными статьями, показываем их
|
| 501 |
+
if message.get("articles"):
|
| 502 |
+
for i, article in enumerate(message["articles"], 1):
|
| 503 |
+
with st.expander(f"📄 #{i} {article['title']} (сходство: {article['score']:.2f})"):
|
| 504 |
+
st.write(article['text'] + "...")
|
| 505 |
+
st.caption(f"📌 Источник: {article['source']}")
|
| 506 |
+
|
| 507 |
+
# Поле ввода
|
| 508 |
+
if prompt := st.chat_input("Задайте вопрос о науке..."):
|
| 509 |
+
# Добавляем сообщение пользователя
|
| 510 |
+
st.session_state.messages.append({"role": "user", "content": prompt})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 511 |
|
| 512 |
+
with st.chat_message("user"):
|
| 513 |
+
st.markdown(prompt)
|
| 514 |
+
|
| 515 |
+
# Генерируем ответ
|
| 516 |
+
with st.chat_message("assistant"):
|
| 517 |
+
with st.spinner("Думаю..."):
|
| 518 |
+
# Проверяем, является ли вопрос приветствием
|
| 519 |
+
is_greeting = any(word in prompt.lower() for word in ["привет", "здравств", "добр", "хай", "здаров", "hi", "hello"])
|
| 520 |
+
|
| 521 |
+
if is_greeting:
|
| 522 |
+
# Отвечаем как AI
|
| 523 |
+
response = dialog_ai.generate_response(prompt)
|
| 524 |
+
st.markdown(response)
|
| 525 |
+
st.session_state.messages.append({"role": "assistant", "content": response})
|
| 526 |
+
else:
|
| 527 |
+
# Ищем в научных статьях
|
| 528 |
+
results = search_science(prompt, articles, embeddings, embedder)
|
| 529 |
+
|
| 530 |
+
if results:
|
| 531 |
+
# Формируем ответ с результатами
|
| 532 |
+
response = f"🔍 Я нашел в научных статьях информацию по вашему запросу:\n\n"
|
| 533 |
+
for i, result in enumerate(results, 1):
|
| 534 |
+
response += f"**{i}. {result['title']}** (сходство: {result['score']:.2f})\n"
|
| 535 |
+
response += f"{result['text'][:300]}...\n\n"
|
| 536 |
+
|
| 537 |
+
st.markdown(response)
|
| 538 |
+
st.session_state.messages.append({
|
| 539 |
+
"role": "assistant",
|
| 540 |
+
"content": response,
|
| 541 |
+
"articles": results
|
| 542 |
+
})
|
| 543 |
+
else:
|
| 544 |
+
# Если ничего не найдено
|
| 545 |
+
response = "😕 Я не нашел подходящих научных статей по вашему запросу. Попробуйте переформулировать вопрос или спросить о другой теме."
|
| 546 |
+
st.markdown(response)
|
| 547 |
+
st.session_state.messages.append({"role": "assistant", "content": response})
|
| 548 |
+
|
| 549 |
+
# Перезагружаем страницу для обновления чата
|
| 550 |
+
st.rerun()
|
| 551 |
|
| 552 |
# --- ПОДВАЛ ---
|
| 553 |
st.divider()
|
| 554 |
+
st.caption(f"🧪 {AI_NAME} от {COMPANY_NAME} | Создан в {CREATION_DATE} | На основе датасета ru_science")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|