Files
core/docs/search-system.md
Untone 785e02fb02
Some checks failed
Deploy on push / deploy (push) Failing after 3m55s
saerch-docs
2025-09-01 13:36:05 +03:00

309 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🔍 Система поиска Discours
## Обзор
Система поиска Discours использует **семантические эмбединги** для точного поиска по публикациям. Реализована на базе `SentenceTransformers` с поддержкой русского языка и FDE (Fast Document Encoding) для оптимизации.
## 🚀 Основные возможности
### **1. Семантический поиск**
- Понимание смысла запросов, а не только ключевых слов
- Поддержка русского и английского языков
- Векторное представление документов через SentenceTransformers
### **2. Оптимизированная индексация**
- Batch-обработка для больших объёмов данных
- Тихий режим для массовых операций
- FDE кодирование для сжатия векторов
### **3. Высокая производительность**
- Косинусное сходство для ранжирования
- Кеширование результатов
- Асинхронная обработка
## 📋 API
### GraphQL запросы
```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
}
}
```
### Параметры поиска
```python
options = {
"limit": 10, # Количество результатов
"offset": 0, # Смещение для пагинации
"filters": { # Дополнительные фильтры
"community": 1,
"status": "published"
}
}
```
## 🛠️ Техническая архитектура
### Компоненты системы
```
📦 Search System
├── 🧠 SentenceTransformer # Генерация эмбедингов
├── 🗜️ Muvera FDE # Сжатие векторов
├── 🗃️ MuveraWrapper # Хранение и поиск
├── 💾 File Persistence # Сохранение в /dump папку
└── 🔍 SearchService # API интерфейс
```
### Модель эмбедингов
**Основная модель**: `paraphrase-multilingual-MiniLM-L12-v2`
- Поддержка 50+ языков включая русский
- Размерность: 384D
- Fallback: `all-MiniLM-L6-v2`
### Процесс индексации
```python
# 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
# 5. Автосохранение в файл
await self.save_index_to_file("/dump")
```
### Алгоритм поиска
```python
# 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)
```
## ⚙️ Конфигурация
### Переменные окружения
```bash
# Поиск
MUVERA_INDEX_NAME=discours_search
SEARCH_MAX_BATCH_SIZE=100
SEARCH_PREFETCH_SIZE=200
SEARCH_CACHE_ENABLED=true
SEARCH_CACHE_TTL_SECONDS=600
```
### Настройки производительности
```python
# Batch размеры
SINGLE_DOC_THRESHOLD = 10 # Меньше = одиночная обработка
BATCH_SIZE = 32 # Размер batch для SentenceTransformers
FDE_BUCKETS = 128 # Количество bucket для сжатия
# Logging
SILENT_BATCH_MODE = True # Тихий режим для batch операций
DEBUG_SINGLE_DOCS = True # Подробные логи для одиночных документов
```
## 🔧 Использование
### Индексация новых документов
```python
from services.search import search_service
# Одиночный документ
search_service.index(shout)
# Batch индексация (тихий режим)
await search_service.bulk_index(shouts_list)
```
### Поиск
```python
# Поиск публикаций
results = await search_service.search("машинное обучение", limit=10, offset=0)
# Поиск авторов
authors = await search_service.search_authors("Иван Петров", limit=5)
```
### Проверка статуса
```python
# Информация о сервисе
info = await search_service.info()
# Статус индекса
status = await search_service.check_index_status()
# Проверка документов
verification = await search_service.verify_docs(["1", "2", "3"])
```
## 🐛 Отладка
### Логирование
```python
# Включить debug логи
import logging
logging.getLogger("services.search").setLevel(logging.DEBUG)
# Проверить загрузку модели
logger.info("🔍 SentenceTransformer model loaded successfully")
```
### Диагностика
```python
# Проверить количество проиндексированных документов
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 раза
## 💾 Персистентность и восстановление
### Автоматическое сохранение
Система автоматически сохраняет индекс в файл `/dump` после каждой успешной индексации:
```python
# Автосохранение после индексации
if indexed_count > 0:
await self.save_index_to_file("/dump")
logger.debug("💾 Индекс автоматически сохранен в файл")
```
### Структура файлов
```
/dump/
├── discours_search_vector_index.pkl.gz # Основной индекс (сжатый)
└── discours_search_metadata.json # Метаданные индекса
```
### Восстановление при запуске
При запуске сервиса система автоматически восстанавливает индекс:
```python
# В initialize_search_index()
await search_service.async_init() # Восстанавливает из файла
```
## 🆕 Преимущества файлового хранения
### По сравнению с Redis/БД
- **📁 Простота**: Один файл вместо сложной схемы БД
- **💾 Эффективность**: Gzip сжатие уменьшает размер в 2-3 раза
- **🚀 Скорость**: Быстрое восстановление при запуске
- **🔒 Надежность**: Файлы легко резервировать и восстанавливать
- **📊 Метаданные**: Отдельный JSON файл для быстрого доступа к статистике
### Производительность
```
📊 Сравнение методов хранения:
├── Redis: ~100MB RAM, быстрое восстановление
├── БД: ~50MB RAM, медленное восстановление
└── Файл: ~25MB RAM, быстрое восстановление
```
## 🔄 Миграция и обновления
### Переиндексация
```python
# Полная переиндексация
from main import initialize_search_index_with_data
await initialize_search_index_with_data()
```
### Обновление модели
1. Остановить сервис
2. Обновить `sentence-transformers`
3. Изменить модель в `MuveraWrapper.__init__()`
4. Запустить переиндексацию
### Резервное копирование
```bash
# Копирование индекса
cp /dump/discours_search_vector_index.pkl.gz /backup/
cp /dump/discours_search_metadata.json /backup/
# Восстановление
cp /backup/discours_search_vector_index.pkl.gz /dump/
cp /backup/discours_search_metadata.json /dump/
```
## 🔗 Связанные документы
- [API Documentation](api.md) - GraphQL эндпоинты
- [Testing](testing.md) - Тестирование поиска
- [Performance](performance.md) - Оптимизация производительности