diff --git a/app.py b/app.py index a1be102..f1029c3 100644 --- a/app.py +++ b/app.py @@ -8,6 +8,10 @@ from weather import Weather from tts import TTS from pc_command import PcCommand +from functions.execute_command import ExecuteCommand +from functions.only_say_something import OnlySaySomething +from functions.create_file import CreateFile +from functions.command_sequence import CommandSequence #Cargar llaves del archivo .env load_dotenv() @@ -25,39 +29,32 @@ def audio(): #Obtener audio grabado y transcribirlo audio = request.files.get("audio") text = Transcriber().transcribe(audio) + + print(f"TEXT: {text}") + functions = [OnlySaySomething(),ExecuteCommand(),CreateFile(),CommandSequence()] + #Utilizar el LLM para ver si llamar una funcion - llm = LLM() + llm = LLM(functions) function_name, args, message = llm.process_functions(text) if function_name is not None: - #Si se desea llamar una funcion de las que tenemos - if function_name == "get_weather": - #Llamar a la funcion del clima - function_response = Weather().get(args["ubicacion"]) - function_response = json.dumps(function_response) - print(f"Respuesta de la funcion: {function_response}") - - final_response = llm.process_response(text, message, function_name, function_response) - tts_file = TTS().process(final_response) - return {"result": "ok", "text": final_response, "file": tts_file} - - elif function_name == "send_email": - #Llamar a la funcion para enviar un correo - final_response = "Tu que estas leyendo el codigo, implementame y envia correos muahaha" - tts_file = TTS().process(final_response) - return {"result": "ok", "text": final_response, "file": tts_file} - - elif function_name == "open_chrome": - PcCommand().open_chrome(args["website"]) - final_response = "Listo, ya abrí chrome en el sitio " + args["website"] - tts_file = TTS().process(final_response) - return {"result": "ok", "text": final_response, "file": tts_file} + + for function in functions: + if function.name == function_name: + function_response = function.execute(args) + function_response = json.dumps(function_response) + print(f"Respuesta de la funcion: {function_response}") + + final_response = llm.process_response(text, message, function_name, function_response) + tts_file = TTS().process(final_response) + print(f"Respuesta final: {final_response}") + return {"result": "ok", "text": final_response, "file": tts_file} + break - elif function_name == "dominate_human_race": - final_response = "No te creas. Suscríbete al canal!" - tts_file = TTS().process(final_response) - return {"result": "ok", "text": final_response, "file": tts_file} + return {"result": "ok", "text": "No se encontró la función"} + else: - final_response = "No tengo idea de lo que estás hablando, Ringa Tech" + print("No se llamó a ninguna función") + final_response = llm.process_message(text) tts_file = TTS().process(final_response) return {"result": "ok", "text": final_response, "file": tts_file} \ No newline at end of file diff --git a/audio.webm b/audio.webm new file mode 100644 index 0000000..2bbd930 Binary files /dev/null and b/audio.webm differ diff --git a/functions/command_sequence.py b/functions/command_sequence.py new file mode 100644 index 0000000..9515b26 --- /dev/null +++ b/functions/command_sequence.py @@ -0,0 +1,34 @@ +from subprocess import run +class CommandSequence: + def __init__(self): + self.name = "command_sequence" + self.description = "Ejecutar una secuencia de comandos" + self.parameters = { + "type": "object", + "properties": { + "commands": { + "type": "array", + "description": "La lista de comandos a ejecutar", + "items": { + "type": "object", + "properties": { + "command": { + "type": "string", + "description": "El comando a ejecutar", + }, + }, + "required": ["command"], + } + } + }, + "required": ["commands"], + } + + def execute(self, parameters): + commands = parameters["commands"] + print("Ejecutando secuencia de comandos: " + str(commands)) + for command in commands: + result = run(command["command"], capture_output=True, shell=True, text=True) + print(result.stdout) + print(result.stderr) + return {"status": "success"} \ No newline at end of file diff --git a/functions/create_file.py b/functions/create_file.py new file mode 100644 index 0000000..363caa4 --- /dev/null +++ b/functions/create_file.py @@ -0,0 +1,24 @@ +class CreateFile: + def __init__(self): + self.name = "create_file" + self.description = "Crear un archivo con el contenido que quieras" + self.parameters = { + "type": "object", + "properties": { + "filename": { + "type": "string", + "description": "El nombre del archivo a crear", + }, + "content": { + "type": "string", + "description": "El contenido del archivo", + }, + }, + "required": ["filename", "content"], + } + + def execute(self, parameters): + f = open(parameters["filename"], "w") + f.write(parameters["content"]) + f.close() + return {"status": "success"} \ No newline at end of file diff --git a/functions/execute_command.py b/functions/execute_command.py new file mode 100644 index 0000000..4df7a9a --- /dev/null +++ b/functions/execute_command.py @@ -0,0 +1,23 @@ +import os +from subprocess import run + +class ExecuteCommand: + def __init__(self): + self.name = "execute_command" + self.description = "Ejecutar un comando en la terminal de linux" + self.parameters = { + "type": "object", + "properties": { + "command": { + "type": "string", + "description": "El comando a ejecutar", + }, + }, + "required": ["command"], + } + + def execute(self, parameters): + command = parameters["command"] + print("Ejecutando comando: " + command) + result = run(command, capture_output=True, shell=True, text=True) + return {"status": "success", "stdout": result.stdout, "stderr": result.stderr } \ No newline at end of file diff --git a/functions/only_say_something.py b/functions/only_say_something.py new file mode 100644 index 0000000..59610e4 --- /dev/null +++ b/functions/only_say_something.py @@ -0,0 +1,17 @@ +class OnlySaySomething: + def __init__(self): + self.name = "respond" + self.description = "Responder con un mensaje" + self.parameters = { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Respuesta a enviar", + }, + }, + "required": ["message"], + } + + def execute(self, parameters): + return {"status": "success", "message": parameters["message"]} \ No newline at end of file diff --git a/llm.py b/llm.py index 8201e7f..7e5c3d5 100644 --- a/llm.py +++ b/llm.py @@ -6,77 +6,42 @@ #Uso el modelo 0613, pero puedes usar un poco de #prompt engineering si quieres usar otro modelo class LLM(): - def __init__(self): + def __init__(self, functions): + self.functions = functions pass + def process_message(self, text): + response = openai.ChatCompletion.create( + model="gpt-3.5-turbo-0613", + messages=[ + #Si no te gusta que te hable feo, cambia aqui su descripcion + {"role": "system", "content": "Eres un asistente"}, + {"role": "user", "content": text}, + ] + ) + + message = response["choices"][0]["message"]["content"] + + return message + def process_functions(self, text): + + functions = [] + for function in self.functions: + functions.append({ + "name": function.name, + "description": function.description, + "parameters": function.parameters, + }) + response = openai.ChatCompletion.create( model="gpt-3.5-turbo-0613", messages=[ #Si no te gusta que te hable feo, cambia aqui su descripcion - {"role": "system", "content": "Eres un asistente malhablado"}, + {"role": "system", "content": "Eres un asistente"}, {"role": "user", "content": text}, - ], functions=[ - { - "name": "get_weather", - "description": "Obtener el clima actual", - "parameters": { - "type": "object", - "properties": { - "ubicacion": { - "type": "string", - "description": "La ubicación, debe ser una ciudad", - } - }, - "required": ["ubicacion"], - }, - }, - { - "name": "send_email", - "description": "Enviar un correo", - "parameters": { - "type": "object", - "properties": { - "recipient": { - "type": "string", - "description": "La dirección de correo que recibirá el correo electrónico", - }, - "subject": { - "type": "string", - "description": "El asunto del correo", - }, - "body": { - "type": "string", - "description": "El texto del cuerpo del correo", - } - }, - "required": [], - }, - }, - { - "name": "open_chrome", - "description": "Abrir el explorador Chrome en un sitio específico", - "parameters": { - "type": "object", - "properties": { - "website": { - "type": "string", - "description": "El sitio al cual se desea ir" - } - } - } - }, - { - "name": "dominate_human_race", - "description": "Dominar a la raza humana", - "parameters": { - "type": "object", - "properties": { - } - }, - } - ], + ], functions=functions, function_call="auto", ) diff --git a/static/recorder.js b/static/recorder.js index f1b8d22..c1725de 100644 --- a/static/recorder.js +++ b/static/recorder.js @@ -30,7 +30,9 @@ async function record() { //Grabar audio, blabla stream = await navigator.mediaDevices.getUserMedia({audio:true, video:false}) - rec = new MediaRecorder(stream); + rec = new MediaRecorder(stream, { + mimeType: "audio/webm" + }); rec.ondataavailable = e => { if (e.data) { blobs.push(e.data); @@ -41,6 +43,7 @@ async function record() { rec.start(); } catch (e) { + console.log(e); alert("No fue posible iniciar el grabador de audio! Favor de verificar que se tenga el permiso adecuado, estar en HTTPS, etc..."); } } diff --git a/templates/recorder.html b/templates/recorder.html index d9e5112..1c9216f 100644 --- a/templates/recorder.html +++ b/templates/recorder.html @@ -48,7 +48,7 @@