RustGPT: un LLM transformer puro implementado completamente desde cero en Rust
(github.com/tekaratzas)- RustGPT es un modelo de lenguaje basado en transformers implementado sin frameworks externos de machine learning, usando solo Rust puro y
ndarray - Está diseñado para aprender conocimiento factual y patrones conversacionales mediante preentrenamiento (Pre-training) y ajuste por instrucciones (Instruction tuning)
- Su estructura sigue la arquitectura típica de un LLM: tokenizer → embeddings → bloques transformer → proyección de salida
- Ofrece una estructura de código modular y código de pruebas para entender en detalle los procesos de entrenamiento, inferencia y optimización
- Es una referencia importante para desarrolladores o estudiantes del ecosistema Rust que quieran implementar un LLM desde cero sin depender de frameworks
Resumen del proyecto
- RustGPT es un proyecto open source que implementa un LLM usando únicamente el lenguaje Rust y la librería de álgebra lineal (
ndarray), sin frameworks externos de machine learning ni dependencias complejas - Su objetivo principal es implementar directamente los componentes clave de los LLM modernos —transformers, attention, embeddings, optimización, etc.— y comprender el proceso de entrenamiento
- A diferencia de otros LLM más populares, aquí se diseñan directamente en código Rust la estructura transformer, la retropropagación, el tokenizer, el optimizador y demás componentes, lo que permite a desarrolladores e investigadores en Rust entender y extender los principios del deep learning desde la base
- Su rasgo diferenciador es que maneja las operaciones matriciales con ndarray y no depende de paquetes externos de machine learning como PyTorch o TensorFlow
- Gracias a su modularidad y buena cobertura de pruebas, es adecuado para distintos experimentos y mejoras, además de servir para fines educativos del tipo "LLM hecho desde cero (From Scratch)"
Características principales y forma de implementación
- Arquitectura transformer: texto de entrada → tokenización → embeddings → bloques transformer → predicción final
- El texto de entrada pasa por un proceso de tokenización y se convierte en vectores de embedding
- Los embeddings pasan por un Transformer Block (multi-head attention + red feedforward)
- Finalmente, la Output Projection Layer genera la distribución de probabilidad del vocabulario para realizar la predicción
Estructura de implementación
main.rs: pipeline de entrenamiento, preparación de datos y ejecución del modo interactivollm.rs: lógica general de propagación hacia adelante, retropropagación y entrenamiento del LLMtransformer.rs,self_attention.rs,feed_forward.rs: bloques centrales del transformerembeddings.rs,output_projection.rs: embeddings y capa final de salidaadam.rs: implementación del optimizador Adam- Cada módulo incluye su código de pruebas correspondiente (
tests/) para validar su funcionamiento
Método de entrenamiento/pruebas y flujo de datos
- Proceso de entrenamiento
- Creación del vocabulario → preentrenamiento (100 epoch, datos de oraciones factuales) → ajuste por instrucciones (100 epoch, datos conversacionales)
- Ejemplo de preentrenamiento: "The sun rises in the east and sets in the west"
- Ejemplo de ajuste por instrucciones: "User: How do mountains form? Assistant: ..."
- Soporte para modo interactivo
- Tras completar el entrenamiento, se puede probar una conversación basada en prompt-respuesta
- Ejemplo: "How do mountains form?" → "Mountains are formed through tectonic forces or volcanism..."
Configuración técnica detallada
- Tamaño del vocabulario: se ajusta dinámicamente con base en los datos de entrenamiento
- Dimensión de embeddings: 128, capas ocultas: 256
- Longitud máxima de secuencia: 80 tokens
- Arquitectura: 3 bloques transformer + embeddings + capa de salida
- Algoritmo de entrenamiento: optimizador Adam, gradient clipping (límite de norma L2 de 5.0)
- Learning rate: pre-training 0.0005, instruction tuning 0.0001
- Función de pérdida: cross-entropy loss
Características del modelo y del código
- Tokenizer personalizado (manejo de puntuación)
- Generación de texto basada en greedy decoding
- Estructura de capas modular e interfaces claras
- Cobertura de pruebas: incluye pruebas unitarias por capa y función
- Dependencias: solo usa ndarray (operaciones matriciales) y rand/rand_distr (inicialización aleatoria); no usa ML externo como PyTorch/TensorFlow
- Valor educativo: ideal para aprender la estructura interna y los principios de entrenamiento de los LLM modernos
Posibilidades de evolución
- Incorporación de arquitecturas avanzadas: multi-head attention, RoPE, codificación posicional, etc.
- Optimización de rendimiento: SIMD, entrenamiento en paralelo y mejora de eficiencia de memoria
- Soporte para guardar/cargar el modelo
- Mejoras en muestreo (beam search, Top-k/Top-p) y adición de métricas de evaluación
Importancia
- Es un proyecto para aprendizaje y experimentación que demuestra que es posible implementar directamente un LLM solo con Rust, sin depender de frameworks basados en Python como PyTorch o TensorFlow
- Es una referencia útil para desarrolladores que quieran entender el funcionamiento interno de un LLM y construir sistemas de ML en un entorno Rust
7 comentarios
Se ve limpio.
Pero, ¿por qué? ¿Es como decir "yo también puedo hacer eso"?
La majestuosidad de un karma de -47 jajaja
Con solo ver la
rde rust ya te empiezas a poner inquieto y hasta te enojas, ¿no? jajajajajajajajajaSupongo que habrá cosas que aprender al hacerlo.
No se puede hacer sin haberlo intentado.
Opiniones de Hacker News
Se nota código con comentarios generados automáticamente por GPT o con constantes ya definidas duplicadas, así que creo que esas partes deberían eliminarse. Por ejemplo, constantes como
const MAX_SEQ_LEN: usize = 80ya están enlib.rs, así que me parece mejor usar esas mismas constantes tal como lo indica el comentarioHe perdido días enteros en el infierno de dependencias de Python, así que la idea de que todo se resuelva con un solo
cargo runen Rust suena como un sueño. Pero me da curiosidad cuál fue la parte más dolorosa al hacerlo sin framework. Apostaría a que fue depurar la lógica de backpropagationuv. En mi experiencia, ejecutar proyectos de Python se volvió 90% más fácil ir a uvcargo runparece un sueño, pero en realidad prefiero la experiencia clásica decargo build, recompilando todo internet y calentando el CPU en inviernocargono entiende bien los trade-offs de la gestión de dependencias. Rehacer siempre todas las librerías como en C es ineficiente, claro, pero cuando traer dependencias se vuelve demasiado fácil, como con npm o cargo, aparecen desventajas serias: explosión de dependencias, tiempos de build, problemas de seguridad, etc. Que un sistema de build sea bueno no significa necesariamente que agregar dependencias deba ser fácil, y tampoco creo que sea un patrón sano depender de un repositorio centralizado de paquetes donde cualquiera puede enredar dependenciasEstoy trabajando en un proyecto similar en Rust. Tiene una versión que corre en el navegador con WebAssembly, y también publiqué el demo en navegador y el código fuente
La combinación de paquetes
ndarray,randyrand_distrse ve bastante limpiacargo tree, y por ahora se ve limpioCreo que la seguridad de memoria de Rust es bastante útil para reducir buffer overflows en implementaciones de transformers. Los kernels CUDA siguen teniendo ventaja en rendimiento. También me da curiosidad si el tokenizer reconstruye BPE desde cero o si usa una biblioteca existente
Yo también hice picogpt en Rust y tomé mucho como referencia el blog de jaykmody, GPT from scratch. Enlace del proyecto
Felicidades; y como observación menor, en un LLM conviene no reutilizar el transformer block sino usar instancias distintas para cada uno. Yo también hice antes un ejercicio similar para aprender fundamentos con Zig y MLX, y luego fui agregando funciones hasta terminar cambiándome a PyTorch/Transformers
El comentario del autor del proyecto está resumido en Reddit
Me gusta que todo el proyecto tenga una estructura realmente fácil de leer
enumsuele verse como más conciso e ideal. Aun así, como experimento de ideas está bastante bienMe da curiosidad el origen del dataset. Voy a buscarlo por mi cuenta, pero dejo la pregunta. Yo desarrollé una arquitectura enfocada en CPU y sin backpropagation, y funciona bien en datasets de clasificación. Permite actualizaciones incrementales por ejemplo individual, así que tal vez también sirva para aprendizaje continuo. Solo he entrenado sobre
tiny.txtcomo demo de juguete y nunca he intentado un LLM. Mi arquitectura parece funcionar bastante bien como asistente on-device o on-premise, así que pienso seguir experimentando. Me pregunto si alguien puede recomendar datasets open source para entrenamiento de LLMmain.rs. Son unas 50 frases cortas de cultura general, probablemente elegidas para reducir el tiempo de entrenamiento. Por eso, fuera de prompts basados en ese guion, el rendimiento cae muchísimo. Ejemplos de prompt y resultado: