La perspectiva del desarrollador alrededor de los chatbots. ¿Cómo desarrollar con Oracle Intelligent Bot? Parte 1.

Por Rolando Carrasco Oracle ACE
Publicado en Octubre 2018

Revisado por Juan Pablo Guisado




Esta es la parte 1 de 2 de este nuevo artículo enfocado al rol del desarrollador en los chatbots, y en específico en el Oracle Intelligent Bot.

En esta primera parte vamos a establecer el tono del artículo y haremos la introducción a la parte del código que un desarrollador tiene que crear en el Oracle Intelligent Bot. En la segunda entrega, nos enfocaremos 100% en el código y otros temas relevantes para los desarrolladores.

¿Te acuerdas de lo siguiente?


Los logos, imágenes, marcas e iconos contenidos en este artículo pertenecen a sus respectivos y legítimos propietarios y solo son usados por el autor con propósitos educativos.



Siempre hemos tenido esa idea de las películas, sobre los robots tomando control de nuestras vidas, o bien que nos van a gobernar.  Pero la verdad es que estamos acostumbrados a interactuar con ellos, por ejemplo:

  1. Cada vez que alguien habla  a un banco, a una compañía telefónica o bien con a una aerolínea, termina hablando con una grabación, con un robot. Y esto lo hace posible un IVR, los cuales tienen años operando y los usuarios tenemos años lidiando con ellos. Nos guste o no, los tenemos que usar y hasta cierto punto, nos hemos acostumbrado
  2. ¿O cuántos de sus hijos, o más bien, cuántos de nosotros no usamos un Tamagotchi?

Estamos más que acostumbrados en interactuar con robots, tanto para jugar como para trabajar. Es algo que ya hacemos de una manera habitual sin fijarnos tanto.



Ahora bien, el artículo está enfocado a describir el aspecto de desarrollo en Oracle Intelligent Bot, por lo que empezaremos a adentrarnos a esa parte.

Vayamos a lo realmente importante y esto es lo que está sucediendo con la simplificación de las interfaces de usuario.

Existe una tendencia que está enfocada simplificar las interfaces gráficas de usuarios. Sean del tipo que sea: una aplicación web; una aplicación móvil; la interface de una Smart TV; un cajero automático, etc.



Antes de ir directo al código, toquemos un último tema que también es de suma relevancia para los desarrolladores. También vamos a tomar un extracto de la Chatbots Magazine, mira:

https://chatbotsmagazine.com/what-is-a-conversational-ui-and-why-it-matters-de358507b9a2


Esto quiere decir que las interfaces conversacionales no son cualquier cosa. Al contrario, pareciera que se volverán una prioridad muy alta para los desarrolladores. Y no solo eso, también habla de cómo tecnológicamente están fundamentadas, a través de microservicios y con la conexión a los back-end (a través de APIs). Y para reconfirmar la relevancia, termina diciendo que esto se vuelve un insumo muy importante para construir y entrenar inteligencia artificial.

¿Y para dónde se está moviendo el mundo tecnológicamente hablando?

  • Automóviles autónomos
  • Bases de datos autónomas
  • Buscar la automatización de lo que más se pueda o bien se deje


Por lo que estamos hablando de un tema trascendental derivado del momento que estamos pasando en la industria de la tecnología.

Entonces, ¿cómo desarrollador qué debo hacer? ¿Debo cambiar mi forma de programar? ¿Debo conocer nuevos lenguajes de programación? ¿Qué tipo de plataformas debo de utilizar?

En primer lugar, sí debes de cambiar tu forma de desarrollar tus interfaces. Ahora debes pensar en interfaces conversacionales, como ya lo comentamos. Un elemento clave es que debes tomar en cuenta al contexto, lo cual varía un poco la forma en la que lo hacías antes.

Con respecto a los lenguajes de programación, sugiero te pongas a estudiar o aprendas: Python, Go, Node.JS. Que entiendas de YAML, JSON, XML. Y que tengas experiencia en crear aplicaciones/servicios orientadas/orientados a eventos y asincrónicas/asincrónicos.

