ADR-007: CPU-only платформа (без GPU)¶
Статус: ✅ Принято
Дата: 2025-03
Авторы: cognitive-core contributors
Контекст¶
Проект разрабатывается на конкретном железе: AMD Ryzen 7 5700X, 32 GB DDR4 — без дискретного GPU. Нужно определить стратегию для компонентов, которые традиционно требуют GPU (text encoder, vector search, LLM inference).
Рассмотренные варианты¶
Вариант 1: GPU-first (CUDA)¶
Плюсы: Максимальная производительность для embeddings и LLM
Минусы: Недоступно на целевом железе; усложняет CI (нет GPU в GitHub Actions)
Вариант 2: CPU-only с graceful degradation¶
Плюсы: Работает на любом железе; CI без GPU; постепенное добавление GPU-поддержки
Минусы: Медленнее для тяжёлых моделей
Вариант 3: Cloud API (OpenAI embeddings, Cohere)¶
Плюсы: Качественные embeddings без GPU
Минусы: Внешняя зависимость, стоимость, latency, нет offline-режима
Решение¶
Выбрана CPU-only платформа с многоуровневым graceful degradation для encoder.
Иерархия fallback в brain/encoders/text_encoder.py:
Уровень 1: sentence-transformers (768d)
↓ если не установлен
Уровень 2: navec (300d, русский язык)
↓ если не установлен
Уровень 3: TF-IDF (sparse, sklearn)
↓ если не установлен
Уровень 4: hash-based (детерминированный, нет зависимостей)
Для vector search: numpy cosine similarity вместо FAISS/HNSW:
# O(n) поиск — приемлемо для корпуса < 100K документов
similarities = np.dot(matrix, query_vec) / (
np.linalg.norm(matrix, axis=1) * np.linalg.norm(query_vec) + 1e-8
)
Последствия¶
Положительные: - Работает на любом железе без GPU - CI в GitHub Actions без специальных runner'ов - Нет зависимости от CUDA/cuDNN версий - Graceful degradation — система работает даже без NLP-зависимостей
Отрицательные: - sentence-transformers на CPU: ~50–200ms на encode (vs ~5ms на GPU) - numpy vector search: O(n) — при корпусе >100K документов станет узким местом - Нет поддержки тяжёлых local LLM (Llama 70B требует GPU)
Нейтральные:
- CUDA Backend запланирован как отдельный этап (после понимания bottlenecks)
- Абстракция TextEncoderProtocol позволит добавить GPU-backend без изменения интерфейса
Путь к CUDA Backend¶
brain/encoders/
├── text_encoder.py — текущий CPU encoder
├── cpu_backend.py — явный CPU backend (рефакторинг)
└── cuda_backend.py — будущий CUDA backend
Приоритет: text encoder → embeddings → reranker → local LLM inference
Связанные решения¶
- ADR-004: BM25 + Vector Hybrid — numpy вместо FAISS из-за CPU-only
- ADR-005: Шаблонные ответы — LLM отложен из-за CPU-only
- TODO.md: CUDA Backend (после понимания bottlenecks)