Eu anoto meus treinos de musculação seis vezes por semana, e sempre achei chato digitar tudo em planilha. Construí o TrainMe: você escreve ou fala "supino reto 3x10 com 7,5" e o app registra as séries e sugere a carga da próxima sessão. Este texto não é sobre o app em si, mas sobre o que descobri ao medir se o modelo estava acertando.
Código: github.com/CibelleSousa/trainme. Dataset: huggingface.co/datasets/CibelleRodrigues/trainme-treino-ptbr.
A regra de projeto: o modelo só lê, o código calcula
O LLM faz duas coisas: extrai exercício, séries, carga e repetições do texto, e escreve a mensagem final. Todo o resto é código com teste: normalizar o nome do exercício, calcular a carga (a barra do supino reto pesa 20 kg, então "7,5" por lado vira 35 kg) e aplicar a regra de progressão. Nenhum número que o usuário vê vem do texto do modelo. Isso tornou o erro mensurável: ou a extração acertou, ou não.
O dataset
São 52 exemplos: 6 reais (relatos escritos ou ditados por mim) e 46 sintéticos. Os reais são poucos, mas densos: três deles são treinos inteiros que ditei de uma vez (segunda, terça e quarta, 17 exercícios no total), com pausas, correções e cargas misturadas. Os sintéticos são frases curtas e limpas. Os 46 sintéticos foram escritos com ajuda de um LLM a partir do meu histórico estruturado e revisados por mim. Já aviso o problema: dados sintéticos escritos por um modelo favorecem modelos parecidos com ele. Está no README, e voltarei a isso abaixo.
Comparei quatro configurações: Qwen3 8B rodando local, sem exemplos (A); Gemini 3.1 Flash Lite sem exemplos (B); Gemini com few-shot (C); Qwen com few-shot (D). A métrica principal é o acerto exato: todos os exercícios, cargas e repetições do exemplo corretos.
Resultados
| Configuração | Exercício | Série | Acerto exato |
|---|---|---|---|
| A: Qwen3 8B, zero-shot | 92% | 39% | 13% |
| B: Gemini, zero-shot | 99% | 97% | 94% |
| C: Gemini, few-shot | 99% | 98% | 92% |
| D: Qwen3 8B, few-shot | 88% | 80% | 67% |
O few-shot levou o modelo local de 13% para 67%. No Gemini, a diferença entre B e C é de um exemplo em 52, ruído: não posso dizer que o few-shot ajudou ali.
O que mais me ensinou
Parte dos erros era do meu pipeline, não do modelo. A análise de erros mostrou o normalizador de nomes falhando com abreviações e com "halter/halteres". Corrigir isso subiu o Gemini mais do que qualquer ajuste de prompt.
Parte dos erros é do próprio texto. Num relato real eu disse "cadeira abdutora" duas vezes para dois aparelhos diferentes (adutora e abdutora). Nenhuma configuração acerta, e nenhuma deveria: o texto não permite resolver. Marquei o exemplo como ambíguo.
Erro de infraestrutura não é erro de modelo. Na primeira rodada, o Gemini marcou 83% (B) e 69% (C), mas as falhas eram erros 503 do servidor do Google. Só ao inspecionar as linhas sem resposta percebi que C, que deveria igualar B, estava com 13 linhas vazias. Refiz só essas linhas com retry, e os números reais apareceram: 94% e 92%.
Usar o app expõe o que a avaliação não vê. Depois de colocar o app no celular, achei um bug de voz que nenhum teste pegou: no Chrome do Android, o reconhecimento de fala em modo contínuo manda o texto acumulado a cada palavra, e o app estava somando tudo ("supino supino reto supino reto 3..."). A correção foi substituir o texto da sessão em vez de acumulá-lo.
Limitações
- 52 exemplos é pouco, e só 6 são reais. Nos reais o Gemini zero-shot acertou 4 de 6; nos sintéticos, 45 de 46. A diferença faz sentido: acertar o exato num relato de treino inteiro exige acertar dezenas de campos de uma vez. Os números são indicativos, não uma medida definitiva de qual configuração é melhor.
- Os sintéticos favorecem o estilo de frase que o próprio Gemini gera.
- É um dataset de uma pessoa, em português, com 37 exercícios.
- A voz usa o reconhecimento do navegador e pode repetir ou cortar texto no Android. O app roda no meu notebook e eu o exponho por túnel para testar no celular; não tem autenticação.
O que vem a seguir
Mais exemplos reais, expor "treino com personal" e repetições na reserva na interface, e uma versão em que o áudio é gravado e transcrito no backend, para a voz não depender do navegador.
Cibelle Rodrigues, estudante de Ciência da Computação na UESC.


