
Mais empresas do que nunca usam chatbots via WhatsApp para interagir com clientes, entender suas necessidades e reunir dados essenciais. No entanto, esse processo de coletar e organizar dados pode apresentar desafios em termos de eficiência. Conheça o WhatsApp Flows.
Integrar chatbots ao WhatsApp Flows permite que as empresas interpretem as informações recebidas do cliente de forma mais eficaz. Os chatbots podem iniciar fluxos específicos personalizados para a coleta de dados, dependendo do contexto dessa conversa.
Neste tutorial, você criará um chatbot usando Llama 2 e Python, conectando-o ao WhatsApp Flows para melhorar seus recursos de coleta de dados. Dessa forma, você verá como o WhatsApp Flows facilita ainda mais para o usuário a experiência do chatbot e aprimora a precisão e a eficiência da coleta de dados do cliente.
Seu chatbot responderá às solicitações e aos comandos do usuário com o WhatsApp Flows para a coleta de dados. Mais especificamente, ele permitirá que os usuários conversem com o chatbot, pesquisem informações sobre serviços oferecidos por um hotel fictício na Espanha e entrem em contato com a empresa para suporte.
O chatbot usará instruções if simples juntamente com o modelo padrão Llama 2 para fornecer acesso a uma base de conhecimento geral suficiente.
Parte 1:
Crie fluxos usando o configurador de fluxos do Gerenciador do WhatsApp.
Parte 2:
Faça a conversão do modelo Llama 2 de GGML para GGUF.
Aqui, você usará o Configurador de fluxo para criar fluxos. Como alternativa, você pode usar a API de Fluxos. No entanto, não falaremos dela neste artigo.
Para conseguir acompanhar o tutorial, você deve ter:
O ngrok instalado.
Uma conta de desenvolvedor verificada no Meta for Developers e conhecer a API de Nuvem hospedada pela Meta.
Por fim, você deve concluir as etapas necessárias para usar os fluxos. Também é possível ver uma prévia do código do projeto concluído.
Para começar, navegue até a página Fluxos na sua conta do WhatsApp Business. Se essa for a sua primeira interação com os fluxos, você verá o botão Começar a criar fluxos. Caso contrário, haverá um botão Criar fluxo à direita da página.
Clique no botão exibido para abrir uma caixa de diálogo onde você pode inserir mais detalhes sobre seu fluxo:

Primeiro, você criará um fluxo que permite que o usuário busque informações sobre serviços oferecidos pela empresa de hotéis.
Insira um nome no campo Nome. Depois, no menu Categorias, escolha Cadastrar-se e deixe o menu Modelo definido para Nenhum. Clique em Enviar.
A próxima página exibirá um editor à esquerda e uma prévia à direita.
Substitua o conteúdo do editor pela marcação JSON para seu fluxo. (Você pode saber mais sobre o JSON de fluxo na documentação do desenvolvedor.)
Salve o fluxo. Sua prévia deve ser semelhante à imagem abaixo:

O fluxo contém uma tela que permite que o usuário insira suas informações, selecione os serviços de interesse e uma mensagem adicional opcional. Quando o usuário clica em Enviar, o fluxo fecha e envia os dados coletados para sua empresa para tratamento. Um método de transmitir esses dados envolve o uso de pontos de extremidade. No entanto, esse projeto não precisa de um ponto de extremidade. Os dados serão transmitidos para o mesmo webhook que alimenta o chatbot.
Essa transferência pode ser realizada usando ações. Você pode definir os dados para que eles sejam movidos para a próxima tela usando o objeto payload:
...
"on-click-action": {
"name": "complete",
"payload": {
"firstname": "${form.first_name}",
"secondname": "${form.second_name}",
"services_interested": "${form.services_interested}",
"additional_info": "${form.additional_info}",
"flow_key": "agentconnect"
}
}
...
No trecho, a ação do usuário de clicar no botão aciona o on-click-action, coletando os dados na carga. Depois, ela envia a carga ao servidor do seu webhook e fecha o fluxo via ação complete.
Você pode atribuir as chaves payload como faria com qualquer variável. Os valores correspondentes podem representar objetos de dados ou nomes de componentes de fluxo (semelhante a um atributo de nome para o formulário HTML).
Agora, você pode ver o fluxo em ação e simular uma experiência de usuário real usando o botão Prévia interativa:

