User51925 commited on
Commit
02c5c9e
·
verified ·
1 Parent(s): f94e353

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -229
app.py CHANGED
@@ -1,244 +1,112 @@
1
- # chatbot_tema.py
2
- # Chatbot por tema específico + vocabulario limitado a 1000 palabras.
3
-
4
- import os
 
 
 
 
5
  import re
6
  import random
7
- from collections import Counter
8
 
9
- # =========================
10
- # CONFIG
11
- # =========================
12
- TOPICO = "entrenamiento en el gimnasio" # <— Cambiá el tema acá
13
- PALABRAS_CLAVE = {
14
- # Palabras que identifican el tema. Agregá o quitá según tu caso.
15
- "gimnasio","entrenar","rutina","pesas","mancuernas","series","repeticiones",
16
- "calentamiento","piernas","pecho","espalda","hombros","biceps","triceps",
17
- "cardio","fuerza","hipertrofia","descanso","nutricion","proteina","creatina",
18
- "tecnica","maquina","sentadilla","press","remar","dominadas","plan","progreso"
 
 
 
 
 
 
 
19
  }
20
- ARCHIVO_VOCAB = "vocab.txt"
21
- TAMANIO_VOCAB = 1000
22
-
23
- # Mensaje de rechazo cuando está fuera de tema
24
- MENSAJE_FUERA_DE_TEMA = (
25
- "lo siento. solo puedo hablar sobre " + TOPICO + ". "
26
- "por favor hacé una pregunta relacionada."
27
- )
28
 
29
- # =========================
30
- # UTILIDADES
31
- # =========================
32
- def normalizar(texto: str) -> str:
33
- texto = texto.lower()
34
- texto = re.sub(r"[^\wáéíóúñü ]", " ", texto, flags=re.UNICODE)
35
- texto = re.sub(r"\s+", " ", texto).strip()
36
- return texto
37
-
38
- def cargar_o_crear_vocab(ruta: str, objetivo: int) -> list:
39
  """
40
- - Si existe vocab.txt: lo carga y valida tamaño.
41
- - Si no existe: crea una lista de palabras base + tokens de relleno hasta llegar a 1000
42
- y la guarda en el archivo para que la puedas editar.
43
  """
