Desarrollando un Asistente Personal Inteligente

Publicado en

“Siri, lee los mensajes de correo electrónico”

“Hola Cortana, ¿cómo está el clima?”

“ Ok Google, ¿cómo se dice hola en Inglés?”

“Alexa, set a timer for 15 minutes”

Este tipo de frases (comandos) se están haciendo parte de nuestra vida cotidiana. Cada día es más común usar nuestra voz y un lenguaje natural para interactuar con dispositivos y servicios. La gran mayoría de los dispositivos y sistemas operativos más populares incorporan lo que se conoce como un asistente personal inteligente; es una tendencia que se está acelerando.

Un asistente personal inteligente (Intelligent Personal Assistant, IPA) es un agente de software que puede realizar tareas u ofrecer servicios a un individuo. El usuario puede interactuar con el IPA usando lenguaje natural a través de voz o texto. El IPA puede además obtener y usar información adicional de contexto tal como la ubicación del usuario, información dentro del mismo dispositivo (fotos, contactos, etc.) y otros servicios para proporcionar una mejor respuesta al usuario.

Los asistentes personales como Siri, Google Now o Cortana pueden ejecutar muchas acciones y responder a una gran variedad de peticiones del usuario. Típicamente, el dispositivo es tan solo una fachada para proveer el servicio, ya que en realidad los servicios que reconocen el habla y determinan la respuesta o acción adecuada, son servicios hospedados en la nube.

Quiero mi propio IPA

Si queremos crear un servicio de IPA, una opción es hacerlo como una extensión a servicios existentes como Siri, Cortana o Alexa. Sin embargo, esto puede tener limitaciones o no darnos el control completo que podríamos requerir. Así que otra opción es que desarrollemos nuestra propia aplicación y simplemente utilicemos los servicios de reconocimiento del habla que exponen algunos de estos motores.

Para construir nuestro IPA primero necesitamos identificar sus distintos componentes o subsistemas. A grandes rasgos son: interfaz para interactuar con el asistente, reconocimiento del habla, lenguaje de dominio específico (DSL), y endpoint para acceder al agente.

A continuación vamos a platicar sobre cada uno de ellos.

Reconocimiento de habla

Es un campo de la lingüística computacional orientado a desarrollar metodologías y tecnologías que permitan que las computadoras puedan entender y traducir lenguaje hablado. Vale la pena aclarar que el reconocimiento del habla es distinto del reconocimiento de voz, ya que este último solo se enfoca en identificar a la persona que habla, mas no lo que está diciendo.

Como pueden imaginar, desarrollar un servicio de reconocimiento del habla es una tarea muy grande y casi imposible para una sola persona. Afortunadamente empresas como Microsoft, Google y Xamarin entre otros, los han desarrollado ya, y los han abierto para que podamos usarlos en nuestras aplicaciones. En el listado 1 muestro cómo podemos inicializar el servicio de reconocimiento del habla en .Net. Posteriormente, en el listado 2 muestro cómo se podría hacer en web utilizando el Web Speech API, que es soportado por Chrome.

 

Listado 1. Código C# para usar Windows Speech Recognition.

 

Listado 2. Código Javascript para usar Web Speech API.

 

Lenguaje de dominio específico (DSL)

Es un lenguaje informático diseñado para representar o resolver un problema específico. Existe una gran variedad de DSLs, desde lenguajes de uso muy común como HTML o SQL, hasta lenguajes de nicho como podría ser CSound para síntesis de sonidos. El dominio puede ser también un área de negocios. Así que por ejemplo, podríamos crear un DSL para gestión de pólizas de seguro.

Cuando se crea un DSL que solo se usará en una aplicación se le acostumbra llamar un mini-lenguaje.

Para implementar el lenguaje necesitamos definir su gramática y crear un parser (analizador sintáctico) para poder interpretar lo que el usuario nos dice y darle una respuesta. Podríamos hacer las dos cosas a mano, pero en la actualidad existen ya muchas herramientas que nos facilitan definir la gramática  y crear nuestro parser.