Depois de testar, você pode publicar o fluxo, pois no momento ele está no estado de rascunho. Para isso, abra o menu à direita de Salvar e clique em Publicar. O fluxo agora está pronto e pode ser usado.
Agora, criará um fluxo "fale conosco".
Comece repetindo o mesmo processo de criação inicial do fluxo. Para a categoria, escolha Fale conosco. Substitua o conteúdo do editor pela marcação JSON para renderizar o seguinte:

Publique o fluxo e avance para a próxima seção para configurar um chatbot. A seção apresenta três funções (send_message, flow_details, e flow_reply_processor) que contêm lógica vital para enviar os fluxos aos usuários. A seção também inclui a lógica para processar cargas recebidas de fluxo. Portanto, recomendamos analisá-la mesmo se já tiver criado um chatbot.
Depois, você configurará o chatbot e o integrará aos seus fluxos.
Antes de continuar, você deve ter:
Conhecimento básico e uma versão recente do Python
A versão HuggingFace do Llama 2 baixada. O modelo HuggingFace Llama 2 não requer ferramentas adicionais nem hardware especializado. Você também pode usar a versão oficial, mas ela necessita de configuração adicional.
O token de acesso à sua conta e a identificação do seu número de telefone
Um editor de código
O chatbot vai operar por meio de um script predefinido criado para ajudar usuários com base nos dados inseridos por eles. Na interação inicial, ele oferece um texto de saudação personalizado e um menu baseado em texto dependendo da mensagem do usuário. Essas opções atendem a necessidades específicas: fazer perguntas sobre os serviços oferecidos pelo hotel, entrar em contato com um dos agentes ou interagir com chatbot com tecnologia da Llama.
Responder a um caractere alfanumérico conectará o usuário ao serviço ou ação correspondente. No entanto, qualquer outra resposta aciona a funcionalidade padrão do chatbot, que ajuda com perguntas gerais ou guia o usuário quanto aos serviços disponíveis com base em mais conversas.
Para começar, crie um ambiente virtual executando o comando abaixo no seu terminal:
python -m venv venv
Ative-o:
source venv/bin/activate
Depois, instale os pacotes obrigatórios:
pip install requests flask llama-cpp-python python-dotenv
Use Flask para criar rotas e interagir com a API, requests para enviar solicitações da internet, llama-cpp-python para interagir com o modelo e python-dotenv para carregar variáveis de ambiente.
Depois, crie um arquivo de ambiente chamado .env e o conteúdo a seguir, atribuindo os valores de forma adequada. (Você pode usar qualquer cadeia de caracteres para o TOKEN.)
TOKEN =
ACCESS_TOKEN =
PHONE_NUMBER_ID =
No mesmo diretório, crie um arquivo chamado main.py e comece adicionando os pacotes que você usará:
import os
import re
import time
import uuid
import requests
from dotenv import load_dotenv
from flask import Flask, request, make_response, json
from llama_cpp import Llama
Agora, inicialize as variáveis e as classes. O trecho também inicia o Flask e chama o método load_dotenv() para ajudar a carregar as variáveis:
app = Flask(__name__)
load_dotenv()
PHONE_NUMBER_ID = os.getenv('PHONE_NUMBER_ID')
url = f"https://graph.facebook.com/v18.0/{PHONE_NUMBER_ID}/messages"
TOKEN = os.getenv('TOKEN')
ACCESS_TOKEN = os.getenv('ACCESS_TOKEN')
code_prompt_texts = ["Contact us", "Chat with our chatbot", "YES", "NO"]
service_list = [
"Accommodation Services",
"Spa Services",
"Dining Services",
"Recreational Facilities",
"Business & Conference Services",
"Transportation Services",
"Accessibility Services",
"Pet-Friendly Services"
]A lista de serviços service_list armazena os serviços oferecidos pelo hotel. A lista code_prompt_texts contém as opções correspondentes às escolhas do usuário, que são 1, 2, Y e N usando a função abaixo. A função abaixo ajudará a mapear as respostas do usuário de acordo com a opção correspondente.
def extract_string_from_reply(user_input):
match user_input:
case "1":
user_prompt = code_prompt_texts[0].lower()
case "2":
user_prompt = code_prompt_texts[1].lower()
case "Y":
user_prompt = code_prompt_texts[2].lower()
case "N":
user_prompt = code_prompt_texts[3].lower()
case _:
user_prompt = str(user_input).lower()
return user_prompt
O código converte as cadeias de caracteres para letras minúsculas a fim de evitar correspondências erradas ao executar a lógica condicional. A estrutura match…case corresponde o comando inserido pelo usuário às ações resultantes. Por exemplo, se o usuário digitar "1", isso acionará a funcionalidade "Contact us".
Depois, a função seguinte contém uma instrução if que usa o pacote Python RegEx, re, para pesquisar certos termos de uma mensagem do cliente a fim de decidir qual tipo de resposta enviar ao usuário:
def user_message_processor(message, phonenumber, name):
user_prompt = extract_string_from_reply(message)
if user_prompt == "yes":
send_message(message, phonenumber, "TALK_TO_AN_AGENT", name)
elif user_prompt == "no":
print("Chat terminated")
else:
if re.search("service", user_prompt):
send_message(message, phonenumber, "SERVICE_INTRO_TEXT", name)
elif re.search(
"help|contact|reach|email|problem|issue|more|information", user_prompt
):
send_message(message, phonenumber, "CONTACT_US", name)
elif re.search("hello|hi|greetings", user_prompt):
if re.search("this", user_prompt):
send_message(message, phonenumber, "CHATBOT", name)
else:
send_message(message, phonenumber, "SEND_GREETINGS_AND_PROMPT", name)
else:
send_message(message, phonenumber, "CHATBOT", name)
Agora, uma mensagem como "Hello there" vai disparar o método send_message com SEND_GREETINGS_AND_PROMPT como segundo argumento. Abaixo, confira o método send_message. Substitua o conteúdo entre <xxx> adequadamente.
def send_message(message, phone_number, message_option, name):
greetings_text_body = (
"\nHello "
+ name
+ ". Welcome to our hotel. What would you like us to help you with?\nPlease respond with a numeral between 1 and 2.\n\n1. "
+ code_prompt_texts[0]
+ "\n2. "
+ code_prompt_texts[1]
+ "\n\nAny other reply will connect you with our chatbot."
)
# loading the list's entries into a string for display to the user
services_list_text = ""
for i in range(len(service_list)):
item_position = i + 1
services_list_text = (
f"{services_list_text} {item_position}. {service_list[i]} \n"
)
service_intro_text = f"We offer a range of services to ensure a comfortable stay, including but not limited to:\n\n{services_list_text}\n\nWould you like to connect with an agent to get more information about the services?\n\nY: Yes\nN: No"
contact_flow_payload = flow_details(
flow_header="Contact Us",
flow_body="You have indicated that you would like to contact us.",
flow_footer="Click the button below to proceed",
flow_id=str("<FLOW-ID>"),
flow_cta="Proceed",
recipient_phone_number=phone_number,
screen_id="CONTACT_US",
)
agent_flow_payload = flow_details(
flow_header="Talk to an Agent",
flow_body="You have indicated that you would like to talk to an agent to get more information about the services that we offer.",
flow_footer="Click the button below to proceed",
flow_id=str("<FLOW-ID>"),
flow_cta="Proceed",
recipient_phone_number=phone_number,
screen_id="TALK_TO_AN_AGENT",
)
match message_option:
case "SEND_GREETINGS_AND_PROMPT":
payload = json.dumps(
{
"messaging_product": "whatsapp",
"to": str(phone_number),
"type": "text",
"text": {"preview_url": False, "body": greetings_text_body},
}
)
case "SERVICE_INTRO_TEXT":
payload = json.dumps(
{
"messaging_product": "whatsapp",
"to": str(phone_number),
"type": "text",
"text": {"preview_url": False, "body": service_intro_text},
}
)
case "CHATBOT":
LLM = Llama(
model_path="/home/incognito/Downloads/llama-2-7b-chat.ggmlv3.q8_0.gguf.bin",
n_ctx=2048,
)
# create a text prompt
prompt = message
# generate a response (takes several seconds)
output = LLM(prompt)
payload = json.dumps(
{
"messaging_product": "whatsapp",
"to": str(phone_number),
"type": "text",
"text": {
"preview_url": False,
"body": output["choices"][0]["text"],
},
}
)
case "CONTACT_US":
payload = contact_flow_payload
case "TALK_TO_AN_AGENT":
payload = agent_flow_payload
case "FLOW_RESPONSE":
payload = json.dumps(
{
"messaging_product": "whatsapp",
"to": str(phone_number),
"type": "text",
"text": {"preview_url": False, "body": message},
}
)
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + ACCESS_TOKEN,
}
requests.request("POST", url, headers=headers, data=payload)
print("MESSAGE SENT")Se a mensagem for uma simples saudação (SEND_GREETINGS_AND_PROMPT), a resposta vai conter comandos adicionais (greetings_text_body).

