Smart Turn Portuguese Fine-Tuning — Research Log
Objetivo
Fine-tuning do modelo Pipecat Smart Turn (detecção de fim de turno em conversas) para português brasileiro, visando melhorar a acurácia de ~68% (modelo original inglês aplicado a PT) para 90%+.
Background
O que é Smart Turn
- Modelo do framework Pipecat para detectar se um falante terminou de falar
- Arquitetura: Whisper encoder + attention pooling + classificador binário (complete/incomplete)
- Janela de 8 segundos de áudio, saída binária: "turno completo" vs "turno incompleto"
- Modelo original treinado em inglês (v3.1), 39M parâmetros (Whisper Tiny)
Por que fine-tuning em português
- O modelo original em inglês tem ~68.6% de acurácia em português
- Prosódia, entonação e padrões de turn-taking são diferentes entre idiomas
- Aplicação: tradução em tempo real de reuniões (BabelCast)
Fase 1: Benchmark do modelo original (pré fine-tuning)
Datasets de avaliação
- NURC-SP Corpus Minimo (nilc-nlp): diálogos reais em PT-BR espontâneo dos anos 1970-1990
- Scripts:
setup_nurc_dataset.py,benchmark_pipecat.py
Resultado baseline
- Acurácia do Smart Turn v3.1 em português: ~68.6%
- Problema principal: modelo não entende padrões prosódicos do português
Fase 2: Fine-tuning v2 — Heurística de corte (2026-03-14)
Abordagem
- Baixar datasets de ASR em português do HuggingFace
- Criar labels heurísticas: "complete" = final da frase, "incomplete" = corte aleatório a 30-75%
- Treinar com speaker-based split para evitar data leakage
Datasets utilizados
| Dataset | Tipo | Horas | Samples |
|---|---|---|---|
| CORAA v1.1 | Conversacional BR-PT | 291h | 7,000 |
| MLS Portuguese | Audiobook (leitura) | 168h | 7,000 |
| CORAA-MUPE-ASR | Entrevistas | 365h | 7,000 |
| Total | 21,000 |
Configuração de treino
- Modelo: Whisper Tiny encoder (39M params)
- GPU: RTX 3090 24GB (Vast.ai, $0.069/hr)
- Batch size: 32
- Learning rate: 2e-5 (encoder: 2e-6, head: 2e-5)
- Augmentation: volume scaling, Gaussian noise
- Split: 13,032 train (4,100 speakers) / 698 val (512 speakers) / 7,270 test (512 speakers)
- Early stopping: patience=5 no val_f1
Infraestrutura (problemas e soluções)
- 6+ instâncias Vast.ai morreram durante o treino (spot instances instáveis)
- 3 pods RunPod falharam (PyTorch images too large for container disk)
- Solução: on-demand Vast.ai instance, RTX 3090, reliability=1.00
- Mac local: treinamento funciona mas deixa a máquina muito lenta (MPS)
- Dependências críticas: PyTorch >= 2.4,
datasets<4(para evitar torchcodec), librosa, typing_extensions >= 4.12
Resultados v2
Progresso por época
| Epoch | Train Loss | Train Acc | Val Acc | Val F1 | Val Prec | Val Rec |
|---|---|---|---|---|---|---|
| 1 | 0.6032 | 0.668 | 0.669 | 0.721 | 0.600 | 0.903 |
| 2 | 0.5019 | 0.748 | 0.716 | 0.751 | 0.643 | 0.903 |
| 3 | 0.4521 | 0.782 | 0.716 | 0.751 | 0.643 | 0.903 |
| 4 | 0.4161 | 0.806 | 0.749 | 0.748 | 0.714 | 0.785 |
| 5 | 0.3962 | 0.817 | 0.742 | 0.717 | 0.748 | 0.689 |
| 6 | 0.3806 | 0.831 | 0.754 | 0.760 | 0.707 | 0.822 |
| 7 | 0.3703 | 0.832 | 0.742 | 0.748 | 0.697 | 0.807 |
| 8 | 0.3566 | 0.845 | 0.739 | 0.709 | 0.752 | 0.671 |
| 9 | 0.3449 | 0.846 | 0.748 | 0.745 | 0.716 | 0.776 |
| 10 | 0.3390 | 0.853 | 0.748 | 0.758 | 0.695 | 0.834 |
| 11 | 0.3237 | 0.865 | 0.754 | 0.756 | 0.713 | 0.804 |
Early stopping na época 11 (sem melhora por 5 épocas).
Melhor modelo (época 6)
- Val Accuracy: 75.4%
- Val F1: 0.760
- Val Precision: 70.7%
- Val Recall: 82.2%
Teste (speakers totalmente novos)
- Test Accuracy: 64.4%
- Test F1: 0.600
- Test Precision: 68.0%
- Test Recall: 53.7%
- TP=1945, FP=916, FN=1674, TN=2735
Análise dos problemas da v2
Labels heurísticas (problema principal): Cortar frases aleatoriamente em 30-75% não simula turn-taking real. O modelo aprendeu "tem silêncio no final?" em vez de "a pessoa terminou de falar?"
MLS é audiobook: 1/3 dos dados são leitura de audiobook — prosódia completamente diferente de conversação real
MUPE speaker_id quebrado: Usava
speaker_type("interviewer"/"interviewee") como speaker_id, comprometendo o speaker splitModelo pequeno: Whisper Tiny (39M params) tem capacidade limitada para capturar padrões prosódicos complexos
Gap val/test grande (75.4% vs 64.4%): Indica que o modelo não generaliza bem para speakers novos
Arquivos gerados
checkpoints/smart_turn_pt_v2/best_model.pt— 31MB PyTorch checkpointcheckpoints/smart_turn_pt_v2/smart_turn_pt.onnx+.onnx.data— 31MB ONNXcheckpoints/smart_turn_pt_v2/finetune.log— log completo
Commits
4517458— feat: Pipecat Smart Turn Portuguese evaluation, fine-tuning pipeline307b0fd— feat: GPU fine-tuning script with HuggingFace Portuguese datasets62e1816— fix: total_mem → total_memory for PyTorch 2.10 compat0039c15— fix: reduce samples to 5k/dataset and workers to prevent OOM51025dd— fix: MPS support, skip Common Voice, increase samples to 7k/dataset
Fase 3: Fine-tuning v3 — Labels por pontuação + Whisper Base (em andamento)
Melhorias implementadas
Labels baseadas em pontuação do texto
- Frase termina com
.!?…→ complete (1.0) - Frase termina com
,;:-→ incomplete (0.0) - Texto sem pontuação com ≤2 palavras → descartado (ambíguo)
- Texto sem pontuação com 3+ palavras → incomplete (transcritor teria colocado ponto se fosse completa)
- Frase termina com
Removido MLS audiobook — só dados conversacionais (CORAA + MUPE)
Whisper Base (74M params) em vez de Whisper Tiny (39M)
- 2x mais parâmetros no encoder
- hidden_size: 512 (vs 384 no Tiny)
- Melhor capacidade para capturar prosódia
Speaker ID do MUPE corrigido — usa hash do audio_path ou agrupamento por index
Mais dados: 25k samples por dataset (vs 7k na v2) = ~50k total
Augmentation melhorada:
- Speed perturbation (0.9x–1.1x)
- Volume scaling (0.6x–1.4x)
- Gaussian noise mais agressivo
- Time shift aleatório (±0.3s)
LR schedule com warmup: 2 épocas de warmup + cosine decay
Classifier head maior: 512→128→1 (vs 256→64→1)
Patience aumentado: 7 épocas (vs 5)
Configuração
- Modelo: Whisper Base (74M params)
- Datasets: CORAA + MUPE (~50k samples)
- LR: 3e-5 (encoder: 3e-6)
- Epochs: até 30 (com early stopping patience=7)
- Batch size: 32
Resultados v3
(a ser preenchido após o treino)
Roadmap futuro (se necessário)
Nível 4 — Dados reais de turn-taking
- Usar NURC-SP com anotações reais de fronteiras de turno
- Gravar dados de reuniões reais em português
- Combinar features de áudio + texto (multimodal)
Nível 5 — Arquitetura avançada
- Whisper Small (244M params)
- Adicionar features linguísticas (completude sintática via LLM)
- Ensemble de modelos
Limites teóricos
- Humanos discordam em ~10-15% dos casos de turn-taking
- Teto realista: 90-95%
- Algumas frases são genuinamente ambíguas ("Sim...", "É...")
Referências
- Pipecat Smart Turn: https://github.com/pipecat-ai/smart-turn
- CORAA v1.1: https://huggingface.co/datasets/Racoci/CORAA-v1.1
- CORAA-MUPE-ASR: https://huggingface.co/datasets/nilc-nlp/CORAA-MUPE-ASR
- NURC-SP Corpus Minimo: https://huggingface.co/datasets/nilc-nlp/NURC-SP_Corpus_Minimo
- MLS Portuguese: https://huggingface.co/datasets/facebook/multilingual_librispeech