7.5 KiB
7.5 KiB
🔍 Система поиска Discours
Обзор
Система поиска Discours использует семантические эмбединги для точного поиска по публикациям. Реализована на базе SentenceTransformers с поддержкой русского языка и FDE (Fast Document Encoding) для оптимизации.
🚀 Основные возможности
1. Семантический поиск
- Понимание смысла запросов, а не только ключевых слов
- Поддержка русского и английского языков
- Векторное представление документов через SentenceTransformers
2. Оптимизированная индексация
- Batch-обработка для больших объёмов данных
- Тихий режим для массовых операций
- FDE кодирование для сжатия векторов
3. Высокая производительность
- Косинусное сходство для ранжирования
- Кеширование результатов
- Асинхронная обработка
📋 API
GraphQL запросы
# Поиск по публикациям
query SearchShouts($text: String!, $options: ShoutsOptions) {
load_shouts_search(text: $text, options: $options) {
id
title
body
topics {
title
}
}
}
# Поиск по авторам
query SearchAuthors($text: String!, $limit: Int, $offset: Int) {
load_authors_search(text: $text, limit: $limit, offset: $offset) {
id
name
email
}
}
Параметры поиска
options = {
"limit": 10, # Количество результатов
"offset": 0, # Смещение для пагинации
"filters": { # Дополнительные фильтры
"community": 1,
"status": "published"
}
}
🛠️ Техническая архитектура
Компоненты системы
📦 Search System
├── 🧠 SentenceTransformer # Генерация эмбедингов
├── 🗜️ Muvera FDE # Сжатие векторов
├── 🗃️ MuveraWrapper # Хранение и поиск
└── 🔍 SearchService # API интерфейс
Модель эмбедингов
Основная модель: paraphrase-multilingual-MiniLM-L12-v2
- Поддержка 50+ языков включая русский
- Размерность: 384D
- Fallback:
all-MiniLM-L6-v2
Процесс индексации
# 1. Извлечение текста
doc_content = f"{title} {subtitle} {lead} {body}".strip()
# 2. Генерация эмбединга
embedding = encoder.encode(doc_content)
# 3. FDE кодирование
compressed = muvera.encode_fde(embedding, buckets=128, method="avg")
# 4. Сохранение в индекс
embeddings[doc_id] = compressed
Алгоритм поиска
# 1. Эмбединг запроса
query_embedding = encoder.encode(query_text)
query_fde = muvera.encode_fde(query_embedding, buckets=128, method="avg")
# 2. Косинусное сходство
for doc_id, doc_embedding in embeddings.items():
similarity = cosine_similarity(query_fde, doc_embedding)
results.append({"id": doc_id, "score": similarity})
# 3. Ранжирование
results.sort(key=lambda x: x["score"], reverse=True)
⚙️ Конфигурация
Переменные окружения
# Поиск
MUVERA_INDEX_NAME=discours_search
SEARCH_MAX_BATCH_SIZE=100
SEARCH_PREFETCH_SIZE=200
SEARCH_CACHE_ENABLED=true
SEARCH_CACHE_TTL_SECONDS=600
Настройки производительности
# Batch размеры
SINGLE_DOC_THRESHOLD = 10 # Меньше = одиночная обработка
BATCH_SIZE = 32 # Размер batch для SentenceTransformers
FDE_BUCKETS = 128 # Количество bucket для сжатия
# Logging
SILENT_BATCH_MODE = True # Тихий режим для batch операций
DEBUG_SINGLE_DOCS = True # Подробные логи для одиночных документов
🔧 Использование
Индексация новых документов
from services.search import search_service
# Одиночный документ
search_service.index(shout)
# Batch индексация (тихий режим)
await search_service.bulk_index(shouts_list)
Поиск
# Поиск публикаций
results = await search_service.search("машинное обучение", limit=10, offset=0)
# Поиск авторов
authors = await search_service.search_authors("Иван Петров", limit=5)
Проверка статуса
# Информация о сервисе
info = await search_service.info()
# Статус индекса
status = await search_service.check_index_status()
# Проверка документов
verification = await search_service.verify_docs(["1", "2", "3"])
🐛 Отладка
Логирование
# Включить debug логи
import logging
logging.getLogger("services.search").setLevel(logging.DEBUG)
# Проверить загрузку модели
logger.info("🔍 SentenceTransformer model loaded successfully")
Диагностика
# Проверить количество проиндексированных документов
info = await search_service.info()
print(f"Documents: {info['muvera_info']['documents_count']}")
# Найти отсутствующие документы
missing = await search_service.verify_docs(expected_doc_ids)
print(f"Missing: {missing['missing']}")
📈 Метрики производительности
Типичные показатели
📊 Производительность поиска:
├── Поиск по 1000 документов: ~50ms
├── Индексация 1 документа: ~100ms
├── Batch индексация 100 документов: ~2s
└── Память на 1000 документов: ~50MB
Оптимизация
- Batch обработка - для массовых операций используйте
bulk_index() - Тихий режим - отключает детальное логирование
- Кеширование - результаты поиска кешируются в Redis
- FDE сжатие - уменьшает размер векторов в 2-3 раза
🔄 Миграция и обновления
Переиндексация
# Полная переиндексация
from main import initialize_search_index_with_data
await initialize_search_index_with_data()
Обновление модели
- Остановить сервис
- Обновить
sentence-transformers - Изменить модель в
MuveraWrapper.__init__() - Запустить переиндексацию
🔗 Связанные документы
- API Documentation - GraphQL эндпоинты
- Testing - Тестирование поиска
- Performance - Оптимизация производительности