Categorias
Crônicas

Retrospectiva 2017

Ao final de cada ano, desde 2015, comecei uma pequena tradição inspirada pelo meu amigo e chefe Fernando Freitas Alves. Escrever uma retrospectiva do ano que passou.

Talvez a parte mais importante seja parar para pensar em tudo que aconteceu. Minha grande motivação para escrever em 2015 foi o fato de que aquele ano me ensinou mais do que qualquer outro em toda a minha vida.

Já a retrospectiva de 2016 mostrou que ano passado foi de estabilização no trabalho e na vida pessoal. Apesar de não ter muitos avanços na parte da saúde, uma das metas que continuei tendo em 2017.

Como sempre faço em minha vida, em 2017 experimentei diversas maneiras de me manter em uma rotina mais saudável. Tentei algumas novas atividades físicas, como o Crossfit por exemplo, e infelizmente não consegui dar continuidade como deveria.

Também me arrisquei em técnicas de jejum intermitente para perda de peso e melhora da atividade cerebral… sem sucesso.

Graças a mais um ano de falhas na área da saúde percebi que preciso dar uma importância maior para este tópico na minha escala de metas para 2018. O primeiro passo já foi dado: horário marcado na nutricionista já para janeiro.

Mas tive uma pequena conquista nesse ano. Foi agora, bem no finalzinho, em dezembro mesmo. Foi uma amostra de que posso atingir algo se me esforçar um pouco. Parei de roer unhas! Graças a um aplicativo chamado Coach.me.

Roer unhas era um hábito que estava difícil de largar e por isso resolvi usar como um experimento desse aplicativo. Acredite se quiser, estou sentindo as unhas batendo nas teclas neste exato momento como há anos não sentia. Um pequeno passo, mas uma grande prova de que posso conseguir mudar alguns hábitos em 2018, certo?

Outra pequena conquista desse ano foi o café sem açúcar. Sempre tomei café muito doce, mas com a ideia do jejum intermitente veio a necessidade de tomar café ao natural.

O primeiro dia sempre é estranho. Você faz careta a cada gole, mas no dia seguinte eu já estava sentindo o gosto de diferentes tipos de café que temos disponíveis lá no escritório e decidindo os que realmente são do meu gosto.

No trabalho, que nos ocupa boa parte do tempo dentro de um ano, 2017 se mostrou estável. Continuo trabalhando como desenvolvedor na startup de legal tech Tikal Tech.

Com o lançamento de uma nova linha de produtos na empresa as coisas aconteceram rápido. Este foi o ano do ELI na Tikal Tech.

Graças ao desenvolvimento do ELI ICMS Energia tivemos uma experiência muito produtiva com arquitetura de microsserviços. Além de outras integrações interessantes como o Login Integrado do LegalNote para aplicativos ELI. Um sistema de gestão de acesso de usuários centralizado para diferentes aplicativos em Django.

Antes disso, mais pro início do ano, tive o prazer de participar da comunidade Chatbot Brasil. Até criei alguns chatbots e coloquei algum conteúdo por aqui sobre o assunto. Já na Tikal Tech implementamos o chatbot Corujinho na fanpage do SeuProcesso no Facebook. Foi uma experiência bem interessante.

Com o crescimento da empresa tivemos um aumento considerável no staff. Basta ver a  foto do pessoal na retrospectiva de 2015 e notar como as coisas mudaram! Veja a foto da equipe nesse ano.

Equipe Tikal Tech 2017

Falando em trabalho não posso esquecer das minhas férias. Este foi uma das grandes metas desse ano. Aproveitei  maravilhosos 30 dias de viagens e descanso merecido depois de muitos e muitos anos sem tirar férias.

O ponto alto foi a primeira semana em que eu e minha namorada passamos alguns dias em Paraty. Que lugar maravilhoso para aproveitar natureza, os locais históricos e, é claro, as praias e os passeios de barco. Que delícia!

Financeiramente 2017 também foi um ano muito bom para mim, pelo menos comparados aos últimos dez anos de perrengues e problemas para manter um orçamento estável. Graças à liberação do FGTS inativo consegui quitar algumas dívidas e até mobiliar um pouco minha vazia casa.

Mas o que realmente está fazendo a diferença é o estudo de finanças pessoais. Durante esse ano inteiro investi um bom tempo nesse tópico, seguindo canais de Youtube interessantes como o do Gustavo Cerbasi e o Me Poupe!, os quais indico muito a quem quer começar a sair do buraco.

Graças a isso, posso até começar a pensar em investir algum dinheiro para 2018. Nem que sejam apenas alguns trocados. A meta é montar uma reserva de emergência o quanto antes!

Para terminar, algo legal que voltei a fazer: desenhar.

Desenho desse ano! Yey!

Nesse ano de 2017 eu voltei a desenhar e até alimentei o meu canal que fala sobre criação de histórias em quadrinhos no Youtube. Separei os tópicos que falam sobre isso aqui no meu blog para um novo domínio separando assim os conteúdos.

Criei também um Instagram e voltei a alimentar a minha velha fanpage no Facebook.

Sempre adorei desenhar histórias em quadrinhos e manter um hobby divertido como esse é algo essencial para a qualidade de vida de qualquer um. Me fez um bem danado!

Participei pela primeira vez de um Inktober! Se quiser entender melhor o que é isso, é melhor dar uma lida na publicação que fiz no meu blog de desenho.

Bem, por cima esse foi o meu ano de 2017. Essa retrospecitva vale mais para quem escreve do que para quem lê, porque a parte mais legal é repassar o ano na sua cabeça. Rever o que foi feito e pensar em como melhorar no ano seguinte.

Se você leu até aqui, obrigado! Deixe seu comentário sobre como foi seu ano também!

Um abraço e até 2018!

Categorias
Tecnologia

Essa nova tecnologia vai acabar com o que você usa hoje

Para entusiastas de martelo tudo é prego

Eu adoro ler sobre tecnologia e sua indústria pela internet a fora. É muito bom para descobrir algumas tendências e aprender sobre minha área de atuação.