Sobre la plataforma, sugiero que te adentres en una plataforma de Chatbots que sea genérica, y no una que esté atada a un canal en específico. Esto, porque no sabemos qué va a haber el día de mañana, con respecto a canales. Lo que sí sabemos es que ocupamos una interface conversacional y que requerimos estar relacionados con Inteligencia Artificial. Ya el canal que lo vaya a usar, ese podrá variar en el futuro. Es por eso que yo recomiendo el uso de Oracle Intelligent Bot, pues es justamente una plataforma genérica.



Bien. Hemos llegado al punto en donde es necesario hablar de código, ya en un artículo anterior escribimos una introducción al Oracle Intelligent Bot y tocamos levemente al lenguaje que usa Oracle para describir el flujo de la conversación (o Conversational Flow en inglés). Oracle le llama BotML, está basado en YAML.

En el artículo anterior, usamos como ejemplo un chatbot que funge como un asistente financiero personal, en el cual puedes:

  1. Consultar tus saldos en cuentas de:
    • Cheques
    • Ahorros
    • Tarjeta de Crédito
  2. Ahora le vamos a agregar que puedas realizar traspasos de dinero entre cuentas
  3. Y también que puedas hacer un seguimiento a tus gastos.

Este ejemplo lo saqué del MOOC (Massive Open Online Course) que hubo hace poco del Oracle Intelligent Bot. Por si te suena familiar, de ahí es de dónde salió.


Así que retomemos en dónde nos quedamos en el artículo anterior, que fue simplemente generar unas Entidades, un Intent y una serie de Utterances que nos permitían consultar el Saldo.

Veamos con detalle el BOTML:


metadata:
  platformVersion: "1.0"
main: true
name: "RolandoBotMainFlow"
context:
  variables:
    accountType: "AccountType"
    iResult: "nlpresult"
states:
  intent:
    component: "System.Intent"
    properties:
      variable: "iResult"
      confidenceThreshold: 0.4
    transitions:
      actions:
        Balances: "startBalances"
        unresolvedIntent: "unresolved"
  startBalances:
    component: "System.SetVariable"
    properties:
      variable: "accountType"
      value: "${iResult.value.entityMatches['AccountType'][0]}"
    transitions: {}
  askBalancesAccountType:
    component: "System.List"
    properties:
      options: "${accountType.type.enumValues}"
      prompt: "For which account do you want your balance?"
      variable: "accountType"
    transitions: {}
  printBalance:
    component: "System.Output"
    properties:
      text: "Balance for ${accountType.value} is $500"
    transitions:
      return: "printBalance"
  unresolved:
    component: "System.Output"
    properties:
      text: "Unable to resolve intent!"
    transitions:
      return: "unresolved"
      


Este es el tipo de código que el desarrollador debe saber expresar y entender para poder programar un flujo conversacional en  Oracle Intelligent Bot.

Expliquemos parte por parte lo que significa.

La primera parte es esta:


metadata:
  platformVersion: "1.0"
main: true
name: "RolandoBotMainFlow"
context:
  variables:
    accountType: "AccountType"
    iResult: "nlpresult"
    


