RustGPT: Ein reines Transformer-LLM, von Grund auf vollständig in Rust implementiert
(github.com/tekaratzas)- RustGPT ist ein transformerbasiertes Sprachmodell, das ohne externe Machine-Learning-Frameworks ausschließlich mit reinem Rust und
ndarrayimplementiert wurde - Es ist darauf ausgelegt, durch Pre-Training und Instruction Tuning faktenbasiertes Wissen und dialogorientierte Muster zu erlernen
- Die Struktur folgt einer typischen LLM-Architektur: Tokenizer → Embeddings → Transformer-Blöcke → Output Projection
- Mit einer modularen Quellstruktur und Testcode lässt sich der Ablauf von Training, Inferenz und Optimierung im Detail nachvollziehen
- Eine wichtige Referenz für Entwickler und Lernende im Rust-Ökosystem, die ein LLM von Grund auf ohne Framework-Abhängigkeiten implementieren möchten
Projektüberblick
- RustGPT ist ein Open-Source-Projekt, das ein LLM ohne externe Machine-Learning-Frameworks oder komplexe Abhängigkeiten ausschließlich mit der Programmiersprache Rust und der linearen Algebra-Bibliothek
ndarrayimplementiert - Das Hauptziel ist, die Kernkomponenten moderner LLMs (Transformer, Attention, Embeddings, Optimierung usw.) direkt zu implementieren und den Trainingsprozess zu verstehen
- Im Unterschied zu anderen gängigen LLMs werden Transformer-Struktur, Backpropagation, Tokenizer und Optimizer vollständig in Rust-Code entworfen. Das ist ein großer Vorteil für Rust-Entwickler und Forschende, die die Prinzipien des Deep Learning von Grund auf verstehen und erweitern möchten
- Ein Unterscheidungsmerkmal ist, dass Matrixoperationen mit ndarray ausgeführt werden und keine Abhängigkeit von externen Machine-Learning-Paketen wie PyTorch oder TensorFlow besteht
- Dank solider Modularisierung und guter Testabdeckung eignet sich das Projekt für vielfältige Experimente und Verbesserungen sowie für Bildungszwecke im Stil eines „LLM from Scratch“
Wichtige Merkmale und Implementierungsansatz
- Transformer-Architektur: Eingabetext → Tokenisierung → Embeddings → Transformer-Blöcke → finale Vorhersage
- Der Eingabetext wird durch den Tokenisierungsprozess in Embedding-Vektoren umgewandelt
- Die Embeddings durchlaufen Transformer Blocks (Multi-Head Attention + Feed-Forward-Netzwerk)
- Abschließend erzeugt die Output Projection Layer eine Wahrscheinlichkeitsverteilung über das Vokabular und führt so die Vorhersage aus
Implementierungsstruktur
main.rs: Trainingspipeline, Datenvorbereitung, Ausführung des interaktiven Modusllm.rs: Forward- und Backward-Pass sowie Trainingslogik des gesamten LLMtransformer.rs,self_attention.rs,feed_forward.rs: zentrale Transformer-Blöckeembeddings.rs,output_projection.rs: Embeddings und finale Ausgabeschichtadam.rs: Implementierung des Adam-Optimizers- Jedes Modul enthält entsprechenden Testcode (
tests/), sodass die Funktionen überprüft werden können
Trainings-/Testverfahren und Datenfluss
- Trainingsprozess
- Vokabularaufbau → Pre-Training (100 Epochen, Datensatz mit Faktensätzen) → Instruction Tuning (100 Epochen, Dialogdaten)
- Beispiel für Pre-Training: "The sun rises in the east and sets in the west"
- Beispiel für Instruction Tuning: "User: How do mountains form? Assistant: ..."
- Unterstützung für interaktiven Modus
- Nach Abschluss des Trainings sind Dialogtests auf Basis von Prompt und Antwort möglich
- Beispiel: "How do mountains form?" → "Mountains are formed through tectonic forces or volcanism..."
Technische Details
- Vokabulargröße: dynamisch auf Basis der Trainingsdaten festgelegt
- Embedding-Dimension: 128, Hidden Layer: 256
- Maximale Sequenzlänge: 80 Tokens
- Architektur: 3 Transformer-Blöcke + Embeddings + Ausgabeschicht
- Trainingsalgorithmus: Adam-Optimizer, Gradient Clipping (Begrenzung auf L2-Norm 5.0)
- Lernrate: Pre-Training 0.0005, Instruction Tuning 0.0001
- Verlustfunktion: Cross-Entropy-Loss
Modell- und Codeeigenschaften
- Benutzerdefinierter Tokenizer (Verarbeitung von Satzzeichen)
- Textgenerierung auf Basis von Greedy Decoding
- Modulare Schichtenstruktur und klare Interfaces
- Testabdeckung: Unit-Tests für jede Schicht und Funktion enthalten
- Abhängigkeiten: nur
ndarray(Matrixoperationen) undrand/rand_distr(Zufallsinitialisierung); keine externen ML-Pakete wie PyTorch/TensorFlow - Pädagogischer Wert: optimal, um interne Strukturen und Trainingsprinzipien moderner LLMs kennenzulernen
Entwicklungspotenzial
- Einführung fortgeschrittener Architekturen: Multi-Head Attention, RoPE, Positionskodierung usw.
- Leistungsoptimierung: SIMD, paralleles Training, Verbesserungen der Speichereffizienz
- Unterstützung zum Speichern/Laden von Modellen
- Verbesserte Sampling-Methoden (Beam Search, Top-k/Top-p) und zusätzliche Evaluationsmetriken
Bedeutung
- Ein Lern- und Experimentalprojekt, das zeigt, dass sich ein LLM direkt nur mit Rust implementieren lässt, ohne auf Python-basierte Frameworks wie PyTorch oder TensorFlow angewiesen zu sein
- Eine nützliche Referenz für Entwickler, die die interne Funktionsweise von LLMs verstehen und ML-Systeme in einer Rust-Umgebung entwickeln möchten
7 Kommentare
Ganz ordentlich.
Nein, warum? So nach dem Motto: Das kann ich auch mal machen?
Die Erhabenheit von Karma -47, lol
Schon beim bloßen Anblick des
rin Rust fängt es bei euch an zu kribbeln und ihr werdet wütend, oder? hahahaDabei lernt man beim Entwickeln sicher eine Menge.
Ohne es auszuprobieren, kann man es nicht bauen.
Hacker-News-Kommentare
Im Code sind Stellen zu sehen, an denen von GPT automatisch erzeugte Kommentare oder bereits definierte Konstanten doppelt geschrieben wurden, daher denke ich, dass solche Teile entfernt werden sollten. Zum Beispiel sind Konstanten wie
const MAX_SEQ_LEN: usize = 80bereits inlib.rsvorhanden, daher wäre es besser, wie im Kommentar beschrieben, diese Konstanten direkt zu verwendenIch habe schon Tage in der Python-Abhängigkeits-Hölle verloren, deshalb wirkt die Rust-Art, bei der ein einziges
cargo runreicht, wie ein Traum. Mich würde aber interessieren, was ohne Framework der schmerzhafteste Teil war. Ich würde wetten, dass es das Debuggen der Backpropagation-Logik warcargo runwie ein Traum wirkt, dann finde ich die besondere Erfahrung voncargo build, das gefühlt das ganze Internet neu kompiliert und im Winter die CPU wärmt, eigentlich noch bessercargoloben, die Trade-offs beim Dependency-Management nicht gut kennen. Es ist zwar ineffizient, wie in C jedes Mal alle Bibliotheken neu zu bauen, aber wenn man Abhängigkeiten wie bei npm odercargozu leicht hereinholen kann, entstehen dafür ernsthafte Nachteile wie eine Flut von Dependencies, längere Build-Zeiten und Sicherheitsprobleme. Ein gutes Build-System ist nicht automatisch dasselbe wie das einfache Hinzufügen von Abhängigkeiten, und auch ein zentrales Package-Repository, in dem jeder beliebig Abhängigkeiten verknüpfen kann, halte ich nicht für ein gesundes MusterIch arbeite an einem ähnlichen Rust-Projekt. Es gibt eine Version, die als WebAssembly im Browser läuft, und sowohl eine Browser-Demo als auch der Quellcode sind veröffentlicht
Die Paket-Zusammenstellung aus
ndarray,randundrand_distrwirkt saubercargo treeden Abhängigkeitsbaum angesehen, und bisher sieht er noch ordentlich ausIch denke, die Memory Safety von Rust ist bei der Implementierung eines Transformers ziemlich nützlich, um Buffer Overflows zu verringern. CUDA-Kernel liegen bei der Performance aber weiterhin vorne. Ich frage mich, ob auch der Tokenizer mit neuem BPE gebaut wird oder ob eine bestehende Bibliothek verwendet wird
Ich habe beim Bauen von picogpt in Rust ebenfalls stark auf den Blog GPT from scratch von jaykmody zurückgegriffen. Projektlink
Glückwunsch, und als kleine Anmerkung würde ich sagen, dass man in einem LLM den Transformer-Block besser nicht wiederverwenden, sondern jede Instanz getrennt anlegen sollte. Ich selbst habe früher mit Zig und MLX auf ähnliche Weise Grundlagenübungen gemacht und später nach und nach mehr Funktionen ergänzt, bevor ich schließlich zu PyTorch/Transformers gewechselt bin
Die Kommentare des Projektautors sind auf Reddit zusammengefasst
Mir gefällt, dass das gesamte Projekt wirklich sehr leicht zu lesen ist
enumgilt als knapper und idealer. Als Ideenexperiment ist es aber völlig in OrdnungIch frage mich, woher der Datensatz stammt. Ich werde selbst danach suchen, wollte die Frage aber trotzdem stellen. Ich habe eine Architektur entwickelt, die vor allem auf der CPU läuft und keine Backpropagation hat, und sie funktioniert gut auf Klassifikations-Datensätzen. Einzelne Beispiele können inkrementell aktualisiert werden, daher könnte sie sich auch für Continual Learning eignen. Ich habe nur als Toy-Demo einmal auf
tiny.txttrainiert und noch nie ein Large Language Model (LLM) ausprobiert. Da ich denke, dass meine Architektur als On-Device- oder On-Premises-Assistent ziemlich gut funktionieren könnte, werde ich weiter experimentieren. Mich würde interessieren, ob es empfehlenswerte Open-Source-Trainingsdatensätze für LLMs gibtmain.rs. Es sind ungefähr 50 kurze Sätze über Allgemeinwissen, vermutlich um die Trainingszeit zu verkürzen. Deshalb bricht die Qualität bei allem ein, was nicht skriptbasiert ist. Beispiel-Prompts und Ergebnisse: