Crewmaster Protocol
Instalación
npm install @crewmaster/protocol@1.x.x
Uso
Este protocolo se usa para la comunicación entre el cliente-app y el servidor de Crewmaster.
El siguiente codigo debe ser implementado por el cliente-app para usar el protocolo en cada interacción con el servidor. Es decir, cada vez que en el chat el usuario agregue un mensaje y se requiera alguna interacción con el LLM.
Para usar el protocolo, se debe instanciar un objeto de la clase RequestHandler
y pasarle los siguientes parámetros:
- bearerToken: Token de autenticación
- serverUrl: URL del servidor
- threadId: Identificador del hilo de conversación actual (establecido por el cliente-app)
- eventConfig: Configuración de eventos (opcional)
Para hacer un request al servidor, se debe llamar al método newRequest
del objeto RequestHandler
y pasarle los siguientes parámetros:
- body: Lista de mensajes intercambiados en el hilo de la conversación (el último mensaje es el mensaje nuevo agregado por el usuario)
- responseStreamHandler: Objeto de la clase `ResponseStreamHandler` que contiene la instancia de la clase que implementa el contrato `PluginPort`, la cual es encargada de manejar la respuesta del serivdor
- answeredClarifications: Lista de aclaraciones respondidas por el usuario (instancia de la clase `AnsweredClarifications`)
const request = new RequestHandler({
bearerToken: this.bearerToken, // Token autenticacion
serverUrl: this.serverUrl, // URL del servidor
threadId: this.threadId, // Identificador del hilo de conversacion actual (establecido por el cliente-app)
eventConfig: {
scope: ScopeType.Answer, // opcional
moments: [MomentType.Start, MomentType.End], // opcional
format: FormatType.Compact // opcional
}
});
const reponseHandler: PluginPort; // Esta es una clase desarrollada por el cliente que implementa el contrato PluginPort
const responseStreamHandler = new ResponseStreamHandler(responseHandler);
request.newRequest(
body, // Lista de mensajes intercambiados en el hilo de la conversacion
// El ultimo mensaje es el mensaje nuevo agreagado por el ususario
responseStreamHandler,
this.answeredClarifications
);
Los tipos y clases relacionadas con el RequestHandler se importan de la siguiente manera:
import { RequestHandler, AnsweredClarifications } from '@imolko/crewmaster-protocol/request-handler';
Los tipos y clases relacionadas con el ResponseStreamHandler se importan de la siguiente manera:
import { ResponseStreamHandler, PluginPort } from '@imolko/crewmaster-protocol/response-stream-handler';
Sobre RequestHandler
La clase RequestHandler
es la encargada de manejar las peticiones al servidor. Esta clase acepta y valida solo dos tipos de solicitudes:
- **Fresh**: Solicitudes de tipo `Fresh` que es un mensaje nuevo agregado por el usuario al chat como parte del inicio o el seguimiento de una conversación con el LLM
- **Clarification**: Solicitudes de tipo `Clarification` en la que el usuario responde a una aclaración requerida por el LLM (crewmaster)
La clase RequestHandler
tiene una logica implementada para saber si el mensaje que se esta enviando es una aclaración o un mensaje nuevo. Para esto, se valida si el mensaje es una respuesta a una aclaración previa o si es un mensaje nuevo agregado por el usuario.
Dicha validacion se hace con ayuda de la clase AnsweredClarifications
que es un objeto que contiene una lista de aclaraciones respondidas por el usuario. La forma en como se hace esa validacion es haciendo match entre el mensaje nuevo agregado por el usuario al chat y las aclaraciones respondidas por el usuario existentes en el objeto AnsweredClarifications
.
Ejemplo teorico:
Cuando un usuario responde a una aclaración el cliente-app agrega a su objeto AnsweredClarifications
la aclaración respondida por el usuario con un mensaje especifico como key
y payload como value
. Luego cuando se ejecuta el RequestHandler.newRequest() esa clase valida si hay match entre el mensaje nuevo agregado por el usuario y las aclaraciones respondidas por el usuario. Si hay match, entonces se envia una solicitud de tipo Clarification
al servidor, de lo contrario se envia una solicitud de tipo Fresh
.
Ejemplo practico: El cliente-app implmenta en su logica una aclaracion para confirmar una operacion, en donde en la interfaz le da dos opciones que el usuario debe seleccionar: 'Confirmar operacion' o 'Rechazar operacion`.
La opcion que el usuario seleccione el cliente-app la debe agregar a su objeto AnsweredClarifications
.
Suponganmos que el cliente selecciona 'Confirmar operacion', entonces el cliente-app agrega a su objeto AnsweredClarifications
:
key: 'Confirmar operacion'
payload: {
confirmation: 'y'
}
Luego el cliente-app debe agregar como ultimo mensaje enviado por el usuario en el chat el mensaje 'Confirmar operacion' para que el RequestHandler pueda validar si hay match entre el mensaje nuevo agregado por el usuario y las aclaraciones respondidas por el usuario.
Y de esa forma el RequestHandler sabra si el mensaje que se esta enviando es una aclaracion o un mensaje nuevo y enviara la solicitud correspondiente al servidor.
Sobre el manejo de respuestas del servidor (ResponseStreamHandler + PluginPort)
La clase ResponseStreamHandler
es la encargada de manejar las respuestas del servidor. Usando el plugin (instancia de una clase propia del cliente-app que implementa el contrato PluginPort
) que se le pase como parametro al constructor de ésta clase.
El contrato PluginPort es una interfaz que debe ser implementada por el cliente-app para manejar las respuestas del servidor. Los metodos que debe implementar el cliente-app son:
connectionStarted(): Este metodo debe manejar cualquier accion que el cliente-app necesite ejecutar cuando sepa que se ha establecido conexion con el serividor, es decir, cuando sepa que se envio correctamente el request al servidor y se esta esperando una respuesta.
publishMessage(): Este metodo debe manejar cada mensaje que se reciba del LLM, puede ser uno o mas mensajes y estan identificados, el cliente-app debe poder manejar cada uno de esos mensajes para mostrarlos al usuario en el chat o ejecutar la logica que requiera.
Si hay errores, la respuesta que se pasa al metodo
publishMessage()
indica que hubo un error y el cliente-app debe manejarlo.Cuando hay errores, se envia el error por publishMessage() y seguidamente se ejecuta el metodo
connectionFinished()
.connectionFinished(): Este metodo indica que la interaccion con el servidor y el LLM finalizo, el cliente-app debe manejar cualquier accion que necesite ejecutar cuando sepa que la interaccion con el servidor y el LLM finalizo.