import logging import gradio as gr from ctransformers import AutoModelForCausalLM import threading from langdetect import detect, DetectorFactory from langid import classify import spacy import os import psutil import time # Obtener el proceso actual process = psutil.Process(os.getpid()) # Función para imprimir el uso de CPU y RAM def print_resource_usage(): while True: # Crear un bucle infinito para que se ejecute continuamente cpu_usage = process.cpu_percent(interval=1) ram_usage = process.memory_info().rss / (1024 * 1024) # Convertir bytes a MB pid = str(process.pid) print(f"Uso de CPU: {cpu_usage}%") print(f"Uso de RAM: {ram_usage} MB") print(f"PID: {pid}") time.sleep(10) # Esperar 2 segundos antes de la próxima impresión # Crear y empezar un hilo para el monitoreo de recursos monitoring_thread = threading.Thread(target=print_resource_usage) monitoring_thread.daemon = True # Establecer como un daemon para que no bloquee el programa de terminar monitoring_thread.start() # Configuración del logger logging.basicConfig(filename='chatterIA_logs.txt', level=logging.INFO, format='%(asctime)s %(levelname)s:%(message)s') DetectorFactory.seed = 0 # Para obtener resultados consistentes en la detección del idioma (outputs) # Introducimos un mensaje para el modelo para que hable solo en español y con respeto system_message ="Eres un asistente que siempre responde en español. A cualquiera de sus peticiones y nunca hablas en ningún otro idioma" # Cargar el modelo una sola vez model_instance = None # Cargar el modelo que detecta el idioma de los mensajes solo 1 vez. (inputs) nlp_sm = spacy.load("es_core_news_sm") def load_llm(): global model_instance if model_instance is None: print("Cargando el modelo...") model_instance = AutoModelForCausalLM.from_pretrained( #"TheBloke/Llama-2-7B-Chat-GGUF", "TheBloke/Llama-2-7B-Chat-GGUF", #model_file='llama-2-7b-chat.Q5_K_M.gguf', model_file='llama-2-7b-chat.Q3_K_M.gguf', model_type='llama', max_new_tokens=2048, context_length = 4096, repetition_penalty=1.13, temperature=0.1 ) print("Modelo cargado éxitosamente") else: print("Ya se ha cargado el modelo anteriormente") return model_instance def truncate_history(history, max_tokens=2048): truncated_history = [] total_tokens = 0 for user_msg, bot_msg in reversed(history): # Asegurarse de que ni user_msg ni bot_msg sean None user_msg = user_msg if user_msg is not None else "" bot_msg = bot_msg if bot_msg is not None else "" msg_tokens = len(user_msg.split()) + len(bot_msg.split()) if total_tokens + msg_tokens > max_tokens: break truncated_history.insert(0, (user_msg, bot_msg)) total_tokens += msg_tokens return truncated_history def clean_response(response): code_block_count = response.count("```") if code_block_count % 2 != 0: last_occurrence_index = response.rfind("```") response = response[:last_occurrence_index] + response[last_occurrence_index+3:] return response def format_history_for_model(history): new_history = "\n".join(f"{user_msg}\n{bot_msg}".strip() for user_msg, bot_msg in history) new_history += "\nRespuesta:" return new_history def detectar_idioma_con_spacy(texto): doc = nlp_sm(texto, disable=["parser","ner"]) return True def prepare_message(message): # Primero, intenta detectar el idioma con langid lang, confidence = classify(message) if lang == 'es': return str(message) # Si langid está seguro de que es español, retorna el mensaje # Si el mensaje es muy corto y langid no lo clasifica definitivamente como español, # utiliza SpaCy como una verificación adicional. if len(message.split()) <= 3: # Considera ajustar este umbral según tus necesidades es_espanol_spacy = detectar_idioma_con_spacy(message) if es_espanol_spacy: return str(message) # Si SpaCy procesa el texto sin problemas, asume que es español # Si ninguna de las verificaciones anteriores concluye que el mensaje es en español, retorna None return None def llm_function(message, chat_history ): try: print(f"Mensaje principal:{message}") logging.info(f"Tipo de Message: {type(message)}, Message: {message}") message = str(message) message_str = str(message) # Aquí puedes añadir cualquier validación adicional del mensaje if not message_str.strip(): logging.info("El mensaje está vacío o solo contiene espacios.") return "Por favor, envía un mensaje no vacío.", chat_history # Continuar con el procesamiento... logging.info(f"Message: {message_str}") print(f"Historial del Chat (segun el chatbot)") for i in chat_history: print (i) print("Fin de variables desde el chat") llm = load_llm() message = prepare_message(message) if message is None: return f"Por favor, envía tu mensaje en español. Actualmente idioma es: {detect(message)}" chat_history = truncate_history(chat_history + [(message, "")]) # Añadir el mensaje actual al historial print("Historial del chat antes de formateo") for i in chat_history: print (i) print("Fin de historial previo a formateo") formatted_history = format_history_for_model(chat_history) # Formatear el historial para el modelo full_message = f"{system_message}\n{formatted_history}" print (f"Mensaje completo: {full_message}") response = llm(full_message) # Generar respuesta cleaned_response = clean_response(response) logging.info(f"Message: {message}") logging.info(f"Response: {response}") try: response_language = detect(response) print(f"Idioma en response_language: {response_language}") print(f"Response:{response}") if response_language != 'es': return "Lo siento, pero no puedo responder correctamente en español a esa pregunta." else: cleaned_response = clean_response(response) return cleaned_response except Exception as e: logging.error(f"Error al detectar el idioma: {e}") return "Hubo un error al procesar tu mensaje." except Exception as e: logging.error(f"Error al procesar el mensaje: {e}") return f"Hubo un error al procesar tu mensaje, revisa que sea un mensaje completo. {e}" def llm_function_with_timeout(message, chat_history, timeout=180): result = [None] # Lista para almacenar el resultado def target(): # Intentar adquirir el semáforo antes de ejecutar la función result[0] = llm_function(message, chat_history) thread = threading.Thread(target=target) thread.start() thread.join(timeout) if thread.is_alive(): # Si el thread todavía está vivo después del timeout, se asume que está bloqueado y se debe manejar thread.join() return "Tu pregunta no ha podido ser respondida en el tiempo estimado. Por favor, intenta de nuevo o reformula tu pregunta." return result[0] title = "ChatterIA" description = """ ChatterIA es un modelo de lenguaje que funciona como un asistente con infinidad de conocimientos, pero no infalible. Si desconoces el uso de este modelo, aquí tienes unas instrucciones para optimizar su uso: