|
import gradio as gr |
|
from huggingface_hub import InferenceClient |
|
from PIL import Image |
|
import io |
|
import base64 |
|
from functools import lru_cache |
|
import tempfile |
|
import hashlib |
|
|
|
|
|
API_TOKEN = "" |
|
|
|
|
|
def update_api_token(new_token): |
|
global API_TOKEN |
|
API_TOKEN = new_token.strip() |
|
return f"✅ Token atualizado com sucesso: {API_TOKEN[:8]}... (ocultado)" |
|
|
|
|
|
def get_inference_client(model): |
|
return InferenceClient(model=model, token=API_TOKEN) |
|
|
|
|
|
@lru_cache(maxsize=128) |
|
def interpret_image_cached(image_hash): |
|
|
|
client = get_inference_client("Salesforce/blip2-opt-2.7b") |
|
|
|
|
|
response = client.post(data=image_hash, task="image-to-text") |
|
description = response.get("generated_text", "").strip().capitalize() |
|
if not description.endswith("."): |
|
description += "." |
|
return description |
|
|
|
|
|
@lru_cache(maxsize=128) |
|
def nutritional_analysis_cached(description): |
|
client = get_inference_client("google/flan-t5-large") |
|
prompt = ( |
|
f"Com base na descrição do prato de comida abaixo, forneça uma análise nutricional detalhada.\n\n" |
|
f"Descrição do prato: {description}\n\n" |
|
f"Siga este formato:\n" |
|
f"- Calorias totais estimadas: [valor]\n" |
|
f"- Macronutrientes (em gramas):\n" |
|
f" - Carboidratos: [valor]\n" |
|
f" - Proteínas: [valor]\n" |
|
f" - Gorduras: [valor]\n" |
|
f"- Recomendações para melhorar o prato: [sugestões]\n\n" |
|
f"Análise nutricional:" |
|
) |
|
response = client.post(json={"inputs": prompt}) |
|
analysis = response.get("generated_text", "").replace("Análise nutricional:", "").strip() |
|
return analysis |
|
|
|
|
|
@lru_cache(maxsize=128) |
|
def health_tips_cached(description): |
|
client = get_inference_client("google/flan-t5-large") |
|
prompt = ( |
|
f"Com base na descrição do prato de comida abaixo, forneça dicas de saúde e sugestões " |
|
f"para melhorar o prato, tornando-o mais equilibrado e nutritivo. Liste as dicas em tópicos.\n\n" |
|
f"Descrição do prato: {description}\n\n" |
|
f"Dicas de saúde:" |
|
) |
|
response = client.post(json={"inputs": prompt}) |
|
tips = response.get("generated_text", "").replace("Dicas de saúde:", "").strip() |
|
return tips |
|
|
|
|
|
def process_image(image): |
|
try: |
|
|
|
buffered = io.BytesIO() |
|
image.save(buffered, format="JPEG") |
|
image_bytes = buffered.getvalue() |
|
image_hash = hashlib.md5(image_bytes).hexdigest() |
|
|
|
description = interpret_image_cached(image_hash) |
|
analysis = nutritional_analysis_cached(description) |
|
tips = health_tips_cached(description) |
|
complete_result = ( |
|
f"Descrição do Prato:\n{description}\n\n" |
|
f"Análise Nutricional:\n{analysis}\n\n" |
|
f"Dicas de Saúde:\n{tips}" |
|
) |
|
feedback_message = "✅ Análise concluída com sucesso!" |
|
return description, analysis, tips, complete_result, complete_result, feedback_message |
|
except Exception as e: |
|
feedback_message = f"❌ Erro ao processar a imagem: {str(e)}" |
|
return "", "", "", "", "", feedback_message |
|
|
|
|
|
def generate_download(complete_result): |
|
try: |
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8") as tmp: |
|
tmp.write(complete_result) |
|
tmp_path = tmp.name |
|
return tmp_path |
|
except Exception: |
|
return None |
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="cyan")) as demo: |
|
with gr.Row(): |
|
gr.Markdown(""" |
|
# �️ Agente Nutricionista Inteligente Avançado |
|
### Revolucione a análise de suas refeições com IA de última geração! |
|
- **[Descrição automática](pplx://action/followup)** de pratos a partir de imagens. |
|
- **[Análise nutricional detalhada](pplx://action/followup)** com estimativas precisas de calorias e macronutrientes. |
|
- **[Dicas de saúde personalizadas](pplx://action/followup)** para aprimorar sua alimentação. |
|
- **[Resultado completo para download](pplx://action/followup)** em formato TXT. |
|
""") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
gr.Markdown("### 📸 Carregue uma Imagem") |
|
image_input = gr.Image(type="pil", label="Upload de Imagem", height=300) |
|
with gr.Column(scale=2): |
|
gr.Markdown("### 🔍 Resultados") |
|
with gr.Tabs(): |
|
with gr.TabItem("Descrição do Prato"): |
|
description_output = gr.Textbox(label="Descrição Gerada", lines=3, interactive=False) |
|
with gr.TabItem("Análise Nutricional"): |
|
analysis_output = gr.Textbox(label="Análise Nutricional", lines=8, interactive=False) |
|
with gr.TabItem("Dicas de Saúde"): |
|
tips_output = gr.Textbox(label="Dicas de Saúde", lines=6, interactive=False) |
|
with gr.TabItem("Resultado Completo"): |
|
complete_result_output = gr.Textbox(label="Resultado Completo", lines=15, interactive=False) |
|
with gr.TabItem("Settings"): |
|
api_token_input = gr.Textbox(label="Token da API Hugging Face", placeholder="Insira seu token aqui...") |
|
update_button = gr.Button("Atualizar Token") |
|
update_feedback = gr.Markdown("") |
|
|
|
with gr.Row(): |
|
submit_button = gr.Button("✨ Analisar Prato", variant="primary") |
|
download_button = gr.Button("💾 Baixar Resultado", variant="secondary") |
|
|
|
|
|
result_state = gr.State("") |
|
feedback = gr.Markdown("") |
|
|
|
submit_button.click( |
|
process_image, |
|
inputs=image_input, |
|
outputs=[description_output, analysis_output, tips_output, complete_result_output, result_state, feedback] |
|
) |
|
|
|
download_button.click( |
|
generate_download, |
|
inputs=result_state, |
|
outputs=gr.File(label="Seu Resultado") |
|
) |
|
|
|
update_button.click( |
|
update_api_token, |
|
inputs=api_token_input, |
|
outputs=update_feedback |
|
) |
|
|
|
demo.launch() |