Los usuarios, después de hablar con asistentes de voz inteligentes, esperan inteligencia de los bots de chat. Si está desarrollando un bot para negocios, las expectativas son aún más altas: el cliente quiere que el usuario siga el escenario deseado y preescrito, y el usuario quiere que el robot responda de manera inteligente y preferiblemente humana a las preguntas planteadas, ayude a resolver problemas y, a veces, solo apoye las pequeñas conversaciones.
Hacemos bots de chat en inglés que se comunican con los usuarios a través de varios canales: Facebook Messenger, SMS, Amazon Alexa y la web. Nuestros bots reemplazan los servicios de soporte, los agentes de seguros y pueden simplemente chatear. Cada una de estas tareas requiere su propio enfoque de desarrollo.
En este artículo le diremos en qué módulos está compuesto nuestro servicio, cómo se hace cada uno de ellos, qué enfoque elegimos y por qué. Compartiremos nuestra experiencia en el análisis de diferentes herramientas: cuando las redes neuronales generativas no son la mejor opción, por qué en lugar de Doc2vec usamos Word2vec, cuál es el encanto y el horror de ChatScript, etc.
A primera vista, puede parecer que los problemas que estamos resolviendo son bastante triviales. Sin embargo, en el campo del procesamiento del lenguaje natural hay una serie de dificultades asociadas tanto con la implementación técnica como con el factor humano.
- Mil millones de personas hablan inglés, y cada hablante nativo lo usa a su manera: hay varios dialectos, características de habla individuales.
- Muchas palabras, frases y expresiones son ambiguas: un ejemplo típico está en esta imagen.
- La interpretación correcta del significado de las palabras requiere contexto. Sin embargo, el bot que le hace preguntas aclaratorias al cliente no parece tan bueno como el que puede cambiar a cualquier tema a solicitud del usuario y responder cualquier pregunta.
- A menudo, en el discurso y la correspondencia vivos, las personas descuidan las reglas gramaticales o responden tan brevemente que es casi imposible restaurar la estructura de la oración.
- A veces, para responder la pregunta de un usuario, es necesario comparar su solicitud con los textos de preguntas frecuentes. Al mismo tiempo, debe asegurarse de que el texto que se encuentra en las preguntas frecuentes es la respuesta y no solo contiene varias palabras que coinciden con la solicitud.

