Criando um chatbot para WhatsApp com Dialogflow CX e Twilio Sandbox 🤳🏾 — Parte 1

João Garrido
google-cloud-brasil
9 min readJan 23, 2023

💭 Introdução

Nós, enquanto usuários, estamos cada vez mais preparados para lidar com a tecnologia em serviços de atendimento ao cliente, seja através de URAs, formulários automatizados e, em alguns casos, Inteligência Artificial.

Um dos grandes desafios dentro de uma estratégia de atendimento é oferecer escalabilidade de forma eficiente e humanizada, o que gradualmente tem sido possível através da implementação de serviços que utilizam IA conversacional, como o Dialogflow, que permite o desenvolvimento de bots tanto para voz quanto para texto através de uma interface amigável.

Neste artigo, vamos entender de forma simples como a suíte de desenvolvimento de IA conversacional do Google (o CCAI), com o uso do Dialogflow CX, nos permite criar chatbots e disponibilizá-los no WhatsApp de forma rápida utilizando a integração sandbox da Twilio.

👨🏾‍🔧 Pré-requisitos

  • Um projeto no Google Cloud com uma VPC subnet em uma região de sua preferência (o tutorial utilizará por padrão a região us-central1) e as seguintes APIs habilitadas:

▹ Dialogflow API
▹ Cloud Functions API
▹ Cloud Firestore API (Native Mode)

💬 Desenhando um fluxo de atendimento

O primeiro passo da nossa jornada será desenvolver um fluxo de atendimento bem simples utilizando o Dialogflow CX. Para isso, vamos nos basear na seguinte topologia:

Representação do fluxo a ser implementado

Cada etapa do nosso fluxo representa uma intenção de contato, que será interpretada pelo Dialogflow a partir da interação do usuário.

A solicitação para detecção de intenção recebe como parâmetros obrigatórios a mensagem (query) a ser interpretada e um id de sessão (session Id), que é utilizado para determinar a janela de tempo (de até 30 minutos a partir da última requisição) no qual o usuário interage com o agente (o nosso bot).

Dessa forma, ao reconhecer um motivo de contato, o Dialogflow pode responder de maneira adequada às solicitações através de um Fulfillment, uma resposta que poderá ser do tipo áudio (transcrito e sintetizado por modelos de voz do Google), texto ou webhooks (que nos dão liberdade para consultar microsserviços e APIs utilizando uma chamada REST que seja compatível com os esquemas de request e response do Dialogflow).

No nosso caso, utilizaremos o fulfillment nas solicitações, ora como respostas estáticas e ora como dinâmicas (via webhook), para consultar um banco de dados Firestore.

🔧 Entendendo as estruturas do Dialogflow CX

Reproduzir o fluxo definido utilizando o Dialogflow CX é bem simples, dado o fato de que o próprio serviço conta com uma interface bem amigável que nos permite criar essas etapas.

Para isso, vamos entender rapidamente quais são as componentes de um agente:

1. Flows/Fluxos: Diálogos complexos envolvem múltiplos tópicos de conversação, portanto, é possível definir diferentes Fluxos em um mesmo agente, de forma totalmente encapsulada

2. Pages/Páginas: Conversas no Dialogflow CX podem ser descritas como máquinas de estado e as Páginas são a representação desses estados, permitindo a criação de grandes agentes com múltiplos turnos e taking

*Fluxos e Páginas utilizam Routes (Rotas) para realizar Transitions (Transições) entre cada uma das etapas de uma conversa

3. Intents/Intenções: Uma Intent categoriza uma intenção do usuário e pode estar associada uma conversão de turno. Intents são obtidas a partir de frases de treinamento, que compõem exemplos de interações que usuário pode realizar com o agente

*Intents também podem utilizar Entities (Entidades), que são estruturas representadas a partir de expressões regulares ou listas de palavras, como mecanismo de tipagem de dados

👨🏾‍💻 Construindo um fluxo de atendimento simples com o Dialogflow CX

Inicialmente, para que possamos reproduzir o fluxo que foi definido, vamos seguir os seguintes passos:

1. Criar o agente

