23 puntos por GN⁺ 2025-09-16 | 7 comentarios | Compartir por WhatsApp
  • 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 interactivo
  • llm.rs: lógica general de propagación hacia adelante, retropropagación y entrenamiento del LLM
  • transformer.rs, self_attention.rs, feed_forward.rs: bloques centrales del transformer
  • embeddings.rs, output_projection.rs: embeddings y capa final de salida
  • adam.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

 
t7vonn 2025-09-18

Se ve limpio.

 
ahwjdekf 2025-09-16

Pero, ¿por qué? ¿Es como decir "yo también puedo hacer eso"?

 
cosine20 2025-09-22

La majestuosidad de un karma de -47 jajaja

 
skrrgang 2025-09-16

Con solo ver la r de rust ya te empiezas a poner inquieto y hasta te enojas, ¿no? jajajajajajajajaja

 
aer0700 2025-09-16

Supongo que habrá cosas que aprender al hacerlo.

 
devjeonghwan 2025-09-16

No se puede hacer sin haberlo intentado.

 
GN⁺ 2025-09-16
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 = 80 ya están en lib.rs, así que me parece mejor usar esas mismas constantes tal como lo indica el comentario

    • Que esas cosas sigan ahí me parece una señal de que no es un resultado hecho por un desarrollador que realmente lo entendió
    • Me pregunto si ya enviaste algún PR relacionado
    • Sobre la forma de usar constantes, también creo que el autor simplemente pudo no haber sabido cómo hacerlo. Yo también recuerdo que en mi primera semana con Rust me rompía mucho la cabeza con los nombres y la estructura del código
    • Me pregunto qué opinan de la idea de que un estilo de Rust tipo vibe coding podría terminar bajando la calidad general del código en el lenguaje
    • Creo que esta crítica es totalmente válida
  • He perdido días enteros en el infierno de dependencias de Python, así que la idea de que todo se resuelva con un solo cargo run en 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 backpropagation

    • Recomiendo la herramienta uv. En mi experiencia, ejecutar proyectos de Python se volvió 90% más fácil ir a uv
    • Creo que la parte más difícil es el uso de recursos como la GPU y similares
    • Esa forma de describir los problemas de dependencias en Python era entendible por ahí de 2010, pero en 2025 me parece una exageración enorme
    • Dices que cargo run parece un sueño, pero en realidad prefiero la experiencia clásica de cargo build, recompilando todo internet y calentando el CPU en invierno
    • Siento que mucha gente que alaba cargo no 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 dependencias
  • Estoy 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, rand y rand_distr se ve bastante limpia

    • Por curiosidad revisé el árbol de dependencias con cargo tree, y por ahora se ve limpio
    • No creo que ese árbol diga gran cosa. El código podría estar implementado de forma ineficiente, y según el caso hasta podría ser mejor usar bibliotecas externas de manera adecuada
    • Me pregunto si esta evaluación es sarcástica o si hace falta más contexto
  • Creo 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

    • Eso sí, creo que este tipo de ejercicios solo tiene sentido cuando escribes el código tú mismo. La experiencia valiosa es hacerlo por cuenta propia, sin ayuda de GPT
  • El comentario del autor del proyecto está resumido en Reddit

  • Me gusta que todo el proyecto tenga una estructura realmente fácil de leer

    • Quiero mencionar que es código generado por IA
    • Tiene un estilo muy procedural/orientado a objetos, así que cuesta llamarlo buen estilo Rust en un sentido estricto. Un estilo más funcional con iteradores (iterators) o enum suele verse como más conciso e ideal. Aun así, como experimento de ideas está bastante bien
    • No sabía que Rust podía verse tan fácil de leer. Más bien me da la impresión de que los ingenieros de Rust evitan este tipo de código simple y participan en una especie de concurso de autoflagelación. Todas las experiencias que tuve con la comunidad de Rust y con la cultura de contratación ahora me hacen sentido
  • Me 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.txt como 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 LLM

    • Hermes-3 Dataset está bien
    • En Hugging Face hay varias cadenas usuario-asistente de openai y anthropic, pero hay que tener cuidado porque tienen muchas alucinaciones (hallucinations). Para instruction fine-tuning sirven bastante bien. Si lo que buscas es instruction following, recomiendo la destilación de kimi k2
    • En este proyecto, los datos de entrenamiento están incluidos directamente dentro del archivo main.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:
      • al ingresar "hello": responde bien con algo como "Eclipses occur when one celestial body moves into the shadow of another"
      • al ingresar "what are facts": repite una lista de palabras sin sentido
      • al ingresar "how are mountains formed?": devuelve palabras inconsistentes y salida sin sentido