Como criar um chatbot humanizado via WhatsApp com a API da Zenvia e a IA Watson da IBM

Veja o passo a passo de como criar um chatbot humanizado para WhatsApp com API da Zenvia e a IA Watson da IBM

A implementação de chatbots pelas empresas aumentou consideravelmente nos últimos anos. Isto ocorre porque este sistema permite que soluções sejam entregues aos usuários sem a necessidade de se comunicar com atendentes.

Porém, um chatbot com um funcionamento robótico sem tratamento humanizado pode causar uma impressão negativa sobre a empresa perante o olhar do usuário.

Neste tutorial, você irá aprender a criar um chatbot humanizado a partir da inteligência artificial Watson da IBM integrado com o WhatsApp via uma aplicação Node.Js utilizando uma API da Zenvia.

Neste exemplo, o chatbot responderá perguntas relacionadas ao COVID-19.

Zenvia

Zenvia é uma provedora oficial do WhatsApp que disponibiliza uma API que permite a criação uma conta gratuita e a utilização limita de seus serviços como a API do WhatsApp.

Para criar a conta basta entrar neste site, clicar em CRIAR UMA CONTA no canto superior direito e preencher os campos.

Após criar a conta, siga o seguinte fluxo:Menu superior > Produtos > Desenvolvedores > Sandbox > Criar novo > Escolha o canal WhatsApp > Próximo

Com o seu celular, leia o QR Code que aparecerá na tela e ele gerará um link que abrirá o seu aplicativo do WhatsApp com o contato da Zenvia e uma mensagem previamente escrita, basta enviá-la para configurar a SandBox e registrar seu número de telefone para o ambiente de testes:

Criando a aplicação Node.js

1- Instale o Node no seu computador (de preferência a versão LTS);

    1.1- opcional – Instale o yarn. O node possui um gerenciador de pacotes padrão chamado npm (Node Package Manager), porém existe um gerenciador diferente chamado yarn. No restante deste artigo, haverão as opções de instalação para ambos gerenciadores de pacote como no passo a seguir.

2- Inicie o projeto criando o package.json com o seguinte comando no terminal:

npm init

yarn init

3- Instale o ts-node, ts-node-dev e o typescript como dependências de desenvolvimento:

npm i ts-node ts-node-dev typescript -D

yarn add ts-node ts-node-dev typescript -D

3.1 – Instale o arquivo de configuração do typescript: 

npx typescript --init

 4- Abra o arquivo package.json e insira o script para iniciar o servidor assim como na área grifada em cinza:

{
  "name": "humanized-whatsapp-chatbot-zenvia",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "dev": "ts-node-dev --transpile-only --ignore-watch node_modules --respawn index.ts"
  },
  "author": "Henry Kimura",
  "license": "MIT",
  "devDependencies": {
    "ts-node": "^9.0.0",
    "ts-node-dev": "^1.0.0",
    "typescript": "^4.0.5"
  }
}

4.1- Sempre que você quiser executar a aplicação basta executar no terminal: 

npm run dev

yarn dev

Criando o assistente Watson

1- Crie uma conta no site da IBM Cloud e faça login.

2- Na tela inicial, acesse o menu de navegação e clique em Watson

3- Agora siga o seguinte fluxo: Menu lateral → Serviços do Watson → Serviços Existentes → Criar Recurso → Watson Assistant → Criar → Launch Watson Assistant (será aberta uma nova guia no navegador) → Menu Lateral → Assistants → My first assistant → Add diolog skill. Configure a Skill e clique em Create dialog skill.

4- Agora abra a skill criada, clique em Content Catalog, clique em Add Skill+ na skill de Covid-19:

Lembre-se desta tela, pois voltaremos nela mais tarde

Criando nossa aplicação e conectando com o Watson

Nossa aplicação Node servirá como um intermediador entre a API da IBM e a API da Zenvia. Construiremos um webhook para capturar informações de ambas APIs e trocar as informações entre elas. Vamos começar a construí-la:

1- Instale as dependências:

npm i express body-parser ibm-watson request-promise

yarn add express body-parser ibm-watson request-promise

2- Menu lateral → Serviços do Watson → Serviços Existentes → Clique no Assistant que você criou e guarde a sua API key e URL 

3- A partir da tela inicial, siga o fluxo: Menu de navegação → Watson → Menu lateral → Serviços do Watson → Serviços Existentes → Criar Recurso → Watson Assistant → Criar → Launch Watson Assistant (será aberta uma nova guia no navegador) → Menu Lateral → Assistants → My first assistant. Clique nos 3 pontos, Settings, View API details, API details e guarde o Assistant ID

