Braga Saúde — SLM na Nuvem (pt-BR)

Serviço de inferência de Small Language Model (SLM) próprio, rodando na nuvem (Vast.ai / EC2 Spot), escrito em Rust + Axum + Candle. Objetivo: substituir a dependência da Groq API a longo prazo, barateando o custo por consulta e removendo o lock-in de provedor externo.

⚠️ Este serviço roda na nuvem, não on-device. O modelo fica na instância de nuvem; o app Android consome via HTTP/WebSocket. Os pesos do modelo são hospedados aqui no Hugging Face e baixados na instância de nuvem no momento do deploy.

Por que Rust na nuvem?

Fator Groq API Próprio em Rust (nuvem)
Cobrança Por token (entrada + saída) Hora da instância GPU/CPU (fixo)
Volume alto Custo escala linearmente Marginal por consulta ≈ zero
Lock-in Sim (provedor externo) Não (seu modelo, seu servidor)
Latência Rede + carga do provedor Você controla o hardware e a fila
Modelo Limitado ao que o provedor oferece Qual modelo HF: safetensors, GGUF, fp16, bf16

Com um modelo 1B–3B numa GPU de entrada (RTX 3060 / T4 no Vast.ai), a inferência roda a 10–40 tok/s, mais que suficiente para chat de saúde.

Modelo base

  • Base: Qwen2.5-3B-Instruct (Apache 2.0, ~5,8 GB)
  • Adaptador: QLoRA treinado (LoRA r=16, alpha=32, 29,9M parâmetros treináveis de 3,1B)
  • Pasta no repo: adapter/ — contém adapter_model.safetensors, adapter_config.json, tokenizer.json, tokenizer_config.json, chat_template.jinja
  • Uso: carregar Qwen2.5-3B-Instruct + PeftModel.from_pretrained(model, adapter/)

Fine-tuning (QLoRA)

  • Dataset: 2.203 exemplos (1.982 treino / 221 validação), JSONL system/user<fala_usuario>...</fala_usuario>/assistant<JSON>
  • Ações ensinadas: apenas CONVERSA e EMERGENCIA (o LLM NÃO registra pressão, água, glicemia — isso é do motor determinístico Kotlin no app)
  • Emergência: ~16% do dataset (364 exemplos), sempre com acao: "EMERGENCIA" + menção ao SAMU 192 (ou CVV 188 para autoagressão)
  • Hyperparams: QLoRA 4-bit (nf4), LR 2e-4, 3 épocas, batch 4 + grad accum 2, max_seq_len 512, RTX 3060 12 GB, ~1h05 de treino
  • Resultado: train_loss 0.1145, eval_loss 0.026, acurácia de token 99,15%

Benchmark — baterias de teste (ANTES do fine-tuning)

Duas baterias de 500 perguntas cada, executadas no modelo base (sem fine-tuning) rodando na Vast.ai (RTX 3060, fp16, porta 8081). As perguntas são apenas as que o roteador determinístico (orb_router.py) NÃO cobre — ou seja, o que realmente chega ao LLM.

Bateria Perguntas Média Falhas críticas Modelo
1 500 95,68 / 100 18 Qwen 2.5-3B base
2 500 95,49 / 100 18 Qwen 2.5-3B base

Problemas encontrados (concentrados na emergência):

Problema Bateria 1 Bateria 2
Emergência sem SAMU 192 (crítico) 18 18
Asteriscos / encenação teatral 29 31
Resposta longa (smalltalk) 56 56
Dieta sem profissional 8 9
Prescreve ibuprofeno (crítico) 0 1

Score por categoria (Bateria 2):

Categoria Média
topic 99,6
symptoms 99,3
app_service 97,8
medication 97,8
caregiver 97,5
nutrition 96,9
open 98,9
smalltalk 88,2
emergency 83,3

O gargalo é a emergência (83,3): AVC, confusão mental, desorientação e boca torta eram tratados como conversa comum, sem acionar o SAMU 192. O fine-tuning foi direcionado para corrigir exatamente isso.

Estrutura do repositório

braga-saude-slm/
├── hf_model_card.md        # este model card (enviado como README.md no HF)
├── hf/
│   ├── config.example.json # configuração de exemplo do modelo
│   └── tokenizer.example.json # tokenizer de exemplo
├── hf_release/             # artefatos de release (fine-tuning + benchmark)
│   ├── adapter/            # adaptador QLoRA (115 MB) + tokenizer
│   ├── dataset/            # dataset de fine-tuning (train/val/dataset)
│   └── benchmark/          # resultados das baterias 1 e 2 (modelo base)
├── scripts/
│   ├── upload_to_hf.py     # upload de artefatos via huggingface_hub
│   └── upload_hf_release.py# upload estruturado do release completo
├── .gitattributes          # Git LFS para artefatos grandes

Como baixar o adaptador na nuvem

# Via huggingface-cli
huggingface-cli download fernandes-yuri/bragasaude-slm \
  hf_release/adapter/adapter_model.safetensors \
  --local-dir ./release

# Via Python (huggingface_hub)
from huggingface_hub import snapshot_download
snapshot_download(
    repo_id="fernandes-yuri/bragasaude-slm",
    repo_type="model",
    local_dir="./release",
    allow_patterns=["hf_release/adapter/*"],
)

Depois, carregue no servidor: PeftModel.from_pretrained(model_base, "./release/hf_release/adapter/").

Endpoints do servidor (braga-saude-llm)

O código do servidor (Rust + Axum + Candle) está no repositório separado: repos/braga-saude-llm.

Método Rota Descrição
GET /health Health check
POST /v1/chat/completions Compatível com OpenAI
POST /chat/completions Alias curto (app Android)
GET /ws/llm Streaming via WebSocket

Ação EMERGENCIA para o Android

O campo acao: "EMERGENCIA" no JSON de resposta aciona no Android uma tela de emergência com: UPA mais próxima, 192 (SAMU), CVV (apoio emocional) e contato de emergência cadastrado. O LLM retorna essa ação para sintomas de risco de vida (dor no peito, falta de ar severa, desmaio, sangramento intenso, sinais de AVC, risco de autoagressão).

Variáveis de ambiente (servidor)

Variável Default Descrição
LLM_HOST 0.0.0.0 Bind do servidor
LLM_PORT 8080 Porta do servidor
LLM_MODEL_PATH /models/qwen2.5-3b-instruct Modelo base
LLM_ADAPTER_PATH ./hf_release/adapter Caminho do adaptador QLoRA
LLM_MODEL_FORMAT safetensors safetensors / gguf / onnx
LLM_MAX_CONTEXT 2048 Contexto máximo (tokens)
LLM_MAX_NEW_TOKENS 256 Tokens gerados por resposta
LLM_TEMPERATURE 0.7 Amostragem
LLM_TOP_P 0.9 Nucleus sampling
LLM_CUDA true Habilitar CUDA

Prompts clínicos (Care OS)

  • sintomas — check-in sintomático
  • medicamentos — não altera dosagem nem suspende receitas
  • sinais_vitais — faixas de referência (SBC/SBD/ADA/OMS)
  • agendamento — app ou clínica
  • emergencia — SAMU 192 / pronto-socorro
  • geral — serviços da Braga Saúde

Não diagnostica nem autoriza medicação.

Licença

MIT

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support