Una de las herramientas más comunes para desarrollar lenguajes es YACC, que nos permite generar un parser basado en una gramática analítica que debemos describir en un metalenguaje similar a la notación de Backus-Naur.

En este caso no usaremos YACC, sino que usaremos Irony, un kit de desarrollo para implementar lenguajes en la plataforma .Net. A diferencia de soluciones como YACC y Lex, que generan un parser a partir de la gramática analítica que hayamos definido, Irony nos permite expresar la gramática de nuestro lenguaje directamente en C#.

El listado 3 muestra cómo definimos la gramática a través de terminales y no-terminales, así como los enunciados que vamos a reconocer.

Listado 3. Definición del DSL.

Endpoint

Vamos a exponer los servicios de nuestro asistente a través de un endpoint alojado en nuestra aplicación web. Este endpoint recibirá como parámetro la consulta del usuario y la  pasará al asistente, el cual interpretará los resultados y enviará una respuesta serializada.


 

App

El usuario podrá interactuar con nuestro asistente inteligente a través de una aplicación móvil.

Ya en los listados 1 y 2 vimos cómo podemos usar las APIs de Chrome y Windows para reconocimiento del habla. Ahora en los listados 4a, 4b y 4c podemos ver cómo lanzar la búsqueda y mostrar los resultados en una aplicación Windows Universal.

El listado 4a muestra cómo disparar una petición asíncrona y desmenuzar los resultados, luego el listado 4b muestra cómo se podrían desplegar y por último el listado 4c muestra cómo podríamos acompañar estos resultados de un mensaje de voz.

 

Listado 4a. Disparar búsqueda y procesar resultados.

Listado 4b. Desplegar resultados.

Listado 4c. Dar mensaje hablado.

Alternativas

Un asistente personal inteligente puede desarrollarse de muchas maneras. En este artículo tomamos algunas decisiones en cuanto a tecnologías y arquitectura, para la parte de reconocimiento del habla podríamos usar servicios de Xamarin que tiene una API de reconocimiento de lenguaje y es multiplataforma. También podríamos integrar nuestra aplicación con servicios como Siri o Cortana. El DSL, como mencionamos, también podríamos haberlo desarrollado con YACC, Lex o alguna variante de estos.

Código fuente

Todo el código fuente en este artículo es parte de un asistente personal pequeño que está hospedado en http://deepthoughtagent.azurewebsites.net/ , en la url: http://deepthoughtagent.azurewebsites.net/Home/preguntas están el tipo de preguntas que puede contestar el asistente; algunos ejemplos son:

  • ¿Cuántas embarcaciones tiene contrato a123456?
  • ¿En cuántos contratos esta embarcación uno?
  • ¿Qué capacidad tiene embarcación Morelos?
  • ¿Qué contrato empieza antes de '12/12/2015'?
  • ¿Cuál embarcación tiene mayor velocidad?
  • ¿Cuál contrato tiene menos embarcaciones?
  • ¿Cuándo empieza contrato ABCDE?
  • Muestra todas las embarcaciones
  • Muestra todos los contratos
  • Muestra el contrato ABCDE
  • Actualiza la embarcación pinta cambia su velocidad por 20
  • ¿Cuánto es 2 + 2?
  • ¿Cuánto es 2 entre 2?

El código fuente se puede obtener en https://github.com/pedro-ramirez-suarez/ScioAssistant, la aplicación móvil (Windows Universal App) está configurada para usar el endpoint http://deepthoughtagent.azurewebsites.net/, siendo que el servicio está hospedado en un servidor con recursos muy limitados no va a poder manejar muchas peticiones, para correr sus propios experimentos basta con hospedar el DSL en otro lugar y cambiar la URL definida en el archivo “AppResources.resx” para que apunte a donde está nuestro endpoint.

Bio

Pedro Ramírez Suárez es Chief Architect en Scio Consulting, desarrollador independiente de juegos,  siempre aprendiendo y buscando nuevas formas de usar la tecnología. https://github.com/pedro-ramirez-suarez