Catbot en Facebook


Actualmente existen varias plataformas para hacer disponible nuestros chatbots a una gran cantidad de usuarios. Esto ofrece la ventaja de que el usuario ya acostumbrado a la plataforma no tiene que aprender habilidades nuevas habilidades para interactuar con nuestro chatbot ya que son usuarios de la plataforma. Algunas ejemplos de plataformas que permiten montar chatbots son:

En esta sesión mostraremos como construir un chatbot para Facebook, pero en realidad los conceptos son similares a otras plataformas.

El modelo

La mayoría de las plataformas tiene un ecosistema establecido en dónde el look y la experiencia del usuario está bien definida. Esto complica la situación porque si quieren permitir que terceros como nosotros desarrollemos chatbots para su plataforma tienen que encontrar un mecanismo para darnos acceso y permitir ejecutar nuestro código con el de ellos. El modelo preferido es el de servicios (webhooks). Este modelo tiene tres elementos:

  • El usuario: que interactua con nuestro chatbot, usualmente tiene una cuenta en la plataforma. En el caso de Facebook, el usuario se trata de alguien que tiene una cuenta y que puede acceder al servicio.
  • La plataforma: esta se encarga de la administración del usuario, en particular de su cuenta y su acceso la interfaz. En el caso de Facebook corresponde a su plataforma messenger y su servicio web. La plataforma es la interfaz entre usuario y chatbot, recibe mensajes del usuario y se los envía al chatbot, y de igual forma recibe respuestas del chatbot y se los presenta al usuario.
  • El chatbot: es el programa que ejecuta la inteligencia del chatbot, y es un servicio web que tiene que estar atento a recibir mensajes y construir la respuesta a dar. En el caso de Facebook se usa una metología de webhooks que son llamadas identificadas entre Facebook y el chatbot. El chatbot sólamente dialoga con la plataforma.

Chatbot en flask

El chatbot lo podemos desarrollar con la misma tecnología que usamos en nuestro chatbot anterior Flask. A diferencia del chatbot anterior ahora nuestro código no tiene que generar la vista html y por lo tanto la lógica del programa es más directa.

La lógica del chatbot es la siguiente

Hay tres tareas que queremos que resuelva nuestro chatbot:

  1. Establecer una conexión segura con Facebook Para eso toda comunicación que enviemos a Facebook tiene que ir cifrada (https) y con una llave de acceso (ACCESS_TOKEN), e igualmente todo lo que nos envíe Facebook irá cifrado (http) y cuando se conecte con nuestro servicio tendrá que enviarnos un código de verificación (VERIFY_TOKEN). Estos valore los deben conocer tanto Facebook como nuestro chat. El _acccestoken lo propone Facebook y el _verifytoken nosotros; pero ambos lo deben conocer. Estos valores se guardan en el archivo de config.
ACCESS_TOKEN = "OBTENER_DE_FACEBOOK"
VERIFY_TOKEN = "VALOR_SECRETO" 
  1. Registrar la conexión Esta es una llamada que tenemos que atender de Facebook a nuestro chatbot y que le pide repetir un valor especial. La llamada la hace Facebook con una acción GET y un argumento: ?hub.mode=suscribe; si nuestro chatbot recibe esta url tenemos que verificar que efectivamente se trate de una llamada de Facebook con el _verifytoken y regresar el valor de argumento challengue con un código de éxito (200). Es lo hace el siguiente código:
	@app.route('/', methods=['GET'])
	def verify():
	    if request.args.get("hub.mode") == "subscribe" and request.args.get("hub.challenge"):
	        if not request.args.get("hub.verify_token") == config.VERIFY_TOKEN:
	            return "Verification token mismatch", 403
	                return request.args["hub.challenge"], 200
	    return "Hello world", 200 

En caso de no cumplir con ser una llamada de registro, se regresa un “Hello wordl” que podemos utilizar para saber que nuestro servicio está arriba.

  1. Recibir un mensaje y contestarlo Una vez registrado, el chatbot está listo para conversar. Nuestro servicio recibirá una llamada con la acción POST que traerá el mensaje, y para el cual tenemos que crear una respuesta. En este sencillo utilizaremos el mismo mecanismo para controlar la inteligencia vía el lenguaje AIML. La función que se encarga de esto queda así:
	@app.route('/', methods=['POST'])   zOdef webhook(): 
	    data = request.get_json()
	    if data["object"] == "page":
	        for entry in data["entry"]:
	            for messaging_event in entry["messaging"]:
	                if messaging_event.get("message"):
	                    # Se obtiene la información del mensaje
	                    sender_id = messaging_event["sender"]["id"]
	                    recipient_id = messaging_event["recipient"]["id"]
	                    message_text = messaging_event["message"]["text"]
	                    ans=k.respond(message_text)
	                    send_message(sender_id, ans)
	   return "ok", 200

