Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,58 +1,190 @@
|
|
|
|
1 |
import gradio as gr
|
2 |
from ctransformers import AutoModelForCausalLM
|
3 |
import threading
|
4 |
from langdetect import detect, DetectorFactory
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
# Introducimos un mensaje para el modelo para que hable solo en español y con respeto
|
7 |
-
system_message =
|
8 |
|
|
|
|
|
|
|
|
|
|
|
9 |
def load_llm():
|
10 |
-
llm = AutoModelForCausalLM.from_pretrained(
|
11 |
-
"TheBloke/Llama-2-7B-Chat-GGUF",
|
12 |
-
model_file='llama-2-7b-chat.Q5_K_M.gguf',
|
13 |
-
model_type='llama',
|
14 |
-
max_new_tokens=2048,
|
15 |
-
context_length = 4096,
|
16 |
-
repetition_penalty=1.13,
|
17 |
-
temperature=0.1
|
18 |
-
)
|
19 |
-
return llm
|
20 |
|
21 |
-
|
22 |
-
llm = load_llm()
|
23 |
-
# Concatenar el mensaje del sistema con el mensaje del usuario
|
24 |
-
full_message = f"{system_message}\nUser: {message}\nAssistant:"
|
25 |
-
response = llm(full_message)
|
26 |
-
# Registrar el mensaje y la respuesta en el archivo de logs
|
27 |
-
logging.info(f"Message: {message}")
|
28 |
-
logging.info(f"Response: {response}")
|
29 |
-
|
30 |
-
# Verificar el idioma de la respuesta
|
31 |
-
try:
|
32 |
-
response_language = detect(response)
|
33 |
-
except:
|
34 |
-
response_language = "error"
|
35 |
|
36 |
-
if
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
else:
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
def target():
|
|
|
46 |
result[0] = llm_function(message, chat_history)
|
47 |
|
48 |
thread = threading.Thread(target=target)
|
49 |
thread.start()
|
50 |
thread.join(timeout)
|
51 |
if thread.is_alive():
|
|
|
52 |
thread.join()
|
53 |
return "Tu pregunta no ha podido ser respondida en el tiempo estimado. Por favor, intenta de nuevo o reformula tu pregunta."
|
54 |
return result[0]
|
55 |
|
|
|
56 |
title = "ChatterIA"
|
57 |
|
58 |
description = """
|
@@ -61,7 +193,7 @@ ChatterIA es un modelo de lenguaje que funciona como un asistente con infinidad
|
|
61 |
<li>Las respuestas de este modelo pueden no ser siempre precisas, al depender de su configuración, capacidad de interpretación y contextualización</li>
|
62 |
<li>Usa este modelo bajo tu responsabilidad.</li>
|
63 |
<li>Si no o obtienes respuesta a tu consulta, intenta volver a reformularla.</li>
|
64 |
-
<li>Si necesitas alguna aclaración o tienes cualquier otra duda, puedes enviar un correo electrónico a soporte: <a href='mailto:[email protected]'> Mandar email </a>. o revisar nuestras guías: <a href='http://fuentezuelas.com/playground/ChatterIA/index.php#guias'
|
65 |
<li>Es importante que sepas este sitio es de uso educativo. El envío de mensajes masivos puede dar error.</li>
|
66 |
</ul>
|
67 |
"""
|
@@ -70,10 +202,14 @@ theme = 'Taithrah/Minimal'
|
|
70 |
|
71 |
examples = [
|
72 |
'Escribe un código de python para conectarte con una base de datos en MySQL y liste todas las tablas.',
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
|
|
|
|
|
|
|
|
77 |
]
|
78 |
css = """
|
79 |
#component-0 {
|
@@ -155,8 +291,7 @@ footer{
|
|
155 |
}
|
156 |
}
|
157 |
"""
|
158 |
-
|
159 |
-
demo = gr.ChatInterface(
|
160 |
fn = llm_function_with_timeout,
|
161 |
chatbot=gr.Chatbot(label="ChatterIA"),
|
162 |
textbox= gr.Textbox(placeholder="Envía tu mensaje...", lines=3, max_lines=10),
|
@@ -164,11 +299,10 @@ demo = gr.ChatInterface(
|
|
164 |
description = description,
|
165 |
theme = theme,
|
166 |
examples = examples,
|
167 |
-
|
168 |
-
|
169 |
submit_btn = "📤 Enviar",
|
170 |
retry_btn = "🔁 Reenviar",
|
171 |
undo_btn = "🔙 Deshacer",
|
172 |
clear_btn= "🗑 Limpiar",
|
173 |
-
)
|
174 |
-
demo.launch()
|
|
|
1 |
+
import logging
|
2 |
import gradio as gr
|
3 |
from ctransformers import AutoModelForCausalLM
|
4 |
import threading
|
5 |
from langdetect import detect, DetectorFactory
|
6 |
+
from langid import classify
|
7 |
+
import spacy
|
8 |
+
import os
|
9 |
+
import psutil
|
10 |
+
import time
|
11 |
+
|
12 |
+
# Obtener el proceso actual
|
13 |
+
process = psutil.Process(os.getpid())
|
14 |
+
|
15 |
+
# Función para imprimir el uso de CPU y RAM
|
16 |
+
def print_resource_usage():
|
17 |
+
while True: # Crear un bucle infinito para que se ejecute continuamente
|
18 |
+
cpu_usage = process.cpu_percent(interval=1)
|
19 |
+
ram_usage = process.memory_info().rss / (1024 * 1024) # Convertir bytes a MB
|
20 |
+
pid = str(process.pid)
|
21 |
+
print(f"Uso de CPU: {cpu_usage}%")
|
22 |
+
print(f"Uso de RAM: {ram_usage} MB")
|
23 |
+
print(f"PID: {pid}")
|
24 |
+
time.sleep(10) # Esperar 2 segundos antes de la próxima impresión
|
25 |
+
|
26 |
+
# Crear y empezar un hilo para el monitoreo de recursos
|
27 |
+
monitoring_thread = threading.Thread(target=print_resource_usage)
|
28 |
+
monitoring_thread.daemon = True # Establecer como un daemon para que no bloquee el programa de terminar
|
29 |
+
monitoring_thread.start()
|
30 |
+
|
31 |
+
|
32 |
+
# Configuración del logger
|
33 |
+
logging.basicConfig(filename='chatterIA_logs.txt', level=logging.INFO,
|
34 |
+
format='%(asctime)s %(levelname)s:%(message)s')
|
35 |
+
|
36 |
+
DetectorFactory.seed = 0 # Para obtener resultados consistentes en la detección del idioma (outputs)
|
37 |
|
38 |
# Introducimos un mensaje para el modelo para que hable solo en español y con respeto
|
39 |
+
system_message ="Eres un asistente que siempre responde en español. A cualquiera de sus peticiones y nunca hablas en ningún otro idioma"
|
40 |
|
41 |
+
# Cargar el modelo una sola vez
|
42 |
+
model_instance = None
|
43 |
+
|
44 |
+
# Cargar el modelo que detecta el idioma de los mensajes solo 1 vez. (inputs)
|
45 |
+
nlp_sm = spacy.load("es_core_news_sm")
|
46 |
def load_llm():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
+
global model_instance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
+
if model_instance is None:
|
51 |
+
print("Cargando el modelo...")
|
52 |
+
model_instance = AutoModelForCausalLM.from_pretrained(
|
53 |
+
"TheBloke/Llama-2-7B-Chat-GGUF",
|
54 |
+
model_file='llama-2-7b-chat.Q5_K_M.gguf',
|
55 |
+
model_type='llama',
|
56 |
+
max_new_tokens=2048,
|
57 |
+
context_length = 4096,
|
58 |
+
repetition_penalty=1.13,
|
59 |
+
temperature=0.1
|
60 |
+
)
|
61 |
+
print("Modelo cargado éxitosamente")
|
62 |
else:
|
63 |
+
print("Ya se ha cargado el modelo anteriormente")
|
64 |
+
|
65 |
+
return model_instance
|
66 |
+
def truncate_history(history, max_tokens=2048):
|
67 |
+
truncated_history = []
|
68 |
+
total_tokens = 0
|
69 |
+
for user_msg, bot_msg in reversed(history):
|
70 |
+
# Asegurarse de que ni user_msg ni bot_msg sean None
|
71 |
+
user_msg = user_msg if user_msg is not None else ""
|
72 |
+
bot_msg = bot_msg if bot_msg is not None else ""
|
73 |
+
|
74 |
+
msg_tokens = len(user_msg.split()) + len(bot_msg.split())
|
75 |
+
if total_tokens + msg_tokens > max_tokens:
|
76 |
+
break
|
77 |
+
truncated_history.insert(0, (user_msg, bot_msg))
|
78 |
+
total_tokens += msg_tokens
|
79 |
+
return truncated_history
|
80 |
+
def clean_response(response):
|
81 |
+
code_block_count = response.count("```")
|
82 |
+
|
83 |
+
if code_block_count % 2 != 0:
|
84 |
+
last_occurrence_index = response.rfind("```")
|
85 |
+
response = response[:last_occurrence_index] + response[last_occurrence_index+3:]
|
86 |
+
|
87 |
+
return response
|
88 |
|
89 |
+
def format_history_for_model(history):
|
90 |
+
new_history = "\n".join(f"{user_msg}\n{bot_msg}".strip() for user_msg, bot_msg in history)
|
91 |
+
new_history += "\nRespuesta:"
|
92 |
+
return new_history
|
93 |
|
94 |
+
|
95 |
+
def detectar_idioma_con_spacy(texto):
|
96 |
+
doc = nlp_sm(texto, disable=["parser","ner"])
|
97 |
+
return True
|
98 |
+
|
99 |
+
def prepare_message(message):
|
100 |
+
# Primero, intenta detectar el idioma con langid
|
101 |
+
lang, confidence = classify(message)
|
102 |
+
if lang == 'es':
|
103 |
+
return str(message) # Si langid está seguro de que es español, retorna el mensaje
|
104 |
+
|
105 |
+
# Si el mensaje es muy corto y langid no lo clasifica definitivamente como español,
|
106 |
+
# utiliza SpaCy como una verificación adicional.
|
107 |
+
if len(message.split()) <= 3: # Considera ajustar este umbral según tus necesidades
|
108 |
+
es_espanol_spacy = detectar_idioma_con_spacy(message)
|
109 |
+
if es_espanol_spacy:
|
110 |
+
return str(message) # Si SpaCy procesa el texto sin problemas, asume que es español
|
111 |
+
|
112 |
+
# Si ninguna de las verificaciones anteriores concluye que el mensaje es en español, retorna None
|
113 |
+
return None
|
114 |
+
|
115 |
+
def llm_function(message, chat_history ):
|
116 |
+
try:
|
117 |
+
print(f"Mensaje principal:{message}")
|
118 |
+
logging.info(f"Tipo de Message: {type(message)}, Message: {message}")
|
119 |
+
message = str(message)
|
120 |
+
message_str = str(message)
|
121 |
+
|
122 |
+
# Aquí puedes añadir cualquier validación adicional del mensaje
|
123 |
+
if not message_str.strip():
|
124 |
+
logging.info("El mensaje está vacío o solo contiene espacios.")
|
125 |
+
return "Por favor, envía un mensaje no vacío.", chat_history
|
126 |
+
|
127 |
+
# Continuar con el procesamiento...
|
128 |
+
logging.info(f"Message: {message_str}")
|
129 |
+
|
130 |
+
print(f"Historial del Chat (segun el chatbot)")
|
131 |
+
for i in chat_history:
|
132 |
+
print (i)
|
133 |
+
print("Fin de variables desde el chat")
|
134 |
+
|
135 |
+
llm = load_llm()
|
136 |
+
message = prepare_message(message)
|
137 |
+
|
138 |
+
if message is None:
|
139 |
+
return f"Por favor, envía tu mensaje en español. Actualmente idioma es: {detect(message)}"
|
140 |
+
chat_history = truncate_history(chat_history + [(message, "")]) # Añadir el mensaje actual al historial
|
141 |
+
|
142 |
+
print("Historial del chat antes de formateo")
|
143 |
+
for i in chat_history:
|
144 |
+
print (i)
|
145 |
+
print("Fin de historial previo a formateo")
|
146 |
+
formatted_history = format_history_for_model(chat_history) # Formatear el historial para el modelo
|
147 |
+
|
148 |
+
full_message = f"{system_message}\n{formatted_history}"
|
149 |
+
print (f"Mensaje completo: {full_message}")
|
150 |
+
response = llm(full_message) # Generar respuesta
|
151 |
+
cleaned_response = clean_response(response)
|
152 |
+
|
153 |
+
logging.info(f"Message: {message}")
|
154 |
+
logging.info(f"Response: {response}")
|
155 |
+
|
156 |
+
try:
|
157 |
+
response_language = detect(response)
|
158 |
+
print(f"Idioma en response_language: {response_language}")
|
159 |
+
print(f"Response:{response}")
|
160 |
+
if response_language != 'es':
|
161 |
+
return "Lo siento, pero no puedo responder correctamente en español a esa pregunta."
|
162 |
+
else:
|
163 |
+
cleaned_response = clean_response(response)
|
164 |
+
return cleaned_response
|
165 |
+
except Exception as e:
|
166 |
+
logging.error(f"Error al detectar el idioma: {e}")
|
167 |
+
return "Hubo un error al procesar tu mensaje."
|
168 |
+
except Exception as e:
|
169 |
+
logging.error(f"Error al procesar el mensaje: {e}")
|
170 |
+
return "Hubo un error al procesar tu mensaje, revisa que sea un mensaje completo."
|
171 |
+
|
172 |
+
def llm_function_with_timeout(message, chat_history, timeout=180):
|
173 |
+
result = [None] # Lista para almacenar el resultado
|
174 |
def target():
|
175 |
+
# Intentar adquirir el semáforo antes de ejecutar la función
|
176 |
result[0] = llm_function(message, chat_history)
|
177 |
|
178 |
thread = threading.Thread(target=target)
|
179 |
thread.start()
|
180 |
thread.join(timeout)
|
181 |
if thread.is_alive():
|
182 |
+
# Si el thread todavía está vivo después del timeout, se asume que está bloqueado y se debe manejar
|
183 |
thread.join()
|
184 |
return "Tu pregunta no ha podido ser respondida en el tiempo estimado. Por favor, intenta de nuevo o reformula tu pregunta."
|
185 |
return result[0]
|
186 |
|
187 |
+
|
188 |
title = "ChatterIA"
|
189 |
|
190 |
description = """
|
|
|
193 |
<li>Las respuestas de este modelo pueden no ser siempre precisas, al depender de su configuración, capacidad de interpretación y contextualización</li>
|
194 |
<li>Usa este modelo bajo tu responsabilidad.</li>
|
195 |
<li>Si no o obtienes respuesta a tu consulta, intenta volver a reformularla.</li>
|
196 |
+
<li>Si necesitas alguna aclaración o tienes cualquier otra duda, puedes enviar un correo electrónico a soporte: <a href='mailto:[email protected]'> Mandar email </a>. o revisar nuestras guías: <a href='http://fuentezuelas.com/ia/playground/ChatterIA/index.php#guias'> Acceder a guías </a></li>
|
197 |
<li>Es importante que sepas este sitio es de uso educativo. El envío de mensajes masivos puede dar error.</li>
|
198 |
</ul>
|
199 |
"""
|
|
|
202 |
|
203 |
examples = [
|
204 |
'Escribe un código de python para conectarte con una base de datos en MySQL y liste todas las tablas.',
|
205 |
+
'Escribe un poema sobre el otoño con rima consonante y en forma de soneto.',
|
206 |
+
'Resume el argumento de "El Quijote", y explícaselo a un niño de 5 años para que le interese.',
|
207 |
+
'Dime como fusionar dos diccionarios en Python y diferentes usos que puede tener esto.',
|
208 |
+
'Dime que debo considerar al comprar un coche usado y que me recomiendas saber al respecto.',
|
209 |
+
'Explica la teoría de la relatividad de Einstein para estudiantes de primaria.',
|
210 |
+
'Dime cuáles podrían ser las implicaciones de la inteligencia artificial en el empleo.',
|
211 |
+
'Redacta un correo para mi jefe en el cual, quiero pedirle un aumento de salario.',
|
212 |
+
'Escribe una cancion que dure aproximadamente 2 minutos y que trate sobre la desigualdad en España.'
|
213 |
]
|
214 |
css = """
|
215 |
#component-0 {
|
|
|
291 |
}
|
292 |
}
|
293 |
"""
|
294 |
+
demo= gr.ChatInterface(
|
|
|
295 |
fn = llm_function_with_timeout,
|
296 |
chatbot=gr.Chatbot(label="ChatterIA"),
|
297 |
textbox= gr.Textbox(placeholder="Envía tu mensaje...", lines=3, max_lines=10),
|
|
|
299 |
description = description,
|
300 |
theme = theme,
|
301 |
examples = examples,
|
302 |
+
css = css,
|
303 |
+
cache_examples=False,
|
304 |
submit_btn = "📤 Enviar",
|
305 |
retry_btn = "🔁 Reenviar",
|
306 |
undo_btn = "🔙 Deshacer",
|
307 |
clear_btn= "🗑 Limpiar",
|
308 |
+
).launch()
|
|