Musculacion / app.py
User51925's picture
Update app.py
c6aeefd verified
# chatbot_tema.py
# Chatbot por tema específico + vocabulario limitado a 1000 palabras.
import os
import re
import random
from collections import Counter
# =========================
# CONFIG
# =========================
TOPICO = "entrenamiento en el gimnasio" # <— Cambiá el tema acá
PALABRAS_CLAVE = {
# Palabras que identifican el tema. Agregá o quitá según tu caso.
"gimnasio","entrenar","rutina","pesas","mancuernas","series","repeticiones",
"calentamiento","piernas","pecho","espalda","hombros","biceps","triceps",
"cardio","fuerza","hipertrofia","descanso","nutricion","proteina","creatina",
"tecnica","maquina","sentadilla","press","remar","dominadas","plan","progreso"
}
ARCHIVO_VOCAB = "vocab.txt"
TAMANIO_VOCAB = 1000
# Mensaje de rechazo cuando está fuera de tema
MENSAJE_FUERA_DE_TEMA = (
"lo siento. solo puedo hablar sobre " + TOPICO + ". "
"por favor hacé una pregunta relacionada."
)
# =========================
# UTILIDADES
# =========================
def normalizar(texto: str) -> str:
texto = texto.lower()
texto = re.sub(r"[^\wáéíóúñü ]", " ", texto, flags=re.UNICODE)
texto = re.sub(r"\s+", " ", texto).strip()
return texto
def cargar_o_crear_vocab(ruta: str, objetivo: int) -> list:
"""
- Si existe vocab.txt: lo carga y valida tamaño.
- Si no existe: crea una lista de palabras base + tokens de relleno hasta llegar a 1000
y la guarda en el archivo para que la puedas editar.
"""
if os.path.exists(ruta):
with open(ruta, "r", encoding="utf-8") as f:
palabras = [normalizar(l) for l in f if l.strip()]
# Quitar duplicados respetando orden
seen = set()
vocab = []
for p in palabras:
if p not in seen:
seen.add(p)
vocab.append(p)
# Ajustar a tamaño deseado (recortar o avisar)
if len(vocab) > objetivo:
vocab = vocab[:objetivo]
elif len(vocab) < objetivo:
faltan = objetivo - len(vocab)
# Relleno controlado
inicio = len(vocab) + 1
for i in range(inicio, inicio + faltan):
vocab.append(f"token{i:03d}")
return vocab
else:
base = set("""
yo tu vos usted ustedes nosotros hola chau gracias por favor si no tal vez
puedo podes podesme decir contar explicar como cuando donde cual porque para
hoy ayer manana semana mes anio ahora antes despues poco mucho bien mal mas
menos igual tema topico relacionado ejemplo paso guia idea ayuda duda
pregunta respuesta claro listo simple rapido seguro lento suave duro facil dificil
cuerpo espalda pecho hombro pierna brazo biceps triceps abdomen gluteo
calentar descanso energia fuerza peso repetir serie rutina plan objetivo
progreso tecnica forma postura respiracion dolor cuidado prevenir riesgo
maquina banco barra mancuerna polea cuerda banda remo press sentadilla
dominada elevacion curl extension cardio cinta bici remadora
tiempo minuto segundo intervalo dia
nutricion comida proteina carbohidrato grasa agua creatina suplemento
tomar comer cocinar batido leche avena huevo arroz pollo carne banana
antes durante despues entrenar
""".split())
# Asegurar que las plantillas puedan hablar
base.update({
"hola","bienvenido","estoy","listo","para","ayudar","sobre","entrenamiento",
"en","el","gimnasio","es","importante","usar","buena","tecnica","y","progresar",
"de","a","poco","si","sos","principiante","empeza","con","poco","peso","y",
"aumenta","cuando","la","forma","sea","solida","queres","rutina","para","hoy",
"tenes","alguna","meta","fuerza","o","hipertrofia","recorda","descansar",
"entre","series","y","dormir","bien"
})
base = [normalizar(w) for w in base if w.strip()]
# Completar hasta objetivo
vocab = []
seen = set()
for w in base:
if w not in seen:
seen.add(w)
vocab.append(w)
i = 1
while len(vocab) < objetivo:
token = f"token{i:03d}"
if token not in seen:
seen.add(token)
vocab.append(token)
i += 1
# Guardar para que puedas editarlo
with open(ruta, "w", encoding="utf-8") as f:
f.write("\n".join(vocab))
return vocab
def es_en_tema(texto_usuario: str, palabras_clave: set) -> bool:
tu = set(normalizar(texto_usuario).split())
# Coincidencia si hay intersección con palabras clave o con el nombre del tópico
if tu & palabras_clave:
return True
for w in normalizar(TOPICO).split():
if w in tu:
return True
return False
def limitar_a_vocab(texto: str, vocab_set: set) -> str:
"""
Asegura que la salida solo use palabras del vocabulario.
Palabras fuera del vocabulario se sustituyen por 'token001'.
"""
palabras = normalizar(texto).split()
out = []
sustituto = "token001" if "token001" in vocab_set else next(iter(vocab_set))
for p in palabras:
out.append(p if p in vocab_set else sustituto)
return " ".join(out)
# =========================
# NUCLEO DE RESPUESTAS
# =========================
def detectar_intencion(texto_usuario: str) -> str:
t = normalizar(texto_usuario)
if any(x in t for x in ["hola","buenas","que tal","buen dia","buenas tardes","buenas noches"]):
return "saludo"
if any(x in t for x in ["rutina","plan","programa","entreno","entrenar","hoy que hago"]):
return "rutina"
if any(x in t for x in ["pecho","espalda","pierna","hombro","biceps","triceps","abdomen","core"]):
return "musculo"
if any(x in t for x in ["tecnica","forma","postura","como hago","como se hace"]):
return "tecnica"
if any(x in t for x in ["nutricion","comer","proteina","creatina","batido","dieta","comida"]):
return "nutricion"
if any(x in t for x in ["descanso","series","repeticiones","cuanto","cuantas","minutos","intervalo"]):
return "parametros"
if any(x in t for x in ["chau","adios","gracias","nos vemos","hasta luego"]):
return "despedida"
return "desconocida"
def generar_respuesta_en_tema(intencion: str) -> str:
# Plantillas sencillas y cortas; todas en vocabulario básico
if intencion == "saludo":
return (
"hola. estoy listo para ayudar sobre entrenamiento en el gimnasio. "
"queres una rutina para hoy o una guia por objetivo."
)
if intencion == "rutina":
return (
"rutina base: cuerpo completo. hacé tres series por ejercicio y ocho a doce repeticiones. "
"ejemplo: sentadilla, press pecho, remo, elevacion hombro, curl biceps, extension triceps, plancha. "
"descanso uno a dos minutos entre series."
)
if intencion == "musculo":
return (
"para ese musculo, usa uno a tres ejercicios con tecnica solida. "
"progresá poco a poco y evita dolor raro. "
"si la forma falla, baja el peso y repetí."
)
if intencion == "tecnica":
return (
"usa postura neutral, abdomen activo y movimiento controlado. "
"sin rebote y con rango que puedas sostener sin dolor. "
"respira: baja tomando aire y sube soltando."
)
if intencion == "nutricion":
return (
"nutricion simple: prioriza proteina en cada comida, hidrata con agua y dormi bien. "
"si usas creatina: cinco gramos al dia con comida. "
"no es magia, es constancia."
)
if intencion == "parametros":
return (
"series: dos a cuatro por ejercicio. repeticiones: seis a doce para hipertrofia. "
"descanso: uno a tres minutos segun esfuerzo. "
"progreso: subí poco el peso cuando la tecnica sea solida."
)
if intencion == "despedida":
return "gracias por charlar. buen entrenamiento y buen descanso."
# desconocida en tema
return (
"puedo hablar sobre rutina, tecnica, nutricion, series y progresion en el gimnasio. "
"decime que queres y armamos algo simple."
)
# =========================
# LOOP PRINCIPAL
# =========================
def main():
vocab = cargar_o_crear_vocab(ARCHIVO_VOCAB, TAMANIO_VOCAB)
vocab_set = set(vocab)
print("chatbot:", limitar_a_vocab(
f"hola. soy un asistente sobre {TOPICO}. usa mensajes simples. escribi 'salir' para terminar.",
vocab_set
))
while True:
try:
user = input("vos: ")
except (EOFError, KeyboardInterrupt):
print("\nchatbot: chau.")
break
if not user:
continue
if normalizar(user) == "salir":
print("chatbot:", limitar_a_vocab("chau. hasta luego.", vocab_set))
break
# Verificar tema
if not es_en_tema(user, PALABRAS_CLAVE):
print("chatbot:", limitar_a_vocab(MENSAJE_FUERA_DE_TEMA, vocab_set))
continue
# Generar respuesta en tema y limitar a vocab
intent = detectar_intencion(user)
respuesta = generar_respuesta_en_tema(intent)
respuesta_limited = limitar_a_vocab(respuesta, vocab_set)
# Asegurar que no quede vacía
if not respuesta_limited.strip():
respuesta_limited = limitar_a_vocab(
"lo siento. no tengo una respuesta. podes repetir con otras palabras.",
vocab_set
)
print("chatbot:", respuesta_limited)
if __name__ == "__main__":
main()
import gradio as gr
iface = gr.Interface(fn=chat, inputs="text", outputs="text")
iface.launch()