Steven
Steven7 min de leitura

Porque a Transcrição com IA Ouve Mal os Termos Técnicos (e Como Resolvemos)

Uma sessão ao vivo ouviu "what is the pointer in C++" como "what is the point in life". Este é o rasto forense desse transcript até ao GeekBye v2.0.11 — keyterm biasing, uma race condition que derrubava a conexão e o dia em que a nossa própria correção saiu pela culatra.

Transcrição
Fiabilidade
Engenharia
Lançamentos GeekBye
Porque a Transcrição com IA Ouve Mal os Termos Técnicos (e Como Resolvemos)

A 2 de julho fizemos uma sessão de teste e fizemos ao GeekBye uma pergunta simples, em voz alta: "What is the pointer in C++?" (o que é o ponteiro em C++?)

O transcript ao vivo respondeu com poesia:

[23:16:37] You: Tell me, what is the point in life? [23:16:52] You: Handy Plus. [23:17:02] You: What the pointer in Plus Plus? [23:17:09] You: C.

Na mesma sessão, as métricas de saúde contaram o resto: 3 conexões de transcrição perdidas em 163 segundos e um buraco de 51 segundos no transcript. E mais uma pista que acabou por ser a mais importante: a nossa passagem de recuperação pós-sessão — que volta a transcrever o áudio guardado localmente para preencher lacunas — acertou quase na frase: "a pointer in plus, plus? What the pointer in plus, plus C++."

O áudio estava bom. O modelo ao vivo simplesmente não tinha razão para esperar C++.

Esta é a história do GeekBye v2.0.11, contada a partir dos transcripts reais e dos logs de produção.

Por que razão os modelos de voz ouvem mal o seu vocabulário

O reconhecimento de voz é um problema de previsão. Perante áudio ambíguo, o modelo escolhe as palavras mais prováveis — e, para um modelo de uso geral, "point in life" (o sentido da vida) é uma frase muito mais provável do que "pointer in C++" (o ponteiro em C++). Qualquer engenheiro que já viu um transcript de reunião transformar Kubernetes em "cube and eddies" conhece esta falha.

A solução não é um microfone melhor. É keyterm biasing: dizer ao modelo, antes de a sessão começar, que palavras improváveis são prováveis para si. O nosso fornecedor de speech-to-text suporta até 50 termos de biasing por sessão. E aqui está a parte embaraçosa: a canalização para esses termos existia de ponta a ponta no nosso stack — cliente, backend, fornecedor — e nada alguma vez a tinha preenchido. Todas as sessões corriam sem qualquer ajuda de domínio.

Correção 1: o seu perfil torna-se o vocabulário do modelo

O GeekBye já conhece o seu domínio — está no seu perfil ativo. A v2.0.11 deriva keyterms de biasing do nome e da descrição do perfil: termos com símbolos (C++, Node.js), acrónimos (SQL, AWS), nomes em camel case (TypeScript, PostgreSQL) e nomes próprios. Um perfil que mencione o seu stack passa a tornar esse stack esperado em vez de exótico.

O dia em que a correção piorou tudo

A nossa primeira versão tratava cada palavra com maiúscula como um nome próprio. Numa build de teste interna (isto nunca chegou aos clientes), um perfil escrito em prosa enviou esta lista de biasing ao modelo:

Senior, Writing, Direct, For, Includes, Write, Role, Intent…

Enviesar um modelo de voz para a palavra "For" é pior do que não o enviesar de todo. Logo na sessão de teste seguinte, a palavra "speak" — dita com clareza, várias vezes — voltou como "Clicky", "Hey, Vicky" e "Peter Paderty". A lição custou-nos uma tarde: enviesar apenas com termos distintivos. As palavras com maiúscula agora só contam quando aparecem a meio da frase (um verdadeiro sinal de nome próprio); os títulos em markdown, onde todas as palavras têm maiúscula, nunca contribuem. Esse mesmo perfil deriva agora exatamente LinkedIn, AI, CEO, MCP — e a sessão de validação transcreveu corretamente áudio multilingue com trocas rápidas durante 199 segundos seguidos, 189 segmentos de transcript, zero erros.

Correção 2: a race condition que derrubava as conexões

Os keyterms explicavam as palavras mal ouvidas. Não explicavam as três conexões perdidas.

Esse rasto levou a um sítio mais subtil. O nosso fornecedor faz commit (finaliza) da transcrição com base na sua própria deteção de atividade de voz, cerca de um segundo depois de começar o silêncio. O nosso cliente também envia um commit de segurança 250 milissegundos depois de o silêncio começar, para despachar qualquer frase parcial pendurada. A confirmação do fornecedor de que já fez commit demora um a três segundos a chegar de volta. Faça as contas com estes três números: sempre que o fornecedor fazia commit primeiro, o nosso commit de segurança disparava contra um buffer quase vazio — e a resposta do fornecedor a isso não era apenas uma recusa educada. Derrubava a conexão. Cada pausa na fala era um lançamento de moeda.

A v2.0.11 traz duas camadas contra isto:

  1. Na app: quando chega um transcript com commit, o cliente agora sabe que o buffer do fornecedor acabou de ser esvaziado e salta o commit de segurança redundante.
  2. No nosso backend, no mesmo dia: o proxy que fica entre a app e o fornecedor espelha exatamente a contabilidade de áudio do fornecedor — vê cada frame de áudio e cada confirmação de commit com latência zero — e simplesmente recusa-se a encaminhar qualquer commit que o fornecedor fosse rejeitar. Esta camada protege todas as versões do cliente de uma só vez, incluindo utilizadores que ainda não atualizaram.

Vimos a correção a funcionar em produção dentro de uma hora. A guarda intercetou commits condenados com 178ms e 256ms de áudio em buffer — cada um deles, antes desse dia, uma conexão perdida garantida e uma lacuna nas notas de reunião de alguém. Uma sessão contínua de 60 minutos nessa tarde registou cinco interceções e zero quedas. Antes da correção, um utilizador real, nessa mesma manhã, tinha reiniciado a gravação cinco vezes em seis minutos a lutar exatamente contra este bug.

Duas correções menores que vêm à boleia

Os insights de IA agora esperam por substância. Aqueles fragmentos truncados do início alimentavam os chips de sugestões ao vivo do GeekBye, que produziam com toda a confiança tópicos como "Defining Life's Ultimate Purpose" a partir de uma pergunta de C++ mal ouvida. As sugestões agora esperam até a sessão ter massa conversacional real.

O texto recuperado recebe o orador certo. A passagem de recuperação que transcreveu corretamente a nossa pergunta de C++ tinha-a atribuído a "Them". A linha temporal de áudio guardada localmente agora regista quem estava a falar, pelo que os segmentos recuperados são atribuídos corretamente a You ou Them.

O placar

Métrica (medida, não estimada) Antes Depois da v2.0.11 + guarda no backend
Quedas de conexão na sessão de teste 3 em 163s 0
Maior buraco no transcript 51s ~6s de pior lacuna na validação
"pointer in C++" "point in life" correto, com vocabulário orientado
Commits condenados a chegar ao fornecedor todos 0 (intercetados no backend)

Se está a construir sobre APIs de voz em tempo real

Três lições transferíveis deste lançamento:

  1. Alimente a funcionalidade de biasing. Se o seu fornecedor de STT suporta keyterms/phrase hints, preenchê-la com um vocabulário pequeno e distintivo é o ganho de precisão mais barato que existe — e preenchê-la com palavras comuns é uma perda de precisão.
  2. Nunca dispute uma corrida com a máquina de estados do próprio fornecedor do lado errado de uma ida e volta na rede. O nosso cliente não podia ganhar uma corrida de informação de 250ms contra 3s. A guarda pertence onde os dois sinais convergem — no nosso caso, o proxy do backend.
  3. Valide numa build real antes de publicar. A regressão dos keyterms foi apanhada porque cada lançamento do GeekBye é testado como build assinada e notarizada contra produção antes de sair. A versão má existiu durante algumas horas numa máquina interna, não no seu Mac.

O GeekBye v2.0.11 já está disponível — se está na v2, já o tem via atualização automática. Para o trabalho de base de fiabilidade em que este lançamento assenta, veja porque é que o seu bloco de notas com IA para de funcionar com Wi-Fi mau e o que mudou no GeekBye v2. Para saber como a transcrição ao vivo funciona no dia a dia, comece por transcrição em tempo real no GeekBye.