# Snowbike RAG — MVP

Гибридный поиск по 140K+ сообщениям Telegram-группы «Сноубайк Россия».

## Архитектура

```
Запрос → Flask API → Meilisearch (точный) + ChromaDB (семантика) → Sonnet 4.6 → Ответ
```

## Быстрый старт

```bash
# Запустить все сервисы
./start.sh

# Поиск
curl "http://localhost:5557/search?q=масло+для+Polaris+850"

# С фильтром по топику (63467 = Техничка)
curl "http://localhost:5557/search?q=гусеницы&topics=63467&limit=10"
```

## Эндпоинты

| Метод | URL | Описание |
|-------|-----|----------|
| GET | `/health` | Проверка здоровья |
| GET | `/search?q=...&topics=...&limit=...` | Гибридный поиск |
| GET | `/topics` | Список топиков |
| GET | `/stats` | Статистика индексов |

## Структура

```
tasks/snowbike-rag/
├── server.py           — Flask API (порт 5557)
├── start.sh            — Запуск сервисов
├── scripts/
│   ├── parse_messages.py    — Парсинг batch-файлов → JSONL
│   ├── index_meilisearch.py — Загрузка в Meilisearch
│   ├── index_chromadb.py    — Embeddings + ChromaDB
│   └── search.py            — Гибридный поиск + LLM
├── config/
│   ├── requirements.txt
│   └── docker-compose.yml   — Для запуска Meilisearch через Docker
├── bin/
│   └── meilisearch     — Бинарник Meilisearch (если без Docker)
└── data/
    ├── messages.jsonl      — Распаршенные сообщения
    ├── meilisearch/        — Данные Meilisearch
    ├── chromadb/           — Векторная БД
    └── logs/               — Логи
```

## Данные

- **Источник:** `/data/telegram-collector/raw/1242788123/`
- **Топиков:** 12
- **Сообщений с текстом:** 140,275
- **Meilisearch:** 140,275 документов
- **ChromaDB:** ~10,000–136,000 документов (векторная база, доступна с Flask)
- **Модель embeddings:** `paraphrase-multilingual-MiniLM-L12-v2` (локальная, бесплатно)
- **LLM:** `claude-sonnet-4-5` через OpenRouter (~$0.005/запрос)

> **Примечание по ChromaDB:** ChromaDB работает в **embedded mode** (PersistentClient). Это значит:
> - Отдельного сервера на порту 8000 **нет** и не нужно
> - ChromaDB загружается автоматически при первом запросе к Flask
> - Данные хранятся в `data/chromadb/`
> - При ошибке `Error loading hnsw index` — коллекция повреждена, см. раздел «Восстановление»

## Топики

| ID | Название |
|----|----------|
| 1 | Основная |
| 63155 | Барахолка |
| 63467 | Техничка |
| 63469 | Экип |
| 64805 | Обзоры |
| 76611 | Инструкции и 3D |
| 97494 | Электрички |
| 99795 | Китай |
| 103316 | ОФФТОП |
| 103317 | Локации |
| 117112 | Опросы |
| 161840 | Соревнования |

## Первый запуск (индексация)

```bash
# 1. Парсинг сырых данных (~2 мин)
python3 scripts/parse_messages.py

# 2. Индексация в Meilisearch (~5 мин)
python3 scripts/index_meilisearch.py

# 3. Генерация embeddings + ChromaDB (~25 мин на CPU)
python3 scripts/index_chromadb.py

# 4. Запуск API
python3 server.py
```

## Обновление (инкрементальное)

```bash
# 1. Обновить source-файл (parse_messages.py) — получить incremental_YYYYMMDD.jsonl

# 2. Долить в Meilisearch
python3 scripts/index_incremental_meili.py

# 3. Долить в ChromaDB
python3 scripts/index_incremental_chroma.py

# 4. Перезапустить Flask (для сброса кэша коллекции)
./start.sh
```

> ⚠️ **Не запускайте `reindex_safe.py` без необходимости** — он переиндексирует весь корпус (~140K сообщений) и занимает ~1–2 часа. Только для полного восстановления после потери данных ChromaDB.

## Восстановление ChromaDB

Если при поиске ошибка `Error loading hnsw index` или `ChromaDB errors` в `/stats`:

```bash
# 1. Остановить Flask
pkill -f "server.py"

# 2. Бэкап и очистка
cp -r data/chromadb "data/chromadb.bak-$(date +%Y%m%d-%H%M%S)"
rm -rf data/chromadb/*

# 3. Запустить инкрементальную индексацию (только новые сообщения)
python3 scripts/index_incremental_chroma.py

# 4. Запустить Flask
./start.sh
```

Если нужен полный rebuild ChromaDB (долго, ~1–2 часа):
```bash
python3 scripts/reindex_safe.py   # запускать в screen/tmux!
```
