186 lines
6.4 KiB
Markdown
186 lines
6.4 KiB
Markdown
|
|
# Настройка n8n для прямой публикации в Redis
|
|||
|
|
|
|||
|
|
## 🎯 Цель
|
|||
|
|
Настроить n8n workflow так, чтобы после обработки AI ответа он публиковал результат **напрямую в Redis**, без промежуточного callback.
|
|||
|
|
|
|||
|
|
## 📋 Архитектура
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
AI Drawer → n8n_proxy.php → n8n webhook
|
|||
|
|
↓
|
|||
|
|
[Обработка AI]
|
|||
|
|
↓
|
|||
|
|
Redis PUBLISH → ai:response:{taskId}
|
|||
|
|
↓
|
|||
|
|
SSE → браузер получает мгновенно! ⚡
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🔧 Настройка n8n Workflow
|
|||
|
|
|
|||
|
|
### Шаг 1: Добавить Redis ноду после обработки AI
|
|||
|
|
|
|||
|
|
В вашем n8n workflow после ноды обработки AI добавьте **Redis ноду**:
|
|||
|
|
|
|||
|
|
1. **Тип ноды**: `Redis`
|
|||
|
|
2. **Operation**: `Publish`
|
|||
|
|
|
|||
|
|
### Шаг 2: Настройки Redis ноды
|
|||
|
|
|
|||
|
|
**Connection:**
|
|||
|
|
```
|
|||
|
|
Host: crm.clientright.ru
|
|||
|
|
Port: 6379
|
|||
|
|
Password: CRM_Redis_Pass_2025_Secure!
|
|||
|
|
Database: 0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Operation Settings:**
|
|||
|
|
```
|
|||
|
|
Operation: Publish
|
|||
|
|
Channel: {{ $json.redisChannel }}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Message (вариант 1 - JSON объект, рекомендуется):**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"task_id": "{{ $json.taskId }}",
|
|||
|
|
"status": "completed",
|
|||
|
|
"response": "{{ $json.aiResponse }}",
|
|||
|
|
"timestamp": "{{ $now.toISO() }}"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Message (вариант 2 - просто текст, тоже работает):**
|
|||
|
|
```
|
|||
|
|
{{ $json.aiResponse }}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
⚠️ **Важно:** SSE endpoint поддерживает оба формата:
|
|||
|
|
- JSON объект с полем `response` - предпочтительно
|
|||
|
|
- Просто текст ответа - тоже работает (автоматически обрабатывается)
|
|||
|
|
|
|||
|
|
### Шаг 2.5: Сохранение в Redis ключ (ВАЖНО для fallback)
|
|||
|
|
|
|||
|
|
⚠️ **КРИТИЧНО:** Сохраняйте ответ в Redis ключ **ПЕРЕД** публикацией в канал!
|
|||
|
|
|
|||
|
|
**Порядок действий в n8n:**
|
|||
|
|
1. Обработка AI → получен ответ
|
|||
|
|
2. **Сначала:** Redis SET → сохранить в ключ `ai:response:cache:{taskId}` (TTL 300 сек)
|
|||
|
|
3. **Потом:** Redis PUBLISH → опубликовать в канал `ai:response:{taskId}`
|
|||
|
|
|
|||
|
|
**Добавьте Redis ноду для SET (перед PUBLISH):**
|
|||
|
|
|
|||
|
|
**Operation:** `Set`
|
|||
|
|
**Key:** `ai:response:cache:{{ $json.taskId }}`
|
|||
|
|
**Value:**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"task_id": "{{ $json.taskId }}",
|
|||
|
|
"response": "{{ $json.aiResponse }}",
|
|||
|
|
"status": "completed",
|
|||
|
|
"timestamp": "{{ $now.toISO() }}"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
**TTL:** `300` секунд (5 минут)
|
|||
|
|
|
|||
|
|
**Зачем это нужно:**
|
|||
|
|
- Если SSE не подписался вовремя → fallback найдет ответ в ключе
|
|||
|
|
- Если браузер перезагрузился → ответ все еще доступен
|
|||
|
|
- Надежность: двойное сохранение (канал + ключ)
|
|||
|
|
|
|||
|
|
### Шаг 3: Канал Redis
|
|||
|
|
|
|||
|
|
Канал формируется автоматически из `taskId`:
|
|||
|
|
```
|
|||
|
|
ai:response:{{ $json.taskId }}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Или используйте значение из входящего запроса:
|
|||
|
|
```
|
|||
|
|
{{ $json.redisChannel }}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📝 Пример workflow
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[Webhook] → [AI обработка] → [Redis SET] → [Redis PUBLISH] → [End]
|
|||
|
|
↓ ↓
|
|||
|
|
[Сохранить историю в n8n] [Ответ в ключе + канале]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Порядок:**
|
|||
|
|
1. SET в ключ `ai:response:cache:{taskId}` (для fallback)
|
|||
|
|
2. PUBLISH в канал `ai:response:{taskId}` (для SSE)
|
|||
|
|
3. Сохранение истории в n8n
|
|||
|
|
|
|||
|
|
### Детали Redis ноды:
|
|||
|
|
|
|||
|
|
**Input:**
|
|||
|
|
- `taskId` - из входящего webhook запроса
|
|||
|
|
- `aiResponse` - результат обработки AI
|
|||
|
|
- `redisChannel` - канал из входящего запроса (`ai:response:{taskId}`)
|
|||
|
|
|
|||
|
|
**Output:**
|
|||
|
|
- Публикация в Redis канал
|
|||
|
|
- Браузер получает через SSE мгновенно
|
|||
|
|
|
|||
|
|
## ✅ Проверка
|
|||
|
|
|
|||
|
|
### Тест публикации из командной строки:
|
|||
|
|
```bash
|
|||
|
|
redis-cli -h crm.clientright.ru -p 6379 -a 'CRM_Redis_Pass_2025_Secure!' \
|
|||
|
|
PUBLISH "ai:response:test-task" '{"task_id":"test-task","response":"Тест","status":"completed"}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Проверка в n8n:
|
|||
|
|
1. Запустите workflow с тестовым запросом
|
|||
|
|
2. Проверьте логи Redis ноды - должна быть успешная публикация
|
|||
|
|
3. В браузере откройте AI Drawer и отправьте сообщение
|
|||
|
|
4. Ответ должен прийти мгновенно через SSE
|
|||
|
|
|
|||
|
|
## 🔍 Отладка
|
|||
|
|
|
|||
|
|
### Если ответ не приходит:
|
|||
|
|
|
|||
|
|
1. **Проверьте канал Redis:**
|
|||
|
|
```bash
|
|||
|
|
redis-cli -h crm.clientright.ru -p 6379 -a 'CRM_Redis_Pass_2025_Secure!' \
|
|||
|
|
MONITOR
|
|||
|
|
```
|
|||
|
|
Должны видеть PUBLISH команды
|
|||
|
|
|
|||
|
|
2. **Проверьте формат сообщения:**
|
|||
|
|
Сообщение должно быть валидным JSON:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"task_id": "task-123",
|
|||
|
|
"response": "Ответ от AI",
|
|||
|
|
"status": "completed"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **Проверьте SSE endpoint:**
|
|||
|
|
```bash
|
|||
|
|
curl -N "https://crm.clientright.ru/aiassist/ai_sse.php?task_id=test-task"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📊 Преимущества новой архитектуры
|
|||
|
|
|
|||
|
|
✅ **Проще** - нет промежуточного callback
|
|||
|
|
✅ **Быстрее** - прямая публикация в Redis
|
|||
|
|
✅ **Надежнее** - меньше точек отказа
|
|||
|
|
✅ **Меньше кода** - убрали БД и callback
|
|||
|
|
|
|||
|
|
## 🚨 Важно
|
|||
|
|
|
|||
|
|
- История диалога сохраняется в n8n автоматически (не нужно дублировать в БД)
|
|||
|
|
- Если Redis недоступен, браузер автоматически переключится на fallback (polling)
|
|||
|
|
- Канал Redis уникален для каждого запроса: `ai:response:{taskId}`
|
|||
|
|
|
|||
|
|
## 📁 Связанные файлы
|
|||
|
|
|
|||
|
|
- `/aiassist/n8n_proxy.php` - отправляет запрос в n8n с параметрами Redis
|
|||
|
|
- `/aiassist/ai_sse.php` - SSE endpoint для получения ответов из Redis
|
|||
|
|
- `/layouts/v7/resources/js/ai-drawer-simple.js` - JavaScript клиент с SSE
|
|||
|
|
|