Cal-AI / app.py
Adanbalf's picture
Update app.py
a56b134 verified
raw
history blame
5.07 kB
import gradio as gr
import torch
from transformers import AutoProcessor, AutoModelForVision2Seq
from PIL import Image
import re
from io import BytesIO
# ============================================
# 🔮 CONFIGURACIÓN DEL MODELO
# ============================================
MODEL_ID = "lmms-lab/llava-onevision-1.5-8b-instruct"
print("⏳ Cargando modelo local con trust_remote_code=True...")
processor = AutoProcessor.from_pretrained(MODEL_ID, trust_remote_code=True)
model = AutoModelForVision2Seq.from_pretrained(
MODEL_ID,
trust_remote_code=True,
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
device_map="auto"
)
print("✅ Modelo cargado correctamente en modo local.")
# ============================================
# 🧠 FUNCIONES DE ANÁLISIS
# ============================================
def extract_macros(text):
"""Extrae proteínas, carbohidratos y grasas del texto generado."""
def find_value(keyword):
m = re.search(rf"{keyword}[^0-9]*([0-9]+)", text.lower())
return int(m.group(1)) if m else 0
p, c, f = find_value("prote"), find_value("carb"), find_value("gras")
kcal = p * 4 + c * 4 + f * 9 if any([p, c, f]) else 0
return {"protein": p, "carbs": c, "fat": f, "kcal": kcal}
def build_macro_card(macros):
"""Genera el HTML visual con barras de progreso tipo dashboard."""
if not any(macros.values()):
return "<div class='card'>⚖️ No se pudieron estimar los macros.</div>"
def bar_html(value, color):
width = min(value, 100)
return f"""
<div class='bar-bg'>
<div class='bar-fill' style='width:{width}%; background:{color};'></div>
</div>
"""
return f"""
<div class='card'>
<h2>🍽️ Estimación Nutricional</h2>
<div class='macro'><span>💪 Proteínas</span><span>{macros['protein']} g</span></div>
{bar_html(macros['protein'], '#b25eff')}
<div class='macro'><span>🥔 Carbohidratos</span><span>{macros['carbs']} g</span></div>
{bar_html(macros['carbs'], '#00f0ff')}
<div class='macro'><span>🥑 Grasas</span><span>{macros['fat']} g</span></div>
{bar_html(macros['fat'], '#ff5efb')}
<div class='macro kcal'><span>🔥 Calorías Totales</span><span>{macros['kcal']} kcal</span></div>
</div>
"""
def analyze_food(image, text_prompt="Describe esta comida y estima sus calorías, proteínas, carbohidratos y grasas."):
"""Procesa la imagen localmente con el modelo y devuelve descripción + macros."""
try:
inputs = processor(text=text_prompt, images=image, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=400)
answer = processor.decode(out[0], skip_special_tokens=True)
macros = extract_macros(answer)
card = build_macro_card(macros)
return f"<div class='desc'>{answer}</div>{card}"
except Exception as e:
return f"<div class='card error'>⚠️ Error: {e}</div>"
# ============================================
# 💅 INTERFAZ DE USUARIO (Glass Neon)
# ============================================
def build_interface():
with gr.Blocks(css="""
/* --- DARK NEON THEME --- */
body {
background: radial-gradient(circle at 20% 20%, #0d001f, #000);
color: #fff;
font-family: 'Inter', sans-serif;
}
.gradio-container {background: transparent !important;}
.card {
backdrop-filter: blur(12px);
background: rgba(30, 0, 60, 0.3);
border: 1px solid rgba(200, 100, 255, 0.2);
border-radius: 16px;
padding: 1.2em;
margin-top: 1em;
box-shadow: 0 0 25px rgba(180, 0, 255, 0.15);
}
h1,h2 {color:#c18fff;}
.bar-bg {
width:100%; height:8px; border-radius:6px;
background:rgba(255,255,255,0.1); margin:4px 0 12px 0;
overflow:hidden;
}
.bar-fill {height:100%; border-radius:6px; transition:width 1s ease;}
.macro {display:flex; justify-content:space-between; font-size:0.95em;}
.kcal {font-weight:600; color:#ffb3ff;}
.desc {
background:rgba(255,255,255,0.05);
padding:1em; border-radius:10px; line-height:1.5em;
box-shadow:inset 0 0 20px rgba(180,0,255,0.1);
}
button {
background:linear-gradient(90deg,#b25eff,#00f0ff);
color:#fff; border:none; border-radius:12px;
font-weight:600; transition:opacity .2s;
}
button:hover {opacity:0.8;}
""") as demo:
gr.Markdown("""
<h1>💜 NasFit Vision AI</h1>
<p>Analiza tus comidas con IA y obtené tu ficha nutricional instantánea.</p>
""")
with gr.Row():
with gr.Column(scale=1):
img = gr.Image(label="📸 Imagen del plato", type="pil")
txt = gr.Textbox(label="💬 Instrucción (opcional)", placeholder="Ej: ¿Cuántas calorías tiene este plato?")
btn = gr.Button("🔍 Analizar", variant="primary")
with gr.Column(scale=1):
out = gr.HTML(label="🧠 Resultado")
btn.click(analyze_food, [img, txt], out)
return demo
if __name__ == "__main__":
demo = build_interface()
demo.launch()