rodrigoaraujorosa's picture
Add requirements.txt for project dependencies
1e1b415
Raw
History Blame
10.9 kB
"""
Aplicação Gradio para Diagnóstico de Diabetes
Autor: Grupo 61 - FIAP 8IADT
Baseado no dataset Pima Indians Diabetes Database
"""
import gradio as gr
import pickle
import pandas as pd
import numpy as np
import os
from dotenv import load_dotenv
from openai import OpenAI
# Carrega variáveis do arquivo .env para uso local (no Hugging Face usa Secrets)
load_dotenv()
# Carregar modelo
print("📦 Carregando modelo de diabetes...")
try:
with open('models/diabetes_random_forest_model_optimized.pkl', 'rb') as f:
modelo = pickle.load(f)
print("✅ Modelo otimizado por algoritmo genético carregado com sucesso!")
except FileNotFoundError:
print("❌ Erro: Arquivo 'models/diabetes_random_forest_model_optimized.pkl' não encontrado!")
raise
def gerar_explicacao_llm(dados_paciente: dict, predicao: int, prob_diabetico: float) -> str:
"""
Gera explicação em linguagem natural do diagnóstico usando OpenAI GPT.
Transforma dados numéricos em insights acionáveis para médicos.
"""
api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
return (
"⚠️ **Chave da API OpenAI não configurada.**\n\n"
"Para habilitar explicações por IA, configure a variável de ambiente "
"`OPENAI_API_KEY` nas **Settings > Secrets** do seu Hugging Face Space "
"ou no ambiente local."
)
status = "DIABÉTICO" if predicao == 1 else "NÃO DIABÉTICO"
confianca = prob_diabetico * 100 if predicao == 1 else (1 - prob_diabetico) * 100
# Estrutura do prompt preparada para receber dados textuais no Módulo 3
prompt_sistema = (
"Você é um assistente médico especializado em diabetes, com expertise em "
"interpretar dados clínicos e fornecer insights acionáveis para profissionais "
"de saúde. Suas respostas devem ser claras, precisas e clinicamente relevantes. "
"Responda sempre em português brasileiro."
)
prompt_usuario = f"""Analise os dados clínicos abaixo e o resultado de um modelo de Machine Learning (Random Forest) treinado no Pima Indians Diabetes Database.
**Dados Clínicos do Paciente:**
- Número de gestações: {dados_paciente['pregnancies']}
- Glicose plasmática: {dados_paciente['glucose']} mg/dL
- Pressão arterial diastólica: {dados_paciente['blood_pressure']} mm Hg
- Espessura da dobra cutânea (tríceps): {dados_paciente['skin_thickness']} mm
- Insulina sérica: {dados_paciente['insulin']} mu U/ml
- IMC: {dados_paciente['bmi']:.1f}
- Função de pedigree de diabetes: {dados_paciente['diabetes_pedigree']:.3f}
- Idade: {dados_paciente['age']} anos
**Resultado do Modelo:**
- Diagnóstico: **{status}**
- Probabilidade de diabetes: {prob_diabetico * 100:.1f}%
- Confiança do diagnóstico: {confianca:.1f}%
Forneça uma análise estruturada com os seguintes tópicos:
1. **Explicação do Diagnóstico**: Explique em linguagem clara o resultado, destacando quais parâmetros mais influenciaram a predição.
2. **Fatores de Risco Identificados**: Liste os principais fatores de risco presentes nos dados do paciente.
3. **Insights Acionáveis para o Médico**: De 3 a 5 recomendações práticas e específicas (exames adicionais, monitoramento, ajustes de conduta, etc.).
4. **Próximos Passos Sugeridos**: Indique as próximas etapas recomendadas para acompanhamento do paciente.
> *Lembrete: este é um modelo preditivo e não substitui avaliação médica completa.*"""
try:
client = OpenAI(api_key=api_key)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": prompt_sistema},
{"role": "user", "content": prompt_usuario},
],
temperature=0.3,
max_tokens=1200,
)
return response.choices[0].message.content # type: ignore
except Exception as e:
return f"⚠️ **Erro ao gerar explicação por IA:** {e}"
def prever_diabetes(pregnancies, glucose, blood_pressure, skin_thickness,
insulin, bmi, diabetes_pedigree, age):
"""
Prediz se um paciente tem diabetes com base em parâmetros clínicos.
Parâmetros:
-----------
pregnancies : int - Número de gestações
glucose : float - Concentração de glicose plasmática (mg/dL)
blood_pressure : float - Pressão arterial diastólica (mm Hg)
skin_thickness : float - Espessura da dobra cutânea do tríceps (mm)
insulin : float - Nível de insulina sérica (mu U/ml)
bmi : float - Índice de Massa Corporal (peso em kg/(altura em m)^2)
diabetes_pedigree : float - Função de pedigree de diabetes
age : int - Idade em anos
Retorna:
--------
resultado, probabilidades, interpretação, explicacao_llm
"""
# Validações básicas
if glucose < 0 or glucose > 300:
return "⚠️ **Erro**: Glicose deve estar entre 0 e 300 mg/dL", "", "", ""
if bmi < 0 or bmi > 70:
return "⚠️ **Erro**: IMC deve estar entre 0 e 70", "", "", ""
if age < 21:
return "⚠️ **Nota**: Este modelo foi treinado com pacientes com 21 anos ou mais", "", "", ""
# Criar dataframe com os dados
dados = pd.DataFrame({
'Pregnancies': [pregnancies],
'Glucose': [glucose],
'BloodPressure': [blood_pressure],
'SkinThickness': [skin_thickness],
'Insulin': [insulin],
'BMI': [bmi],
'DiabetesPedigreeFunction': [diabetes_pedigree],
'Age': [age]
})
# Fazer previsão
predicao = modelo.predict(dados)[0]
probabilidades = modelo.predict_proba(dados)[0]
prob_nao_diabetico = float(probabilidades[0])
prob_diabetico = float(probabilidades[1])
# Resultado principal
if predicao == 1:
resultado = f"⚠️ **DIABÉTICO**\n\n**Confiança:** {prob_diabetico*100:.1f}%"
emoji = "🔴"
else:
resultado = f"✅ **NÃO DIABÉTICO**\n\n**Confiança:** {prob_nao_diabetico*100:.1f}%"
emoji = "🟢"
# Probabilidades
prob_texto = f"""
## 📊 Probabilidades:
- **Não Diabético:** {prob_nao_diabetico*100:.1f}%
- **Diabético:** {prob_diabetico*100:.1f}%
"""
# Interpretação dos dados
interpretacao = f"""
## 📋 Análise dos Parâmetros:
### Glicose: {glucose} mg/dL
"""
if glucose < 140:
interpretacao += "- ✅ **Normal** (< 140 mg/dL)\n"
elif glucose < 200:
interpretacao += "- ⚠️ **Pré-diabetes** (140-199 mg/dL)\n"
else:
interpretacao += "- 🔴 **Diabético** (≥ 200 mg/dL)\n"
interpretacao += f"\n### IMC: {bmi:.1f}\n"
if bmi < 18.5:
interpretacao += "- Abaixo do peso\n"
elif bmi < 25:
interpretacao += "- ✅ Peso normal\n"
elif bmi < 30:
interpretacao += "- ⚠️ Sobrepeso\n"
else:
interpretacao += "- 🔴 Obesidade\n"
interpretacao += f"\n### Idade: {age} anos\n"
interpretacao += f"### Gestações: {pregnancies}\n"
interpretacao += f"### Pressão Arterial: {blood_pressure} mm Hg\n"
interpretacao += """
---
**⚕️ Nota Importante:** Este é um modelo preditivo baseado em Machine Learning
e **NÃO substitui** uma avaliação médica profissional. Consulte sempre um médico
para diagnóstico e tratamento adequados.
"""
# Geração da explicação via LLM
dados_paciente = {
"pregnancies": pregnancies,
"glucose": glucose,
"blood_pressure": blood_pressure,
"skin_thickness": skin_thickness,
"insulin": insulin,
"bmi": bmi,
"diabetes_pedigree": diabetes_pedigree,
"age": age,
}
explicacao_llm = gerar_explicacao_llm(dados_paciente, predicao, prob_diabetico)
return resultado, prob_texto, interpretacao, explicacao_llm
# Exemplos de casos para teste
exemplos = [
[6, 155, 80, 35, 85, 33.6, 0.627, 50], # Alto risco
[1, 85, 49, 33, 134, 24, 0.351, 31], # Baixo risco
[8, 188, 76, 25, 109, 23.3, 0.672, 32], # Risco moderado
[1, 89, 66, 23, 94, 27, 0.167, 21], # Jovem baixo risco
[0, 137, 40, 35, 168, 43.1, 2.288, 33] # Risco elevado
]
# Interface Gradio
interface = gr.Interface(
fn=prever_diabetes,
inputs=[
gr.Slider(minimum=0, maximum=17, step=1, value=1, label="🤰 Gestações"),
gr.Slider(minimum=0, maximum=200, step=1, value=141, label="🩸 Glicose (mg/dL)"),
gr.Slider(minimum=0, maximum=122, step=1, value=43, label="💓 Pressão Arterial Diastólica (mm Hg)"),
gr.Slider(minimum=0, maximum=99, step=1, value=25, label="📏 Espessura da Pele (mm)"),
gr.Slider(minimum=0, maximum=846, step=1, value=90, label="💉 Insulina (mu U/ml)"),
gr.Slider(minimum=0, maximum=67, step=0.1, value=23.3, label="⚖️ IMC"),
gr.Slider(minimum=0.0, maximum=2.5, step=0.001, value=0.672, label="🧬 Função Pedigree de Diabetes"),
gr.Slider(minimum=21, maximum=81, step=1, value=32, label="👤 Idade (anos)")
],
outputs=[
gr.Markdown(label="🎯 Resultado da Predição"),
gr.Markdown(label="📊 Probabilidades"),
gr.Markdown(label="📋 Interpretação dos Parâmetros"),
gr.Markdown(label="🤖 Análise por IA (OpenAI GPT)"),
],
title="🏥 Diagnóstico de Diabetes - Random Forest + IA Generativa",
description="""
### Sistema de Suporte ao Diagnóstico de Diabetes com IA Generativa
Esta aplicação combina **Machine Learning (Random Forest)** com **IA Generativa (OpenAI GPT)**
para predizer diabetes e gerar explicações clínicas em linguagem natural.
**Apenas para uso acadêmico e informativo.**
**📚 Baseado no dataset:** Pima Indians Diabetes Database (NIH)
**🎯 Como funciona:**
1. Ajuste os parâmetros clínicos do paciente usando os controles deslizantes
2. O modelo Random Forest calcula a probabilidade de diabetes
3. O GPT (OpenAI) interpreta o resultado e gera insights acionáveis para o médico
**🔑 Requisito:** Configure a secret `OPENAI_API_KEY` nas configurações do Space para habilitar a análise por IA.
**💡 Dica:** Experimente os exemplos abaixo para ver diferentes cenários!
---
**👥 Desenvolvido por:** Grupo 61
**🎓 Projeto:** IA para DEVs - Tech Challenge Fase 2 - Diagnóstico de Doenças com otimização do modelo via algoritmo genético
""",
examples=exemplos,
examples_per_page=5,
flagging_mode="never"
)
if __name__ == "__main__":
print("\n" + "="*80)
print("🚀 GRADIO - DIAGNÓSTICO DE DIABETES COM MODELO OTIMIZADO POR ALGORITMO GENÉTICO")
print("="*80)
print("\n💡 Interface será aberta no navegador")
print("🏥 Grupo 61 - FIAP 8IADT Tech Challenge - Fase 2")
print("="*80 + "\n")
interface.launch(theme=gr.themes.Soft()) # type: ignore