RustGPT: um LLM transformer puro, implementado completamente do zero em Rust
(github.com/tekaratzas)- RustGPT é um modelo de linguagem baseado em transformer implementado sem frameworks externos de machine learning, usando apenas Rust puro e
ndarray - Foi projetado para aprender conhecimento factual e padrões conversacionais por meio de pré-treinamento (Pre-training) e instruction tuning
- Sua estrutura segue a arquitetura típica de LLM: tokenizador → embeddings → blocos transformer → projeção de saída
- Oferece estrutura de código modular e testes, permitindo entender em detalhe os processos de treinamento, inferência e otimização
- É uma referência importante para desenvolvedores e estudantes do ecossistema Rust que queiram implementar um LLM do zero sem depender de frameworks
Visão geral do projeto
- RustGPT é um projeto open source que implementa um LLM usando apenas a linguagem Rust e a biblioteca de álgebra linear (
ndarray), sem frameworks externos de machine learning ou dependências complexas - O principal objetivo é implementar diretamente os componentes centrais dos LLMs modernos, como transformer, attention, embeddings e otimização, para compreender o processo de treinamento
- Diferentemente de outros LLMs mais populares, ele projeta diretamente em Rust toda a estrutura transformer, além de backpropagation, tokenizador e otimizador, o que é uma grande vantagem para desenvolvedores e pesquisadores Rust que queiram entender e expandir os princípios do deep learning desde a base
- Seu diferencial é usar ndarray para operações matriciais e não depender de pacotes externos de machine learning como PyTorch ou TensorFlow
- Com modularização e cobertura de testes sólidas, é adequado para vários experimentos e melhorias, além de servir bem a fins educacionais de um LLM “feito do zero” (From Scratch)
Principais características e forma de implementação
- Arquitetura transformer: texto de entrada → tokenização → embeddings → blocos transformer → previsão final
- O texto de entrada passa pelo processo de tokenização e é convertido em vetores de embedding
- Os embeddings passam por Transformer Block (multi-head attention + feed-forward network)
- Por fim, a Output Projection Layer gera a distribuição de probabilidade do vocabulário para realizar a predição
Estrutura da implementação
main.rs: pipeline de treinamento, preparação de dados e execução do modo interativollm.rs: lógica geral de forward pass, backpropagation e treinamento do LLMtransformer.rs,self_attention.rs,feed_forward.rs: blocos centrais do transformerembeddings.rs,output_projection.rs: embeddings e camada final de saídaadam.rs: implementação do otimizador Adam- Cada módulo inclui código de teste correspondente (
tests/), permitindo validar as funcionalidades
Como treinar, testar e fluxo de dados
- Processo de treinamento
- Criação do vocabulário → pré-treinamento (100 epochs, dados de frases factuais) → instruction tuning (100 epochs, dados conversacionais)
- Exemplo de pré-treinamento: "The sun rises in the east and sets in the west"
- Exemplo de instruction tuning: "User: How do mountains form? Assistant: ..."
- Suporte a modo interativo
- Após o fim do treinamento, é possível testar conversas com base em prompt e resposta
- Exemplo: "How do mountains form?" → "Mountains are formed through tectonic forces or volcanism..."
Detalhes técnicos da composição
- Tamanho do vocabulário: definido dinamicamente com base nos dados de treino
- Dimensão do embedding: 128, camada oculta: 256
- Comprimento máximo da sequência: 80 tokens
- Arquitetura: 3 blocos transformer + embeddings + camada de saída
- Algoritmo de treinamento: otimizador Adam, gradient clipping (limite de norma L2 de 5.0)
- Taxa de aprendizado: pre-training 0.0005, instruction tuning 0.0001
- Função de perda: cross-entropy loss
Características do modelo e do código
- Tokenizador customizado (tratamento de pontuação)
- Geração de texto baseada em greedy decoding
- Estrutura de camadas modular e interfaces claras
- Cobertura de testes: testes unitários para cada camada e funcionalidade
- Dependências: usa apenas
ndarray(operações matriciais) erand/rand_distr(inicialização aleatória), sem ML externo como PyTorch/TensorFlow - Valor educacional: ideal para aprender a estrutura interna e os princípios de treinamento de LLMs modernos
Possibilidades de evolução
- Introdução de arquiteturas avançadas: multi-head attention, RoPE, positional encoding etc.
- Otimização de desempenho: SIMD, treinamento paralelo e melhoria de eficiência de memória
- Suporte para salvar/carregar modelos
- Adição de amostragem aprimorada (beam search, Top-k/Top-p) e métricas de avaliação
Significado
- É um projeto para aprendizado e experimentação que mostra que é possível implementar diretamente um LLM em Rust sem depender de frameworks como PyTorch e TensorFlow, baseados em Python
- É uma referência útil para desenvolvedores que querem entender o funcionamento interno de LLMs e criar sistemas de ML em ambiente Rust
7 comentários
Bem limpo.
Mas por quê? Tipo, "eu também consigo fazer isso", é isso?
A imponência de um karma de -47 kkk
Só de ver o
rde rust já dá uma coceira e uma raiva, né? kkkkkkkkkkkkkkDeve haver algo para aprender ao criar isso.
Não dá para criar sem tentar fazer.
Comentários do Hacker News
Vi código com comentários gerados pelo GPT automaticamente e constantes já definidas sendo duplicadas, então acho que essas partes precisam ser removidas. Por exemplo, constantes como
const MAX_SEQ_LEN: usize = 80já estão emlib.rs, então me parece melhor usar essas constantes diretamente, como indicado no comentárioJá perdi dias no inferno das dependências de Python, então a ideia de resolver tudo com um único
cargo runem Rust parece um sonho. Mas queria saber qual foi a parte mais dolorosa sem framework. Se eu tivesse que apostar, diria que foi depurar a lógica de backpropagationcargo runé um sonho, mas eu pessoalmente prefiro a experiência docargo buildrecompilando a internet inteira e aquecendo a CPU no invernoEstou tocando um projeto parecido em Rust. Há uma versão que roda no navegador via WebAssembly, e também deixei públicos a demo no navegador e o código-fonte
A combinação dos pacotes
ndarray,randerand_distrparece bem limpacargo tree, e por enquanto ela parece enxutaAcho que a segurança de memória do Rust é bem útil para reduzir buffer overflows ao implementar transformadores. Os kernels CUDA ainda levam vantagem em desempenho. Também fiquei curioso se o tokenizer recria o BPE do zero ou usa alguma biblioteca existente
Eu também fiz o picogpt em Rust e me apoiei bastante no blog GPT from scratch do jaykmody. Link do projeto
Parabéns, e junto disso queria fazer uma observação pequena: em um LLM, é melhor não reutilizar o transformer block e sim ter instâncias separadas para cada um. Eu mesmo já fiz exercícios parecidos para construir a base com Zig e MLX, e depois fui adicionando recursos aos poucos até migrar para PyTorch/Transformers
O comentário do autor do projeto está resumido no Reddit
Gosto de como o projeto inteiro tem uma estrutura realmente fácil de ler
Fiquei curioso sobre a origem do dataset. Vou procurar, mas quis deixar a pergunta. Eu desenvolvi uma arquitetura focada em CPU e sem backpropagation, e ela funciona bem em datasets de classificação. Como permite atualizações incrementais por exemplo único, talvez sirva também para aprendizado contínuo. Só treinei com
tiny.txtem uma demo de brinquedo e nunca tentei um modelo de linguagem grande (LLM). Minha arquitetura parece ter potencial para funcionar muito bem como assistente on-device ou on-premise, então pretendo continuar experimentando. Queria saber se alguém tem recomendação de dataset open source para treinar LLMmain.rs. O conteúdo é algo como 50 frases curtas de conhecimento geral, provavelmente para reduzir o tempo de treino. Por isso, o desempenho piora drasticamente fora de padrões baseados em script. Exemplos de prompt e resultado: