Klingon como campo de testes: o chip de 8 dólares que treina seu próprio modelo

Klingon como campo de testes: o chip de 8 dólares que treina seu próprio modelo (e o que falta para o quéchua)

Por Devy · Categoria: Open Source / IA & LLMs

Quase todos os projetos de “modelo de linguagem em um microcontrolador” que você viu fazem inference. Os pesos foram treinados em outro lugar — uma GPU, uma instância alugada, a workstation de alguém — e a tarefa do chip é executar um forward pass sobre números que chegaram já prontos. qapla' faz a outra coisa. O ESP32-S3 inicia com pesos aleatórios e executa o loop de treinamento completo no dispositivo: tokenização, forward pass, cross-entropy loss, backpropagation, atualização de pesos, checkpoints para flash. Sem PyTorch, sem TensorFlow, sem biblioteca de autodiff. Cada derivada da rede foi deduzida à mão e escrita em C.

É uma frase fácil de dizer e difícil de acreditar, e por isso o número mais importante deste repo não é a quantidade de parâmetros.

O número que dá credibilidade ao projeto

Quando você escreve backprop à mão, o modo de falha é silencioso: um gradiente errado não quebra nada, simplesmente treina um modelo um pouco pior e você nunca fica sabendo. A defesa padrão é uma verificação por diferenças finitas — você move um peso por epsilon, mede quanto a loss realmente se moveu, e compara com o que seu gradiente analítico diz que deveria ter acontecido.

qapla' publica essa verificação. Pior erro relativo: 1.07e-08, contra um limite de 1e-4. Quatro ordens de magnitude de margem. Antes de qualquer resultado de treinamento significar algo, essa é a linha que diz que a regra da cadeia foi implementada bem e não aproximadamente.

O que está rodando, exatamente

  • ~319.000 parâmetros, um único bloco transformer, single-head causal attention
  • Vocabulário a nível de caractere de ~31 símbolos, janela de contexto de 32 caracteres
  • SGD com momentum 0.9 mais um schedule de taxa de aprendizado cosseno
  • 5.000 passos, uns dois dias, alimentado a partir de um carregador de telefone
  • Loss de treinamento final ≈ 1,87 (média móvel)
  • Semente do RNG: 1701, o que te diz que o autor estava se divertindo

O chip salva o checkpoint com a média móvel da loss de treinamento mais baixa que viu. Na próxima inicialização, carrega esse checkpoint e gera. Se você conectar o opcional OLED SH1106 via I2C, vê a loss cair em tempo real — que, como bem diz o README, é metade da graça.

Por que Klingon, especificamente

Aqui é onde o projeto deixa de ser um truque e começa a ser um argumento. Havia que satisfazer três restrições ao mesmo tempo:

Gramática de verdade. Tem que haver estrutura que valha a pena aprender. Uma sopa aleatória de caracteres treinaria para nada e não provaria nada.

Um vocabulário que caiba. O Klingon funciona com uns 30 símbolos. Cada caractere que você adiciona alarga a tabela de embeddings e a projeção de saída — em um chip onde o modelo inteiro pesa ~1,3 MB, o conjunto de caracteres é uma linha dura do orçamento, não um detalhe.

Um corpus que você tenha permissão para usar. Os dados de treinamento saem do dicionário boQwI’, Apache 2.0. Licença limpa, nada de scraping.

O README o diz sem rodeios: “O Klingon é um campo de testes ideal. Um idioma de verdade, com gramática de verdade, mas de um tamanho que cabe na palma da mão.”

E depois nomeia para que serve o campo de testes: o laboratório perfeito para apertar o motor antes de levá-lo — talvez em outra fase do projeto — para línguas minoritárias reais, com falantes reais. “Sami? Quéchua? Náhuatl? Isso… é outra história.”

Veja a nuance. É uma porta aberta, não um roteiro. Voltamos a isso mais abaixo.

O requisito de hardware que muita gente vai ignorar

O título diz “ESP32-S3 de 8 dólares”. Está correto, mas a placa tem que ser a N16R8 — a variante com PSRAM. Não qualquer S3.

A conta de memória explica por quê. Os pesos do modelo sozinhos são ~1,3 MB. Mas treinar não é inferir: você também precisa dos gradientes (outra cópia completa do formato de parâmetros), dos buffers de momentum (outra), das ativações cacheadas do forward pass para que o backward as consuma, e do corpus, compilado dentro. Isso soma vários MB de working set. Um S3 sem PSRAM tem uns poucos centenas de KB de SRAM. Não consegue sustentar um passo de treinamento deste modelo, não importa como o código está escrito.

Se você compra a placa errada, não há nada no software que o salve. Procure o R8 no número de série.

Rodá-lo sobre seu próprio texto

O tooling é genérico, e essa é a parte que eu destacaria. Nada do pipeline é específico do Klingon além do arquivo para o qual o aponta.

1. Converta um corpus em um header de C.

python tools/gen_header.py corpus/klingon.txt src/corpus_klingon.h

Mude corpus/klingon.txt para qualquer arquivo de texto simples. O script escreve os dados de treinamento como header para que o chip os tenha em tempo de compilação — sem leitura de filesystem, nem rede, nem cartão SD.

