Processamento de mídia¶
Paciente pode enviar:
- Imagem (receita médica, carteirinha de convênio, print de pedido)
- PDF (pedido de exame emitido pelo médico)
- Áudio (prefere falar que digitar)
O workflow transforma tudo em texto antes de chamar o agente.
Imagens — Google Gemini¶
# processors.py
import google.generativeai as genai
from config import GEMINI_API_KEY, GEMINI_MODEL
import requests, base64
genai.configure(api_key=GEMINI_API_KEY)
_model = genai.GenerativeModel(GEMINI_MODEL) # ex: "gemini-2.5-flash"
def process_image(image_url: str, mime_type: str = "image/jpeg") -> str:
# Baixa a imagem
resp = requests.get(image_url, timeout=30)
resp.raise_for_status()
image_data = resp.content
prompt = """Esta imagem foi enviada por um paciente no WhatsApp de uma clínica.
Descreva em PT-BR:
- Tipo de documento (pedido médico, carteirinha de convênio, receita, outro)
- Informações relevantes: nome do paciente, CPF, data de nascimento,
nome do médico, convênio, procedimento/exame solicitado, data do pedido.
- Se não for documento médico, descreva o que é em 1-2 frases.
Responda apenas com os dados extraídos, formato chave: valor.
"""
response = _model.generate_content([
prompt,
{"mime_type": mime_type, "data": image_data},
])
return response.text.strip()
Uso típico no prompt do Gemini: detectar pedido médico → extrair nome do médico, especialidade, exame → o agente usa no fluxo de agendamento.
PDFs — também via Gemini¶
def process_document(doc_url: str, mime_type: str = "application/pdf") -> str:
resp = requests.get(doc_url, timeout=30)
resp.raise_for_status()
doc_data = resp.content
prompt = "Extraia dados relevantes do documento anexo..."
response = _model.generate_content([
prompt,
{"mime_type": mime_type, "data": doc_data},
])
return response.text.strip()
Gemini aceita PDFs nativamente até ~20 páginas. Para mais, seria necessário pré-processar.
Áudio — OpenAI Whisper¶
# processors.py
from openai import OpenAI
from config import OPENAI_API_KEY
import requests, tempfile, os
_openai = OpenAI(api_key=OPENAI_API_KEY)
def process_audio(audio_url: str) -> str:
resp = requests.get(audio_url, timeout=30)
resp.raise_for_status()
with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f:
f.write(resp.content)
tmp_path = f.name
try:
with open(tmp_path, "rb") as audio_file:
transcript = _openai.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language="pt",
)
return transcript.text
finally:
os.unlink(tmp_path)
Roteamento no workflow¶
# workflow.py (resumo)
def processar_conteudo(content: dict) -> str:
tipo = content.get("type", "TEXT")
if tipo == "TEXT":
return content.get("text", "")
details = content.get("details") or {}
file_info = details.get("file") or {}
url = file_info.get("publicUrl") or file_info.get("publicUrlDownload")
mime = file_info.get("mimeType", "")
if not url:
return ""
if tipo == "IMAGE":
texto = process_image(url, mime)
return f"[imagem enviada pelo paciente]\n{texto}"
if tipo == "DOCUMENT":
texto = process_document(url, mime)
return f"[documento enviado pelo paciente]\n{texto}"
if tipo == "AUDIO":
texto = process_audio(url)
return f"[audio transcrito]\n{texto}"
return ""
Metadado [imagem enviada] no prefixo¶
Prefixar a mensagem com [imagem enviada pelo paciente]\n... dá contexto
ao LLM. Ele entende que aquilo é descrição do modelo de visão, não
algo que o paciente digitou.
Custo¶
| Provedor | Modelo | Custo (ordem de grandeza) |
|---|---|---|
| Gemini (imagem) | gemini-2.5-flash |
~$0.0005 por imagem |
| Gemini (PDF) | gemini-2.5-flash |
~$0.001 por doc |
| Whisper (áudio) | whisper-1 |
~$0.006 por minuto |
Média por sessão com mídia: ~$0.01. Em alta demanda (clínica grande), vale acompanhar.
Erros e fallback¶
Se a API do Gemini/Whisper falha:
def processar_conteudo(content):
try:
...
except Exception as e:
log_error("media_error", str(e), session_id, phone)
return "[paciente enviou uma mídia que não pude processar]"
O agente lê [paciente enviou uma midia...] e pede ao paciente para
descrever em texto, ou transfere.
Limites¶
- Imagem: até ~7 MB é ok; além disso o Gemini pode negar.
- PDF: até ~20 páginas recomendado.
- Áudio: até ~25 MB (limite Whisper). Áudios > 5 min começam a ficar imprecisos.
Tipos especiais não tratados¶
- Stickers, emojis como imagem: Gemini descreve, pode entrar no contexto como ruído. Considerar filtrar por tamanho.
- Vídeo: nenhum projeto processa vídeo. System prompt orienta a transferir se o paciente manda vídeo.
- Localização: idem — tratar manualmente se relevante.