44
- if os.path.exists(ruta):
45
- with open(ruta, "r", encoding="utf-8") as f:
46
- palabras = [normalizar(l) for l in f if l.strip()]
47
- # Quitar duplicados respetando orden
48
- seen = set()
49
- vocab = []
50
- for p in palabras:
51
- if p not in seen:
52
- seen.add(p)
53
- vocab.append(p)
54
- # Ajustar a tamaño deseado (recortar o avisar)
55
- if len(vocab) > objetivo:
56
- vocab = vocab[:objetivo]
57
- elif len(vocab) < objetivo:
58
- faltan = objetivo - len(vocab)
59
- # Relleno controlado
60
- inicio = len(vocab) + 1
61
- for i in range(inicio, inicio + faltan):
62
- vocab.append(f"token{i:03d}")
63
- return vocab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  else:
65
- base = set("""
66
- yo tu vos usted ustedes nosotros hola chau gracias por favor si no tal vez
67
- puedo podes podesme decir contar explicar como cuando donde cual porque para
68
- hoy ayer manana semana mes anio ahora antes despues poco mucho bien mal mas
69
- menos igual tema topico relacionado ejemplo paso guia idea ayuda duda
70
- pregunta respuesta claro listo simple rapido seguro lento suave duro facil dificil
71
- cuerpo espalda pecho hombro pierna brazo biceps triceps abdomen gluteo
72
- calentar descanso energia fuerza peso repetir serie rutina plan objetivo
73
- progreso tecnica forma postura respiracion dolor cuidado prevenir riesgo
74
- maquina banco barra mancuerna polea cuerda banda remo press sentadilla
75
- dominada elevacion curl extension cardio cinta bici remadora
76
- tiempo minuto segundo intervalo dia
77
- nutricion comida proteina carbohidrato grasa agua creatina suplemento
78
- tomar comer cocinar batido leche avena huevo arroz pollo carne banana
79
- antes durante despues entrenar
80
- """.split())
81
- # Asegurar que las plantillas puedan hablar
82
- base.update({
83
- "hola","bienvenido","estoy","listo","para","ayudar","sobre","entrenamiento",
84
- "en","el","gimnasio","es","importante","usar","buena","tecnica","y","progresar",
85
- "de","a","poco","si","sos","principiante","empeza","con","poco","peso","y",
86
- "aumenta","cuando","la","forma","sea","solida","queres","rutina","para","hoy",
87
- "tenes","alguna","meta","fuerza","o","hipertrofia","recorda","descansar",
88
- "entre","series","y","dormir","bien"
89
- })
90
- base = [normalizar(w) for w in base if w.strip()]
91
- # Completar hasta objetivo
92
- vocab = []
93
- seen = set()
94
- for w in base:
95
- if w not in seen:
96
- seen.add(w)
97
- vocab.append(w)
98
- i = 1
99
- while len(vocab) < objetivo:
100
- token = f"token{i:03d}"
101
- if token not in seen:
102
- seen.add(token)
103
- vocab.append(token)
104
- i += 1
105
- # Guardar para que puedas editarlo
106
- with open(ruta, "w", encoding="utf-8") as f:
107
- f.write("\n".join(vocab))
108
- return vocab
109
-
110
- def es_en_tema(texto_usuario: str, palabras_clave: set) -> bool:
111
- tu = set(normalizar(texto_usuario).split())
112
- # Coincidencia si hay intersección con palabras clave o con el nombre del tópico
113
- if tu & palabras_clave:
114
- return True
115
- for w in normalizar(TOPICO).split():
116
- if w in tu:
117
- return True
118
- return False
119
-
120
- def limitar_a_vocab(texto: str, vocab_set: set) -> str:
121
- """
122
- Asegura que la salida solo use palabras del vocabulario.
123
- Palabras fuera del vocabulario se sustituyen por 'token001'.
124
- """
125
- palabras = normalizar(texto).split()
126
- out = []
127
- sustituto = "token001" if "token001" in vocab_set else next(iter(vocab_set))
128
- for p in palabras:
129
- out.append(p if p in vocab_set else sustituto)
130
- return " ".join(out)
131
-
132
- # =========================
133
- # NUCLEO DE RESPUESTAS
134
- # =========================
135
- def detectar_intencion(texto_usuario: str) -> str:
136
- t = normalizar(texto_usuario)
137
- if any(x in t for x in ["hola","buenas","que tal","buen dia","buenas tardes","buenas noches"]):
138
- return "saludo"
139
- if any(x in t for x in ["rutina","plan","programa","entreno","entrenar","hoy que hago"]):
140
- return "rutina"
141
- if any(x in t for x in ["pecho","espalda","pierna","hombro","biceps","triceps","abdomen","core"]):
142
- return "musculo"
143
- if any(x in t for x in ["tecnica","forma","postura","como hago","como se hace"]):
144
- return "tecnica"
145
- if any(x in t for x in ["nutricion","comer","proteina","creatina","batido","dieta","comida"]):
146
- return "nutricion"
147
- if any(x in t for x in ["descanso","series","repeticiones","cuanto","cuantas","minutos","intervalo"]):
148
- return "parametros"
149
- if any(x in t for x in ["chau","adios","gracias","nos vemos","hasta luego"]):
150
- return "despedida"
151
- return "desconocida"
152
-
153
- def generar_respuesta_en_tema(intencion: str) -> str:
154
- # Plantillas sencillas y cortas; todas en vocabulario básico
155
- if intencion == "saludo":
156
- return (
157
- "hola. estoy listo para ayudar sobre entrenamiento en el gimnasio. "
158
- "queres una rutina para hoy o una guia por objetivo."
159
- )
160
- if intencion == "rutina":
161
- return (
162
- "rutina base: cuerpo completo. hacé tres series por ejercicio y ocho a doce repeticiones. "
163
- "ejemplo: sentadilla, press pecho, remo, elevacion hombro, curl biceps, extension triceps, plancha. "
164
- "descanso uno a dos minutos entre series."
165
- )
166
- if intencion == "musculo":
167
- return (
168
- "para ese musculo, usa uno a tres ejercicios con tecnica solida. "
169
- "progresá poco a poco y evita dolor raro. "
170
- "si la forma falla, baja el peso y repetí."
171
- )
172
- if intencion == "tecnica":
173
- return (
174
- "usa postura neutral, abdomen activo y movimiento controlado. "
175
- "sin rebote y con rango que puedas sostener sin dolor. "
176
- "respira: baja tomando aire y sube soltando."
177
- )
178
- if intencion == "nutricion":
179
- return (
180
- "nutricion simple: prioriza proteina en cada comida, hidrata con agua y dormi bien. "
181
- "si usas creatina: cinco gramos al dia con comida. "
182
- "no es magia, es constancia."
183
- )
184
- if intencion == "parametros":
185
- return (
186
- "series: dos a cuatro por ejercicio. repeticiones: seis a doce para hipertrofia. "
187
- "descanso: uno a tres minutos segun esfuerzo. "
188
- "progreso: subí poco el peso cuando la tecnica sea solida."
189
- )
190
- if intencion == "despedida":
191
- return "gracias por charlar. buen entrenamiento y buen descanso."
192
- # desconocida en tema
193
- return (
194
- "puedo hablar sobre rutina, tecnica, nutricion, series y progresion en el gimnasio. "
195
- "decime que queres y armamos algo simple."
196
  )