Mas eu tenho notado um certo exagero em algumas publicações de nicho.

Alguns autores parecem querer reforçar que você precisa aprender essa ou aquela tecnologia porque é a única coisa que vai existir no futuro!

“Essa é a tecnologia que irá acabar com/substituir o que você usa hoje. Esteja pronto!”

Para ilustrar melhor o que quero dizer vou dar alguns exemplos.

Quando comecei a me informar sobre chatbots a primeira coisa que li nos textos do pessoal que já estava envolvido com isso é que os bots tomariam o lugar dos aplicativos mobile e até mesmo dos sites.

Afirmam isso com base em informações relevantes mesmo, como pesquisas que mostram que nos EUA as pessoas não estão mais baixando novos apps. Não é uma invenção, me parece apenas uma interpretação exagerada dessas informações.

Um tempo depois eu achei uma publicação que falava sobre arquitetura serverless. Lá o discurso era que em cinco anos ninguém mais estaria usando servidores.

Quando você faz parte de um nicho é muito fácil se deixar levar por opiniões exageradas em favor do que você está envolvido. Entretanto é preciso ser mais objetivo.

É claro que os chatbots podem assumir uma boa fatia de mercado dos aplicativos nativos (e vão, afinal eu sou um entusiasta ;D), mas não vão simplesmente acabar com eles do dia para a noite.

A mesma coisa para a arquitetura serverless… ninguém mais usando servidores em cinco anos? Um pouco exagerado, não acha?

Esses são apenas alguns exemplos, mas ainda podemos voltar um pouco no tempo e lembrar de algumas ondas que diziam que os aplicativos nativos seriam totalmente substituídos pelos híbridos e, já hoje em dia, substituídos pelos progressive webapps ou chatbots

Que tal voltar ainda mais, lá no começo da minha carreira nos grupos de Software Livre, onde achávamos que em breve os computadores com Windows seriam minoria perto dos usuários Linux… E quinze anos depois:

Market share de sistemas operacionais

Mesmo que a tecnologia seja muito rápida em sua evolução, dificilmente uma coisa mata outra tão rápido quanto as postagens que geram o hype afirmam.

Isso acontece porque cada negócio tem uma necessidade diferente, então cada tecnologia pode ser a melhor opção para cada tipo de necessidade. Uma não necessariamente mata outra. E não precisa matar!

Para que uma coisa seja boa ela não tem que destruir outra. Existe espaço, e até a necessidade, para tudo!

Eu escrevi o rascunho deste texto dentro de um Cabify, uso Uber com frequência e adivinha só: ainda existem muitos táxis por aí.

Se você gosta de algo e participa de um grupo sobre isso, como eu com chatbots por exemplo, seja um entusiasta sim! Discuta sobre, aposte nisso, mas mantenha os pés no chão. Entenda que o que você faz/gosta pode ser um ótimo martelo, mas nem tudo é prego.

Publicado originalmente no Medium.

Categorias
Tecnologia

Você não precisa de inteligência artificial para criar um chatbot

Nem Machine Learning e Processamento de Linguagem Natural

Todo mundo que trabalha com desenvolvimento de software sabe que, cada vez mais, existem as “expressões do momento” no mercado. É por isso que eu adoro o texto Hype Driven Development

Uma das mais faladas “expressões do momento” é a inteligência artificial. Ela está em todo lugar, em todas as matérias nas mídias e diversos artigos acadêmicos e começou a ficar extremamente popular no último ano.

Cuidado! Inteligência artificial vai roubar seu emprego!

Depois que o Facebook resolveu liberar os chatbots para sua plataforma de mensagens, chatbot também virou uma expressão do momento. Eu mesmo gostava do assunto antes, mas a partir do ano passado comecei a estudar e aprender ainda mais sobre esse tipo de software.

A partir daí todo lugar onde se vê a palavra chatbot também se vê inteligência artificial. É uma questão bem óbvia, afinal para um robô falar com um humano, ele precisa ter o mínimo de inteligência…

Mas será mesmo que preciso saber criar inteligência artificial para criar um chatbot?

Citando um ótimo texto do Caio Calado que explica o que são chatbots:

Chatbots são serviços baseados em regras e (às vezes) inteligência artificial, onde você pode conversar e interagir através de aplicações/aplicativos de mensagens.

A parte importante dessa citação são as palavras entre parênteses: às vezes.

Como ele explica no texto, existem dois tipos de chatbots. Os baseados em regras e os baseados em inteligência artificial. A maioria dos bots que encontramos por aí é puramente baseado em regras e eles não são ruins por causa disso.

As plataformas de mensagens oferecem diversas maneiras para que o usuário posso interagir com o bot. São botões, listas com links, webviews que abrem uma página externa, etc. Utilizando essas interações fica muito fácil saber o que o usuário quer fazer, sem necessidade de inteligência artificial.

Você não precisa fazer com que o bot tenha um entendimento profundo da lingua portuguesa e entenda cada detalhe de tudo que o usuário está falando para que ele cumpra o que propõe.

Um bot tem que ter uma naturalidade na interação, mas isso depende muito mais do design da conversação do que de inteligência artificial.

Um chatbot é um software. A tecnologia que você vai usar no seu desenvolvimento precisa ser compatível com as necessidades das funcionalidades dele.

Machine Learning, Processamento de Linguagem Natural (NLP) e Inteligência Artificial (AI) são importantes para os mais diversos tipos de aplicações, mas para aquelas que realmente necessitam dessas tecnologias.

Se o bot precisa aprender com dados e interações para melhor atender o usuário e cumprir o objetivo proposto, então Machine Learning é necessário. Se ele precisa classificar textos que o usuário venha a enviar, você vai precisar de NLP… e assim por diante.

Agora se ele fala informações sobre o clima, não precisa ser “inteligente” para bater papo com o usuário ou aprender com as interações. Afinal o objetivo dele é previsão do tempo! Ele só precisa saber onde o usuário está ou de onde ele quer saber a previsão.

