| # 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](https://github.com/pipecat-ai/smart-turn) 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 |
|
|
| 1. **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?" |
|
|
| 2. **MLS é audiobook**: 1/3 dos dados são leitura de audiobook — prosódia completamente diferente de conversação real |
|
|
| 3. **MUPE speaker_id quebrado**: Usava `speaker_type` ("interviewer"/"interviewee") como speaker_id, comprometendo o speaker split |
| |
| 4. **Modelo pequeno**: Whisper Tiny (39M params) tem capacidade limitada para capturar padrões prosódicos complexos |
| |
| 5. **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 checkpoint |
| - `checkpoints/smart_turn_pt_v2/smart_turn_pt.onnx` + `.onnx.data` — 31MB ONNX |
| - `checkpoints/smart_turn_pt_v2/finetune.log` — log completo |
| |
| ### Commits |
| - `4517458` — feat: Pipecat Smart Turn Portuguese evaluation, fine-tuning pipeline |
| - `307b0fd` — feat: GPU fine-tuning script with HuggingFace Portuguese datasets |
| - `62e1816` — fix: total_mem → total_memory for PyTorch 2.10 compat |
| - `0039c15` — fix: reduce samples to 5k/dataset and workers to prevent OOM |
| - `51025dd` — 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 |
| |
| 1. **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) |
| |
| 2. **Removido MLS audiobook** — só dados conversacionais (CORAA + MUPE) |
| |
| 3. **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 |
| |
| 4. **Speaker ID do MUPE corrigido** — usa hash do audio_path ou agrupamento por index |
| |
| 5. **Mais dados**: 25k samples por dataset (vs 7k na v2) = ~50k total |
| |
| 6. **Augmentation melhorada**: |
| - Speed perturbation (0.9x–1.1x) |
| - Volume scaling (0.6x–1.4x) |
| - Gaussian noise mais agressivo |
| - Time shift aleatório (±0.3s) |
| |
| 7. **LR schedule com warmup**: 2 épocas de warmup + cosine decay |
| |
| 8. **Classifier head maior**: 512→128→1 (vs 256→64→1) |
| |
| 9. **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 |
|
|