197
 
198
- # =========================
199
- # LOOP PRINCIPAL
200
- # =========================
201
- def main():
202
- vocab = cargar_o_crear_vocab(ARCHIVO_VOCAB, TAMANIO_VOCAB)
203
- vocab_set = set(vocab)
204
-
205
- print("chatbot:", limitar_a_vocab(
206
- f"hola. soy un asistente sobre {TOPICO}. usa mensajes simples. escribi 'salir' para terminar.",
207
- vocab_set
208
- ))
209
-
210
- while True:
211
- try:
212
- user = input("vos: ")
213
- except (EOFError, KeyboardInterrupt):
214
- print("\nchatbot: chau.")
215
- break
216
-
217
- if not user:
218
- continue
219
 
220
- if normalizar(user) == "salir":
221
- print("chatbot:", limitar_a_vocab("chau. hasta luego.", vocab_set))
222
- break
223
-
224
- # Verificar tema
225
- if not es_en_tema(user, PALABRAS_CLAVE):
226
- print("chatbot:", limitar_a_vocab(MENSAJE_FUERA_DE_TEMA, vocab_set))
227
- continue
228
-
229
- # Generar respuesta en tema y limitar a vocab
230
- intent = detectar_intencion(user)
231
- respuesta = generar_respuesta_en_tema(intent)
232
- respuesta_limited = limitar_a_vocab(respuesta, vocab_set)
233
 
234
- # Asegurar que no quede vacía
235
- if not respuesta_limited.strip():
236
- respuesta_limited = limitar_a_vocab(
237
- "lo siento. no tengo una respuesta. podes repetir con otras palabras.",
238
- vocab_set
239
- )
240
 
241
- print("chatbot:", respuesta_limited)
 
242
 
 
243
  if __name__ == "__main__":
244
- main()
 
1
+ # chatbot_fitness_avanzado.py
2
+ # ------------------------------------------------------------
3
+ # Chatbot asistente personal de fitness y musculación
4
+ # Detecta información de textos largos y naturales
5
+ # Todo en español
6
+ # ------------------------------------------------------------
7
+
8
+ import gradio as gr
9
  import re
10
  import random
 
11
 
12
+ # Diccionario de respuestas generales
13
+ respuestas_generales = {
14
+ "ganar_masa": [
15
+ "Para ganar masa muscular, es importante entrenar con fuerza, enfocándote en ejercicios compuestos como sentadillas, press de banca y peso muerto. ",
16
+ "Consumí suficientes proteínas y un superávit calórico moderado. Comer cada 3-4 horas ayuda a mantener el músculo nutrido.",
17
+ "No olvides descansar lo suficiente, ya que el crecimiento muscular ocurre principalmente durante la recuperación."
18
+ ],
19
+ "perder_grasa": [
20
+ "Para perder grasa, combina entrenamiento de fuerza con algo de cardio y un déficit calórico moderado.",
21
+ "Prioriza proteínas magras y vegetales, controlando las porciones y evitando ultraprocesados.",
22
+ "Dormí bien, la recuperación y el descanso son esenciales para mantener el metabolismo activo."
23
+ ],
24
+ "general": [
25
+ "Recuerda siempre calentar antes de entrenar y estirar al finalizar para evitar lesiones.",
26
+ "La paciencia y la consistencia son claves: los resultados llegan con el tiempo.",
27
+ "Escucha a tu cuerpo: si sentís dolor intenso, detente y descansá."
28
+ ]
29
  }
 
 
 
 
 
 
 
 
30
 
31
+ # Función para extraer datos del texto
32
+ def extraer_datos(texto, usuario):
 
 
 
 
 
 
 
 
33
  """
34
+ Extrae edad, peso, altura y experiencia de un texto largo en español.
35
+ Guarda los datos en el diccionario usuario.
 
36
  """