Para isso, basta acessar a console do Dialogflow CX, selecionar o projeto do Google Cloud que possui a Dialogflow API habilitada e criar um novo agente, com as seguintes configurações:

  • Location: global
  • Timezone: (GMT-3:00) America/Buenos_Aires
  • Linguagem-padrão: pt-br
Instruções para criação de um novo agente

2. Criar Rotas e Intents

Para a criação de rotas e intenções, vamos utilizar o próprio fluxo padrão Start do Dialogflow.

Basta acessar o fluxo Start e adicionar novas rotas para cada uma das etapas que definimos, no caso, começando por “Status do Pedido”, adicionando uma nova intent de nome “status.pedidos”, e adicionando frases de exemplo relacionadas a essa interação:

Instruções para criação de Intents

Em seguida, basta fazer o mesmo para a Intent de Encerramento, adicionando frases que representem esse tipo de contato, por exemplo: “Gostaria de encerrar a sessão”, entre outras…

Também é válido ressaltar que, por padrão, o Dialogflow CX já nos fornece uma Default Welcome Intent, que será utilizada como nossa Intent de boas-vindas.

3. Atribuir Fulfillments e Transitions

Conforme definimos anteriormente, a medida em que as Intents forem reconhecidas, iremos utilizar diferentes formatos de resposta, da seguinte maneira:

Rota: Default Welcome Intent
Tipo de resposta: Fulfillment de texto
Transição: Nenhuma

Rota: encerramento
Tipo de resposta: Fulfillment de texto
Transição: End Session

Rota: pedidos.status
Tipo de resposta: Webhook (chamada de API)
Transição: Nenhuma

Como a rota Default Welcome Intent já possui frases de resposta pré-cadastradas, vamos nos ater somente às rotas de encerramento e pedidos.status, a começar pela primeira. Para adicionar o fulfillment e a transição, basta acessar a rota e atribuir os campos:

Instruções para criação de fulfillment e transições

A página End Session é uma das páginas pré-disponíveis no Dialogflow CX, e garante que, uma vez realizada a transição até ela, a sessão estabelecida será encerrada

De forma similar, vamos adicionar o Fulfillment para a rota de status de pedidos, com uma única diferença, ao invés de adicionarmos um texto estático, a ideia é retornarmos os resultados de forma dinâmica, utilizando um webhook para consultar um banco de dados via REST API. Veremos como fazer isso nas próximas seções.

🪄 Fulfillment dinâmico utilizando webhooks

Para realizar a consulta de status de pedidos no banco de dados, vamos desenvolver uma API que será utilizada como webhook no fulfillment da rota pedidos.status.

A ideia da API é bem simples: consultar um banco de dados orientado a documentos utilizando o número de telefone do usuário como chave para retornar os status de seus pedidos. Faremos a implementação utilizando o Cloud Functions, um serviço simples e muito prático para desenvolvimento de integrações e o Cloud Firestore como banco de dados.

O primeiro passo é acessar o Cloud Firestore pela console do Google Cloud, cadastrar uma nova collection e um novo documento, utilizando o número de telefone de origem das mensagens (i.e., o número de celular que você utilizará para entrar em contato com o bot via WhatsApp) como id. Em seguida, basta cadastrar os pedidos, seguindo a seguinte estrutura:

Instruções para criação dos registros no banco de dados Firestore

*Atente-se à estrutura de dados dos documentos, , que será composta por dois campos-raíz: “nome”, uma string contendo o nome do usuário e “pedidos”, um array contendo estruturas map com os campos “item”, “numero” e “status”.

Em seguida, vamos desenvolver a API que realizará as consultas no banco de dados. Para isso, utilizaremos o SDK do Firestore para Python 3.7.

Também é importante nos atentarmos a dois pontos:

  1. Respeitar o esquema do WebhookRequest e WebhookResponse do Dialogflow CX no request e response da API
  2. Utilizar uma conta de serviço com acesso de leitura ao Firestore para o deployment no Cloud Functions — para isso, você pode utilizar uma conta de serviço que já esteja disponível no seu projeto ou criar uma nova e então conceder a role roles/datastore.viewer a ela através do IAM

💡 Confira aqui mais detalhes sobre o que é e como criar uma Conta de Serviço (ou Service Account)

Atentando-se a esses critérios, estaremos aptos a utilizar a nossa API como webhook.

