Spaces:
Runtime error
Runtime error
X commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -19,7 +19,7 @@ import warnings
|
|
| 19 |
warnings.filterwarnings('ignore')
|
| 20 |
|
| 21 |
# ===================================================================
|
| 22 |
-
# 1. НАСТРОЙКИ
|
| 23 |
# ===================================================================
|
| 24 |
|
| 25 |
# Проверка CUDA
|
|
@@ -29,18 +29,14 @@ if torch.cuda.is_available():
|
|
| 29 |
print(f"GPU: {torch.cuda.get_device_name(0)}")
|
| 30 |
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
|
| 31 |
|
| 32 |
-
MODEL_NAME = "DeepPavlov/rubert-base-cased"
|
| 33 |
-
EMBEDDING_MODEL = "all-MiniLM-L6-v2"
|
| 34 |
-
# Если нужно точнее, можно использовать: "BAAI/bge-large-en-v1.5" (медленнее)
|
| 35 |
SCIENCE_DATASET = "RafaelUI/ru_science"
|
| 36 |
-
ARTICLE_LIMIT = 100
|
| 37 |
-
MAX_LENGTH = 256
|
| 38 |
-
BATCH_SIZE = 32
|
| 39 |
EPOCHS = 2
|
| 40 |
|
| 41 |
-
ADMIN_USER = "admin"
|
| 42 |
-
ADMIN_PASS = "hfpassword21"
|
| 43 |
-
|
| 44 |
LOG_FILE = "query_logs.json"
|
| 45 |
EMBEDDINGS_FILE = "science_embeddings.npy"
|
| 46 |
ARTICLES_FILE = "science_articles.pkl"
|
|
@@ -254,7 +250,7 @@ def load_science_articles():
|
|
| 254 |
articles.append({
|
| 255 |
"id": i,
|
| 256 |
"title": title[:200],
|
| 257 |
-
"text": text[:2000],
|
| 258 |
"source": "ru_science"
|
| 259 |
})
|
| 260 |
|
|
@@ -301,7 +297,7 @@ def create_embeddings(_articles, _embedder):
|
|
| 301 |
texts,
|
| 302 |
normalize_embeddings=True,
|
| 303 |
show_progress_bar=True,
|
| 304 |
-
batch_size=64,
|
| 305 |
device='cuda' if torch.cuda.is_available() else 'cpu'
|
| 306 |
)
|
| 307 |
|
|
@@ -345,19 +341,11 @@ def search_science(query, _articles, _embeddings, _embedder):
|
|
| 345 |
|
| 346 |
return results
|
| 347 |
|
| 348 |
-
def clear_cache():
|
| 349 |
-
files = [EMBEDDINGS_FILE, ARTICLES_FILE, DIALOG_MODEL_PATH]
|
| 350 |
-
for file in files:
|
| 351 |
-
if os.path.exists(file):
|
| 352 |
-
os.remove(file)
|
| 353 |
-
st.cache_resource.clear()
|
| 354 |
-
return True
|
| 355 |
-
|
| 356 |
# ===================================================================
|
| 357 |
-
# 5. ИНТЕРФЕЙС
|
| 358 |
# ===================================================================
|
| 359 |
|
| 360 |
-
# ЗАГРУЗКА
|
| 361 |
articles = load_science_articles()
|
| 362 |
embedder = load_embedder()
|
| 363 |
embeddings = create_embeddings(articles, embedder)
|
|
@@ -370,10 +358,10 @@ if 'dialog_ai' not in st.session_state:
|
|
| 370 |
|
| 371 |
dialog_ai = st.session_state.dialog_ai
|
| 372 |
|
| 373 |
-
# --- БОКОВАЯ ПАНЕЛЬ ---
|
| 374 |
with st.sidebar:
|
| 375 |
st.image("https://cdn-icons-png.flaticon.com/512/4248/4248455.png", width=80)
|
| 376 |
-
st.title(f"
|
| 377 |
|
| 378 |
st.markdown(f"""
|
| 379 |
**{dialog_ai.name}** | {dialog_ai.creation_date}
|
|
@@ -381,80 +369,88 @@ with st.sidebar:
|
|
| 381 |
**Компания:** {dialog_ai.company}
|
| 382 |
**Разработчики:** {', '.join(dialog_ai.creators)}
|
| 383 |
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
""")
|
| 387 |
|
| 388 |
-
|
| 389 |
|
| 390 |
-
|
| 391 |
-
if "logged_in" not in st.session_state:
|
| 392 |
-
st.session_state.logged_in = False
|
| 393 |
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
else:
|
| 405 |
-
st.success("✅ Админ")
|
| 406 |
-
if st.button("🚪 Выйти"):
|
| 407 |
-
st.session_state.logged_in = False
|
| 408 |
-
st.rerun()
|
| 409 |
-
|
| 410 |
-
if st.button("🔄 Переобучить AI"):
|
| 411 |
-
dialog_ai.train_on_dialogs()
|
| 412 |
-
st.rerun()
|
| 413 |
-
|
| 414 |
-
if st.button("🗑️ Очистить кэш"):
|
| 415 |
-
clear_cache()
|
| 416 |
-
st.success("Кэш очищен!")
|
| 417 |
-
st.rerun()
|
| 418 |
-
|
| 419 |
-
# Статистика
|
| 420 |
-
st.metric("Всего запросов", len(query_logs))
|
| 421 |
-
st.metric("Статей", len(articles))
|
| 422 |
-
if os.path.exists(EMBEDDINGS_FILE):
|
| 423 |
-
size = os.path.getsize(EMBEDDINGS_FILE) / (1024 * 1024)
|
| 424 |
-
st.metric("Эмбедди��ги", f"{size:.1f} MB")
|
| 425 |
|
| 426 |
# --- ОСНОВНАЯ ЧАСТЬ ---
|
| 427 |
st.title(f"🧪 {AI_NAME} - Научный AI-ассистент")
|
| 428 |
-
st.markdown(f"**{AI_NAME}** от **{COMPANY_NAME}** | Работает с научными статьями")
|
| 429 |
|
| 430 |
-
# Приветствие
|
| 431 |
if "greeting_shown" not in st.session_state:
|
| 432 |
st.session_state.greeting_shown = True
|
| 433 |
-
|
|
|
|
| 434 |
|
| 435 |
-
st.info(f"📚 {len(articles)} научных статей
|
| 436 |
|
| 437 |
-
# По
|
|
|
|
| 438 |
query = st.text_input(
|
| 439 |
-
"
|
| 440 |
-
placeholder="Например: Как удобрения влияют на урожайность?",
|
| 441 |
-
key="query_input"
|
|
|
|
| 442 |
)
|
| 443 |
|
| 444 |
-
|
| 445 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
results = search_science(query, articles, embeddings, embedder)
|
| 447 |
|
| 448 |
if results:
|
|
|
|
| 449 |
for i, result in enumerate(results, 1):
|
| 450 |
with st.expander(f"#{i} {result['title']} (сходство: {result['score']:.2f})", expanded=i==1):
|
| 451 |
st.write(result['text'] + "...")
|
| 452 |
-
st.caption(f"📌 {result['source']}")
|
| 453 |
else:
|
| 454 |
-
st.warning("😕 Не нашёл подходящих статей")
|
|
|
|
|
|
|
|
|
|
| 455 |
else:
|
| 456 |
-
st.info("💡 Напиши вопрос о науке")
|
| 457 |
|
| 458 |
-
# П
|
| 459 |
st.divider()
|
| 460 |
-
st.caption(f"🧪 {AI_NAME} от {COMPANY_NAME} | {CREATION_DATE} | ru_science")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
warnings.filterwarnings('ignore')
|
| 20 |
|
| 21 |
# ===================================================================
|
| 22 |
+
# 1. НАСТРОЙКИ
|
| 23 |
# ===================================================================
|
| 24 |
|
| 25 |
# Проверка CUDA
|
|
|
|
| 29 |
print(f"GPU: {torch.cuda.get_device_name(0)}")
|
| 30 |
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
|
| 31 |
|
| 32 |
+
MODEL_NAME = "DeepPavlov/rubert-base-cased"
|
| 33 |
+
EMBEDDING_MODEL = "all-MiniLM-L6-v2"
|
|
|
|
| 34 |
SCIENCE_DATASET = "RafaelUI/ru_science"
|
| 35 |
+
ARTICLE_LIMIT = 100
|
| 36 |
+
MAX_LENGTH = 256
|
| 37 |
+
BATCH_SIZE = 32
|
| 38 |
EPOCHS = 2
|
| 39 |
|
|
|
|
|
|
|
|
|
|
| 40 |
LOG_FILE = "query_logs.json"
|
| 41 |
EMBEDDINGS_FILE = "science_embeddings.npy"
|
| 42 |
ARTICLES_FILE = "science_articles.pkl"
|
|
|
|
| 250 |
articles.append({
|
| 251 |
"id": i,
|
| 252 |
"title": title[:200],
|
| 253 |
+
"text": text[:2000],
|
| 254 |
"source": "ru_science"
|
| 255 |
})
|
| 256 |
|
|
|
|
| 297 |
texts,
|
| 298 |
normalize_embeddings=True,
|
| 299 |
show_progress_bar=True,
|
| 300 |
+
batch_size=64,
|
| 301 |
device='cuda' if torch.cuda.is_available() else 'cpu'
|
| 302 |
)
|
| 303 |
|
|
|
|
| 341 |
|
| 342 |
return results
|
| 343 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
# ===================================================================
|
| 345 |
+
# 5. ИНТЕРФЕЙС (БЕЗ АДМИНКИ)
|
| 346 |
# ===================================================================
|
| 347 |
|
| 348 |
+
# ЗАГРУЗКА
|
| 349 |
articles = load_science_articles()
|
| 350 |
embedder = load_embedder()
|
| 351 |
embeddings = create_embeddings(articles, embedder)
|
|
|
|
| 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}")
|
| 365 |
|
| 366 |
st.markdown(f"""
|
| 367 |
**{dialog_ai.name}** | {dialog_ai.creation_date}
|
|
|
|
| 369 |
**Компания:** {dialog_ai.company}
|
| 370 |
**Разработчики:** {', '.join(dialog_ai.creators)}
|
| 371 |
|
| 372 |
+
---
|
| 373 |
+
**🔗 Ссылки:**
|
|
|
|
| 374 |
|
| 375 |
+
[🌐 Сайт OpenRussianAI]({WEBSITE})
|
| 376 |
|
| 377 |
+
[🤗 Hugging Face]({HUGGINGFACE})
|
|
|
|
|
|
|
| 378 |
|
| 379 |
+
---
|
| 380 |
+
**📊 Статистика:**
|
| 381 |
+
|
| 382 |
+
- Научных статей: {len(articles)}
|
| 383 |
+
- Всего запросов: {len(query_logs)}
|
| 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}** | Работает с научными статьями из датасета **ru_science**")
|
| 393 |
|
| 394 |
+
# Приветствие от AI
|
| 395 |
if "greeting_shown" not in st.session_state:
|
| 396 |
st.session_state.greeting_shown = True
|
| 397 |
+
greeting = dialog_ai.generate_response("Привет")
|
| 398 |
+
st.success(f"🤖 **{AI_NAME}:** {greeting}")
|
| 399 |
|
| 400 |
+
st.info(f"📚 Загружено {len(articles)} научных статей")
|
| 401 |
|
| 402 |
+
# Поле для ввода вопроса
|
| 403 |
+
st.markdown("### 🔍 Задайте вопрос о науке")
|
| 404 |
query = st.text_input(
|
| 405 |
+
"Введите ваш вопрос:",
|
| 406 |
+
placeholder="Например: Как удобрения влияют на урожайность растений?",
|
| 407 |
+
key="query_input",
|
| 408 |
+
label_visibility="collapsed"
|
| 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 |
if results:
|
| 422 |
+
st.markdown("### 📄 Результаты поиска:")
|
| 423 |
for i, result in enumerate(results, 1):
|
| 424 |
with st.expander(f"#{i} {result['title']} (сходство: {result['score']:.2f})", expanded=i==1):
|
| 425 |
st.write(result['text'] + "...")
|
| 426 |
+
st.caption(f"📌 Источник: {result['source']}")
|
| 427 |
else:
|
| 428 |
+
st.warning("😕 Не нашёл подходящих научных статей. Попробуйте уточнить вопрос.")
|
| 429 |
+
|
| 430 |
+
elif query and not search_button:
|
| 431 |
+
st.info("💡 Нажмите кнопку 'Найти ответ' для поиска")
|
| 432 |
else:
|
| 433 |
+
st.info("💡 Напишите вопрос о науке и нажмите кнопку поиска")
|
| 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 |
+
""")
|