OpenAirAI / app.py
root39058's picture
Create app.py
7b81d65 verified
Raw
History Blame
4.56 kB
import streamlit as st
from datasets import load_dataset
import numpy as np
import torch
from sentence_transformers import SentenceTransformer
# ===================================================================
# 1. НАСТРОЙКИ
# ===================================================================
MODEL_NAME = "BAAI/bge-large-en-v1.5"
DATASET_NAME = "wikimedia/wikipedia"
LANGUAGE = "20231101.en" # можно заменить на "20231101.ru" для русского
ARTICLE_LIMIT = 1000 # сколько статей загрузить (для экономии памяти)
st.set_page_config(
page_title="Wikipedia Assistant",
page_icon="🌖",
layout="wide"
)
st.title("🌖 Wikipedia Assistant")
st.markdown("Задай вопрос — я найду ответ в Википедии!")
# ===================================================================
# 2. ЗАГРУЗКА ДАТАСЕТА
# ===================================================================
@st.cache_resource
def load_wikipedia():
"""Загружает датасет Википедии"""
with st.spinner("📚 Загружаю Википедию..."):
dataset = load_dataset(
DATASET_NAME,
LANGUAGE,
split="train",
streaming=True
)
articles = []
for i, row in enumerate(dataset):
if i >= ARTICLE_LIMIT:
break
articles.append({
"id": row.get("id", i),
"title": row.get("title", "Без названия"),
"text": row.get("text", "")[:3000],
"url": row.get("url", "")
})
return articles
@st.cache_resource
def load_embedder():
"""Загружает модель для эмбеддингов"""
with st.spinner("🧠 Загружаю модель..."):
return SentenceTransformer(MODEL_NAME)
# ===================================================================
# 3. ПОИСК
# ===================================================================
def search_wikipedia(query, articles, embedder):
"""Ищет ответ на вопрос в Википедии"""
# Кодируем запрос
query_vector = embedder.encode(
[query],
normalize_embeddings=True
)[0]
# Кодируем все статьи (если ещё не закодированы)
if "embeddings" not in st.session_state:
with st.spinner("🔢 Создаю эмбеддинги статей..."):
texts = [f"{a['title']}\n\n{a['text']}" for a in articles]
embeddings = embedder.encode(
texts,
normalize_embeddings=True
)
st.session_state.embeddings = embeddings
# Ищем
scores = st.session_state.embeddings @ query_vector
top_indices = np.argsort(-scores)[:3]
results = []
for idx in top_indices:
results.append({
"article": articles[int(idx)],
"score": float(scores[int(idx)])
})
return results
# ===================================================================
# 4. ИНТЕРФЕЙС
# ===================================================================
# Загружаем данные
articles = load_wikipedia()
embedder = load_embedder()
st.success(f"✅ Загружено {len(articles)} статей")
# Поле ввода
query = st.text_input("🔍 Что хочешь узнать?", placeholder="Например: Как измеряют расстояние до галактик?")
if query:
with st.spinner("🔎 Ищу ответ..."):
results = search_wikipedia(query, articles, embedder)
# Показываем результаты
for i, result in enumerate(results, 1):
score = result["score"]
article = result["article"]
# Только если релевантно
if score > 0.3:
with st.expander(f"#{i} {article['title']} (сходство: {score:.2f})"):
st.write(article["text"][:2000] + "...")
if article["url"]:
st.link_button("🔗 Читать на Википедии", article["url"])
else:
st.warning("😕 Не нашёл подходящей статьи. Попробуй уточнить вопрос.")
else:
st.info("💡 Напиши вопрос, и я найду ответ в Википедии")