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(""); } }