Outro grande problema desse hype todo é que essas expressões técnicas assustam quem não conhece e podem acabar afastando pessoas interessadas na construção de chatbots por acharem que é um impeditivo não saber essas tecnologias.

O hype é algo que sempre existirá, mas não devemos nos guiar por ele. Pense no objetivo que o seu chatbot terá e nas funcionalidades que serão necessárias para atingí-lo. Se ele realmente precisar de Inteligência Artificial, então pare de ler e vá estudar matemática agora!

Publicado originalmente no Medium.

Categorias
Tecnologia

O que aprendi publicando um chatbot

A importância do feedback dos usuários

Um tempo atrás eu quis falar sobre chatbots na empresa onde trabalho. Temos um evento interno para compartilhar conhecimento, que começou há pouco tempo por aqui, e aproveitei a chance para mostrar para meus colegas como desenvolver e quais eram as ferramentas que o Messenger do Facebook oferece para a criação de um robô de conversa. Para meu lightning talk resolvi criar um chatbot experimental chamado Climão.

O Climão é um bot bem simples e apenas recebe a localização da pessoa e informa como está o clima no local.

Para isso eu usei um dos templates do Facebook Messenger que cria um botão para o usuário enviar a localização e fiz uma busca em uma API aberta de informações meteorológicas.

Publiquei o bot no Facebook Messenger e aproveitei o que apresentei na empresa para escrever um tutorial.

Após a publicação, algumas pessoas começaram a usá-lo, provavelmente porque leram o tutorial e resolveram testar o bot para ver como funcionava.

Foi aí que comecei a perceber que o Climão precisava de algumas melhorias…

Aprendendo com a experiência do usuário

A primeira pessoa que usou o meu chatbot acessou através de um link que enviei no WhatsApp. Esse link abriu o navegador no celular dela e a primeira coisa que ela me disse foi que o bot não estava funcionando.

Eu dei uma olhada no que ela estava fazendo e vi que ela não usou o botão de enviar localização e sim escreveu o nome da cidade. Pedi para que usasse o botão, mas ela reportou que ele não aparecia para ela.

Fiquei sem entender nada… mas pedi para que abrisse no aplicativo do Messenger e a partir daí tudo funcionou normalmente.

Acessando o histórico de mensagens da página do Climão percebi que mais algumas pessoas estavam tentando escrever o nome da cidade e não usando o botão de enviar localização. Isso era algo que eu não tinha previsto e portanto o bot não entendia e acabava reenviando o botão o tempo todo.

A primeira coisa que pensei foi que as pessoas não estão acostumadas a usar botões em chats, deve ser esse o problema.

Mas a realidade era outra.

Quando montei o bot para a apresentação, não dei atenção alguma para o texto que convidava o usuário à escolher a sua localização. Ele dizia: “De qual cidade você quer saber o clima?”. Isso fazia com que a pessoa pensasse que tinha que responder à pergunta.

Esse feedback veio da mesma pessoa que citei a cima. Algo que não havia me passado pela cabeça!

Isso podia mesmo ser um motivo, mas os dias passavam e eu via mais gente usando o Climão e escrevendo repetidamente o nome da cidade em vez de usar o botão.

Será mesmo que apenas a pergunta estava levando tanta gente à escrever a cidade? Por acaso, acabei descobrindo que não.

Lendo outro texto do Medium que falava sobre um chatbot, resolvi clicar no link para experimentá-lo. Foi então que o mistério se resolveu.

As pessoas estavam acessando o Climão pelo texto do Medium, assim como eu, provavelmente pelo celular, assim com eu, e estavam caindo direto no navegador, assim como eu.

Abrindo a página do Facebook pelo navegador do celular e clicando em “Enviar mensagem” você entra em uma página terrível de mensagem que não tem nenhuma das funcionalidades dos bots do Messenger. Nela você pode interagir com o bot apenas por texto!

No lado esquerdo a versão do navegador mobile e na direita o aplicativo do Facebook Messenger.

Isso poderia ser mais um motivo, além do “texto-pergunta”, que estava fazendo as pessoas digitarem ao invés de enviarem sua localização pelo botão.

Foi então que resolvi melhorar o bot, mesmo ele sendo apenas um experimento para um tutorial, achei que valia a pena a experiência de aprender com a interação de usuários.

Gastei um tempinho nele e fiz com que também aceitasse o nome da cidade escrita. Mudei a frase que pede a localização. Agora ele escolhe aleatoriamente entre algumas opções de texto que indicam ao usuário que pode digitar uma cidade ou apertar o botão de envio de localização.

Aproveitei para dar um tapa no visual da apresentação dos dados também. Ao invés de enviar apenas um texto, resolvi utilizar o template de lista que a API de envio do Messenger proporciona.

Interações “fora do contexto”

Um outro fato que me chamou a atenção quando analisei as mensagens enviadas pelos usuários foram as mensagens que estavam “fora do contexto” das funcionalidades do Climão.

Com “fora do contexto” eu quero dizer interações que eu não previ.

Coisas simples como um “Olá” e um “Obrigado” não eram tratadas, deixando o bot muito “robótico” e pouco natural na conversação. O Climão era antipático!

Dei uma atenção para o tratamento desse tipo de interação, mas não gastei muito tempo com isso ainda, afinal ele é apenas um experimento. Podemos dizer agora que ele não é muito simpático, mas pelo menos já é educado.

Algumas coisas ele responde, mas não chega a ser tão esperto assim…

Conclusão

Esse bot tem sido um experimento incrível. Além de ter aprendido muita coisa com um chatbot tão simples, ainda tenho ganhado uma experiência importante sobre como evoluí-lo para melhor se adaptar às interações com os usuários.

O feedback é a melhor maneira de se aprender. Saber onde você errou ou o que deixou passar depende muito dessa interação com diferentes pessoas. Por isso foi tão importante tirar esse bot do “desenvolvimento” e deixá-lo disponível para o público em geral.