4- Crie um arquivo authenticationValues.ts para armazenar as informações de autenticação da API da IBM substitua <YOUR_KEY>  <YOUR_SERVICE_URL> <YOUR_ASSISTANT_ID>  pelas informações que eu pedi para você guardar nos passos anteriores:

const authenticationValues = {
    apikey: '<YOUR_KEY>',
    serviceUrl:    '<YOUR_SERVICE_URL>',
    version: '2018-02-16',
    assistantId: '<YOUR_ASSISTANT_ID>',
}

export default authenticationValues

5- Crie um arquivo index.ts com o seguinte código:

import AssistantV2 from 'ibm-watson/assistant/v2'
import { IamAuthenticator } from 'ibm-watson/auth'
import express from 'express'
import bodyParser from 'body-parser'
import authenticationValues from './authenticationValues'

// Inicializa o express e define uma porta
const app = express()
const port = 3000

// Indica para o express usar o JSON parsing do body-parser
app.use(bodyParser.json())

// Separa os valores de autenticação armazenados no arquivo authenticationValues.ts (substitua seus dados nesse arquivo)
const { apikey, serviceUrl, version, assistantId } = authenticationValues

// Inicializa o assistant e faz a autenticação na API
const assistant = new AssistantV2({
    authenticator: new IamAuthenticator({
        apikey,
    }),
    serviceUrl,
    version,
})

app.post('/hook', (req, res) => {
    console.log(req.body)
})

app.listen(port, () => console.log(`Running on port ${port}`))

Configurando a API da Zenvia

Para saber mais sobre o funcionamento da API de WhatsApp da Zenvia, você pode acessar este artigo

1- Após ter configurado seu número de testes com a SandBox anteriormente, ele aparecerá na aba de contatos:

2- Crie uma pasta chamada src e, dentro dela, crie um arquivo chamado sendMessageToWhatsApp.ts. Copie e cole o código de exemplo abaixo e substitua <YOUR-TOKEN> pelo seu token gerado pela plataforma Zenvia, substitua o <REMETENTE> e o <DESTINATÁRIO> também:

import request_promise from 'request-promise'
const { post } = request_promise

const sendMessageToWhatsApp = (message: string) => {
    post({
        uri: 'https://api.zenvia.com/v2/channels/whatsapp/messages',
        headers: {
            'X-API-TOKEN': '<YOUR-TOKEN>',
        },
        body: {
            from: '<REMETENTE>',
            to: '<REMETENTE>',
            contents: [
                {
                    type: 'text',
                    text: message,
                },
            ],
        },
        json: true,
    })
        .then((response) => {
            console.log('Response:', response)
        })
        .catch((error) => {
            console.log('Error:', error)
        })
}

export default sendMessageToWhatsApp

As informações solicitadas podem ser encontradas nesta tela: 

3- Faça as alterações destacadas no arquivo index.ts:

import AssistantV2 from 'ibm-watson/assistant/v2'
import { IamAuthenticator } from 'ibm-watson/auth'
import express from 'express'
import bodyParser from 'body-parser'
import authenticationValues from './authenticationValues'
import sendMessageToWhatsApp from './src/sendMessageToWhatsApp' // Função que envia mensagem ao usuário via WhatsApp (será criada posteriormente)


// Inicializa o express e define uma porta
const app = express()
const port = 3000

// Indica para o express usar o JSON parsing do body-parser
app.use(bodyParser.json())

// Separa os valores de autenticação armazenados no arquivo authenticationValues.ts (substitua seus dados nesse arquivo)
const { apikey, serviceUrl, version, assistantId } = authenticationValues

// Inicializa o assistant e faz a autenticação na API
const assistant = new AssistantV2({
    authenticator: new IamAuthenticator({
        apikey,
    }),
    serviceUrl,
    version,
})

