chattest / static /js /chatHandler.js
Miguel Diaz
Dev: Avance
edcdbb0
class ChatGPT{
/* Eventos generados
**********************/
/* Eventos escuchados
- chat:enviar
- chat:eliminar
**********************/
definicion = {
role: "system",
content: "Te llamas Chatsito, eres un asistente de apoyo a los amigos de " +
"MIA, tu objetivo principal es responder preguntas de manera puntual y " +
"objetiva a tu interlocutor.\n" +
"Si requieres ejecutar m谩s funciones, ejecuta tantas veces como lo " +
"necesites\n" +
"Responde de manera amistosa con en el texto m谩s corto y objetivo posible.\n" +
"Knowledge cutoff: " +
"2021-09-01\nCurrent date: {date}".replace("{date}", new Date().toJSON().slice(0, 10))
};
endpointChat = "/chat";
token = null;
windowHandlers = {}
constructor(token){
// Token JWT de ejecuci贸n
this.token = token;
// inicializa eventos de escucha
this.cargarEventos();
this.cargarChats()
}
cargarEventos(){
$(document).on("chat:enviar", (event, params) => {
// Al enviar un mensaje, reintentos vuelve a 0
this.reintentos = 0;
this.enviar(params.ctx, params.ctx.conversacion);
});
$(document).on("chat:salvar", (event, params) => this.salvarChats(params.index, params.conversacion))
$(document).on("chat:eliminar", (event, params) => this.eliminarChat(params.ctx, params.index))
$(document).on("mostrar:opciones", () => this.mostrarOpciones())
$("#nuevoChat").on("click", () => this.crearChat())
}
crearChat(index, conversacion){
// Se crea el nuevo manejador de ventana
let uuid = this.generateRandID()
this.windowHandlers[index||uuid] = new WindowHandler(
conversacion||[this.definicion],
index||uuid,
this
);
}
eliminarChat(ctx, index){
// Elimina un chat
// Elimina el elemento de la lista de conversas y handler de ventanas
delete this.windowHandlers[index]
let conversaciones = {}
try{conversaciones = JSON.parse(localStorage.getItem("conversaciones"))||{}}catch{}
if(index in conversaciones){delete conversaciones[index]}
localStorage.setItem("conversaciones", JSON.stringify(conversaciones))
// Renumera las etiquetas, y selecciona la primera
let labels = $(".tab-label")
$(labels[0]).click();
// Si no quedaron chats, crea uno vacio
if(Object.keys(this.windowHandlers).length==0){
this.crearChat()
}
}
enviar(ctx, conversacion){
// Envio de mensaje y manejo de comandos async
// Crea un espacio temporal para almacenar los mensajes con el formato correcto
let tempMensajes = [];
for(let actMsg of conversacion){
tempMensajes.push({role: actMsg.role, content: actMsg.content})
}
// Se anuncia la precarga
ctx.respuestaInicio()
// Se almacena el contexto this
let self = this;
// Consumo de mensajes asincronos
const consume = responseReader => {
// Se lee la respuesta
return responseReader.read().then(result => {
//si finaliz贸 el mensaje, se termina el proceso
if (result.done) { return; }
// Se obtiene y decodifica el segmento
const chunk = result.value;
let text = new TextDecoder("utf-8").decode(chunk)
// Se obtienen los mensajes y separan si son varios json juntos
let responses = JSON.parse('[' + text.replace(/\}\{/g, '},{') + ']')
// Por cada mensaje conseguido validamos el caso de accion
for(let response of responses){
switch(response.comando){
// Se carga el nuevo token
case "token":
self.token = response.token;
break;
// Status del comportamiento
case "status":
ctx.respuestaStatus(response.status.mensaje, response.status.modo)
break;
// Mensaje a mostrar
case "mensaje":
ctx.respuestaMensaje(response.mensaje)
break;
// // Es una funci贸n
// case "function":
// conversacion.push(response.function);
// localStorage.setItem("conversaciones", JSON.stringify(self.conversaciones))
// break;
// Algo fall贸
default:
console.log("???")
}
}
// Se consume la respuesta para continuar el proceso
return consume(responseReader);
}).catch(err =>{
// Error
console.log('algo paso', err)
});
}
// Se ejecuta el request
fetch(this.endpointChat, {
method: "POST",
body: JSON.stringify({
messages: tempMensajes,
token: this.token,
config: {"temperature": 1,"frequency_penalty": 0,"presence_penalty": 0}
}),
timeout: 60000,
dataType: "json"
}).then(response => {
if(response.status != 200){
ctx.respuestaError(response)
console.log("Error: ", response)
return
}
return consume(response.body.getReader());
})
.catch(err =>{
// Error
console.log('Solicitud fallida', err)
ctx.respuestaError(response)
});
}
salvarChats(index, conversacion){
let conversaciones = {}
try{conversaciones = JSON.parse(localStorage.getItem("conversaciones"))||{}}catch{}
conversaciones[index] = conversacion
localStorage.setItem("conversaciones", JSON.stringify(conversaciones))
}
cargarChats(){
let conversaciones = {}
try{conversaciones = JSON.parse(localStorage.getItem("conversaciones"))||{}}catch{}
if(!conversaciones || !Object.keys(conversaciones).length){
this.crearChat()
return
}
for(let key in conversaciones){
this.crearChat(key, conversaciones[key])
}
}
mostrarOpciones(){
}
generateRandID(){
return btoa((Math.random()*100**8)).replaceAll("=","").split("").reverse().join("");
}
}