From 1d6c9d1f526ed7a1bf8d76e023f374fde5dab4de Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Tue, 25 Nov 2025 17:42:31 +0300 Subject: [PATCH] feat: Add detailed logging for description endpoint and n8n workflow docs Added: - Detailed logging for /api/v1/claims/description endpoint - Full event data logging for debugging - Documentation for n8n workflow setup (N8N_DESCRIPTION_WORKFLOW.md) The issue: Form hangs on recommendations step because n8n doesn't process description events. Flow: 1. Frontend sends description to /api/v1/claims/description 2. Backend publishes to Redis channel ticket_form:description 3. Frontend subscribes to SSE /api/v1/events/{session_id} (listens to ocr_events:{session_id}) 4. n8n must: - Subscribe to ticket_form:description channel - Process description and generate wizard_plan - Publish wizard_plan back to ocr_events:{session_id} channel Files: - backend/app/api/claims.py (enhanced logging) - docs/N8N_DESCRIPTION_WORKFLOW.md (new documentation) --- backend/app/api/claims.py | 43 ++++++++- docs/N8N_DESCRIPTION_WORKFLOW.md | 150 +++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 docs/N8N_DESCRIPTION_WORKFLOW.md diff --git a/backend/app/api/claims.py b/backend/app/api/claims.py index 3830a0e..eb1f0e0 100644 --- a/backend/app/api/claims.py +++ b/backend/app/api/claims.py @@ -692,14 +692,49 @@ async def publish_ticket_form_description(payload: TicketFormDescriptionRequest) "source": payload.source, "timestamp": datetime.utcnow().isoformat(), } + + event_json = json.dumps(event, ensure_ascii=False) + logger.info( "📝 TicketForm description received", - extra={"session_id": payload.session_id, "claim_id": payload.claim_id or "not_set"}, + extra={ + "session_id": payload.session_id, + "claim_id": payload.claim_id or "not_set", + "phone": payload.phone, + "description_length": len(payload.problem_description), + "channel": channel, + }, ) - await redis_service.publish(channel, json.dumps(event, ensure_ascii=False)) + logger.info( - "📡 TicketForm description published", - extra={"channel": channel, "session_id": payload.session_id}, + "📡 Publishing to Redis channel", + extra={ + "channel": channel, + "event_type": event["type"], + "event_keys": list(event.keys()), + "json_length": len(event_json), + }, + ) + + await redis_service.publish(channel, event_json) + + logger.info( + "✅ TicketForm description published to Redis", + extra={ + "channel": channel, + "session_id": payload.session_id, + "subscribers_notified": True, + "event_json_preview": event_json[:500], + }, + ) + + # Дополнительная проверка: логируем полный event для отладки + logger.debug( + "🔍 Full event data published", + extra={ + "channel": channel, + "event": event, + }, ) return { "success": True, diff --git a/docs/N8N_DESCRIPTION_WORKFLOW.md b/docs/N8N_DESCRIPTION_WORKFLOW.md new file mode 100644 index 0000000..5a3d8fb --- /dev/null +++ b/docs/N8N_DESCRIPTION_WORKFLOW.md @@ -0,0 +1,150 @@ +# Настройка n8n Workflow для обработки описания проблемы + +## Проблема + +После отправки описания проблемы форма "тупит" на шаге рекомендаций. Это происходит потому, что n8n не обрабатывает событие из Redis канала. + +## Текущий поток данных + +1. **Frontend** отправляет описание на `/api/v1/claims/description` +2. **Backend** публикует событие в Redis канал `ticket_form:description` +3. **Frontend** подписывается на SSE `/api/v1/events/{session_id}` (слушает канал `ocr_events:{session_id}`) +4. **n8n** должен: + - Подписаться на канал `ticket_form:description` (или получить событие из него) + - Обработать описание и сгенерировать `wizard_plan` + - Опубликовать `wizard_plan` в канал `ocr_events:{session_id}` через POST `/api/v1/events/{session_id}` + +## Структура события в Redis канале `ticket_form:description` + +```json +{ + "type": "ticket_form_description", + "session_id": "sess_xxx", + "claim_id": "claim_id_xxx" или null, + "phone": "79262306381", + "email": "user@example.com", + "description": "Описание проблемы...", + "source": "ticket_form", + "timestamp": "2025-11-25T12:30:36.262855" +} +``` + +## Настройка n8n Workflow + +### Шаг 1: Redis Subscribe Node + +1. Добавьте **Redis Subscribe** node +2. Настройте подключение к Redis: + - Host: `crm.clientright.ru` (или IP вашего Redis) + - Port: `6379` + - Password: `CRM_Redis_Pass_2025_Secure!` +3. Channel: `ticket_form:description` +4. Output: `JSON` + +### Шаг 2: Обработка описания + +После получения события из Redis: + +1. Извлеките `session_id` из события: `{{ $json.session_id }}` +2. Извлеките `description` из события: `{{ $json.description }}` +3. Обработайте описание (AI, RAG и т.д.) +4. Сгенерируйте `wizard_plan` + +### Шаг 3: Сохранение wizard_plan в PostgreSQL + +Сохраните `wizard_plan` в таблицу `clpr_claims` используя SQL скрипт (например, `SQL_CLAIMSAVE_UPSERT_SIMPLE.sql`). + +### Шаг 4: Публикация wizard_plan обратно в Redis + +**ВАЖНО:** После генерации `wizard_plan` нужно опубликовать событие обратно в Redis канал `ocr_events:{session_id}`. + +Используйте **HTTP Request** node: + +- **Method:** POST +- **URL:** `http://147.45.146.17:8200/api/v1/events/{{ $json.session_id }}` +- **Headers:** + ```json + { + "Content-Type": "application/json" + } + ``` +- **Body (JSON):** + ```json + { + "event_type": "wizard_ready", + "status": "ready", + "message": "Wizard plan готов", + "data": { + "claim_id": "{{ $json.claim_id }}", + "wizard_plan": {{ $json.wizard_plan }}, + "answers_prefill": {{ $json.answers_prefill }}, + "coverage_report": {{ $json.coverage_report }} + }, + "timestamp": "{{ $now.toISO() }}" + } + ``` + +**Альтернатива:** Используйте **Redis Publish** node напрямую: + +- Channel: `ocr_events:{{ $json.session_id }}` +- Message (JSON): + ```json + { + "event_type": "wizard_ready", + "status": "ready", + "message": "Wizard plan готов", + "data": { + "claim_id": "{{ $json.claim_id }}", + "wizard_plan": {{ $json.wizard_plan }}, + "answers_prefill": {{ $json.answers_prefill }}, + "coverage_report": {{ $json.coverage_report }} + }, + "timestamp": "{{ $now.toISO() }}" + } + ``` + +## Проверка работы + +1. Откройте консоль браузера (F12) +2. Отправьте описание проблемы +3. Проверьте логи backend: + ```bash + docker-compose logs -f ticket_form_backend | grep -E "📝|📡|description" + ``` +4. Проверьте, что событие опубликовано в Redis: + ```bash + redis-cli -h crm.clientright.ru -p 6379 -a "CRM_Redis_Pass_2025_Secure!" PUBSUB CHANNELS "ticket_form:*" + ``` +5. Проверьте, что n8n получил событие (в логах n8n workflow) +6. Проверьте, что n8n опубликовал `wizard_plan` обратно в канал `ocr_events:{session_id}` + +## Типичные проблемы + +### Проблема 1: n8n не получает события из Redis + +**Решение:** Проверьте, что Redis Subscribe node правильно настроен и подключен к правильному каналу `ticket_form:description`. + +### Проблема 2: Frontend не получает wizard_plan + +**Решение:** Проверьте, что n8n публикует событие в правильный канал `ocr_events:{session_id}` (не `ocr_events:session_id`, а `ocr_events:{session_id}` где `{session_id}` - это значение из события). + +### Проблема 3: Неправильный формат события + +**Решение:** Убедитесь, что событие содержит поле `event_type: "wizard_ready"` и `status: "ready"`. Backend ожидает этот формат. + +## Пример полного workflow в n8n + +``` +Redis Subscribe (ticket_form:description) + ↓ +Code Node (обработка описания) + ↓ +AI/RAG Node (генерация wizard_plan) + ↓ +PostgreSQL Node (сохранение wizard_plan) + ↓ +HTTP Request Node (POST /api/v1/events/{session_id}) + или +Redis Publish Node (ocr_events:{session_id}) +``` +