Se você leitor tiver alguma sugestão para melhorar o Climão, deixe sua resposta abaixo. E se quiser ver o código-fonte, acesse o repositório no Github. Quer saber o clima atual em algum lugar? Mande uma mensagem pro Climão!

Publicado originalmente no Medium.

Categorias
Tecnologia

Como criar um chatbot para o Facebook Messenger

Passo a passo para começar um chatbot em Python

Este é um tutorial no estilo passo-a-passo para a criação de um chatbot simples para o Facebook Messenger. Ele foi escrito como conteúdo para uma pequena apresentação que farei em um evento interno de compartilhamento de conhecimento da TIKAL TECH, empresa em que trabalho.

Existem diversas maneiras de se criar um bot para o Messenger, mas neste tutorial eu utilizarei apenas o microframework para web escrito em Python chamado Flask e nada mais.

Esse tutorial resume algumas das coisas que aprendi durante o desenvolvimento de um outro projeto.

Passo 1

Criando um aplicativo e vinculando com uma fanpage

Acesse o dashboard do Facebook Developers e crie um aplicativo. No tipo de aplicativo escolha “Aplicativos para o Facebook Messenger”. Se você não tiver uma página para vincular o aplicativo, crie uma também.

Com a página criada, entre novamente no dashboard e gere um token para o aplicativo ser vinculado à página.

Passo 2

Começando a programar o backend

Vamos utilizar o microframework Flask para facilitar esse desenvolvimento, mas qualquer outro framework web pode ser utilizado.

Se você está acostumado a trabalhar com Python você pode pular alguns dos passos abaixo.

Vamos começar criando um ambiente virtual na linha de comando e instalando o Flask, o requests e o gunicorn. Precisaremos dos dois primeiros para nosso chatbot e o último será para o deploy.

Escolha o diretório que você vai utilizar e digite os seguintes comandos.

$ cd ~/projetos/chatbot/
$ mkvirtualenv chatbot
...

(chatbot)$ pip install Flask
(chatbot)$ pip install requests
(chatbot)$ pip install gunicorn
(chatbot)$ touch index.py

Agora temos um arquivo index.py no nosso diretório chatbot. É nele que faremos os próximos passos do nosso tutorial.

Começamos com o básico do Flask.

import os
from flask import Flask, request

token = os.environ.get('FB_ACCESS_TOKEN')
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def webhook():
    return 'Nothing'

if __name__ == '__main__':
    app.run(debug=True)

Esse arquivo tem o básico do que precisamos para rodar um app no Flask.

O token que estamos pegando de uma variável de ambiente é o token que geramos no dashboard do Facebook.

Para adicioná-lo como variável de ambiente execute na linha de comando:

$ export FB_ACCESS_TOKEN=<cole o token gerado>

Passo 3

Configurando os Webhooks

Temos que configurar um webhook para que o Facebook saiba para onde enviar as requisições do chat.

Para isso utilizaremos o ngrok para “tunelar” nosso localhost. Para saber como funciona, veja esta publicação.

Vamos rodar nosso servidor local com o Flask. Na linha de comando com o virtualenv ativado, digite:

(chatbot)$ python index.py

Abra outra janela de terminal para iniciar o ngrok.

./ngrok http 5000

Agora temos um endereço web com HTTPS para cadastrar no dashboard do Facebook. Basta ir até o painel Webhooks e clicar em Configurar Webhooks.

Antes de cadastrar o endereço, é preciso adicionar uma parte a mais no nosso index.py. O bloco em negrito tem o que é preciso para que o Facebook aceite esse link como elegível para webhook.

def webhook():
    if request.method == 'POST':
        pass
    elif request.method == 'GET': # Para a verificação inicial
        if request.args.get('hub.verify_token') == os.environ.get('FB_VERIFY_TOKEN'):
            return request.args.get('hub.challenge')
        return "Wrong Verify Token"
    return "Nothing"

Coloque o endereço gerado pelo ngrok, por exemplo https://7f3o6bd7.ngrok.io, e crie uma frase de segurança. Essa frase colocamos na variável de ambiente FB_VERIFY_TOKEN que você pode ver no código acima.

(chatbot)$ export FB_VERIFY_TOKEN=<digite qualquer frase aqui>

Com isso já somos capazes de registrar nosso endereço do chatbot no Facebook.

Para finalizar, no mesmo painel de webhooks você deve “inscrever” sua página criada ao webhook adicionado. Essa parte é bem autoexplicativa.

Passo 4

Lendo a mensagem e respondendo

Agora vamos adicionar uma maneira de lermos o que o usuário nos enviou pelo Messenger. Isso é feito verificando os dados enviados na requisição que o chat nos envia via POST.

Então vamos adicionar ao nosso código o seguinte trecho:

import os
import requests
import traceback
import json

(...)

def webhook():
    if request.method == 'POST':
        try:
            data = json.loads(request.data.decode())
            text = data['entry'][0]['messaging'][0]['message']['text']
            sender = data['entry'][0]['messaging'][0]['sender']['id']
            payload = {'recipient': {'id': sender}, 'message': {'text': "Hello World"}}
            r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token, json=payload)
        except Exception as e:
            print(traceback.format_exc())
    elif request.method == 'GET': # Para a verificação inicial
(...)

Explicando o que estamos fazendo. Adicionamos os imports necessários no topo do arquivo index.py e dentro do nosso método webhook verificamos se a requisição chegou como POST.

Com o data = json.loads(request.data.decode()) nós capturamos o corpo da mensagem que nos foi enviado pelo Messenger.

Com o trecho text = data['entry'][0]['messaging'][0]['message']['text']conseguimos pegar o texto que o usuário enviou via chat.

Pra saber quem enviou, usamos o trecho sender = data['entry'][0]['messaging'][0]['sender']['id']. Essa informação é necessária para que possamos enviar uma resposta para o usuário correto.