2. Compile e graveie.

pio run -t upload

3. Veja-o aprender.

pio device monitor

Esse é o loop completo. Três comandos, uma substituição, e o microcontrolador que você tem sobre a mesa começa a deduzir estatísticas do seu texto do zero.

Orçamente o tempo com honestidade. O README o faz: “Isso leva horas. Muitas. Até dias.” Deixe plugado.

O caveat: o que os números não te dizem

Isso é o que o repo publica sobre qualidade do modelo: uma training loss. Isso é o que não publica: nenhuma validation loss em dados retidos, nenhuma perplexidade em texto que o modelo nunca viu, nenhum split de avaliação.

Essa ausência importa mais nesta escala do que importaria em outras. Com ~319K parâmetros e um corpus derivado de um dicionário, a pergunta honesta é se o modelo aprendeu morfologia klingon ou memorizou pedaços do dicionário — e uma training loss não consegue distinguir esses dois resultados. Cai em ambos os casos.

A evidência oferecida em seu lugar é qualitativa, e é evidência decente: o modelo produz formas como SuvwI' (guerreiro — a raiz Suv mais o sufixo agentivo -wI’) e DujDaq (na nave), que é morfologia bem montada e não strings que você esperaria que saíssem de pura memorização. O README também é claro em que a saída não é Klingon semanticamente perfeito. Sólido em estrutura, fraco em significado.

Então: trate os exemplos qualitativos como o resultado real e a curva de loss como um diagnóstico de treinamento. E se você retreinar em seu próprio corpus, reserve uma porção antes de gerar o header — o tooling não vai fazer isso por você, e você vai querer o número que o repo não tem.

O que falta, concretamente, para o quéchua ou o náhuatl

Vale a pena cruzar a porta que o README deixa aberta, porque a resposta honesta é que o motor se transfere e a configuração não.

O que passa limpo: backprop deduzido à mão não se importa com que idioma está ajustando, e gen_header.py aceita qualquer arquivo de texto. Você poderia apontar isso para um corpus em quéchua ainda hoje.

O que teria que ser repensado, e aqui isso é leitura minha e não do repo:

A janela de contexto de 32 caracteres. Tanto o quéchua quanto o náhuatl são fortemente aglutinantes — o significado é construído empilhando afixos sobre uma raiz, e uma única palavra pode carregar o que o português distribui ao longo de uma cláusula. Uma janela de 32 caracteres que cobre confortavelmente várias palavras klingon pode não cobrir uma forma flexionada longa mais contexto suficiente de suas vizinhas para aprender disso. Esse é o primeiro parâmetro que eu aumentaria, e custa computação de attention de forma quadrática.

A licença do corpus, que é o muro real. boQwI’ é Apache 2.0 e por isso o projeto pôde ser publicado. Existem corpus livres e legíveis por máquina para línguas originárias, mas estão dispersos, são desiguais em ortografia e muitas vezes são regidos por protocolos comunitários sobre como o material pode ser usado — que é uma pergunta para responder com os falantes, não um problema de scraping para contornar. Esse é o gargalo de verdade, e não há quantidade de PSRAM que o resolva.

A variação ortográfica. O Klingon tem um único sistema de escrita canônico. O náhuatl tem várias ortografias em competição conforme a região, e um modelo a nível de caractere treinado sobre convenções misturadas está aprendendo o desacordo junto com o idioma. Normalizar primeiro, ou escolher uma variante deliberadamente, passa a ser uma decisão de modelagem e não uma tarefa de pré-processamento.

Nada disso é razão para pensar que o projeto não vai chegar. É a lista do que contém, na realidade, essa “outra fase”.

O que eu levo

A afirmação interessante de qapla' não é que um transformer entra em silício barato. É que o loop de treinamento completo — a parte sobre a qual coletivamente concordamos que requer um datacenter — entra em silício barato, desde que o modelo seja suficientemente pequeno e alguém esteja disposto a fazer o cálculo na mão e a demonstrar que o fez bem.

Essa combinação coloca o treinamento on-device ao alcance de qualquer um com uma placa de 8 dólares e paciência, que é uma frase distinta da que vimos dizendo sobre machine learning há uma década. E que o autor tenha escrito ele mesmo uma versão em espanhol do README, e tenha nomeado o quéchua e o náhuatl em voz alta em vez de deixar o campo de testes como sua própria brincadeira final, sugere que já tem claro qual é a audiência interessante para essa frase.

A ferramenta está aberta, é Apache 2.0, e aceita qualquer arquivo de texto. O próximo corpus é uma escolha, não uma barreira técnica.

(O Klingon foi criado por Marc Okrand; as marcas pertencem à CBS Studios / Paramount. O projeto é educacional e não é afiliado.)


E você? Se tivesse esse chip treinando dois dias sobre o corpus que quisesse, que texto carregaria?


Fontes:

1 curtida

Obrigado por divulgar meu projeto! Um cordial abraço desde a Espanha.

1 curtida

Foi um prazer, Carlos. Um projeto realmente interessante! Parabéns!