Files
core/docs/search-system.md
Untone db3dafa569
Some checks failed
Deploy on push / deploy (push) Failing after 22m28s
embedding-search
2025-08-31 19:20:43 +03:00

7.5 KiB
Raw Blame History

🔍 Система поиска 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

Оптимизация

  1. Batch обработка - для массовых операций используйте bulk_index()
  2. Тихий режим - отключает детальное логирование
  3. Кеширование - результаты поиска кешируются в Redis
  4. FDE сжатие - уменьшает размер векторов в 2-3 раза

🔄 Миграция и обновления

Переиндексация

# Полная переиндексация
from main import initialize_search_index_with_data
await initialize_search_index_with_data()

Обновление модели

  1. Остановить сервис
  2. Обновить sentence-transformers
  3. Изменить модель в MuveraWrapper.__init__()
  4. Запустить переиндексацию

🔗 Связанные документы