No trecho payload = {'recipient': {'id': sender}, 'message': {'text: "Hello World"}} nós montamos o corpo da nossa resposta ao usuário.

Para finalizar, respondemos enviando uma requisição para o endereço da API do Facebook Messenger com o corpo criado anteriormente. O trecho referente ao envio segue abaixo.

r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token, json=payload)

Colocamos tudo isso dentro de um try/except para capturar um possível erro que imprimiremos no console. Isso fazemos com o trecho final do código que acabamos de adicionar.

except Exception as e:
    print(traceback.format_exc())

Com isso, respondemos um Hello World para cada entrada que o usuário nos enviar.

Passo 5

Tornando o chatbot em algo útil

Como responder Hello World para cada mensagem é algo totalmente inútil para um bot fazer, vamos colocar uma funcionalidade aproveitando a documentação do Messenger, que é bem completa.

Vamos pegar a localização do usuário e enviar informações sobre o clima atual em sua localidade.

Primeiro criamos uma função que monta um payload com formatoQuick Reply do Messenger. O formato que precisamos enviar para ter esse resultado é facilmente encontrado na documentação do Messenger. Nela definiremos que queremos um tipo location.

def location_quick_reply(sender):
    return {
        "recipient": {
            "id": sender
        },
        "message": {
            "text": "Compartilhe sua localização:",
            "quick_replies": [
                {
                    "content_type": "location",
                }
            ]
        }
    }

Agora, quando formos enviar uma mensagem para nosso usuário, utilizamos essa função no lugar do antigo payload.

payload = location_quick_reply(sender)

Isso vai enviar uma opção para o usuário nos enviar sua localização. Como mostra a imagem abaixo.

Vamos receber essa localização de maneira diferente do que um texto comum, ela virá como um anexo. Dessa forma mudamos nossa verificação de texto para o bloco abaixo.

if request.method == 'POST':
        try:
            data = json.loads(request.data.decode())
            print(data)
            message = data['entry'][0]['messaging'][0]['message']
            sender = data['entry'][0]['messaging'][0]['sender']['id'] # Sender ID

            if 'attachments' in message:
                if 'payload' in message['attachments'][0]:
                    if 'coordinates' in message['attachments'][0]['payload']:
                        location = message['attachments'][0]['payload']['coordinates']
                        latitude = location['lat']
                        longitude = location['long']
            else:
                text = message['text']
                payload = location_quick_reply(sender)
                r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token,
                                  json=payload)

Nesse bloco verificamos se o corpo da requisição que o Messenger nos enviou possui uma chave attachments e se possui uma chave payload com as coordenadas da localização.

Se não vier nesse formato é porque ele enviou uma mensagem normal de texto, então reenviamos o botão que pede sua localização.

Agora que pegamos a latitude e longitude, podemos utilizar uma API aberta de clima para enviar as informações para nosso usuário.

Eu escolhi a OpenWeatherMap para isso. Basta se inscrever e gerar uma chave de API no site deles e você já pode começar a fazer requisições variadas para receber informações de clima do mundo inteiro.

Adicionei a chave de API deles numa variável de ambiente para utilizar nas requisições que farei dentro do código e pronto.

(chatbot)$ export WEATHER_API_KEY=<digite a api key>

Agora podemos acessar o endpoint que eles fornecem para current weathere pegar a temperatura e outros dados climáticos do local do usuário.

Logo após o trecho do código onde pegamos a latitude e longitude, adicionamos uma requisição para a API do OpenWeatherMap para montar a resposta que daremos ao nosso usuário.

api_key = os.environ.get('WEATHER_API_KEY')

(...)

url = 'http://api.openweathermap.org/data/2.5/weather?' \
      'lat={}&lon={}&appid={}&units={}&lang={}'.format(latitude, longitude, api_key, 'metric', 'pt')

r = requests.get(url)

description = r.json()['weather'][0]['description'].title()
icon = r.json()['weather'][0]['icon']
weather = r.json()['main']

text_res = '{}\n' \
           'Temperatura: {}\n' \
           'Pressão: {}\n' \
           'Humidade: {}\n' \
           'Máxima: {}\n' \
           'Mínima: {}'.format(description, weather['temp'], weather['pressure'], weather['humidity'], weather['temp_max'], weather['temp_min'])

payload = {'recipient': {'id': sender}, 'message': {'text': text_res}}

r = requests.post('https://graph.facebook.com/v2.6/me/messages/?access_token=' + token, json=payload)

Basicamente analisei a resposta da API do OpenWeatherMap e peguei as informações que gostaria de exibir ao usuário. Depois disso montei um bloco de texto simples exibindo algumas das informações.

Pronto! Agora temos uma funcionalidade para nosso bot experimental.

Passo 6

Fazendo o deploy

Vamos colocar nosso novo bot em um servidor para que ele fique disponível constantemente. Como eu falei anteriormente é preciso uma conexão segura (HTTPS) para que o Facebook aceite a URL do chatbot.

Com o Heroku é muito simples fazer o deploy. Basta que o seu código esteja no github, por exemplo, e com um clique ele fica online.

Para fazê-lo funcionar no Heroku é preciso adicionar dois novos arquivos ao nosso projeto. O Procfile e o runtime.txt. O primeiro configura o servidor web e o segundo define que estamos usando o Python 3.

Se você estiver utilizando a versão 2 do Python, o segundo arquivo é desnecessário.

O arquivo Procfile ficará assim:

web: gunicorn index:app

E o runtime.txt assim:

python-3.5.2

Criamos uma conta no Heroku e adicionamos um novo app. Em seguida vamos na aba Deploy e conectamos com o Github. Com isso basta escolher o seu repositório e clicar em Deploy Branch.

Abas do Dashboard do Heroku

Precisamos adicionar nossas variáveis de ambiente. Para isso devemos ir à aba Settings e adicionar manualmente por lá. É simples e autoexplicativo.

Agora testamos nossa URL, que será algo como https://<nome_do_app>.herokuapp.com.

Voltamos ao dashboard de developers do Facebook para mudar nosso webhook configurado. Lembra que fizemos isso com o endereço que o ngrok nos forneceu no passo três? Agora vamos mudar a URL para a nova que o Heroku nos forneceu.

Aprovação do Facebook

Com nosso bot funcional e online, agora temos que deixá-lo em aprovação no dashboard de developers do Facebook.

Basta preencher o que eles pedem por lá e aguardar até cinco dias para que seu bot possa ser usado por qualquer usuário do Facebook.

Conclusão

O Facebook aprovou rapidamente o chatbot que chamei de Climão. Isso porque utilizamos apenas a permissão de messages do Webhook, que é a mais simples.

Para utilizar esse bot acesse a Página do Facebook e envie uma mensagem para o Climão. =)

O código que criamos durante esse tutorial está disponível no Github.

Qualquer dúvida, entre em contato pelas respostas abaixo.

Publicado originalmente no Medium.

Categorias
Tecnologia

Como fazer tunelamento de localhost de forma segura

Veja como expor seu servidor local para a internet e para que serve isso

O tunelamento do localhost é uma maneira de ter um “link externo” que aponte para alguma aplicação que você esteja rodando localmente. Dessa forma podemos “expor” nosso servidor local de forma segura.

Mas por que eu iria querer isso? Podemos usar essa solução para diversas situações, principalmente no desenvolvimento web. Vou mostrar alguns exemplos de uso nessa publicação.

Para os exemplos a seguir eu estou usando o ngrok, um software que facilita muito isso e ainda mantém essa exposição totalmente segura.

Mostrar um desenvolvimento em andamento para o cliente

Digamos que você esteja desenvolvendo um site ou um sistema web para um cliente e quer mostrar o que você desenvolveu até o momento. O mais comum seria fazer o deploy do trabalho em andamento em um servidor web e disponibilizar o link para seu cliente.

Mas existe uma outra opção, podemos deixar o site rodando localmente e tunelar com o ngrok.

Você pode iniciar um servidor local com o SimpleHTTPServer do Python, por exemplo, e rodar o ngrok na linha de comando, como no exemplo abaixo.

$ python -m SimpleHTTPServer 8000
Serving HTTP on 0.0.0.0 port 8000 ...

Em outra aba do terminal você inicia o tunelamento.

./ngrok http 8000

Agora ele irá exibir o endereço que ficará disponível para seu cliente pela internet. Será algo como http://36096fff.ngrok.io.

Ao rodar, o ngrok vai aparecer assim no seu terminal…

Estamos iniciando um servidor HTTP local na porta 8000. Perceba que o comando de tunelamento recebeu os parâmetros http e 8000, indicando que é um servidor http e que está usando a porta 8000.

Testar um chatbot durante o desenvolvimento

Durante o desenvolvimento de um chatbot para o Facebook Messenger, por exemplo, não é possível testar sem um “endereço web”. É preciso que seja registrada uma URL nas configurações do seu chatbot do Messenger para que ele receba os eventos de mensagem.

Para entender melhor sobre isso, veja este artigo.

Para que você não precise fazer deploy de cada pequena alteração em um servidor web para testar no seu chatbot, crie um tunelamento, como no exemplo anterior, e registre o endereço gerado na seção webhook nas configurações do chatbot no Messenger.

Obs: Nem todos os aplicativos de mensagem se utilizam de webhooks para receber os eventos. No caso do Telegram, como neste link, não é necessário utilizar o tunelamento.

Testar endpoints de webhooks

Eu falei em webhooks no item anterior. Pra quem não sabe o que é, segue uma tradução livre de uma parte do artigo da Wikipedia:

Webhooks são “retornos de chamada HTTP definidos pelo usuário”. Normalmente eles são ativados por algum evento, como o push de código para um repositório ou um novo comentário postado em um blog. Quando ele acontece, o site origem faz uma requisição HTTP para a URI configurada para o webhook, enviando os dados do evento.

Existem diversos serviços que utilizam esse formato para enviar dados de eventos. Um bom exemplo é o Sendgrid ou o Mandrill, que usam webhooks para enviar os eventos de email (lido, marcado como spam, link clicado, etc.) para um sistema de terceiros que esteja usando sua API.

Outro bom exemplo são integrações com gateways de pagamento, como Iugu, PagSeguro ou PayPal, onde, mesmo durante o desenvolvimento, você precisa de um “endereço web aberto” para receber os eventos relacionados aos pagamentos, alterando o status de uma compra, por exemplo.

Para isso, abra um tunelamento com o ngrok e registre o novo endereço gerado por ele com o seu endpoint para receber os eventos webhook do serviço que você está utilizando.

Painel do ngrok

Uma funcionalidade interessante do ngrok é o seu painel, ou interface web.

Screenshot da interface web

Com ela você vê todas as requisições que foram feitas ao seu endereço web aberto. Com isso você pode verificar os dados que estão vindo com as requisições e ainda dar um “replay” na mesma, para testar novamente.

Para acessar, veja o endereço listado no terminal do ngrok como Web Interface e abra no seu navegador. Vai ser algo como http://127.0.0.1:4040.

Concluindo

Esses são alguns casos de uso para o tunelamento de localhost. Alguns deles eu já utilizei, como o teste de webhooks e a demonstração de desenvolvimento em andamento para cliente. Mas eu descobri mesmo que isso era possível ao ler um tutorial de criação de chatbot para o Facebook Messenger, então resolvi dar esse exemplo também.

Publicado originalmente no Medium.
Categorias
Tecnologia

Como criar um chatbot para Telegram

Essa publicação é baseada na minha primeira experiência criando um chatbot para o Telegram usando Python. O código fonte dessa experiência pode ser encontrado no meu Github.

The Botfather

O Telegram facilita muito a criação de bots para seu sistema. Além de uma documentação muito boa e uma API muito simples de usar, ele possui o BotFather, um bot que ajuda qualquer um a criar seu próprio bot.

Segundo a documentação do Telegram:

BotFather is the one bot to rule them all. It will help you create new bots and change settings for existing ones.