Da mesma forma, quando um usuário faz uma pergunta sobre os serviços oferecidos, uma mensagem de texto (service_intro_text) contendo os serviços é enviada ao usuário. Além dos serviços, ela também contém um comando para o usuário escolher se deseja falar com um agente.

Se a entrada requer uma resposta do chatbot (CHATBOT), você inicializa o modelo, alimenta-o com o conteúdo da mensagem e processa a resposta para enviar de volta ao usuário. FLOW_RESPONSE exibe uma resposta capturada do fluxo.
As outras opções, CONTACT_US e TALK_TO_AN_AGENT, enviam as cargas de fluxo para o usuário. As cargas do fluxo se originam da função flow_details, cujo corpo é mostrado abaixo. A carga incorpora detalhes essenciais do fluxo, incluindo o FLOW_ID, que você pode recuperar da página Fluxos da sua conta do WhatsApp Business. Também é possível definir essas identificações nas variáveis do ambiente.
def flow_details(flow_header,
flow_body,
flow_footer,
flow_id,
flow_cta,
recipient_phone_number,
screen_id
):
# Generate a random UUID for the flow token
flow_token = str(uuid.uuid4())
flow_payload = json.dumps({
"type": "flow",
"header": {
"type": "text",
"text": flow_header
},
"body": {
"text": flow_body
},
"footer": {
"text": flow_footer
},
"action": {
"name": "flow",
"parameters": {
"flow_message_version": "3",
"flow_token": flow_token,
"flow_id": flow_id,
"flow_cta": flow_cta,
"flow_action": "navigate",
"flow_action_payload": {
"screen": screen_id
}
}
}
})
payload = json.dumps({
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": str(recipient_phone_number),
"type": "interactive",
"interactive": json.loads(flow_payload)
})
return payload
Esse método cria a action.parameters.flow_token gerando um UUID aleatório. O action.parameters.flow_action_payload.screen é transmitido como parâmetro (screen_id). Idealmente, ele deve representar a identificação da tela inicial que você pretende mostrar para o usuário quando action.parameters.flow_cta é executado.
Por fim, adicione as rotas do webhook. A solicitação GET do webhook é iniciada ao adicionar o webhook ao app no Meta for Developers. Ela retorna o hub.challenge da solicitação quando bem-sucedida.
@app.route("/webhook", methods=["GET"])
def webhook_get():
if request.method == "GET":
if (
request.args.get("hub.mode") == "subscribe"
and request.args.get("hub.verify_token") == TOKEN
):
return make_response(request.args.get("hub.challenge"), 200)
else:
return make_response("Success", 403)
A solicitação POST extrai e processa a carga da mensagem usando o método user_message_processor introduzido anteriormente. Como o código só atende à carga da mensagem, ele vai gerar erros ao capturar qualquer outra carga. Por esse motivo, você pode usar uma instrução if para verificar se há um corpo messages.
@app.route("/webhook", methods=["POST"])
def webhook_post():
if request.method == "POST":
request_data = json.loads(request.get_data())
if (
request_data["entry"][0]["changes"][0]["value"].get("messages")
) is not None:
name = request_data["entry"][0]["changes"][0]["value"]["contacts"][0][
"profile"
]["name"]
if (
request_data["entry"][0]["changes"][0]["value"]["messages"][0].get(
"text"
)
) is not None:
message = request_data["entry"][0]["changes"][0]["value"]["messages"][
0
]["text"]["body"]
user_phone_number = request_data["entry"][0]["changes"][0]["value"][
"contacts"
][0]["wa_id"]
user_message_processor(message, user_phone_number, name)
else:
# checking that there is data in a flow's response object before processing it
if (
request_data["entry"][0]["changes"][0]["value"]["messages"][0][
"interactive"
]["nfm_reply"]["response_json"]
) is not None:
flow_reply_processor(request)
return make_response("PROCESSED", 200)
Além disso, você pode usar uma função auxiliar chamada flow_reply_processor para extrair uma resposta do fluxo e enviá-la para o usuário:
def flow_reply_processor(request):
request_data = json.loads(request.get_data())
name = request_data["entry"][0]["changes"][0]["value"]["contacts"][0]["profile"]["name"]
message = request_data["entry"][0]["changes"][0]["value"]["messages"][0]["interactive"]["nfm_reply"][
"response_json"]
flow_message = json.loads(message)
flow_key = flow_message["flow_key"]
if flow_key == "agentconnect":
firstname = flow_message["firstname"]
reply = f"Thank you for reaching out {firstname}. An agent will reach out to you the soonest"
else:
firstname = flow_message["firstname"]
secondname = flow_message["secondname"]
issue = flow_message["issue"]
reply = f"Your response has been recorded. This is what we received:\n\n*NAME*: {firstname} {secondname}\n*YOUR MESSAGE*: {issue}"
user_phone_number = request_data["entry"][0]["changes"][0]["value"]["contacts"][0][
"wa_id"]
send_message(reply, user_phone_number, "FLOW_RESPONSE", name)
Ela usa uma chave (flow_key) para diferenciar entre os dois fluxos e, assim, extrair as respostas adequadamente ao transmitir as primeiras identificações de tela corretas.
Antes de executar o código, compare-o com a versão completa e confirme se há correspondência entre tudo.
Antes de continuar, execute este comando do seu terminal:
flask --app main run --port 5000
Se tiver sucesso, você poderá usar a seguinte mensagem:
* Running on http://127.0.0.1:5000
Em seguida, execute ngrok http 5000 para obter um URL que mapeia seu app. Copie o link.
Depois, na conta de desenvolvedor do Meta for Developers, clique no menu Configuração sob WhatsApp no painel de navegação esquerdo:

