Mejora de la interfaz de usuario del bot de JavaScript con localStorage
Las interfaces de bot son divertidas para los usuarios y ventajosas para quienes las construyen (si se hacen bien). El concepto no es nuevo, aunque hoy en día es especialmente poderoso.
Para los desarrolladores, los bots significan menos tiempo dedicado a diseñar y crear interfaces personalizadas. Son solo burbujas de texto; Además, muchas plataformas existentes ofrecen evitar por completo este proceso con las API de sus aplicaciones ya exitosas (es decir, el Asistente de Google).
Para los usuarios, los bots significan una posibilidad de interacción manos libres (a través de la voz) y una forma más natural y/o fluida de conversar con las máquinas.
Cuando construyo cosas, tiendo a buscar soluciones simples, sin excesos, que puedan entenderse y personalizarse fácilmente. Desafortunadamente, cuando estaba buscando uno el año pasado, no había ninguno para mi caso de uso…
Mi equipo y yo hemos implementado y entrenado un motor de clasificación de lenguaje natural, Archie.AIy le dio el poder de comprender y generar respuestas a partir de Google Analytics. El bot puede brindar informes diarios sobre el estado del negocio de los usuarios, predecir el número de futuros visitantes y responder 430 preguntas relacionadas. Es una excelente manera de ahorrar tiempo al buscar una métrica en particular o un consejo comercial instantáneo.
Funciona maravillosamente con el Asistente de Google y Alexa, sin embargo, cuando llegó el momento de obtener una interfaz rápida y limpia para la web, no había opciones lo suficientemente buenas. Así que construí uno y lo mantuve de código abierto. chat-bubble
es el archivo JavaScript de un kilobyte sin dependencias que es realmente fácil de implementar y comprender:
var chatWindow = new Bubbles(
document.getElementById("chat"),
"chatWindow"
);
chatWindow.talk();// https://github.com/dmitrizzle/chat-bubble#demos--more-usage-examples
Baterias incluidas: un conjunto completo de estilos CSS y animaciones sincronizadas con precisión, la capacidad de ejecutar funciones de forma segura en respuesta a las acciones del usuario y una motor de procesamiento enchufable.
Por “motor de procesamiento conectable” me refiero a que el script no le dirá cómo entender las consultas de su usuario. es tú decides para implementar su propio NLC. es tú decides para generar dinámicamente o escribir guiones de respuesta. Sin embargo, no te deja colgando. Actualmente hay tres formas de hacer que responda a sus usuarios:
- Ofrezca opciones a sus usuarios, que aparecen como botones (vea el gif a continuación). No es necesario hacer nada aquí, esto está integrado.
- Use el código de muestra provisto que utiliza una lógica de coincidencia aproximada simple para asignar la entrada de sus usuarios a las opciones que prescribe (vea el gif a continuación).
- Conecte su propio motor NLC (vea el gif arriba).
Esas opciones son para reconocer la entrada del usuario. La salida (lo que dice el bot) es igual de personalizable. Podría ser tan simple como una variable de objeto de JavaScript estructurado. O podrían ser datos JSON importados dinámicamente. Por supuesto, no tiene que ser solo un gran archivo JSON, ¡eso sería ineficiente! En nuestro caso (nuevamente, vea el gif anterior), lo dividimos en respuestas individuales para las respuestas que requieren un viaje al servidor (a pedido) y algunos cálculos de nuestra parte.
// a simple conversation script written with JSONvar conversationScript =
Durante los siguientes meses, probamos el script en producción con cerca de mil usuarios, mientras agregamos algunos ajustes y mejoramos el rendimiento en navegadores más antiguos. También se ha descargado más de 700 veces hasta el día de hoy.
La biblioteca funciona igualmente bien en computadoras de escritorio y dispositivos móviles. Sin embargo, cuando llegó el momento de publicarlo como parte de nuestra extensión del navegador Google Chrome, la experiencia del usuario sufrió. Porque chat-bubble
no tenía persistencia heredada, el historial de conversaciones se evaporaría cada vez que se cerrara la ventana del complemento. Y eso sucedió con bastante frecuencia, ya que Chrome tiende a eliminar por completo el DOM de los complementos cada vez que el usuario cambia de enfoque.
Eso tiene que arreglarse.
No hay una sola forma de mantener el historial de conversaciones en el disco. Consideré usar Redux para administrar el estado, sin embargo, esa es una dependencia y la filosofía hasta ahora es no tener una. Eso también complicaría demasiado las cosas.
En cambio, decidí almacenar un objeto JSON modificado que compartiría la misma estructura que el script de conversación en localStorage
. Se recordará cada vez que se abra el bot, sin embargo, también deberá:
- Tener el potencial de ser utilizado con una base de datos o cualquier otro método de almacenamiento de datos.
- Tener una interactividad y un estilo de interfaz de usuario diferentes a los del resto del bot (una señal visual para el usuario).
- Sea una mejora progresiva que no rompa el resto de la aplicación.
A prueba de futuro.
Mantener una opción abierta para implementar una solución de almacenamiento del lado del servidor es bastante sencillo. La biblioteca completa tiene menos de 340 líneas de JavaScript comentado y sin comprimir. Si alguien intentara implementar eso, todo lo que necesitaría cambiarse es JSON.parse(localStorage.getItem(interactionsLS))
método para acceder a la historia y localStorage.setItem(interactionsLS, JSON.stringify(interactionsHistory))
método para guardar el historial.
El único obstáculo que puedo ver aquí es tener que agregar un Promise
-escriba verificaciones para asegurarse de que todo lo necesario para mostrar el historial se descargue antes de continuar. Algo como esto podría requerir algo de trabajo, ya que sería necesario tomar algunas decisiones con respecto a cuándo debería comenzar la descarga y qué funciones debería bloquear. Eso lo dejo para mañana.
Interfaz de usuario personalizada para conversaciones recuperadas.
Para simplificar las cosas, las conversaciones anteriores aparecerían en el chat tan pronto como el usuario lo abra.
Sin embargo, como efecto secundario de esa decisión, esas conversaciones tener tener un estilo diferente para evitar confundir al usuario. Además, las respuestas de los usuarios necesitarían una atención especial cuando se almacenan y recuperan, ya que las respuestas de los usuarios no puede tener ninguna interactividad asociada a ellos.
Lo que quiero decir es que si bien resaltar las burbujas de chat en negro y hacerlas flotar correctamente para las respuestas de los usuarios no es tan difícil, hay implicaciones cuando el chat usa botones en lugar de mensajes de entrada de teclado. sigue leyendo
Considere el ejemplo (a continuación) cuando al usuario se le presentan opciones para seleccionar uno de los dos o más botones como una forma de responder al bot. Obviamente, almacenar opciones de respuesta en el historial no es útil: no tienen nada que ver con la estructura de la conversación después de haber interactuado con ellas. Solo la respuesta del usuario (su burbuja de respuesta seleccionada) es relevante. El truco es no almacenar nada en el historial hasta que el usuario haya creado su interacción final.
Para este propósito, he creado dos funciones para guardar el historial: interactionsSave()
y interactionsSaveCommit()
– donde el primero sería llamado para mutar el objeto guardado propuesto en RAM y el segundo enviaría ese objeto a localStorage
.
interactionSave()
se llamará cada vez que el bot produzca una respuesta, pero solo después de que el usuario haya confirmado su respuesta. Porque cuando el usuario hace clic en una burbuja, nuestro script ya “olvidó” cómo se veía ese botón en términos de estructura DOM, se crearía uno nuevo, específicamente para comprometerse con el historial de conversación:
// add re-generated user picks to the history stack
if (_convo[key] !== undefined && content !== undefined)
interactionsSaveCommit()
se llamaría cada vez que se crea una nueva burbuja de diálogo en DOM por medio de addBubble()
función.
Mejorando progresivamente.
Esta es una característica relativamente nueva que no todos querrían usar, por supuesto. También es experimental y podría exagerarse fácilmente (si alguien intentara recordar 1000 interacciones, el rendimiento y la experiencia del usuario disminuirían cada vez que se cargara el barco). Entonces, por defecto, lo dejé desactivado:
recallInteractions = options.recallInteractions || 0
Sin embargo, hacer que funcione es súper simple:
var chatWindow = new Bubbles(
document.getElementById("chat"),
"chatWindow",
);
…Todo lo que hace es decir esto interactionsSave()
para tirar cosas innecesarias:
if (interactionsHistory.length > recallInteractions)
interactionsHistory.shift()
En aras de la simplicidad, todo el trabajo en chat-bubble
se realiza sin ningún tipo de pasos de compilación. Todo JavaScript se escribe y se ejecuta inmediatamente en el navegador (aunque los desarrolladores que lo implementan tienen la opción de usar ES6 Import
método). Debido a que los navegadores leen JavaScript del disco duro en modo de desarrollo, cualquier intento de usar localStorage
rompe todo el código base ya que no está permitido (debido a restricciones de seguridad). Lo que me hizo pensar: esto podría suceder con bastante frecuencia en otros entornos. Así que he implementado una alternativa con una advertencia:
// local storage for recalling conversations upon restart
var localStorageCheck = function()
var localStorageAvailable = localStorageCheck() && recallInteractions > 0
Ahora todo debería funcionar incluso si el navegador no puede acceder a la memoria del disco.