Spaces:
Runtime error
Runtime error
File size: 5,883 Bytes
2c9f880 bc9c9ab 2c9f880 3692f8e 2c9f880 65f4d38 12e96ed 2c9f880 12e96ed 65f4d38 7ce4819 bee9e2b 2badcc4 2c9f880 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from huggingface_hub import login
import os
from transformers import pipeline
from PIL import Image
import io
import base64
from datetime import datetime
from typing import Optional
# Login no Hugging Face
#login(new_session=False)
app = FastAPI(
title="CareLink Medical API",
description="API para análise de exames médicos usando IA",
version="1.0.0"
)
# Configurar CORS para permitir requisições do frontend
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Em produção, especifique o domínio do frontend
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Inicializar o pipeline do modelo (fazer isso uma vez no startup)
print("Carregando modelo MedGemma...")
pipe = None
import os
from transformers import pipeline
def get_hf_token():
return (
os.environ.get("HUGGINGFACE_HUB_TOKEN")
or os.environ.get("HF_TOKEN")
)
@app.on_event("startup")
async def startup_event():
global pipe
token = get_hf_token()
if not token:
raise RuntimeError("HF_TOKEN não encontrado no ambiente")
pipe = pipeline(
"image-text-to-text",
model="google/medgemma-4b-it",
token=token # 👈 ESTE é o ponto crítico
)
print("Modelo MedGemma carregado com sucesso!")
import logging
logging.basicConfig(level=logging.INFO)
logging.info("===================================")
logging.info("🚀 Application ready")
logging.info(f"🌐 Space URL: {SPACE_URL}")
logging.info(f"📡 Gradio endpoint: {SPACE_URL}/run/predict")
logging.info("===================================")
@app.get("/")
def root():
return {
"message": "CareLink Medical API",
"status": "online",
"version": "1.0.0",
"endpoints": {
"analyze_exam": "/api/analyze-exam (POST)",
"health": "/health (GET)"
}
}
@app.get("/health")
def health_check():
return {
"status": "healthy",
"model_loaded": pipe is not None,
"timestamp": datetime.now().isoformat()
}
@app.post("/api/analyze-exam")
async def analyze_exam(
file: UploadFile = File(...),
patient_name: Optional[str] = None
):
"""
Analisa uma imagem de exame médico usando o modelo MedGemma.
- **file**: Imagem do exame (JPEG, PNG, etc)
- **patient_name**: Nome do paciente (opcional)
"""
if pipe is None:
raise HTTPException(
status_code=503,
detail="Modelo ainda não foi carregado. Tente novamente em alguns instantes."
)
# Validar tipo de arquivo
if not file.content_type.startswith('image/'):
raise HTTPException(
status_code=400,
detail="O arquivo enviado não é uma imagem válida"
)
try:
# Ler a imagem
contents = await file.read()
image = Image.open(io.BytesIO(contents))
# Converter imagem para base64 para retornar ao frontend (opcional)
buffered = io.BytesIO()
image.save(buffered, format=image.format or "PNG")
img_base64 = base64.b64encode(buffered.getvalue()).decode()
# Preparar mensagem para o modelo
messages = [
{
"role": "user",
"content": [
{"type": "image", "image": image},
{
"type": "text",
"text": "Analise esta imagem de exame médico. Descreva o que você observa, "
"identifique possíveis achados clínicos e forneça uma análise detalhada. "
"Se possível, indique se há algo que requer atenção médica."
}
]
}
]
# Processar com o modelo
print(f"Analisando exame para paciente: {patient_name or 'não especificado'}")
result = pipe(messages)
# Extrair a resposta do modelo
analysis_text = ""
if isinstance(result, list) and len(result) > 0:
if isinstance(result[0], dict) and "generated_text" in result[0]:
analysis_text = result[0]["generated_text"]
else:
analysis_text = str(result[0])
else:
analysis_text = str(result)
# Montar resposta estruturada
response = {
"success": True,
"timestamp": datetime.now().isoformat(),
"patient_name": patient_name,
"file_info": {
"filename": file.filename,
"content_type": file.content_type,
"size_bytes": len(contents)
},
"analysis": {
"model": "google/medgemma-4b-it",
"result": analysis_text,
"confidence": "high" # Você pode adicionar lógica para calcular confiança
},
"image_preview": f"data:image/png;base64,{img_base64[:100]}..." # Preview truncado
}
print(f"Análise concluída com sucesso para: {file.filename}")
return response
except Exception as e:
print(f"Erro ao processar imagem: {str(e)}")
raise HTTPException(
status_code=500,
detail=f"Erro ao processar a imagem: {str(e)}"
)
@app.get("/api/test-model")
def test_model():
"""Endpoint para testar se o modelo está funcionando"""
if pipe is None:
return {"status": "error", "message": "Modelo não carregado"}
return {
"status": "ok",
"model": "google/medgemma-4b-it",
"message": "Modelo carregado e pronto para uso"
}
|