La función _sendmessage tiene la función de preparar el mensaje de la siguiente forma:

    def send_message(recipient_id, message_text):
        params = {
            "access_token": config.ACCESS_TOKEN
        }
        headers = {
            "Content-Type": "application/json"
        }
        data = json.dumps({
            "recipient": {
                "id": recipient_id 
            },
            "message": { 
                "text": message_text} 
            }
        )
        r = requests.post("https://graph.facebook.com/v2.6/me/messages", params=params, headers=headers, data=data)

Como podemos ver prepara una estructura de tipo json y manda el menaje a una dirección de Facebook con el identificador de la comunicación para que así encuentre su camino a nuestro chatbot.

A este mecanismo de ligar un servicio de plataforma con nuestro código lo conocemos como webhook. Las llamadas que puede atender nuestro servidor se le conoce como webhook.

Ejecutando nuestro webhook

Un problema como desarrollador es que al estar probando ejecutamos nuestro código en nuestra computadora personal, y Facebook necesita acceder a nuestro webhook con una URL pública. Para lograr hacer visible a nuestro servicio tenemos tres opciones:

  1. Configurar nuestro firewall para redireccionar el tráfico que llegué a el en cierto puerto a nuestra computadora. Requerimos acceso al firewall/ruteado/punto de acceso.
  2. Tomar nuestro código y ponerlo en un servicio web como Amazon AWS, Heruko, etc. Muchos de estos servicios cuestan dinero, pero es la mejor opción cuando ya dejamos de desarrollar y queremos que el resto del mundo disfrute de nuestro chatbot.
  3. Finalmente, podemos usar un servicio de tuneling que transfiera nuestra comunicación con una URL pública hasta nuestra computadora. En particuclar [ngrok] es lo que hace. Como desarrolladores es nuestra mejor opción.
./ngrok http 5000

Y nos entrega la siguiente información:

|ngrok by @inconshreveable                                                 (Ctrl+C to quit)

Session Status                online                                             
Version                       2.2.4                                               
Region                        United States (us)                                 
Web Interface                 http://127.0.0.1:4040                               
Forwarding                    http://92399a00.ngrok.io -> localhost:5000         
Forwarding                    https://92399a00.ngrok.io -> localhost:5000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00 

En particular las URLs para Forwarding son las que nos interesa, cómo queremos una conexión segura debemos apuntar la que comienza con https. En esta vista también podremos ver el flujo de la información entre Facebook y nuestro chatbot

Con lo anterior cuando corramos nuestro chat con:

python app.py 

Permitirá acceder nuestro chat desde la dirección URL para todo el internet.

Alta en Facebook

Antes de poder correr nuestro chatbot tenemos que registrarlo en Facebook. El chatbot está asociado a una página de Facebook:

  1. Entrar a Facebook
  2. Crear una página de Facebook en dónde vivirá nuestro chatbot, esto se puede hacer aquí
  3. Darnos de alta como desarrolladores de Facebook aquí
  4. Ya dados de alta podemos crear una aplicación de Facebook, esto se podrá hacer desde las opciones después de registrarnos como desarrolladores o el correo que nos da la bienvenida.
  5. Una vez que creamos la app, vamos a tener que seleccionar los productos, en nuestro caso es Messenger.
  6. Con el producto Messenger ahora tenemos que escoger los mensajes que se enviara, recomendamos escoger messeges que nos permitirá recibir mensajes.
  7. Con esto, podremos recibir el token de acceso de Facebook y nosotros podremos fijar el token de verificación. Estos los tenemos que anotar en nuestro archiv config.py y volver a ejecutar nuestra app.
  8. También nos pedirá el URL de nuestro webhook que para nosotros será la dirección que nos regresa ngrok o la dirección final en la que vivirá nuestro chatbot.
  9. Si el proceso de verificación pasa (para esto nuestro chatbot necesita estár levantado y funcionando), entonces podemos ir a nuestro página de facebook y buscar el ícono del messenger y comenzar a chatear.

Problemas comunes

  • Nuestro chatbot no está corriendo, ejecutarlo
  • La URL de nuestro webhook cambio, hay que entrar modificar el webhook
  • No hay respuesta, nuestro código de AIML está fallando

Existen varios tutoriales para hacer el chatbot. Además también existen más opciones de comunicación entre la plataforma Facebook y chatbot.