Marco para el desarrollo de aplicaciones de chat bot.
Asegúrese de tener instalado node y npm. A partir de ahora, este módulo se ha probado con la versión del nodo 0.12 dentro del proceso de CI de Travis.
Simplemente ejecute el comando npm install
para instalar:
npm install --save talkify
Requerir el módulo principal, tipos y dependencias. El siguiente comando carga todo lo que necesita del módulo.
// Core dependency
const talkify = require ( 'talkify' ) ;
const Bot = talkify . Bot ;
// Types dependencies
const BotTypes = talkify . BotTypes ;
const Message = BotTypes . Message ;
const SingleLineMessage = BotTypes . SingleLineMessage ;
const MultiLineMessage = BotTypes . MultiLineMessage ;
// Skills dependencies
const Skill = BotTypes . Skill ;
// Training dependencies
const TrainingDocument = BotTypes . TrainingDocument ;
Una vez que se hayan cargado las dependencias, puede inicializar el núcleo del bot.
const bot = new Bot ( ) ;
El constructor Bot()
también acepta parámetros en forma de objeto de configuración. Aquí puede pasar valores de cambio de configuración o implementaciones alternativas para cosas como ContextStore
y Classifier
, etc. Lo cubriremos más adelante en la sección Opciones de configuración.
Una vez inicializado el Bot, lo primero que debes hacer es entrenarlo. Para entrenarlo un documento a la vez de forma sincrónica, puedes usar el método train
:
bot . trainAll ( [
new TrainingDocument ( 'how_are_you' , 'how are you' ) ,
new TrainingDocument ( 'how_are_you' , 'how are you going' ) ,
new TrainingDocument ( 'how_are_you' , 'how is it going' ) ,
new TrainingDocument ( 'help' , 'how can you help' ) ,
new TrainingDocument ( 'help' , 'i need some help' ) ,
new TrainingDocument ( 'help' , 'how could you assist me' )
] , function ( ) { } ) ;
El código anterior entrena al bot para que reconozca el tema how_are_you
cuando el texto se vea como how are you
o how are you doing
y how is it going
pero para que reconozca help
del tema cuando el texto se vea como how can you help
o i need some help
y también how can you assist me
. Así es como entrenarías al robot.
El método trainAll
acepta una serie de objetos TrainingDocument
así como una función de devolución de llamada. El constructor del objeto TrainingDocument
acepta dos parámetros. Estos son topicName
y trainingData
. El parámetro topicName
es el nombre del tema para el que desea entrenar los trainingData
y los trainingData
es la oración que está alimentando al bot como datos de entrenamiento. Más adelante, el topicName
se asignará a las habilidades reales a las que el bot puede responder.
La devolución de llamada para el método trainAll
es una función que el bot puede llamar cuando se completa el entrenamiento. Si tiene demasiados datos de entrenamiento, debe implementarlos correctamente. En este ejemplo, dado que no hay muchos datos de entrenamiento, pasamos una function
vacía.
No hace falta decir que el bot mejora con más datos de entrenamiento. En este tutorial estamos usando el clasificador predeterminado, que actualmente es el clasificador LogisticRegression
de la biblioteca talkify-natural-classifier. Este clasificador normalmente necesita un poco más de datos de entrenamiento para empezar, pero es más preciso que otros en la mayoría de las condiciones.
Una vez que haya entrenado al bot para algunos temas, deberá agregar algunas habilidades. Las habilidades son acciones que el bot ejecutará cuando reconozca un tema. Entonces, los temas y las habilidades se relacionan 1:1.
Para agregar una habilidad, primero debes crearla. Una habilidad requiere tres cosas. Nombre de la habilidad que es exclusiva del bot. El nombre se utiliza para relacionar habilidades más adelante dentro del contexto. Un tema al que se asigna y una función que el bot llamará para ejecutar la habilidad. Esta función tomará cuatro parámetros, a saber: context, request, response, next
. El parámetro context
se utiliza para almacenar cualquier información contextual útil de esa habilidad. El parámetro request
contiene información sobre la solicitud, lo mismo para response
. El next
parámetro es una función a la que puede llamar para informarle al bot que ha terminado de procesar. Así es como se ve una habilidad:
var howAction = function ( context , request , response , next ) {
response . message = new SingleLineMessage ( 'You asked: "' + request . message . content + '". I'm doing well. Thanks for asking.' ) ;
next ( ) ;
} ;
var helpAction = function ( context , request , response , next ) {
response . message = new SingleLineMessage ( 'You asked: "' + request . message . content + '". I can tell you how I'm doing if you ask nicely.' ) ;
next ( ) ;
} ;
var howSkill = new Skill ( 'how_skill' , 'how_are_you' , howAction ) ;
var helpSkill = new Skill ( 'help_skill' , 'help' , helpAction ) ;
Nota: El nombre de una habilidad puede no estar definido. Sin embargo, tenga en cuenta que hacerlo significará que el bot ejecutará esa habilidad siempre que su nivel de confianza sea 0 para responder a una consulta determinada.
Una vez que haya definido algunas habilidades, deberá agregarlas al bot. Agregue la habilidad al bot así:
bot . addSkill ( howSkill ) ;
bot . addSkill ( helpSkill ) ;
Una vez agregado, ahora puedes pedirle al bot que resuelva algo. Aquí es donde le consulta al bot con una oración y este responderá con un mensaje de forma asincrónica. La función de resolución toma tres parámetros: contextId, text, callback
. El contextId
ayuda al bot a resolver el contexto de cualquier conversación anterior. El text
es la pregunta o fragmento de cadena en lenguaje natural que el robot necesita interpretar y responder. Por último, la callback
es la función de devolución de llamada que el bot llamará con err, messages
para indicar un error (si corresponde) y sus mensajes de respuesta.
var resolved = function ( err , messages ) {
if ( err ) return console . error ( err ) ;
return console . log ( messages ) ;
} ;
bot . resolve ( 123 , 'Assistance required' , resolved ) ;
Ejecútelo como un archivo de nodo simple y debería imprimir lo siguiente en la consola.
[ { type: 'SingleLine',
content: 'You asked: "Assistance required". I can tell you how I'm doing if you ask nicely.' } ]
Intente cambiar bot.resolve
a esto y observe el cambio en respuesta.
bot . resolve ( 456 , 'How's it going?' , resolved ) ;
Preguntemos dos cosas a la vez. Cambie bot.resolve
nuevamente a:
bot . resolve ( 456 , 'How's it going? Assistance required please.' , resolved ) ;
Cuando ejecute su código, debería recibir dos mensajes de respuesta:
[ { type : 'SingleLine' ,
content : 'You asked: "How's it going? Assistance required please.". I'm doing well. Thanks for asking.' } ,
{ type : 'SingleLine' ,
content : 'You asked: "How's it going? Assistance required please.". I can tell you how I'm doing if you ask nicely.' } ]
Actualmente, los métodos train
, addSkill
y resolve
se pueden encadenar. Eso significa que puede crear objetos Bot y métodos en cascada como se menciona a continuación.
new Bot ( ) . train ( topic , sentence ) . addSkill ( skill ) . resolve ( ... . )
El núcleo del bot también acepta una implementación alternativa para el almacén de contexto integrado. Consulte Gestión de contexto para obtener más detalles.
También puedes proporcionar tu propia versión del clasificador al bot. Esta opción se usó principalmente para facilitar las pruebas; sin embargo, aún se puede usar en producción si tiene una mejor versión del clasificador integrado.
El clasificador integrado es el clasificador natural talkify. Este clasificador proporciona dos implementaciones:
LogisticRegressionClassifier
BayesClassifier
LogisticRegressionClassifier
es el clasificador predeterminado. Si prefieres implementar BayesClassifier
desde talkify-natural-classifier
, puedes hacer lo siguiente:
var BayesClassifier = require ( 'talkify-natural-classifier' ) . BayesClassifier ;
var bot = new Bot ( { classifier : new BayesClassifier ( ) } ) ;
Si prefiere utilizar el clasificador de procesamiento de lenguaje natural de IBM Watson, debe utilizar la biblioteca talkify-watson-classifier. Consulte la guía en la página del repositorio de Github para obtener más detalles sobre cómo usar ese clasificador.
Si crees que el tuyo funciona mejor, ¡avísame! Estaría encantado de saberlo y posiblemente trabajar para implementarlo dentro del módulo principal.
Para proporcionar su propia implementación de la estrategia de resolución de habilidades, simplemente pase la definición de función en el objeto de configuración de la siguiente manera:
var mySkillResolutionStrategy = function ( ) {
this . addSkill = function ( skill , options ) { ... } ;
this . getSkills = function ( ) { ... } ;
this . resolve = function ( err , resolutionContext , callback ) {
...
} ;
return this ;
} ;
var bot = new Bot ( {
skillResolutionStrategy : mySkillResolutionStrategy
} ) ;
El núcleo del bot creará una instancia de su objeto de estrategia de resolución de habilidades en el inicio y lo usará como instancia única en todas las resoluciones.
Para proporcionar su propia implementación de la estrategia de resolución de temas, simplemente pase la definición de función en el objeto de configuración de la siguiente manera:
var myTopicResolutionStrategy = function ( ) {
this . collect = function ( classification , classificationContext , callback ) { callback ( ) } ;
this . resolve = function ( callback ) { callback ( [ { name : "topic_name" , confidence : 0.5 ] ) } ;
return this ;
} ;
var bot = new Bot ( {
topicResolutionStrategy : myTopicResolutionStrategy
} ) ;
El núcleo del bot creará una nueva instancia de su estrategia de resolución de temas para cada llamada que reciba en el método de resolución.
De forma predeterminada, el núcleo del bot utiliza su versión integrada de ContextStore. Si observa lib/ContextStore.js, encontrará que es una implementación muy simple en la que el contexto se almacena en un mapa simple en memoria donde el contextId
es la clave y el objeto de contexto es el valor. Por supuesto, cuando llegue el momento de implementar esto, el almacén de contexto integrado será muy limitante.
Ampliar el almacén de contexto es muy fácil. Dentro de la configuración, puede proporcionar su propia implementación para el objeto ContextStore. El siguiente código proporciona una implementación muy trivial que simplemente registra los valores en la consola.
var myContextStore = {
put : function ( id , context , callback ) {
console . info ( 'put' ) ;
console . info ( id ) ;
console . info ( context ) ;
} ,
get : function ( id , callback ) {
console . info ( 'get' ) ;
console . info ( id ) ;
} ,
remove : function ( id , callback ) {
console . info ( 'remove' ) ;
console . info ( id ) ;
}
}
var bot = new Bot ( { contextStore : myContextStore } ) ;
La especificación actual para ContextStore
requiere la implementación de tres funciones. Estos se put, get and remove
. Siempre que se proporcionen estos métodos, al bot no le importa de dónde proviene el valor del campo contextStore
en la configuración.
Si ejecutara ese código con algunas consultas resueltas, encontrará que nunca se llama a la función de eliminación. Este es un trabajo en progreso ya que actualmente no hay límite en cuanto a cuánto tiempo se debe recordar un contexto.
Como se mencionó anteriormente, el clasificador predeterminado que usa el bot es de la biblioteca talkify-natural-classifier. Eres libre de escribir tu propio clasificador y utilizarlo en tu aplicación. Para hacer esto, necesita ampliar la interfaz del clasificador definida en la biblioteca talkify-classifier.
Una vez que haya extendido con éxito esa implementación, puede proporcionar su clasificador al bot de esta manera:
var myClassifier = new MyAwesomeClassifier ( ) ;
var bot = new Bot ( { classifier : myClassifier } ) ;
Me encantaría ver su implementación del clasificador talkify. Si ha ampliado la interfaz e implementado con éxito su clasificador, ¡avíseme! Estaría encantado de conocer su experiencia al utilizar esta biblioteca.
Desde la versión 2.1.0, puedes especificar varios clasificadores para tu bot. Consulte los documentos sobre el clasificador para obtener más información.
Una estrategia de resolución de habilidades es un componente que puede generar una habilidad, dado un contexto de resolución. Un contexto de resolución es un objeto compuesto por una lista de temas y la oración original, ingredientes esenciales necesarios para resolver una habilidad.
+-------------+
| Topic | | |
+---------+ | +----> +--------------+
|-----------+ | | |
+-------------+ | Skill | +---------+
| Resolution +----> | Skill |
| Strategy | +---------+
+------------+ | |
| Sentence | +---> +--------------+
+------------+
Una estrategia de resolución de temas le permite conectar una lógica personalizada para resolver un tema, dados los datos de clasificación. Al conectar una estrategia de resolución de temas personalizada, el núcleo del bot espera que se pase la definición de la función en lugar del resultado de la ejecución de la función. Esto se debe a que el objeto de estrategia de resolución de temas se construye utilizando un método new
para cada llamada a resolve
.
El proceso de resolución de temas funciona en dos partes:
La primera etapa del proceso de resolución de temas es la fase de recopilación. Aquí, el núcleo del bot envía la clasificación para cada conjunto de clasificación devuelto por el clasificador junto con cualquier contexto requerido. El núcleo del bot también pasa una función de devolución de llamada que debe invocarse para que el núcleo del bot sepa que la invocación fue exitosa.
+------------------+ +
| Classification | |
+------------------+ |
| +-----------+
+--------> Collect |
| +-----------+
+-----------+ |
| Context | |
+-----------+ +
La segunda etapa es la fase de resolución. Aquí, el núcleo del bot espera que se devuelva una lista de clasificaciones. La resolución se llama solo después de que todas las colecciones hayan terminado de ejecutarse.
+-----------+ +---------+-+-+
| Resolve +---->+ Topic | | |
+-----------+ +---------+ | |
|-----------+ |
+-------------+
Un objeto de estrategia de resolución de temas debe exponer dos métodos:
El método de recopilación se llama cada vez que un clasificador devuelve clasificaciones. Se llama con classification, context, callback
. El objeto classification
contiene la clasificación devuelta por el clasificador (o un conjunto de clasificadores si se utilizan quórums). El objeto context
es el objeto que contiene el contexto de solicitud. La última callback
de parámetro es la función que se debe invocar para que el núcleo del bot sepa que ha terminado de recopilar los parámetros pasados.
El método de resolución se llama una vez que el núcleo del bot termina de llamar collect
en su estrategia de resolución de temas. Esta es la llamada final del núcleo del bot y está destinada a recopilar información sobre la resolución del tema. El método resolve
se llama con un parámetro callback
. Esta es la función de devolución de llamada que se debe llamar con dos parámetros de error, topics
. El parámetro de error debe definirse como un objeto de error en caso de que haya ocurrido un error al resolver el tema. En cualquier otro caso, este objeto debe estar undefined
. El segundo parámetro topics
debe ser una serie de temas resueltos por la estrategia de resolución.
Consulte la guía de contribución para obtener más detalles.