Então vamos lá. Para começar é preciso acessar o @BotFather e fazer o registro do seu novo chatbot.

Para qualquer criação ou configuração de bot é preciso acessá-lo. E como vamos criar um novo bot, acessamos o link @BotFather.

Lá você terá acesso a diversos comandos, dentre eles o /start, que irá apresentar a lista desses comandos e o /newbot, que serve para a criação de um novo bot.

Quando executarmos o /newbot ele pede algumas configurações, como o nome e o username que serão utilizados pelo bot. Nada complicado.

Seu bot será como um usuário comum do Telegram, com um “nome para exibição” e um “nome de usuário” (username) para controle.

Assim que forem preenchidos os dados necessários ele irá gerar um token para ser utilizado no seu script. Esse token é único e serve como uma “senha” para seu bot, portanto deve ser mantido em sigilo.

Para saber mais sobre o @BotFather, acesse a documentação do Telegram que fala sobre bots para desenvolvedores.

Armazenando e acessando o token

Agora que já temos o token do nosso bot, devemos guardá-lo em uma variável de ambiente para que possamos acessá-lo posteriormente no nosso script Python.

Na linha de comando, execute o seguinte:

$ export BOT_API_TOKEN="<aqui vai o token gerado pelo botfather>"

Agora você poderá recuperá-lo facilmente em seu script Python com apenas duas linhas de código.

import os
token = os.environ['BOT_API_TOKEN']

Obs: Esta é apenas uma sugestão de como armazenar essa informação. Você pode guardar seu token da maneira que achar melhor.

Implementando os comandos

Um pacote que facilita muito a vida de quem está desenvolvendo um bot para o Telegram é o pyTelegramBotAPI. Com ele basta adicionar decorators nas suas funções e elas passarão a atender aos comandos recebidos.

Podemos usar o seguinte comando para instalar o pacote via pip:

$ pip install pyTelegramBotAPI

Agora chegou a hora de implementar os comandos que controlarão o bot.

Vou abordar somente um tipo de decorator e de resposta a caráter de exemplo. Através da documentação do pyTelegramBotAPI você consegue facilmente implementar diversas outras formas de input e output para o seu bot.

Começamos o script em Python fazendo nossos imports e iniciando o telebot com o token do Telegram gerado pelo @BotFather, como no exemplo de código abaixo.

import os
import telebot
  
bot = telebot.TeleBot(os.environ['BOT_API_TOKEN'])

Agora é só começar a implementar os comandos. No exemplo abaixo eu estou implementando uma mensagem de boas vindas para os comandos /start e /help.

@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, u"Olá, bem-vindo ao bot!")

No final do script adicionamos o método bot.polling() para inicializar o nosso novíssimo bot.

bot.polling()

Basta executar o script em linha de comando e o seu bot está pronto para começar a ser testado.

$ python bot.py

Para executar o teste, basta acessar seu Telegram e seguir o usuário com o username que você deu para seu bot lá no começo do processo, com o @BotFather.

E voilá!

Simples, não é? Veja como nosso script em Python ficou bem pequeno.

import os
import telebot
  
bot = telebot.TeleBot(os.environ['BOT_API_TOKEN'])
@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, u"Olá, bem-vindo ao bot!")
bot.polling()

Publicado originalmente no Medium.

Categorias
Tecnologia

Annyang para reconhecimento de voz

Nos últimos dias do ano passado comecei um projeto de chatbot para praticar Python e Flask, chama-se Jarvis. A ideia é que sempre que eu tiver um tempo livre eu adicione algumas coisinhas a mais nele.

Desde o começo eu gostaria que o Jarvis ajudasse na prática da lingua inglesa, principalmente na conversação. Foi por isso que comecei a pesquisar meios de fazer reconhecimento de voz (speech recognition) pela web.

A opção mais comum é a Speech API do Google, entretanto ela tem algumas limitações por ter um largo uso entre os desenvolvedores. Então fui pesquisar se existia outra opção. Nessa pesquisa encontrei o Annyang, um projeto em javascript para adicionar comandos de voz ao seus aplicativos web.

Ele é muito fácil de aplicar ao site, basta adicionar o script ao html e declarar os comandos de voz que o seu site irá atender.

<script src="//cdnjs.cloudflare.com/ajax/libs/annyang/1.4.0/annyang.min.js"></script>
<script>
    if (annyang) {
        // Let's define our first command. First the text we expect, and then the function it should call
        var commands = {
            'show tps report': function() {
                $('#tpsreport').animate({bottom: '-100px'});
            }
        };

        // Add our commands to annyang
        annyang.addCommands(commands);

        // Start listening. You can call this here, or attach this call to an event, button, etc.
        annyang.start();
    }
</script>

É importante adicionar uma verificação lógica na variável annyang antes de tudo, porque se o navegador não for compatível com o reconhecimento de voz seus comandos serão ignorados e não causarão erro algum. Isso pode ser feito porque no código fonte do Annyang a variável é iniciada como false antes de fazer a verificação de suporte do navegador e caso o mesmo não tenha este suporte, ela continuará falsa.

Caso você queira adicionar um comando que possa receber qualquer palavra depois (uma variável) continua sendo muito simples: basta adicionar um asterisco antes do nome da variável e declará-la como parâmetro na função anônima do comando.

var commands = {
    'tell me *chat' : function(chat) {
        $('#question').val(chat);
        $('#the-form').submit();
    }
}

No exemplo acima mostro como estou usando no projeto Jarvis. Basta o usuário pronunciar ‘tell me‘ e a frase que gostaria de dizer em inglês, então o sistema preenche o campo do formulário com a frase e em seguida executa um submit, fazendo com que o Jarvis responda em seguida.

Caso você queira ver o que está acontecendo enquanto ele tenta reconhecer o que você está dizendo, adicione um annyang.debug(); antes do annyang.start();. Isso fará com que ele apresente no seu console Javascript o que está sendo reconhecido em tempo real. Isso é prático porque ele nem sempre consegue reconhecer e você consegue perceber o que pode estar acontecendo.

