Skip to content

docs: um passeio guiado pela arquitetura, e o faster-whisper declarado - #10

Merged
kerlonr merged 3 commits into
mainfrom
docs/como-funciona
Sep 3, 2026
Merged

docs: um passeio guiado pela arquitetura, e o faster-whisper declarado#10
kerlonr merged 3 commits into
mainfrom
docs/como-funciona

Conversation

@kerlonr

@kerlonr kerlonr commented Sep 3, 2026

Copy link
Copy Markdown
Member

O que é

O README.md deste repositório tem 69 KB e cobre instalação, configuração, troca de voz e solução de problemas. O que faltava era outra coisa: um documento que responda "como isso funciona?" para quem nunca viu o projeto — sem exigir que a pessoa leia 69 KB para descobrir.

COMO-FUNCIONA.md é esse documento. Quinze minutos, com diagramas Mermaid que o GitHub renderiza:

  • o caminho de uma pergunta em dez passos, do bloco de 30 ms do microfone até os olhos se mexendo junto com a voz;
  • as peças uma a uma, agrupadas por pasta, cada uma com o que faz e por que existe;
  • as quatro decisões que explicam o desenho — falar antes de terminar de pensar, duas IAs com troca invisível, a face que não pode engasgar, e sobreviver ao próprio hardware;
  • os três serviços systemd do robô, e por que a ponte BLE roda separada e como root;
  • os três contratos que precisam bater com os outros repositórios.

E um defeito de empacotamento

Achado ao escrever a seção de instalação: o extra stt declarava só o vosk — mas o backend padrão é o whisper (HearingSettings.backend = "whisper"), que precisa do faster-whisper, não declarado em lugar nenhum.

No robô atual funciona porque alguém o instalou à mão (pip show confirma: Required-by: vazio). Num cartão novo, --escuta instalaria o Vosk, o baixar-modelo-escuta.sh falharia no import faster_whisper, o setup seguiria com um aviso — e o robô subiria com a escuta ligada, no motor padrão, sem a biblioteca dele. Surdo, e sem nada explicando por quê.

Verificação

  • 703 testes passam, ruff limpo
  • os 3 diagramas foram validados com o mermaid-cli, não só escritos
  • os links relativos entre documentos foram conferidos

🤖 Generated with Claude Code

https://claude.ai/code/session_0173mr3mDsAKQuPUNaPghe9v

kerlonr and others added 3 commits September 3, 2026 12:42
O `README.md` deste repositorio tem 69 KB e cobre instalacao, configuracao,
troca de voz e solucao de problemas. O que faltava era outra coisa: um
documento que responda **"como isso funciona?"** para quem nunca viu o
projeto, sem exigir que a pessoa leia 69 KB para descobrir.

`COMO-FUNCIONA.md` e esse documento. Quinze minutos, com diagramas Mermaid
(que o GitHub renderiza):

- o caminho de uma pergunta em dez passos, do bloco de 30 ms do microfone ate
  os olhos se mexendo junto com a voz;
- as pecas uma a uma, agrupadas por pasta, cada uma com o que faz e por que
  existe;
- as quatro decisoes que explicam o desenho — falar antes de terminar de
  pensar, duas IAs com troca invisivel, a face que nao pode engasgar, e
  sobreviver ao proprio hardware;
- os tres servicos systemd do robo, e por que a ponte BLE roda separada e como
  root;
- os tres contratos que precisam bater com os outros repositorios.

**E um defeito de empacotamento, achado ao escrever a secao de instalacao.** O
extra `stt` declarava so o `vosk` — mas o backend padrao e o `whisper`
(`HearingSettings.backend = "whisper"`), que precisa do `faster-whisper`, que
nao estava declarado em lugar nenhum. No robo atual funciona porque alguem o
instalou a mao (`pip show` confirma: `Required-by:` vazio). Num cartao novo,
`--escuta` instalaria o Vosk, o `baixar-modelo-escuta.sh` falharia no
`import faster_whisper`, o setup seguiria com um aviso — e o robo subiria com
a escuta ligada, no motor padrao, sem a biblioteca dele. Surdo, e sem nada
explicando por que.

De quebra, o `CLAUDE.md` dizia que `Event` tem 8 subclasses. Tem 10:
`SpeechHeard` e `ListeningChanged` entraram depois e a contagem ficou para tras.

703 testes passam, ruff limpo. Os 3 diagramas foram validados com o
`mermaid-cli`, nao so escritos.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0173mr3mDsAKQuPUNaPghe9v
A `main` estava vermelha desde o merge anterior, e a culpa e deste teste.

`test_reabre_e_volta_a_entregar_frases` exercita o contrato que importa — quem
consome `frases()` nao percebe a queda do dispositivo — e para isso chama a
funcao publica. Mas `frases()` importa o `sounddevice` antes de qualquer coisa,
de proposito: e o que faz o robo falhar cedo, com mensagem boa, numa maquina
sem audio.

O teste substitui `_uma_captura`, entao nunca chega a usar o `sounddevice`. So
que passa pelo import. Resultado: ele so roda onde o extra `tts` estiver
instalado, e a CI instala apenas `[dev]`.

    HearingError: microfone indisponivel: No module named 'sounddevice'

Nao apareceu aqui porque o venv local tem o extra completo. Agora o teste poe
um modulo vazio no lugar, e a verificacao foi feita como a CI faz: venv novo,
`pip install -e ".[dev]"`, sem `sounddevice` — 703 passam.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0173mr3mDsAKQuPUNaPghe9v
O caminho da sintese adiantada terminava em `continue` e pulava o `finally` do
outro caminho — o unico lugar que chamava `_idle.set()` e `_set_speaking(False)`.

Consequencia: quando a **ultima** fala de uma resposta vinha pronta — o caso
comum, porque a sintese se adianta de proposito enquanto a frase anterior toca
— o locutor a dizia e voltava a esperar na fila sem nunca ter anunciado
silencio. `wait_until_idle` esperava para sempre e `is_speaking` ficava preso em
True ate alguem enfileirar outra coisa.

Aparecia como teste instavel, e era um instavel dos ruins: medido aqui,
`test_lote_respeita_o_teto_de_tamanho` falhava **14 de 40 vezes**. Dependia de a
ultima fala das doze cair no caminho adiantado ou no normal. Um teste que
reprova um terco do tempo sem apontar nada e pior que teste nenhum — foi ele que
deixou a CI da main vermelha, e o reflexo natural seria culpar a CI.

A correcao junta os dois caminhos num metodo so,
`_anunciar_silencio_se_acabou()`, que olha os **tres** lugares onde uma fala
pode estar esperando: a fila, `_held` (o que ja saiu da fila e nao foi dito) e
`_pronto` (o audio ja sintetizado da proxima).

Quatro testes novos no lugar do instavel, todos deterministicos. O que cobre o
defeito exato deixa uma fala em `_pronto` **antes** de o laco arrancar, forcando
o caminho adiantado: falha 100% das vezes sem a correcao, passa 100% com ela.
Conferido desfazendo a correcao e rodando de novo.

707 testes passam, nos dois ambientes — o venv completo e um venv novo com
apenas `[dev]`, igual ao da CI. Trinta repeticoes seguidas da suite do locutor,
zero falhas. ruff e mypy limpos.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0173mr3mDsAKQuPUNaPghe9v
@kerlonr
kerlonr merged commit 1b1c7a7 into main Sep 3, 2026
9 of 10 checks passed
@kerlonr
kerlonr deleted the docs/como-funciona branch September 3, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant