Spaces:
Runtime error
Runtime error
| class ChatGPT{ | |
| /* Eventos generados | |
| **********************/ | |
| /* Eventos escuchados | |
| - chat:enviar | |
| - chat:eliminar | |
| **********************/ | |
| definicion ={ | |
| conversacion: [], | |
| usedTokens: 0 | |
| }; | |
| config = { | |
| temperature: 0.5, | |
| frequency_penalty: 0.0, | |
| presence_penalty: 0.0, | |
| useTool: true, | |
| assistant: "clasico", | |
| assistantPrompt: "" | |
| } | |
| tokens = { | |
| month: 0, | |
| total: 0 | |
| } | |
| endpointChat = "/chat"; | |
| challenge = null; | |
| windowHandlers = {} | |
| constructor(secHand){ | |
| // Token JWT de ejecuci贸n | |
| this.secHand = secHand; | |
| this.obtenerToken(); | |
| this.cargarEventos(); | |
| } | |
| obtenerToken(){ | |
| $.ajax({ | |
| method: "POST", | |
| url: "/getToken", | |
| headers: { | |
| "Autorization": "Bearer " + this.token, | |
| 'Content-Type': 'application/json', | |
| }, | |
| data: JSON.stringify({ | |
| fingerprint: this.secHand.fingerprint, | |
| public_key: this.secHand.publicKey | |
| }), | |
| timeout: 5000, | |
| dataType: "json" | |
| }).done((data) => { | |
| if(data.redirect){ | |
| $("#inserted")[0].showModal() | |
| $("#inserted").html("<iframe src='"+data.redirect+"'>") | |
| $("#inserted").on("close", (event) =>{ | |
| document.location.reload() | |
| }) | |
| return | |
| } | |
| this.secHand.sign(data.challenge).then( | |
| (result) => { | |
| this.challenge = result | |
| this.cargarConfigs(false, true); | |
| }) | |
| this.token = data.token | |
| }).fail((data => { | |
| $("#inserted")[0].showModal() | |
| $("#inserted").html("<iframe src='/login'>") | |
| $("#inserted").on("close", (event) =>{ | |
| document.location.reload() | |
| }) | |
| $("#inserted iframe").on("load", (event) =>{ | |
| let location = event.target.contentDocument.location.pathname | |
| if(location == "/login"){ | |
| $("#inserted iframe")[0].contentWindow.data = { | |
| fp: this.secHand.fingerprint, | |
| pk: this.secHand.publicKey | |
| } | |
| } | |
| if(location == "/"){ | |
| $("#inserted").html("") | |
| $("#inserted")[0].close() | |
| } | |
| }) | |
| })) | |
| } | |
| cargarConfigs(abrirMenu, starting){ | |
| self = this | |
| $.ajax({ | |
| method: "POST", | |
| url: "/getConfigs", | |
| headers: { | |
| "Autorization": "Bearer " + this.token, | |
| 'Content-Type': 'application/json', | |
| }, | |
| data:JSON.stringify({ | |
| challenge: this.challenge, | |
| fingerprint: this.secHand.fingerprint | |
| }), | |
| timeout: 5000, | |
| dataType: "json" | |
| }).done((data) => { | |
| let challenge = data["challenge"]; | |
| delete data["challenge"]; | |
| $("#assistant option[value='"+ data.assistant +"']")[0].selected=true | |
| this.secHand.sign(challenge).then((result) => {this.challenge = result;}) | |
| this.config = data | |
| for(let confEl in data){ | |
| if(typeof(data[confEl]) == "boolean"){ | |
| $("#"+confEl).prop("checked", data[confEl]) | |
| }else{ | |
| $("#"+confEl).val(data[confEl]) | |
| } | |
| } | |
| $(".range input").each(recalculateRanges) | |
| $(".range input").on("input", recalculateRanges) | |
| $(".item.parent input").on("change", function(){ | |
| self.config[this.id] = this.checked | |
| if(!this.checked){ | |
| $(".item."+this.id+" input").prop("disabled", true) | |
| }else{ | |
| $(".item."+this.id+" input").prop("disabled", false) | |
| } | |
| }) | |
| $(".range select").on("change", function(){ | |
| self.config[this.id] = this.value | |
| }) | |
| $("#tokensUsedMonth").text(data.tokens.month) | |
| $("#tokensUsedTotal").text(data.tokens.total) | |
| if(abrirMenu) $("#menu")[0].showModal() | |
| function recalculateRanges(){ | |
| let value = (Math.round(this.value * 100) / 100).toFixed(2) | |
| $(this).parent().find("span").text(value); | |
| self.config[this.id] = parseFloat(value) | |
| } | |
| $(".item.parent input").trigger("change") | |
| if(starting){this.cargarChats()} | |
| }) | |
| .fail(() => { | |
| document.location.href = "/"; | |
| }) | |
| } | |
| 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()) | |
| $("#menu .saveButton").on("click", () => this.salvarConfigs()) | |
| } | |
| 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){ | |
| if(!conversaciones[key]){ | |
| continue | |
| } | |
| if(Object.keys(conversaciones[key]).indexOf('conversacion')!=-1){ | |
| this.crearChat(key, conversaciones[key].conversacion) | |
| }else{ | |
| this.crearChat(key, conversaciones[key]) | |
| } | |
| } | |
| localStorage.setItem("conversaciones", JSON.stringify(conversaciones)) | |
| } | |
| salvarConfigs(){ | |
| $.ajax({ | |
| method: "POST", | |
| url: "/setConfigs", | |
| headers: { | |
| "Autorization": "Bearer " + this.token, | |
| 'Content-Type': 'application/json', | |
| }, | |
| data: JSON.stringify( | |
| {...this.config, | |
| fingerprint: this.secHand.fingerprint, | |
| challenge: this.challenge, | |
| }), | |
| timeout: 5000, | |
| dataType: "json" | |
| }).done((data) => { | |
| this.secHand.sign(data.challenge).then((result) => {this.challenge = result}) | |
| this.token = data.token | |
| this.config.assistantPrompt = data.assistantPrompt | |
| }).fail(() => { | |
| document.location.href = "/"; | |
| }) | |
| } | |
| crearChat(index, conversacion){ | |
| // Se crea el nuevo manejador de ventana | |
| let uuid = this.generateRandID() | |
| this.windowHandlers[index||uuid] = new WindowHandler( | |
| conversacion||[], | |
| index||uuid, | |
| this | |
| ); | |
| } | |
| eliminarChat(ctx, index){ | |
| // 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; | |
| // Se carga el nuevo challenge | |
| case "challenge": | |
| this.secHand.sign(response.challenge).then((result) => {self.challenge = result}) | |
| 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("???", response) | |
| } | |
| } | |
| // 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, | |
| challenge: this.challenge, | |
| fingerprint: this.secHand.fingerprint | |
| }), | |
| headers: { | |
| "Autorization": "Bearer " + this.token, | |
| 'Content-Type': 'application/json', | |
| }, | |
| 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) | |
| document.location.href = "/"; | |
| }); | |
| } | |
| salvarChats(index, conversacion){ | |
| let conversaciones = {} | |
| try{conversaciones = JSON.parse(localStorage.getItem("conversaciones"))||{}}catch{} | |
| let temp = {} | |
| for (let i in conversaciones){ | |
| temp[i]=conversaciones[i] | |
| } | |
| temp[index] = conversacion | |
| localStorage.setItem("conversaciones", JSON.stringify(temp)) | |
| } | |
| mostrarOpciones(){ | |
| this.cargarConfigs(true); | |
| } | |
| generateRandID(){ | |
| return btoa((Math.random()*100**8)).replaceAll("=","").split("").reverse().join(""); | |
| } | |
| } | |