Em seguida, vamos utilizar o seguinte bloco de código, criando o arquivo main.py, para realizar o deployment da nossa API como uma Cloud Function:

# Importando dependências
import firebase_admin
from firebase_admin import firestore
from flask import jsonify

# Instânciando o Client do Firestore
firebase_admin.initialize_app()
db = firestore.client()

def webhook(request):
# Armazenando os dados do request em um dicionário
request_json = request.get_json()

try:
# Recuperando o número de contato do campo "sessão" do request
# O número de contato seguirá o formato "+{CÓDIGO_DE_AREA}{DDD}{NÚMERO}")
number = request_json["sessionInfo"]["session"].split(":")[1]

# Consultando o documento do usuário a partir do número de contato
doc = db.collection(u'users_number').document(u'{}'.format(number)).get()
user = doc.to_dict()

# Definindo cabeçalho da mensagem de status de pedidos
status = f"🛒 Olá {user['name']}, seguem os status dos seus pedidos ativos:"

# Iterando e incorporando os pedidos ao cabeçalho
for pedido in user['pedidos']:
pedidos_report = f"📦 [Pedido {pedido['number']}]\n- Produto: {pedido['item']}\n- Status: {pedido['status']}"
status += "\n\n" + pedidos_report

except Exception as e:
# Definindo mensagem de falha caso os pedidos não sejam localizados
status = "😓 Infelizmente não conseguimos identificar o seu número na nossa base"

# Retornando o status como resposta da API no formato WebhookResponse
response = {"fulfillment_response": {"messages": [{"text": {"text": [status]}}]}}

return jsonify(response)

No nosso repositório, também será necessário criar um segundo arquivo, requirements.txt, contendo os pacotes que serão utilizados pela nossa API:

firebase
firebase-admin
flask

A ideia é que ao final tenhamos a seguinte estrutura no nosso diretório:

└── dir/
├── main.py
← arquivo contendo o código Python da API
└── requirements.txt
← arquivo contendo as dependências da API

Em seguida, estando no diretório raiz do código e das dependências (representado por dir na árvore ASCII acima), podemos realizar o deployment da nossa API no Cloud Functions, utilizando o gcloud CLI.

Basta substituir o campo indicado na linha de comando a seguir com o e-mail da conta de serviço que contém acesso de leitura ao Firestore e, em seguida, executá-lo:

gcloud functions deploy dialogflow_status_pedidos \
--runtime=python37 \
--region=us-central1 \
--source=. \
--entry-point=webhook \
--trigger-http \
--allow-unauthenticated \
--service-account="INSIRA SUA CONTA DE SERVIÇO AQUI"

Rapidamente a nossa API será provisionada e poderemos ter acesso à URL do endpoint, utilizando o seguinte comando:

gcloud functions describe dialogflow_status_pedidos

Basta procurar pelo campo httpsTrigger.url na resposta da linha de comando, ele seguirá o seguinte formato: https://us-central1-PROJECT_ID.cloudfunctions.net/dialogflow_status_pedidos

Dessa forma, podemos adicionar o endpoint da nossa API como um novo webhook no Dialogflow CX, basta navegar até a aba “Manage” do agente, acessar “Webhooks”, e registrá-lo conforme a taxonomia:

Instruções para registro do webhook

Após criar o seu webhook, acesse o fluxo Start do seu agente, selecione a rota pedidos.status e atualize o fulfillment para que passe a utilizar o webhook:

Instruções para adição do webhook registrado ao fulfillment

Prontinho, agora você já pode testar o seu webhook através da própria interface do Dialogflow CX. Basta realizar qualquer interação que acione a intent pedidos.status :

Demonstração de uma interação com o bot que aciona o webhook ao detectar a intenção de status de pedido

Note que, por ainda estarmos interagindo com o nosso bot através da interface (e não do WhatsApp), não é possível capturar o número de celular como id de sessão (conforme é esperado pela nossa API), ou seja, a consulta ao banco não retornará nenhum pedido.

Para que consigamos consultar o status dos nossos pedidos através do bot, vamos disponibilizá-lo no WhatsApp utilizando a integração do ambiente sandbox da Twilio na parte 2 deste artigo, continue acompanhando.

--

--