Aquí simplemente estamos identificando la versión de la plataforma; el nombre del bot, así como la declaración de las variables generales del flujo:

  1. accountType. Esta es de tipo AccountType, que es la entidad que creamos en el artículo anterior (poner el link). Por lo que ahí vamos a querer almacenar valor del tipo de cuenta sobre la cual se está solicitando el saldo. Mas adelante igualmente se va a usar para identificar la cuenta de la cual queremos tomar el dinero para hacer un traspaso a otra.

  2. iResult. Esta variable es de tipo nlpresult. Esta contiene el intent sobre del cual se hará la transición más adelante en el código. Digamos que esta variable tiene lo que el usuario haya escrito, pero internamente lo interpreta y cataloga, de manera que lo asocia a un intent, a partir del confidence threshold que se haya configurado, mismo que viene en la siguiente sección.
    
 states:
  intent:
    component: "System.Intent"
    properties:
      variable: "iResult"
      confidenceThreshold: 0.4
    transitions:
      actions:
        Balances: "startBalances"
        Intent.None: "unresolved"
  startBalances:
    component: "System.SetVariable"
    properties:
      variable: "accountType"
      value: "${iResult.value.entityMatches['AccountType'][0]}"
    transitions: {}
  askBalancesAccountType:
    component: "System.List"
    properties:
      options: "${accountType.type.enumValues}"
      prompt: "For which account do you want your balance?"
      variable: "accountType"
    transitions: {}
  printBalance:
    component: "System.Output"
    properties:
      text: "Balance for ${accountType.value} is $500"
    transitions:
      return: "printBalance"
  unresolved:
    component: "System.Output"
    properties:
      text: "Unable to resolve intent!"
    transitions:
      return: "unresolved"

    


En esta vemos los estados, así como las transiciones. Veamos la primera:


 states:
  intent:
    component: "System.Intent"
    properties:
      variable: "iResult"
      confidenceThreshold: 0.4
    transitions:
      actions:
        Balances: "startBalances"
        unresolvedIntent: "unresolved"



El primer estado es intent. Pues a partir de la interacción del usuario, cruzándolo con las utterances configuradas y asociadas al intent, justamente va determinar cuál fue la intención del usuario. Esto lo hace, también, usando la propiedad de confidenceThreshold. En este caso del 40%, es decir si lo que más se le parece a lo que puso el usuario, revasa el 40% entonces eso asociará y lo almacenará en la variable iResult. En base al valor de esta variable, se determina el Intent y realiza la transición, ejecutando la acción deseada.

En este caso, si determina que lo que quiso decir el usuario está relacionado con los saldos (Balances en inglés) entonces hará match con dicho Intent y lo llevará al estado de startBalances, caso contrario lo mandará unresolvedIntent y al estado unresolved.

Ahora veamos los siguientes tres estados:


  startBalances:
    component: "System.SetVariable"
    properties:
      variable: "accountType"
      value: "${iResult.value.entityMatches['AccountType'][0]}"
    transitions: {}
  askBalancesAccountType:
    component: "System.List"
    properties:
      options: "${accountType.type.enumValues}"
      prompt: "For which account do you want your balance?"
      variable: "accountType"
    transitions: {}
  printBalance:
    component: "System.Output"
    properties:
      text: "Balance for ${accountType.value} is $500"
    transitions:
      return: "printBalance"



El estado startBalances, busca conseguir la cuenta de la cual quieres tu saldo. Recuerda que ya estamos adentro del Intent Balances, por lo que ya está en ese contexto, y ahora está buscando conseguir información de lo que el usuario está buscando. Por lo que la expresión:
value: "${iResult.value.entityMatches['AccountType'][0]}" justamente hace eso, buscar si el Usuario escribió algún valor similar al del listado de AccountType y lo almacenará en la variable accountType.

Posteriormente, siguiendo el flujo conversacional, nos encontraremos con el estado: askBalancesAccountType. En caso el usuario haya escrito desde el inicio algo relacionado con su cuenta, entonces este paso se lo brincará pues el dato ya lo tendrá. Caso contrario, le preguntará al usuario que le indique de qué cuenta quiere saber el saldo. Esto lo podemos ver con esta expresión:

options: "${accountType.type.enumValues}"

prompt: "For which account do you want your balance?"

variable: "accountType

En caso el usuario haya indicado el tipo de cuenta, entonces  la pregunta: From which account do you want your balance? Ya no se ejecutará. En caso el usuario no haya indicado el tipo de cuenta, entonces aparecerá un menú con las opciones de los tipos de cuenta.

Finalmente, lo que se hace es imprimir el valor del saldo:


  printBalance:
    component: "System.Output"
    properties:
      text: "Balance for ${accountType.value} is $500"
    transitions:
      return: "printBalance"



