gb/zap.md
Rodrigo Rodriguez (Pragmatismo) ff9e3f56a9 feat(whatsapp): update submodule with list isolation and code removal
- Update botserver submodule to commit 97661d75
- Add list isolation as single messages in WhatsApp
- Add JavaScript/C# code block removal
- Update zap.md with streaming example and correction history
- Change restart.sh logging from trace to debug level

Related: botserver submodule update
2026-03-08 14:53:43 -03:00

11 KiB

WhatsApp - Bot Salesianos

Status: Operacional

Campo Valor
Bot ID 32c579e5-609b-4a07-8599-4e0fccc4d764
Phone +15558293147
Phone ID 323250907549153
Business ID 1261667644771701

Comandos

  • /clear - Limpa histórico da conversa

Streaming

  1. Mensagens sem lista: enviar a cada 3 parágrafos
  2. Mensagens com lista: ISOLAR como mensagem única (sem texto antes ou depois)
  3. Limite máximo: 4000 caracteres por mensagem

Exemplo de Agrupamento Correto

Resposta completa do bot:

Olá! 😊

Infelizmente, não tenho a informação específica sobre o horário de funcionamento da Escola Salesiana no momento.

Para obter essa informação, você pode:
1. *Entrar em contato com a secretaria* - Posso te ajudar a enviar uma mensagem perguntando sobre os horários
2. *Agendar uma visita* - Assim você conhece a escola pessoalmente e obtém todas as informações necessárias

Gostaria que eu te ajudasse com alguma dessas opções? Se quiser entrar em contato com a secretaria, preciso apenas de:
- Seu nome
- Telefone
- Email
- Sua pergunta sobre os horários

Ou, se preferir, posso agendar uma visita para você conhecer a escola! 🏫

O que prefere?

Deve ser enviado como 5 mensagens separadas:

Mensagem 1:

Olá! 😊

Infelizmente, não tenho a informação específica sobre o horário de funcionamento da Escola Salesiana no momento.

Para obter essa informação, você pode:

Mensagem 2 (LISTA ISOLADA):

1. *Entrar em contato com a secretaria* - Posso te ajudar a enviar uma mensagem perguntando sobre os horários
2. *Agendar uma visita* - Assim você conhece a escola pessoalmente e obtém todas as informações necessárias

Mensagem 3:

Gostaria que eu te ajudasse com alguma dessas opções? Se quiser entrar em contato com a secretaria, preciso apenas de:

Mensagem 4 (LISTA ISOLADA):

- Seu nome
- Telefone
- Email
- Sua pergunta sobre os horários

Mensagem 5:

Ou, se preferir, posso agendar uma visita para você conhecer a escola! 🏫

O que prefere?

Regras:

  • Cada lista = 1 mensagem ISOLADA (nunca misturar com texto)
  • Texto antes da lista = mensagem separada
  • Texto depois da lista = mensagem separada
  • Listas nunca são quebradas no meio

Testar Webhook (Simular Callback)

Script de teste em /tmp/test_whatsapp.sh:

#!/bin/bash
# Testa o webhook do WhatsApp simulando uma mensagem

BOT_ID="32c579e5-609b-4a07-8599-4e0fccc4d764"
FROM="5521972102162"  # Número de teste

curl -X POST "http://localhost:8080/webhook/whatsapp/${BOT_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "object": "whatsapp_business_account",
    "entry": [{
      "id": "1261667644771701",
      "changes": [{
        "field": "messages",
        "value": {
          "messaging_product": "whatsapp",
          "metadata": {
            "display_phone_number": "15558293147",
            "phone_number_id": "323250907549153"
          },
          "contacts": [{
            "wa_id": "'${FROM}'",
            "profile": { "name": "Teste Usuario" }
          }],
          "messages": [{
            "id": "test_msg_'$(date +%s)'",
            "from": "'${FROM}'",
            "timestamp": "'$(date +%s)'",
            "type": "text",
            "text": { "body": "Olá, como posso ajudar?" }
          }]
        }
      }]
    }]
  }'

Executar teste:

bash /tmp/test_whatsapp.sh

Testar Comando /clear

BOT_ID="32c579e5-609b-4a07-8599-4e0fccc4d764"
FROM="5521972102162"

curl -X POST "http://localhost:8080/webhook/whatsapp/${BOT_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "object": "whatsapp_business_account",
    "entry": [{
      "id": "1261667644771701",
      "changes": [{
        "field": "messages",
        "value": {
          "messaging_product": "whatsapp",
          "metadata": {
            "display_phone_number": "15558293147",
            "phone_number_id": "323250907549153"
          },
          "contacts": [{
            "wa_id": "'${FROM}'",
            "profile": { "name": "Teste Usuario" }
          }],
          "messages": [{
            "id": "test_clear_'$(date +%s)'",
            "from": "'${FROM}'",
            "timestamp": "'$(date +%s)'",
            "type": "text",
            "text": { "body": "/clear" }
          }]
        }
      }]
    }]
  }'

Debug

# Verificar servidor
curl http://localhost:8080/health

# Monitorar logs
tail -f botserver.log | grep -iE "(whatsapp|Embedding)"

# Verificar sessões ativas (requer acesso ao banco)
# SELECT * FROM user_sessions WHERE bot_id = '32c579e5-609b-4a07-8599-4e0fccc4d764';

Arquivos Relacionados

  • Config: /opt/gbo/data/salesianos.gbai/salesianos.gbot/config.csv
  • Handler: botserver/src/whatsapp/mod.rs
  • Adapter: botserver/src/core/bot/channels/whatsapp.rs
  • Cache: botserver/src/llm/cache.rs