app.post('/hook', (req, res) => {
    // Verifica se a mensagem veio do WhatsApp
    if (req.body.message) { // Se sim:
        const message = req.body.message.contents[0].text // Armazena em uma variável a mensagem

        assistant
            // Inicia a sessão com o assistant
            .createSession({
                assistantId,
            })
            .then((res) => {
                // Manda a mensagem vinda da API da Zenvia para o assistant
                sendMessageToWatson(
                    {
                        message_type: 'text',
                        text: message,
                    },
                    res.result.session_id
                )
            })
            .catch((err) => {
                console.log(err)
            })

        res.status(200).end() // Responde quem solicitou o webhook com status 200
        // Verifica se a mensagem veio do Watson
    } else {
            sendMessageToWhatsApp(req.body.send) // Se for outros casos, mande a resposta do Assistant para o WhatsApp
    }
})
const sendMessageToWatson = (messageInput: AssistantV2.MessageInput, sessionId: string) => {
    assistant
        .message({
            assistantId,
            sessionId,
            input: messageInput,
        })
        .then((res) => {
            processResponse(res.result)
        })
        .catch((err) => {
            console.log(err)
        })
}

// Processa a resposta e exibe ela no console
const processResponse = (response: any) => {
    // Exibe a saída do assistant
    if (response.output.generic) {
        if (response.output.generic.length > 0) {
            if (response.output.generic[0].response_type === 'text') {
                console.log('process')
                console.log(response.output.generic[0].text)
            }
        }
    }
}

app.listen(port, () => console.log(`Running on port ${port}`))

Aqui, você fez a importação da função sendMessageToWhatsApp (será criada posteriormente) no index.ts e inseriu as funções sendMessageToWatson e processResponse, permitindo o envio de mensagens ao Watson e processamento do retorno dele. 

4-Precisamos tornar nosso webhook visível para que a API da Zenvia e o Watson possam nos enviar requisições, para isto vamos utilizar o ngrok. Faça login no site, baixe a versão para Windows, extraia o zip, execute a aplicação (abrirá um terminal), autentique-se digitando ngrok authtoken SEU_TOKEN (seu token está na primeira tela do seu dashboard) e exponha a porta da aplicação (3000) digitando ngrok http 3000. Copie o URL da seção Forwarding gerado pelo ngrok:

5- Vá para a seção Subscription, cole seu link no campo “Message Webhook URL”, coloque /hook (rota criada no nosso webhook o passo 5 da seção Criando nossa aplicação e conectando com o Watson)ao final do URL na aba Subscriptione clique em Salvar:

Programando o Watson

Lembra-se da tela do passo 4 da seção Criando o assistente Watson? Vamos partir dela para salvar o URL do seu webhook no Watson (lembre-se que toda vez que você abrir sua porta com o ngrok, é gerado um novo URL, então lembre-se de sempre alterar na API):

1- Clique em OptionsWebhooks, cole o URL gerado pelo ngrok no campo para isso e lembre-se de colocar /hook ao final do URL.

2- Clique em Dialog, agora vamos configurar os casos de resposta do nosso chatbot. A vantagem do Watson é que ele consegue avaliar as mensagens e identificar a intenção do usuário. Você pode criar intenções, nomeando ela e inserindo algumas frases de exemplos para que o Watson aprenda. Para este exemplo, vamos usar um conjunto de intenções sobre a COVID-19 que o Watson já possui que adicionamos anteriormente. Clique em dialog, remova o card Bem-vindo:

3- Adicione um novo nó e vamos configurá-lo:

3.1 – Configure para que este nó chame nosso webhook:

3.2- Continue configurando o nó. No parâmetro Value você coloca o que o bot responderá quando identificar a determinada intenção:

3.3- Este é o momento de criação de fato do seu chatbot. Crie nós com os casos de intenção do usuário e suas respectivas mensagens para o seu chatbot. Neste exemplo, criaremos apenas 3 casos e 1 para quando o chatbot não compreender a intenção do usuário (utilize o nó que já está criado e apenas o modifique, configurando para enviar uma requisição ao webhook com a resposta desejada). Crie seus nós seguindo os mesmos passos anteriores:

Se você quiser seguir o mesmo exemplo criado neste artigo, segue as respostas utilizadas:

              #Cancelamento_Eventos_Covid: “Segundo um artigo da AgenciaBrasil, o Ministério da Saúde recomendou para que as organizações o cancelem ou adiem de eventos com grande participação de pessoas em razão da epidemia do novo coronavírus (Covid-19).”;

             #Descrição_Covid: “Segundo o Ministério da Saúde, os coronavírus são uma grande família de vírus. A COVID-19 é uma doença causada pelo coronavírus, denominado SARS-CoV-2, que apresenta um espectro clínico variando de infecções assintomáticas a quadros graves. Os pacientes com COVID-19 podem ser assintomáticos ou oligossintomáticos (poucos sintomas), e aproximadamente 20% dos casos detectados requer atendimento hospitalar por apresentarem dificuldade respiratória, dos quais aproximadamente 5% podem necessitar de suporte ventilatório.”;

            #Contagem_Casos_Covid: “cases” (no próximo passo será explicado melhor sobre esta resposta)

            anything_else: “Eu não entendi. Você pode tentar reformular a frase.”

