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 # Variável global para armazenar o token da API (padrão vazio) API_TOKEN = "" # Função para atualizar o token da API def update_api_token(new_token): global API_TOKEN API_TOKEN = new_token.strip() return f"✅ Token atualizado com sucesso: {API_TOKEN[:8]}... (ocultado)" # Função para criar uma instância da API com o token atualizado usando InferenceClient def get_inference_client(model): return InferenceClient(model=model, token=API_TOKEN) # Função para interpretar a imagem com cache utilizando InferenceClient (captioning) @lru_cache(maxsize=128) def interpret_image_cached(image_hash): # Instanciar o client para o modelo de captioning client = get_inference_client("Salesforce/blip2-opt-2.7b") # Chamada da API usando método post para gerar a descrição da imagem response = client.post(data=image_hash, task="image-to-text") description = response.get("generated_text", "").strip().capitalize() if not description.endswith("."): description += "." return description # Função para análise nutricional com cache utilizando InferenceClient e método post @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 # Função para gerar dicas de saúde com cache utilizando InferenceClient e método post @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 # Função principal para processar a imagem e gerar resultados def process_image(image): try: # Converter imagem para bytes e gerar um hash 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 # Função para gerar um arquivo de download com o resultado completo 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 # Interface Gradio com aba Settings para configurar o token da API 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") # Estado oculto para armazenar o resultado completo para o download 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()