Pendências

  1. Filtrar caracteres Markdown inválidos no WhatsApp (###, **, etc) Concluído em 2025-03-08
  2. Configurar webhook na Meta Business Suite para produção
  3. Configurar SSL/TLS no servidor de produção

Histórico de Correções

2025-03-08: Sanitização de Markdown para WhatsApp

Problema: O WhatsApp não suporta Markdown completo (headers, links formatados, etc), causando exibição incorreta de mensagens.

Solução: Adicionada função sanitize_for_whatsapp() em botserver/src/core/bot/channels/whatsapp.rs que:

  • Remove headers Markdown (###, ##, #)
  • Converte links [texto](url) para texto: url
  • Remove sintaxe de imagem ![alt](url)
  • Converte checkboxes [ ] e [x] para bullets
  • Remove horizontal rules (---, ***)
  • Remove tags HTML
  • Limpa linhas em branco excessivas

Resultado: Mensagens agora são exibidas corretamente no WhatsApp.

2025-03-08: Cache Semântico

Problema: O cache semântico estava enviando todo o histórico de conversa (10000+ chars) para o embedding, causando falsos positivos.

Solução: Modificado botserver/src/llm/cache.rs para extrair apenas a última pergunta do usuário do array de mensagens.

// Antes (problemático):
let combined_context = format!("{}\n{}", prompt, actual_messages);

// Depois (corrigido):
let latest_user_question = msgs.iter().rev()
    .find_map(|msg| {
        if msg.get("role") == Some("user") {
            msg.get("content").and_then(|c| c.as_str())
        } else { None }
    });

Resultado: Embedding agora usa apenas ~52 chars (pergunta do usuário) em vez de 10000+ chars.

2025-03-08: Correção de Streaming para Listas

Problema: Listas numeradas estavam sendo quebradas em múltiplas mensagens durante o streaming, mesmo quando cabiam em uma única mensagem de 4000 caracteres.

Causa: A detecção de lista era feita APÓS decidir fazer flush baseado em 3 parágrafos. Quando o streaming enviava chunks parciais, o código não detectava que uma lista estava começando.

Solução: Melhorada a lógica de detecção em botserver/src/whatsapp/mod.rs:

  1. Detecção mais precisa de listas numeradas: Agora requer padrão N. ou N) seguido de espaço (ex: "1. Item", "10) Item")
  2. Detecção de início de lista: Nova função looks_like_list_start() detecta quando o buffer parece estar começando uma lista (header terminando em : ou número no início)
  3. Logs detalhados: Adicionado logging para debug de streaming

Resultado: Listas agora são acumuladas corretamente e enviadas em uma única mensagem quando possível.

2025-03-08: Detecção de Fim de Lista no Streaming

Problema: Listas estavam sendo enviadas como mensagens únicas apenas quando o streaming terminava (is_final), mesmo que a lista já tivesse terminado. Isso causava atrasos na entrega de mensagens quando havia conteúdo após a lista.

Causa: Uma vez que uma lista era detectada (has_list = true), o código esperava até is_final ou buffer.len() >= MAX_WHATSAPP_LENGTH para fazer flush. Não havia detecção de quando a lista terminava.

Solução:

  • Adicionada função looks_like_list_end() em botserver/src/whatsapp/mod.rs que detecta quando uma lista terminou (verifica se as últimas 2 linhas não-brancas não são itens de lista)
  • Modificada a lógica de streaming para fazer flush quando list_ended = true
  • Adicionados testes unitários para validar o novo comportamento

Resultado: Listas agora são enviadas assim que terminam, sem esperar o streaming completar. Conteúdo após a lista é entregue prontamente, melhorando a experiência do usuário.

2025-03-08: Isolamento de Listas como Mensagens Únicas

Problema: Listas estavam sendo enviadas misturadas com texto antes e depois, em vez de serem isoladas como mensagens únicas. Por exemplo, "Texto introdutório\n1. Item\n2. Item\nTexto final" era enviado como uma única mensagem, quando deveria ser 3 mensagens separadas.

Causa: A lógica de streaming acumulava todo o buffer quando detectava uma lista, sem separar o texto antes/depois da lista. O buffer era enviado como um bloco único.

Solução: Implementado isolamento de listas em botserver/src/whatsapp/mod.rs:

  • Adicionada função split_text_before_list() para separar texto antes da lista
  • Adicionada função split_list_from_text() para separar lista do texto depois
  • Modificada lógica de streaming para:
    1. Detectar quando lista termina (list_ended = true)
    2. Separar texto ANTES da lista e enviar como mensagem
    3. Separar lista e enviar como mensagem ISOLADA
    4. Manter texto DEPOIS no buffer para próxima mensagem

Resultado: Listas agora são enviadas como mensagens ISOLADAS, sem misturar com texto antes ou depois. Cada lista = 1 mensagem separada, melhorando a legibilidade e experiência do usuário no WhatsApp.

2025-03-08: Remoção de Blocos de Código JavaScript

Problema: Código de programação (JavaScript, C#, etc.) estava vazando nas mensagens do WhatsApp. Exemplos como var telefoneDigits = new string(args.Phone.Where(char.IsDigit).ToArray()); eram enviados para os usuários, quando deveriam ser removidos.

Causa: A função sanitize_for_whatsapp() em botserver/src/core/bot/channels/whatsapp.rs removia Markdown e HTML, mas não removia blocos de código cercados por crases (backticks).

Solução: Adicionados padrões regex à função sanitize_for_whatsapp():

  • Remove blocos de código com crases triplas: code
  • Remove código inline com crase simples: code
  • Limpa código de programação antes de enviar para WhatsApp

Resultado: Mensagens do WhatsApp agora estão livres de código de programação, exibindo apenas texto legível para o usuário. Código JavaScript, C#, e outras linguagens são automaticamente removidos durante a sanitização.