37
+ # Edad
38
+ edad_match = re.search(r'(\d{1,2})\s*(años|años de edad)?', texto)
39
+ if edad_match:
40
+ usuario["edad"] = int(edad_match.group(1))
41
+ # Peso en kg
42
+ peso_match = re.search(r'(\d{2,3})\s*(kg|kilos|kilogramos)', texto)
43
+ if peso_match:
44
+ usuario["peso"] = int(peso_match.group(1))
45
+ # Altura en cm o metros
46
+ altura_match_cm = re.search(r'(\d{2,3})\s*(cm|centímetros)', texto)
47
+ altura_match_m = re.search(r'(\d\.\d{1,2})\s*m', texto)
48
+ if altura_match_cm:
49
+ usuario["altura"] = int(altura_match_cm.group(1))
50
+ elif altura_match_m:
51
+ usuario["altura"] = int(float(altura_match_m.group(1))*100)
52
+ # Nivel de experiencia aproximado
53
+ if "principiante" in texto.lower():
54
+ usuario["nivel"] = "principiante"
55
+ elif "intermedio" in texto.lower() or "medio" in texto.lower():
56
+ usuario["nivel"] = "intermedio"
57
+ elif "avanzado" in texto.lower() or "experiencia" in texto.lower():
58
+ usuario["nivel"] = "avanzado"
59
+ return usuario
60
+
61
+ # Función principal del chatbot
62
+ def chatbot_fitness_avanzado(input_text, historial, usuario):
63
+ texto = input_text.lower()
64
+ usuario = extraer_datos(texto, usuario)
65
+
66
+ # Verificar si hay datos mínimos para personalizar
67
+ if not usuario.get("peso") or not usuario.get("altura") or not usuario.get("nivel") or not usuario.get("edad"):
68
+ return historial + [[input_text, "Gracias por la información. Para darte recomendaciones más precisas, contame también tu peso, altura, nivel de experiencia y objetivo."]], usuario
69
+
70
+ # Detectar intención básica según palabras o frases
71
+ if any(palabra in texto for palabra in ["ganar masa", "subir peso", "hipertrofia", "aumentar músculo"]):
72
+ tema = "ganar_masa"
73
+ elif any(palabra in texto for palabra in ["bajar grasa", "perder peso", "definir", "adelgazar"]):
74
+ tema = "perder_grasa"
75
+ elif any(palabra in texto for palabra in ["rutina", "entrenamiento", "ejercicio", "pesas"]):
76
+ tema = "general"
77
  else:
78
+ return historial + [[input_text, "Lo siento, solo puedo responder preguntas relacionadas con entrenamiento, nutrición y ejercicio."]], usuario
79
+
80
+ # Construir respuesta adaptada al usuario
81
+ resp_base = random.choice(respuestas_generales[tema])
82
+ resp_personalizada = (
83
+ f"{resp_base}\n\nTu información actual: "
84
+ f"Edad {usuario.get('edad','?')} años, Peso {usuario.get('peso','?')} kg, "
85
+ f"Altura {usuario.get('altura','?')} cm, Nivel {usuario.get('nivel','?')}.\n"
86
+ "Si querés, contame más detalles de tus hábitos y rutinas para recomendaciones más precisas."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  )
88
 
89
+ historial.append([input_text, resp_personalizada])
90
+ return historial, usuario
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ # Interfaz de Gradio
93
+ with gr.Blocks() as demo:
94
+ gr.Markdown("# 💪 Asistente Personal de Musculación")
95
+ gr.Markdown(
96
+ "Hola, soy tu asistente de IA de musculación. Contame tu situación y te daré consejos personalizados "
97
+ "sobre entrenamiento, nutrición y descanso. Podés escribir como si me contaras toda tu experiencia y datos físicos."
98
+ )
99
+
100
+ chatbot = gr.Chatbot()
101
+ historial = gr.State([])
102
+ usuario = gr.State({})
 
 
103
 
104
+ mensaje = gr.Textbox(label="Escribí tu situación aquí", placeholder="Ej: Hace 2 años que entreno, peso 90 kg, mido 1,80, quiero ganar masa...")
105
+ enviar_mensaje = gr.Button("Enviar")
 
 
 
 
106
 
107
+ # Enviar pregunta al chatbot
108
+ enviar_mensaje.click(fn=chatbot_fitness_avanzado, inputs=[mensaje, historial, usuario], outputs=[chatbot, usuario])
109
 
110
+ # Ejecutar la aplicación
111
  if __name__ == "__main__":
112
+ demo.launch()