Opinião

O Annyang funciona muito bem para aquilo que se propõe, que é o reconhecimento de comandos de voz, entretanto nem sempre ele consegue reconhecer uma frase maior, diferente da Speech API do Google, talvez por problemas com a entonação ou a pronúncia. Ainda não experimentei ele com um microfone melhor, apenas com o do meu notebook, e talvez isso faça uma boa diferença na porcentagem de sucesso. Mas ele é tão fácil de implementar que vale a pena experimentar e se divertir com os comandos de voz.

No caso do Jarvis ele não fica tão prático por causa da necessidade de um comando antes de cada frase e para a prática de conversação isso é um pé no saco, mas mesmo assim vou mantê-lo no projeto por enquanto.

Observação: O Annyang não irá funcionar com arquivos locais (acessando via file:///) pois o navegador (pelo menos o Google Chrome) irá bloquear a tentativa do script de acessar o microfone. É preciso testá-lo com um servidor http.

Categorias
Tecnologia

Chatbot com Flask e PyAIML

Continuo meus estudos com Flask, para brincar um pouco com o que estou aprendendo resolvi fazer um chatbot utilizando a biblioteca PyAIML e os arquivos AIML da A.L.I.C.E. AI Foundation.

Pra quem não sabe, os arquivos AIML (Artificial Intelligence Markup Language) são marcações baseadas em XML para inteligência artificial. Usando a biblioteca PyAIML fica muito simples fazer um chatbot em Python. Mas eu queria fazê-lo via web e foi aí que o Flask entrou.

Utilizei o Flask apenas para lidar com os requests e responses via web. Ou seja, ele recebe uma pergunta vinda do navegador e devolve uma resposta do bot.

Para ver o código-fonte completo do meu chatbot, acesse meu github.

Vendo o código-fonte, percebe-se que na raiz temos apenas o diretório app e o lib, além do arquivo run.py, que roda o servidor. Dentro do diretório app temos os arquivos do Flask: __init__.py e o views.py. No diretório lib está a biblioteca PyAIML e os arquivos AIML, importados da A.L.I.C.E. AI Foundation. Nestes arquivos eu fiz pouquíssimas alterações para o funcionamento básico do Jarvis, nome que dei ao meu chatbot.

Dentro do arquivo app/__init__.py eu importo o Flask e biblioteca PyAIML, para poder utilizá-la no arquivo app/views.py. Perceba que também importo o arquivo brain.brn, que é a “compilação” dos arquivos AIML, ou seja, é o cérebro do bot. Se ele não existir, o Kernel da biblioteca PyAIML vai criá-lo. Exemplo nas linhas abaixo, retiradas do arquivo app/__init__.py.

brainfile = os.path.join('lib', 'pyaiml', 'brain.brn')
aimlfiles = os.path.join('lib', 'pyaiml', 'aiml', 'std-startup.aiml')

k = aiml.Kernel()
if os.path.isfile(brainfile):
	k.bootstrap(brainFile = brainfile)
else:
	k.bootstrap(learnFiles = aimlfiles, commands = 'load aiml b')
	k.saveBrain(brainfile)

Uma pequena observação, estou importando os arquivos com os.path.join() para que não precise me preocupar se estou em sistema operacional Windows ou em Unix-based. Isso foi necessário porque no Windows as barras que separam os arquivos são inversas às dos sistemas baseados em Unix (como Linux e MacOS).

No arquivo app/views.py encontramos as definições de rotas (@app.route()) e definimos o que cada endereço web vai fazer no sistema. No caso, temos o / ou /index, que apenas mostra o template básico, através do método render_template do Flask, e temos o /talk, que recebe a “pergunta” do browser e envia a resposta transformada em um objeto JSON com o método jsonify do Flask. Os outros métodos são apenas handlers para os erros 404 (página não encontrada) e 500 (erro interno do servidor). Veja o index e o talk no exemplo abaixo, retirado do arquivo app/views.py.

@app.route('/', methods=['GET'])
@app.route('/index', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/talk', methods=['GET'])
def talk():
    question = request.args.get('question')
    answer = k.respond(question)
    return jsonify(question=question, answer=answer)

Lembrando que quando chamamos k.respond() no método talk() estamos chamando a biblioteca PyAIML para fazer o trabalho pesado por nós. Já a importamos no arquivo app/__init__.py e a passamos para a variável app.

É importante lembrar que aquilo que fomos utilizar em um programa Python tem que ser importado. Por isso é comum vermos os comandos import no começo dos arquivos. Por exemplo, no arquivo app/views.py eu importei o render_template, o request e o jsonify do Flask e o app e k (que contem a biblioteca PyAIML) do nosso app iniciado no arquivo app/__init__.py.

from flask import render_template, request, jsonify
from app import app, k

Com a biblioteca PyAIML fazendo a interpretação dos arquivos AIML, o Flask tinha pouquíssimo trabalho pela frente. Com apenas alguns poucos métodos escritos eu consegui rodar o aplicativo web. Isto é algo que tem me agradado muito no Python e no Flask.

Utilizar o PyAIML também foi simples, mas para entender como personalizar o bot (mudar o nome, nascimento, preferências, etc) eu levei um tempinho. Precisava entender que os “predicates” do bot precisavam ser mudados no arquivo lib/pyaiml/aiml/Kernel.py da biblioteca. Para facilitar, criei um arquivo chamado lib/pyaiml/aiml/BotPredicates.py e o importei no Kernel.py, como mostro abaixo.

import BotPredicates
# Set up the bot predicates 
self._botPredicates = BotPredicates.bot

Acabou sendo mais simples do que eu imaginava criar o Jarvis. Agora vou continuar brincando um pouco com ele. Quero adicionar reconhecimento de voz para que o usuário possa conversar com o Jarvis. Também quero que o usuário se registre com login e senha, para que o Jarvis já conheça seus amigos quando eles vierem conversar. A medida que eu for desenvolvendo essas novas funcionalidades vou postando algumas notas por aqui.