Pular para conteúdo

Projeto de referência: MEDCENTER

Clínica Medcenter — Açailândia/MA. Clínica multi-especialidade. Chatbot chamado Mel.

  • Repositório: /home/DOCKER/MEDCENTER/
  • Domínio OTIMUS: https://medcenteracai-node.otimusclinic.com/api/v1
  • LLM: gpt-4.1 (modelo grande — prompt com ~660 linhas)

Visão rápida

Componente Caminho
Webhook FastAPI server.py
Workflow LangGraph workflow.py
Agente agent.py (896 linhas)
Cliente OTIMUS scheduling.py (642 linhas)
Cliente WTS wts_client.py
Processamento mídia processors.py
DB db.py + init.sql
Telemetria tracking.py
Relatório gerado gerar_relatorio.py (273 linhas — script)

Médicos (7 com agendamento web)

# scheduling.py:34-43
PROCEDIMENTOS = [
    {"id_especialidade": 450, "id_agenda": 3,  "id_procedimento": 64639,
     "procedimento": "CONSULTA ORTOPEDISTA MAURICIO",
     "medico": "MAURICIO SIQUEIRA CAMILO"},
    {"id_especialidade": 450, "id_agenda": 1,  "id_procedimento": 64640,
     "procedimento": "CONSULTA ORTOPEDISTA VALMIR",
     "medico": "VALMIR MARTINS MOREIRA JUNIOR"},
    {"id_especialidade": 75,  "id_agenda": 5,  "id_procedimento": 64138,
     "procedimento": "CONSULTA CIRURGIAO GERAL",
     "medico": "JURIADYSON MONTEIRO BARROS DALCOL"},
    {"id_especialidade": 452, "id_agenda": 9,  "id_procedimento": 64139,
     "procedimento": "CONSULTA OTORRINOLARINGOLOGISTA",
     "medico": "REGINA MARIA DA CUNHA"},
    {"id_especialidade": 448, "id_agenda": 10, "id_procedimento": 64140,
     "procedimento": "CONSULTA CLINICA/DERMATOLOGIA - DRA SABRINA",
     "medico": "SABRINA DA CUNHA CASTRO DALCOL"},
    {"id_especialidade": 453, "id_agenda": 12, "id_procedimento": 64142,
     "procedimento": "CONSULTA ENDOCRINOLOGISTA",
     "medico": "CHRISTIANE DE FATIMA PEREIRA BRITO"},
    {"id_especialidade": 457, "id_agenda": 16, "id_procedimento": 64145,
     "procedimento": "CONSULTA ANGIOLOGISTA",
     "medico": "JOAO PAULO DE OLIVEIRA ALMEIDA"},
]

Convênios (5 com automação)

# scheduling.py:64-71
CONVENIOS = [
    {"id": 1,  "convenio": "PARTICULAR"},
    {"id": 19, "convenio": "NOTREDAME"},
    {"id": 26, "convenio": "SEPACO"},
    {"id": 30, "convenio": "VALE"},
    {"id": 39, "convenio": "AURA SAUDE"},
]

Outros convênios (Medprev, Pagrisa, Redesanta, etc.) aparecem no system prompt com instrução de transferir para humano — não têm agendamento web.

Keywords de doutor (primeiro nome + fallback)

# scheduling.py:48-62
_DOCTOR_KEYWORDS = [
    ("JOAO PAULO",  6),     # multi-palavra primeiro
    ("MAURICIO",    0),
    ("VALMIR",      1),
    ("JURIADYSON",  2),
    ("REGINA",      3),
    ("SABRINA",     4),
    ("CHRISTIANE",  5),
    ("BRITO",       5),     # sobrenomes 100% únicos
    ("ALMEIDA",     6),
    ("SIQUEIRA",    0),
]

Ver problema do primeiro nome para a crítica desse padrão.

Tools do agente

Chamadas in-process (não via HTTP loopback):

# agent.py (trecho)
@tool
def consultar_horarios(nome_medico, nome_procedimento, nome_convenio) -> str: ...

@tool
def agendar_consulta(nome_completo, cpf, data_nascimento, nome_medico,
                     data_exame, hora_exame, nome_procedimento, nome_convenio) -> str: ...

@tool
def transferir_atendimento(motivo: str) -> str: ...

TOOLS = [transferir_atendimento, consultar_horarios, agendar_consulta]

Regras invioláveis no prompt (destaques)

# agent.py:215-221
<REGRAS_INVIOLAVEIS_DE_EXCECAO_NA_AGENDA>
A Doutora citada nesse topico nao esta disponivel para agendamento.

Dra Ellen Thais: se o paciente quiser agendar, responda:
"No momento nossa psiquiatra esta de licenca por tempo indeterminado."
Essa doutora NAO deve ser citada em listas de disponibilidade.

Dr Diogo Sales: agenda temporariamente desativada. Se o paciente perguntar,
informe que a agenda esta desativada e ofereca outro ortopedista
(Dr. Mauricio ou Dr. Valmir).
</REGRAS_INVIOLAVEIS_DE_EXCECAO_NA_AGENDA>

Telefones exclusivos (fora do agendamento web)

# agent.py:226-230
- (99) 99144-0979 → SOMENTE para agendar com a Dra. Ana Claudia (Gin/USG)
- (99) 98489-3521 ou (99) 3538-3523 → SOMENTE com a Dra. Silvana (Gin)
  Somente ligacoes, secretaria atende de terca a quinta.

Esses telefones são passados para o paciente quando ele pede um médico sem agendamento automático.

Tabela de preços gigantesca

agent.py linhas 339-649 contêm ~311 linhas de preços particulares de consultas e exames. Exemplo:

<VALORES_CONSULTAS_PARTICULAR>
Juliana Dos Santos Araujo - R$500,00 em ate 2x ou R$450,00 a vista.
Felipe Xavier - R$350,00 em ate 2x ou R$320,00 a vista.
...

Qualquer atualização de preço requer redeploy do container. Ver Hardcoding crítico.

Horários dos médicos (também no prompt)

# agent.py:652-662
Mauricio Siqueira Camilo (Ortopedia): Quarta (manha) as 08h00;
Segunda, terca, quinta e sexta (tarde) as 13h00.
Valmir Martins Moreira Junior (Ortopedia): Segunda e quinta:
somente a tarde, as 12h30. Apenas particular.
...

Débitos técnicos notórios

  1. Token e URL OTIMUS hardcoded em scheduling.py:26-32.
  2. id: 123 hardcoded no cadastro de paciente.
  3. Tabela de preços no prompt (grande demais, difícil de manter).
  4. Regra do primeiro nome do médico (escala mal; ver aqui).
  5. ALLOWED_INSTANCE default hardcoded em config.py:26.
  6. agent.py com 896 linhas (metade é prompt). Considerar mover prompt para arquivo separado ou buscar do DB.

Diferenças vs. Clinfeto

Aspecto Medcenter Clinfeto
Tool → OTIMUS In-process Loopback HTTP
Modelo gpt-4.1 gpt-4.1-mini
Debounce 2s 10s
Tamanho do prompt ~660 linhas ~880 linhas
ordenacao em /horarios "desc" "asc"
Range de datas 90 dias 90 dias
Filtro de slots 5 dias × 2 manhã + 2 tarde idem
Guardian validator não implementado sim (anti-inversão)
Procedimentos 1 por médico (consulta) ~100 por médico (exames)
Aliases não ~100

Para comparação lado-a-lado completa: ver Comparação.