Estos son solo algunos de los aspectos más obvios, y también hay argot, jerga, humor, sarcasmo, errores de ortografía y pronunciación, abreviaturas y otros problemas que dificultan el trabajo en esta área.
Para resolver estos problemas, desarrollamos un bot que utiliza un conjunto de enfoques. La parte de IA de nuestro sistema consiste en un administrador de diálogo, un servicio de reconocimiento e importantes microservicios complejos que resuelven problemas específicos: clasificador de intención, servicio de preguntas frecuentes, Small Talk.
Comienza una conversación. Gerente de diálogo
La tarea de Dialog Manager en el bot es una simulación de software de comunicación con un agente en vivo: debe guiar al usuario a través de un escenario de conversación hacia algún objetivo útil.
Para hacer esto, en primer lugar, averigüe qué quiere el usuario (por ejemplo, calcule el costo del seguro para automóviles) y, en segundo lugar, descubra la información necesaria (dirección y otros datos del usuario, datos sobre conductores y automóviles). Después de eso, el servicio debería dar una respuesta útil: complete el formulario y proporcione al cliente el resultado de estos datos. Al mismo tiempo, no deberíamos preguntarle al usuario qué ya ha indicado.
Dialog Manager le permite crear un escenario de este tipo: describirlo mediante programación, construir a partir de pequeños ladrillos: problemas o acciones específicos que deberían ocurrir en un momento determinado. De hecho, el escenario es un gráfico dirigido, donde cada nodo es un mensaje, una pregunta, una acción, y el borde determina el orden y las condiciones de la transición entre estos nodos, si hay una opción múltiple de transición de un nodo a otro.
Los principales tipos de nodos
- Los nodos esperan hasta llegar a la cola y aparecerán en los mensajes.
- Nodos que esperan que el usuario muestre cierta intención (por ejemplo, escriba: "Quiero obtener un seguro").
- Nodos que esperan datos del usuario para validar y guardar.
- Nodos para la implementación de varios diseños algorítmicos (bucles, ramas, etc.).
Si el nodo está cerrado, el control ya no se transferirá a él y el usuario no verá la pregunta que ya se le hizo. Por lo tanto, si hacemos una búsqueda profunda en dicho gráfico hasta el primer nodo abierto, recibimos una pregunta que debe hacerse al usuario en un momento dado. A su vez, respondiendo las preguntas que genera Dialog Manager, el usuario cerrará gradualmente todos los nodos en el gráfico, y se considerará que ha ejecutado el script prescrito. Luego, por ejemplo, le damos al usuario una descripción de las opciones de seguro que podemos ofrecer.
"¡Ya dije todo!"
Supongamos que le pedimos al usuario un nombre, y en un mensaje también dará su fecha de nacimiento, nombre, sexo, estado civil, dirección o enviará una foto de su licencia de conducir. El sistema extraerá todos los datos relevantes y cerrará los nodos correspondientes, es decir, ya no se harán preguntas sobre la fecha de nacimiento y el género.
"Por cierto ..."
Dialog Manager también brinda la capacidad de comunicarse simultáneamente sobre varios temas. Por ejemplo, un usuario dice: "Quiero obtener un seguro". Luego, sin terminar este diálogo, agrega: "Quiero hacer un pago en una póliza previamente adjunta". En tales casos, Dialog Manager guarda el contexto del primer tema, y después de completar el segundo script, ofrece reanudar el diálogo anterior desde el lugar donde fue interrumpido.
Es posible volver a las preguntas que el usuario ya ha respondido. Para esto, el sistema guarda la instantánea del gráfico al recibir cada mensaje del cliente.
Cuales son las opciones?
Además del nuestro, consideramos otro enfoque de IA para la implementación del administrador de diálogo: la intención del usuario y los parámetros se alimentan a la entrada de la red neuronal, y el sistema mismo genera los estados correspondientes, la siguiente pregunta que debe formularse. Sin embargo, en la práctica, este método requiere la adición de un enfoque basado en reglas. Quizás esta opción de implementación sea adecuada para escenarios triviales, por ejemplo, para pedir comida, donde solo necesita obtener tres parámetros: qué quiere pedir el usuario, cuándo quiere recibir el pedido y dónde llevarlo. Pero en el caso de escenarios complejos, como en nuestra área temática, esto aún es inalcanzable. Por el momento, las tecnologías de aprendizaje automático no pueden guiar cualitativamente al usuario hacia el objetivo en un escenario complejo.
Dialog Manager está escrito en Python, Tornado framework, ya que inicialmente nuestra parte de IA fue escrita como un servicio único. Se eligió un idioma en el que todo esto se puede realizar sin gastar recursos en comunicación.
"Vamos a decidir". Servicio de reconocimiento
Nuestro producto puede comunicarse a través de diferentes canales, pero la parte de IA es completamente independiente del cliente: esta comunicación solo se presenta en forma de texto proxy. El administrador de diálogo transfiere el contexto, la respuesta del usuario y los datos recopilados al Servicio de reconocimiento, que es responsable de reconocer la intención del usuario y recuperar los datos necesarios.
Hoy, el Servicio de reconocimiento consta de dos partes lógicas: el Administrador de reconocimiento, que gestiona la canalización de reconocimiento, y los extractores.
Gerente de reconocimiento
Recognition Manager es responsable de todas las etapas básicas del reconocimiento del significado del habla: tokenización, lematización, etc. También determina el orden de los extractores (objetos que reconocen entidades y atributos en los textos) por los que se omitirá un mensaje, y decide cuándo detener el reconocimiento y devolverlo. Resultado terminado. Esto le permite ejecutar solo los extractores necesarios en el orden más esperado.
Si le preguntamos cuál es el nombre del usuario, es lógico verificar primero si el nombre figura en la respuesta. El nombre ha llegado y no hay más texto útil, lo que significa que el reconocimiento se puede completar en este paso. Han aparecido otras entidades útiles, lo que significa que el reconocimiento debe continuar. Lo más probable es que la persona haya agregado otros datos personales; en consecuencia, debe ejecutar el extractor para procesar datos personales.
Dependiendo del contexto, el orden de puesta en marcha de los extractores puede variar. Este enfoque nos permite reducir significativamente la carga en todo el servicio.
Extractores
Como se mencionó anteriormente, los extractores pueden reconocer ciertas entidades y atributos en los textos. Por ejemplo, un extractor reconoce números de teléfono; otro determina si una persona respondió positiva o negativamente a una pregunta; el tercero: reconoce y verifica la dirección en el mensaje; el cuarto son datos sobre el vehículo del usuario. Pasar un mensaje a través de un conjunto de extractores: este es el proceso de reconocer nuestros mensajes entrantes.
Para el funcionamiento óptimo de cualquier sistema complejo, es necesario combinar enfoques. Nos adherimos a este principio cuando trabajamos en extractores. Destacaré algunos de los principios de trabajo que utilizamos en los extractores.
Usando nuestros microservicios con Machine Learning dentro (los extractores envían un mensaje a este servicio, a veces lo complementan con la información que tienen y devuelven el resultado).
- Uso de etiquetado POS, análisis sintáctico, análisis semántico (por ejemplo, determinar la intención del usuario por el verbo)
- Uso de la búsqueda de texto completo (se puede usar para encontrar la marca y el modelo de la máquina en los mensajes)
- Uso de expresiones regulares y patrones de respuesta
- Uso de API de terceros (como la API de Google Maps, SmartyStreets, etc.)
- Una búsqueda textual de oraciones (si una persona respondió "sí" en breve, entonces no tiene sentido pasarlo a través de algoritmos ML para buscar la intención).
- También utilizamos soluciones de procesamiento de lenguaje natural listas para usar en extractores.
Cuales son las opciones?
Observamos las bibliotecas NLTK, Stanford CoreNLP y SpaCy. NLTK cae primero en los SERP de Google cuando comienza una revisión de NLP. Es muy bueno para las soluciones de creación de prototipos, tiene una amplia funcionalidad y es bastante simple. Pero su rendimiento es pobre.
Stanford CoreNLP tiene un serio inconveniente: extrae una máquina virtual Java con módulos muy grandes, bibliotecas integradas y consume muchos recursos. Además, el resultado de esta biblioteca es difícil de personalizar.
Como resultado, nos instalamos en SpaCy, porque tiene suficiente funcionalidad para nosotros y tiene la relación óptima de ligereza y velocidad. La biblioteca SpaCy funciona docenas de veces más rápido que NLTK y ofrece diccionarios mucho mejores. Sin embargo, es mucho más fácil que Stanford CoreNLP.
Por el momento, utilizamos spaCy para la tokenización, vectorización de mensajes (utilizando la red neuronal entrenada incorporada), reconocimiento primario de parámetros del texto. Como la biblioteca cubre solo el 5% de nuestras necesidades de reconocimiento, tuvimos que agregar muchas funciones.
"Solía ser ..."
El servicio de reconocimiento no siempre ha sido una estructura de dos partes. La primera versión fue la más trivial: nos turnamos para usar diferentes extractores y tratamos de entender si había algún parámetro o intención en el texto. La IA ni siquiera olía allí: era un enfoque completamente basado en reglas. La dificultad era que la misma intención se puede expresar de una gran cantidad de formas, cada una de las cuales debe describirse en las reglas. En este caso, es necesario tener en cuenta el contexto, ya que la misma frase de usuario, dependiendo de la pregunta planteada, puede requerir diferentes acciones. Por ejemplo, del diálogo: "¿Estás casado?" - "Ya dos años", puede entender que el usuario está casado (significado booleano). Y del diálogo "¿Cuánto tiempo manejas este auto?" - "Ya dos años" necesita extraer el valor "2 años".
Desde el principio, entendimos que el soporte de soluciones basadas en reglas requeriría mucho esfuerzo y, a medida que aumenta el número de intenciones compatibles, el número de reglas aumentará mucho más rápido que en el caso de un sistema basado en ML. Sin embargo, el punto de vista de los negocios. necesitábamos ejecutar MVP, un enfoque basado en reglas nos permitió hacerlo rápidamente. Por lo tanto, lo usamos y, en paralelo, trabajamos en el modelo ML de reconocimiento de intenciones. Tan pronto como apareció y comenzó a dar resultados satisfactorios, gradualmente comenzaron a alejarse del enfoque basado en reglas.
Para la mayoría de los casos de extracción de información, utilizamos ChatScript. Esta tecnología proporciona su propio lenguaje declarativo que le permite escribir plantillas para extraer datos de un lenguaje natural. Gracias a WordNet, esta solución es muy poderosa bajo el capó (por ejemplo, puede especificar un "color" en la plantilla de reconocimiento, y WordNet reconoce cualquier concepto de limitación, como "rojo"). No vimos análogos en ese momento. Pero ChatScript está escrito de forma muy torcida y con errores, con su uso es casi imposible implementar una lógica compleja.
Al final, las desventajas se superaron y abandonamos ChatScript en favor de las bibliotecas de PNL en Python.
En la primera versión del Servicio de reconocimiento, llegamos al límite de la flexibilidad. La introducción de cada nueva característica desaceleró en gran medida todo el sistema en su conjunto.
Así que decidimos reescribir completamente el Servicio de reconocimiento, dividiéndolo en dos partes lógicas: extractores pequeños y livianos y el Administrador de reconocimiento, que administrará el proceso.
"¿Qué quieres?" Clasificador de intenciones
Para que el bot se comunique adecuadamente, para proporcionar la información necesaria a pedido y registrar los datos del usuario, es necesario determinar la intención (intención) del usuario en función del texto que se le envió. La lista de intenciones por las cuales podemos interactuar con los usuarios está limitada por las tareas comerciales del cliente: puede ser la intención de averiguar las condiciones del seguro, completar información sobre usted, obtener una respuesta a una pregunta frecuente, etc.
Existen muchos enfoques para la clasificación de intentos basados en redes neuronales, en particular, en LSTM / GRU recurrente. Se han demostrado en estudios recientes, pero tienen un inconveniente común: se requiere una muestra muy grande para un funcionamiento adecuado. En una pequeña cantidad de datos, tales redes neuronales son difíciles de entrenar o producen resultados insatisfactorios. Lo mismo ocurre con el marco de texto rápido de Facebook (lo revisamos porque es una solución de vanguardia para procesar frases cortas y medianas).
Nuestras muestras de capacitación son de muy alta calidad: los conjuntos de datos están formados por un equipo de lingüistas a tiempo completo que dominan el inglés y conocen los detalles del campo de los seguros. Sin embargo, nuestras muestras son relativamente pequeñas. Intentamos diluirlos con conjuntos de datos públicos, pero esos, con raras excepciones, no coincidían con nuestros detalles. También intentamos atraer a freelancers con Amazon Mechanical Turk, pero este método también resultó inoperante: los datos que enviaron eran de calidad parcialmente pobre, las muestras tuvieron que ser verificadas nuevamente.
Por lo tanto, estábamos buscando una solución que funcione en una muestra pequeña. La buena calidad del procesamiento de datos fue demostrada por el clasificador Random Forest, capacitado en datos que se convirtieron en los vectores de nuestro modelo de bolsa de palabras. Mediante la validación cruzada, seleccionamos los parámetros óptimos. Entre las ventajas de nuestro modelo están la velocidad y el tamaño, así como la relativa facilidad de implementación y reciclaje.
En el proceso de trabajar en el Clasificador de intención, quedó claro que para algunas tareas su uso no es óptimo. Supongamos que un usuario desea cambiar el nombre indicado en el seguro o el número del automóvil. Para que el clasificador determine correctamente esta intención, habría que agregar manualmente al conjunto de datos todas las frases de plantilla que se utilizan en este caso. Encontramos otra forma: hacer un pequeño extractor para el Servicio de reconocimiento, que determina la intención por palabras clave y métodos de PNL, y usar Clasificador de intención para frases no estándar en las que el método con palabras clave no funciona.
"Siempre preguntan por esto". FAQ
Muchos de nuestros clientes tienen secciones de preguntas frecuentes. Para que el usuario recibiera dichas respuestas directamente del chatbot, era necesario proporcionar una solución que a) reconociera la solicitud de preguntas frecuentes; b) encontraría la respuesta más relevante en nuestra base de datos y la emitiría.
Hay varios modelos entrenados en el conjunto de datos de Stanford SQUAD. Funcionan bien cuando el texto de respuesta de las preguntas frecuentes contiene las palabras de la pregunta del usuario. Digamos que las preguntas frecuentes dicen: "Frodo dijo que llevaría el Anillo a Mordor, aunque no sabía el camino". Si el usuario pregunta: "¿A dónde llevará Frodo el Anillo?", El sistema responderá: "A Mordor".
Nuestro escenario, como regla, era diferente. Por ejemplo, para dos solicitudes similares: "¿Puedo pagar?" y "¿Puedo pagar en línea?" El bot debe responder de manera diferente: en el primer caso, ofrezca a una persona una forma de pago, en la segunda respuesta, sí, puede pagar en línea, aquí está la dirección de la página.
Otra clase de soluciones para evaluar la similitud de los documentos se centra en respuestas largas, al menos algunas sugerencias, entre las cuales se incluye información de interés para el usuario. Desafortunadamente, en casos con preguntas y respuestas breves (“¿Cómo pago en línea?” - “Puede pagar con PayPal”) funcionan de manera muy inestable.
Otra solución es el enfoque Doc2vec: el texto grande se destila en una representación vectorial, que luego se compara con otros documentos en la misma forma y se revela el coeficiente de similitud. Este enfoque también tuvo que ser eliminado: se enfoca en textos largos, pero tratamos principalmente con preguntas y respuestas de una o dos oraciones.
Nuestra decisión se basó en dos pasos. Primero: usando incrustaciones, tradujimos cada palabra en una oración en vectores usando el modelo Google Word2vec.
Después de eso, consideramos el vector promedio para todas las palabras, representando una oración en forma de un vector. El segundo paso, tomamos el vector de la pregunta y lo encontramos en la base de datos de preguntas frecuentes, almacenado en el mismo formulario vectorial, la respuesta más cercana hasta cierto punto, en nuestro caso, el coseno.Las ventajas incluyen facilidad de implementación, extensibilidad muy fácil e interpretabilidad bastante simple. Las desventajas son una débil oportunidad de optimización: este modelo es difícil de modificar: funciona bien en la mayoría de sus casos de usuario o debe abandonarlo."¿Y hablar?" Pequeña charla
A veces, el usuario escribe algo completamente irrelevante, por ejemplo: "Hoy hace buen tiempo". Esto no está incluido en la lista de intenciones que nos interesan, pero aún queremos responder de manera significativa, demostrando la inteligencia de nuestro sistema.Para tales decisiones, se usa una combinación de los enfoques descritos anteriormente: se basan en soluciones muy simples basadas en reglas o en redes neuronales generativas. Queríamos obtener un prototipo temprano, por lo que tomamos un conjunto de datos público de Internet y utilizamos un enfoque muy similar al utilizado para las preguntas frecuentes. Por ejemplo, un usuario escribió algo sobre el clima, y utilizando un algoritmo que compara las representaciones vectoriales de dos oraciones con una determinada medida del coseno, buscamos una oración en el conjunto de datos públicos que esté lo más cerca posible del tema del clima.Entrenamiento
Ahora no tenemos el objetivo de crear un bot que se capacite en cada mensaje recibido de los clientes: en primer lugar, como lo demuestra la experiencia, este es el camino hacia la muerte del bot (recuerde cómo IBM Watson tuvo que borrar la base porque comenzó a diagnosticar con un tapete y el bot de Twitter de Microsoft logró convertirse en racista en solo un día). En segundo lugar, nos esforzamos por cerrar las tareas de las compañías de seguros de la manera más cualitativa posible; Un robot de autoaprendizaje no es nuestra tarea comercial. Hemos escrito una serie de herramientas para lingüistas y comandos de control de calidad con los que pueden entrenar manualmente a los bots, explorar diálogos y correspondencia con los usuarios durante la moderación posterior.Sin embargo, nuestro bot ya parece estar listo para pasar la prueba de Turing. Algunos usuarios comienzan una conversación seria con él, creyendo que están hablando con un agente de seguros, y uno incluso comenzó a amenazar con una queja al jefe cuando el bot lo entendió mal.Planes
Ahora estamos trabajando en la parte visual: mostrar el gráfico completo del script y la capacidad de componerlo usando la GUI.En el lado del Servicio de Reconocimiento, estamos introduciendo un análisis lingüístico para reconocer y comprender el significado de cada palabra en el mensaje. Esto mejorará la precisión de la reacción y extraerá datos adicionales. Por ejemplo, si una persona llena un seguro de auto y menciona que tiene una casa sin seguro, el bot podrá recordar este mensaje y enviarlo al operador para contactar al cliente y ofrecerle un seguro de hogar.Otra característica en el trabajo es el procesamiento de comentarios. Después de completar el diálogo con el bot, le preguntamos al usuario si le gustó el servicio. Si Sentiment Analysis reconoció la opinión del usuario como positiva, lo invitamos a compartir su opinión en las redes sociales. Si el análisis muestra que el usuario reaccionó negativamente, el bot aclara lo que estaba mal, corrige la respuesta, dice: "OK, lo arreglaremos" y no ofrece compartir la revisión en la transmisión.Una de las claves para hacer que la comunicación con el bot sea lo más natural posible es hacer que el bot sea modular y ampliar el rango de reacciones disponibles. Estamos trabajando en eso. Tal vez debido a esto, el usuario estaba listo para tomar sinceramente nuestro bot como agente de seguros. El siguiente paso: asegúrese de que la persona esté tratando de agradecerle al bot.
El artículo fue escrito con Sergei Kondratyuk y Mikhail Kazakov . Escriba sus preguntas en los comentarios, prepararemos materiales más prácticos sobre ellas.