Ya sea que el usuario haya indicado la cuenta desde el principio, o bien la haya escogido a partir del menú que generó en el bot, se imprimirá el mensaje: Balance for $accounType.value is $500, donde $accountType.value es justamente el valor del tipo de cuenta.


Veamos esto en acción, para confirmar lo que acabo de explicar:

  1. Primero vamos a probar el nivel de confianza que mencionamos hace rato. Si yo escribo: My Balance, esto pasa a nivel de los Intents






    Mira cómo su nivel de confianza es del 30.7, por lo que el resultado de esto debe ser que no resolvió ningún intent, pues recordemos que estamos usando 0.4 de confidenceTreshold, de acuerdo a nuestro código. Por lo que el resultado es este:






    Si le bajamos al nivel de confianza, digamos a 0.1:






    Ahora pasa lo siguiente:



    Tanto que puedo ajustar el nivel de confianza, como agregar el ejemplo como un utterance mas.






  2. Ahora bien, ya que me presenta la lista de cuentas, vemos la siguiente pantalla:

    Para poder hacer esto, debió pasar por los estados: startBalances y askBalancesAccountType.  Como ya explicamos, en startBalances, el engine busca la información de la cuenta. Posteriormente pasa a askBalancesAccounType, en caso ya tenga el dato de la cuenta, entonces lo lleva  imprimir el saldo directamente, pero si no, entonces muestra lo que está en la pantalla anterior, es decir ejecutó esta parte del código:
     

      askBalancesAccountType:     component: "System.List"     properties:       options: "${accountType.type.enumValues}"       prompt: "For which account do you want your balance?"       variable: "accountType"     transitions: {}
    





  3. Finalmente, una vez que escogemos la cuenta, nos manda al estado printBalance, tal como aparece en la pantalla:






  4. Ahora cambiemos la forma de pedir el saldo. Digámosle: I want the balance on my AMEX. En este caso, ¿qué es AMEX? Recuerda que, en el artículo anterior, creamos una entidad de nombre AccountType y adentro de ella una lista de valores, en donde uno de ellos fue Credit Card con el sinónimo AMEX. Así que, al ejecutarlo, obtenemos:



    Lo mismo podemos hacer con la cuenta de cheques o ahorros. Pruébalo y verás el resultado.






  5. Date cuenta cómo el usuario tiene la libertad de pedir las cosas con un lenguaje natural. En vez de poner: I want my balance on my AMEX, también pudo poner cosas como: How much money I have in my Checkings account? O también: Do I have money in my savings?



    Hay libertad y naturalidad en cómo relacionarte con la interface.






Así que, al momento hemos visto:

  1. La relevancia de tener una interface conversacional
  2. A qué se debe decir un desarrollador, cuando lo llamen a participar en un proyecto de chatbots
  3. Cómo escribir BotML
  4. Explicamos la estructura básica del mismo
  5. Cómo manipular el confidence threshold
  6. Cómo ejecutar y validar la ejecución del flujo de la conversación
  7. La naturalidad con la que el usuario se relaciona con la interface

En el siguiente artículo vamos a comentar a nuestro bot con APIs expuestas en el Mobile Cloud Service Oracle, así como seguir explicando el BotML.




Rolando Carrasco es un Oracle ACE enfocado a las tecnologías de Middleware. Su experiencia es de casi 15 años en la integración de aplicaciones. Actualmente se desempeña como CTO de una firma mexicana de consultoría, llamada S&P Solutions. Rolando ha trabajado con tecnología Oracle desde el 2001, fue parte del equipo de Product Management de Oracle Fusion Middleware, por lo que tiene un background grande en el uso de estas tecnologías a lo largo de la región de latinoamérica. Rolando es co-líder del grupo de usuarios de Oracle en México.

Este artículo ha sido revisado por el equipo de productos Oracle y se encuentra en cumplimiento de las normas y prácticas para el uso de los productos Oracle.