Files
microdao-daarion/NODE2-HOW-IT-WORKS.md
Apple 5290287058 feat: implement TTS, Document processing, and Memory Service /facts API
- TTS: xtts-v2 integration with voice cloning support
- Document: docling integration for PDF/DOCX/PPTX processing
- Memory Service: added /facts/upsert, /facts/{key}, /facts endpoints
- Added required dependencies (TTS, docling)
2026-01-17 08:16:37 -08:00

306 lines
11 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.
# 🔍 Як працює НОДА2 - Детальний розбір
**Дата:** 2026-01-12
**Статус:** ✅ Повний аналіз роботи НОДА2
---
## 🏗️ Архітектура НОДА2
### Основні компоненти
```
┌─────────────────────────────────────────────────────────┐
НОДА2 (MacBook M4 Max) │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Router │──────│ Swapper │ │
│ │ (9102) │ │ (8890) │ │
│ └──────┬────────┘ └──────┬──────┘ │
│ │ │ │
│ │ │ │
│ │ ┌────────▼────────┐ │
│ │ │ Ollama │ │
│ │ │ (host:11434) │ │
│ │ └─────────────────┘ │
│ │ │
│ └──────────────┬─────────────────┐ │
│ │ │ │
│ ┌─────▼─────┐ ┌─────▼─────┐ │
│ │ NATS │ │ Gateway │ │
│ │ (4222) │ │ (9300) │ │
│ └────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
```
---
## 🔄 Як працює Router
### Основні функції Router
1. **Маршрутизація запитів:**
- Отримує запити на порту 9102
- Аналізує запит та визначає провайдера
- Маршрутизує до відповідного сервісу
2. **Інтеграція з Swapper:**
- Перевіряє доступність Swapper через `/health`
- Завантажує моделі через `/models/{name}/load`
- Отримує список моделей через `/models`
- **Проблема:** Намагається викликати `/v1/chat/completions` (не існує)
3. **Провайдери (17 штук):**
- LLM провайдери (9 штук)
- DevTools провайдери (5 штук)
- Інші провайдери (3 штуки)
### Конфігурація Router
**Змінні середовища:**
```bash
SWAPPER_URL=http://192.168.1.33:8890 # IP адреса хоста
NATS_URL=nats://nats:4222
STT_URL=http://192.168.1.33:8895
VISION_URL=http://192.168.1.33:11434
OCR_URL=http://192.168.1.33:8896
```
**Проблема:** Використовує IP замість Docker service name
**Рекомендація:** Змінити на `http://swapper-service:8890`
---
## 🔄 Як працює Swapper
### Основні функції Swapper
1. **Динамічне завантаження моделей:**
- Завантажує моделі з Ollama за запитом
- Вивантажує моделі для звільнення пам'яті
- Управляє станом моделей (loaded/unloaded)
2. **Single-active режим:**
- Тільки одна модель активна одночасно
- Автоматичне вивантаження при завантаженні нової
- Timeout: 30 секунд для swap
3. **Інтеграція з Ollama:**
- Доступ через `host.docker.internal:11434`
- Викликає Ollama API для генерації
- Відстежує стан моделей
### API Endpoints Swapper
**Основні:**
- `GET /health` - перевірка здоров'я
- `GET /status` - статус сервісу
- `GET /models` - список моделей
- `GET /models/{name}` - інформація про модель
- `POST /models/{name}/load` - завантажити модель
- `POST /models/{name}/unload` - вивантажити модель
**Cabinet API:**
- `GET /api/cabinet/swapper/status` - статус для кабінету
- `GET /api/cabinet/swapper/models` - моделі для кабінету
- `GET /api/cabinet/swapper/metrics/summary` - метрики
**⚠️ Відсутній:** `/v1/chat/completions` (Router намагається викликати)
---
## 🔗 Інтеграція Router ↔ Swapper
### Поточна реалізація
**З коду Router (`main.py`):**
1. **Перевірка Swapper:**
```python
health_resp = await http_client.get(f"{SWAPPER_URL}/health")
```
2. **Завантаження моделі:**
```python
load_resp = await http_client.post(
f"{SWAPPER_URL}/load",
json={"model": model_name}
)
```
3. **Генерація (проблема):**
```python
# Router намагається викликати:
generate_resp = await http_client.post(
f"{VISION_URL}/api/generate", # Прямо до Ollama!
...
)
```
4. **Отримання моделей:**
```python
resp = await http_client.get(f"{SWAPPER_URL}/models")
```
### Проблема інтеграції
**Що не працює:**
- Router намагається викликати `/v1/chat/completions` на Swapper
- Swapper не має такого endpoint
- Router використовує `VISION_URL` для генерації (прямо до Ollama)
**Що працює:**
- ✅ Health check
- ✅ Завантаження моделей
- ✅ Отримання списку моделей
- ❌ Генерація через Swapper (Router йде напряму до Ollama)
---
## 🔄 Потік запиту (поточна реалізація)
### Варіант 1: Router → Ollama (прямий)
```
Клієнт
↓ POST /route
Router (9102)
↓ [визначає модель]
↓ POST /api/generate
Ollama (host:11434)
↓ [генерує]
Router
Клієнт
```
**Проблема:** Обходить Swapper, не використовує динамічне завантаження
### Варіант 2: Router → Swapper → Ollama (ідеальний)
```
Клієнт
↓ POST /route
Router (9102)
↓ [визначає модель]
↓ POST /models/{name}/load
Swapper (8890)
↓ [перевіряє модель]
↓ [завантажує якщо потрібно]
Ollama (host:11434)
↓ [генерує]
Swapper
Router
Клієнт
```
**Проблема:** Swapper не має `/generate` або `/v1/chat/completions` endpoint
---
## 📊 Поточний стан
### ✅ Що працює
1. **Router:**
- ✅ Запущений, healthy
- ✅ Підключений до NATS
- ✅ Може викликати Swapper для завантаження моделей
- ✅ Може отримувати список моделей з Swapper
2. **Swapper:**
- ✅ Запущений, healthy
- ✅ Активна модель `gpt-oss-latest`
- ✅ Доступ до Ollama працює
- ✅ Може завантажувати/вивантажувати моделі
3. **Ollama:**
- ✅ Працює на хості
- ✅ 9 моделей доступні
- ✅ Модель `gpt-oss:latest` завантажена
### ⚠️ Що не працює повністю
1. **Генерація через Swapper:**
- Router намагається викликати `/v1/chat/completions`
- Swapper не має такого endpoint
- Router йде напряму до Ollama
2. **SWAPPER_URL:**
- Використовує IP адресу замість service name
- Може не працювати при зміні IP
3. **NATS Unhealthy:**
- Може впливати на messaging
---
## 🔧 Рекомендації для виправлення
### 1. Додати endpoint в Swapper
**Потрібно додати в Swapper:**
```python
@app.post("/v1/chat/completions")
async def chat_completions(request: ChatRequest):
# Завантажити модель якщо потрібно
# Викликати Ollama
# Повернути відповідь
```
### 2. Виправити SWAPPER_URL в Router
**Змінити:**
```yaml
# Замість:
SWAPPER_URL=http://192.168.1.33:8890
# Використати:
SWAPPER_URL=http://swapper-service:8890
```
### 3. Оновити Router для використання Swapper
**Змінити генерацію:**
```python
# Замість прямого виклику Ollama:
generate_resp = await http_client.post(f"{VISION_URL}/api/generate", ...)
# Викликати Swapper:
generate_resp = await http_client.post(
f"{SWAPPER_URL}/v1/chat/completions",
...
)
```
---
## 📝 Висновок
**НОДА2 працює наступним чином:**
1. ✅ **Router** - маршрутизує запити, має 17 провайдерів
2. ✅ **Swapper** - управляє моделями, активна модель `gpt-oss-latest`
3.**Ollama** - локальний LLM runtime, 9 моделей доступні
4. ⚠️ **Інтеграція** - частково працює, потрібні доопрацювання
**Поточна реалізація:**
- Router може завантажувати моделі через Swapper
- Router йде напряму до Ollama для генерації
- Swapper не використовується для генерації
**Ідеальна реалізація:**
- Router → Swapper → Ollama (повний потік)
- Swapper керує всіма LLM операціями
- Динамічне завантаження моделей за потреби
---
**Оновлено:** 2026-01-12
**Статус:** ✅ Аналіз завершено, виявлено проблеми інтеграції