No cartão Webhook, clique em Editar.
Depois, no campo URL de retorno na caixa de diálogo aberta, adicione o URL copiado e anexe o /webhook a ele.
Adicione a variável TOKEN do arquivo .env ao campo Verificar token. Clique em Verificar e salvar para fechar a caixa de diálogo.
Agora, no mesmo cartão, clique em Gerenciar e marque o campo mensagens. O cartão deve aparecer conforme segue:

Agora, o webhook está pronto.
Você pode enviar uma mensagem como "Olá" ao número da sua conta. Você receberá a resposta correspondente. Tente responder com um comando mostrado no menu para testar os fluxos:

Abaixo está outra captura de tela mostrando a resposta do chatbot. O usuário pede uma tradução rápida, que o bot pode fornecer.

O WhatsApp Flows é uma ferramenta poderosa para empresas coletarem informações estruturadas, melhorando as integrações do cliente e simplificando a comunicação entre empresas e consumidores. Uma das formas de criar fluxos é com o Configurador do fluxo do Gerenciador do WhatsApp, que oferece uma interface fácil de usar para a criação de fluxos.
Esse app de demonstração oferece um vislumbre de como você pode usar o WhatsApp Flows para melhorar o engajamento do cliente e a análise baseada em dados. Para usos mais especializados, você também pode configurar o Llama 2 e o WhatsApp Flows para conectar seu chatbot a um modelo personalizado ou treiná-lo em relação a fontes de dados proprietários, permitindo que ele responda a perguntas sobre seus produtos e outras funcionalidades usando uma linguagem natural.
Use o WhatsApp Flows para melhorar as integrações com seus clientes e simplifique a coleta de dados nos seus apps hoje mesmo. Experimente já.

20 de agosto de 2025

1 de julho de 2025

27 de fevereiro de 2024
Cadastre-se para receber atualizações mensais da Meta for Developers.