3.4- Vamos criar um exemplo diferente onde ao invés do Watson dar uma resposta diretamente ao usuário, vamos utilizá-lo para identificar a intenção do usuário, mandar uma mensagem “cases” para nosso webhook fazer uma busca a uma API externa e dar uma resposta atualizada sobre os casos de COVID-19 no Brasil:

Note que a Key é sempre a mesma: send. Este é o nome do atributo que o webhook está preparado para receber, se você alterar aqui, precisa alterar o código do webhook.

Voltando para a aplicação

1- Dentro da pasta src, crie o arquivo covidCases.ts com o código abaixo:

import request_promise from 'request-promise'
import sendMessageToWhatsApp from './sendMessageToWhatsApp' // Importação da função de envio de mensagem via WhatsApp
const { get } = request_promise

const covidCases = () => {
    get({
        uri: 'https://covid19-brazil-api.now.sh/api/report/v1/brazil',
    })
        .then((response) => {
            const covid = JSON.parse(response)
            const { confirmed, deaths } = covid.data
            sendMessageToWhatsApp(
                `No Brasil, há ${confirmed} casos confirmados e ${deaths} mortes.`
            )
        })
        .catch((error) => {
            console.log('Error:', error)
        })
}

export default covidCases

Esta função faz uma consulta à COVID-19 Brazil API e envia uma mensagem via WhatsApp ao usuário com os números sobre os casos de COVID-19.

2- Altere o index.ts importando a função covidCases e fazendo a verificação se o usuário deseja saber sobre os casos.

import AssistantV2 from 'ibm-watson/assistant/v2'
import { IamAuthenticator } from 'ibm-watson/auth'
import express from 'express'
import bodyParser from 'body-parser'
import authenticationValues from './authenticationValues'
import sendMessageToWhatsApp from './src/sendMessageToWhatsApp'
import covidCases from './src/covidCases'

//...

app.post('/hook', (req, res) => {
    // Verifica se a mensagem veio do WhatsApp
    if (req.body.message) { // Se sim:
        const message = req.body.message.contents[0].text // Armazena em uma variável a mensagem

        assistant
            // Inicia a sessão com o assistant
            .createSession({
                assistantId,
            })
            .then((res) => {
                // Manda a mensagem vinda da API da Zenvia para o assistant
                sendMessageToWatson(
                    {
                        message_type: 'text',
                        text: message,
                    },
                    res.result.session_id
                )
            })
            .catch((err) => {
                console.log(err)
            })

        res.status(200).end() // Responde quem solicitou o webhook com status 200
        // Verifica se a mensagem veio do Watson
    } else {
        // Verifica se o usuário quer saber sobre os casos
        if (req.body.send === 'cases') {
            covidCases() // Chama a função que busca a COVID-19 Brazil API
        } else {
            sendMessageToWhatsApp(req.body.send) // Se for outros casos, mande a resposta do Assistant para o WhatsApp
        }
    }
})

//...

3- Agora, você pode executar a aplicação e enviar mensagens no WhatsApp pelo celular configurado na Sandbox da API da Zenvia sobre alguma das intenções configuradas por você no Watson e ver seu chatbot inteligente funcionando:

Desenvolver um chatbot que funcione através do WhatsApp é fácil e rápido. Através da API da Zenvia e ao Watson da IBM, é possível alcançar resultados impressionantes que atingirão o usuário de forma positiva. 

Para concluir nosso objetivos, criamos um webhook que recebe as mensagens vindas do WhatsApp e enviamos ao Watson através da API da IBM.

O Watson interpreta essa mensagem e identifica qual é a intenção e envia, ao nosso webhook, a resposta ao WhatsApp. Antes de responder o usuário, verificamos se ele perguntou sobre os casos de COVID-19 no Brasil e buscamos informações em uma API externa para respondermos com dados atualizados.

O resultado final da aplicação produzida neste tutorial está disponível no github.

Escrito por

Zenvia

Leia também

Fique por dentro e confira as nossas dicas sobre o mercado mobile e interação digital.