KI ist immer noch das Thema der Stunde und weil inzwischen in Social Media viele Leute ihre Theorien auf Grundlage von KI-Auswertungen aufbauen, habe ich ein kleines Experiment gewagt. Ich habe eine eigene KI geschrieben.
Der ein oder andere wird denken, jetzt bin ich komplett durchgedreht. Aber nein, so schwer war es nicht. Es war vor allen Dingen Mathematik und Programmierung und ein relativ schmales Script wirft relativ schnell irgendetwas aus. Das Ergebnis – hier im Bild zu sehen – mag euch nicht davon überzeugen, dass ich das wirklich getan habe, aber lasst mich kurz erklären, warum das wirklich so ist:
Zunächst: So etwas wie künstliche Intelligenz gibt es nicht. Noch nicht. Was ihr hier seht bei mir und was ihr bei vielen dieser KI-Dienste seht, sind sogenannte Large Language Modells (LLMs). Das sind Modelle, welche de facto nur auf zwei Dingen basieren: Statistik und Stochastik. Ich habe dieses ganze Projekt angefangen, weil ich dieses Prinzip bis zu Ende verstehen wollte. Und das ist mir gelungen. Lasst es mich kurz erklären:
Zunächst: Ich bin sehr limitiert in den Sprachen, die ich schreiben kann. Daher habe ich mich zunächst gefragt, ob es möglich ist, so etwas wie ein LLM auch in PHP zu schreiben. Und ja, das ist es. Es gibt einige Dinge, die uns da beschränken: PHP wird auf der CPU ausgeführt. Die Verteilung von Prozessen geht da nicht. Ich kann also die ganze Zeit, wenn ich mein Skript laufen lasse, lediglich einen Kern dauerhaft mit meiner Aufgabe betrauen, weswegen alles, was ich da tue, unfassbar lange dauert. Aber das ist erst einmal egal, denn wichtig war, den Prozess, der in einem LLM abläuft, transparent zu machen. Ich habe mir also verschiedene Papers angeschaut, wie sowas eigentlich funktioniert und dann ein schnelles Script gebaut.
Dieses Scirpt besteht genau genommen nur aus acht Dateien. Der Kern ist eine stochastische Matrix, gesteuert wird das Ganze durch eine Modellklasse, die bei mir MiniLLM heißt. Ich habe ein paar Bilder angehangen, um das mal zu zeigen, wie das aussieht. Diese ganzen Dateien haben ein Gesamtgewicht von 35 KB. Das ist winzig. Aber das ist der ganze Zauber. Auf dieser Grundlage habe ich dann, mit nicht viel mehr Aufwand, zwei Dateien geschrieben: Die eine Datei trainiert mein Modell, die andere entwickelt Ausgaben. Soviel dazu erst einmal.
Was aber macht mein Modell? Das ist eigentlich ganz einfach erklärt: Zunächst einmal lernen. Und das geht wie folgt:
Damit ein Sprachmodell überhaupt etwas „kann“, muss es zuerst lernen. Dieses Lernen funktioniert nicht wie bei einem Menschen, sondern eher wie bei einer riesigen Statistikmaschine. Das Modell versteht keine Bedeutung, keine Wahrheit und keine Zusammenhänge. Es merkt sich nur, welche Zeichen und Wörter in welchen Situationen häufig zusammen vorkommen. Mehr passiert nicht.
Am Anfang ist das Modell völlig leer. Es weiß nichts über Sprache, Grammatik oder Sinn. Es kennt nur viele Zahlen, die zufällig gesetzt sind. Dann bekommt es Trainingsdaten. In meinem Falle 75 KB des kommunistischen Manifests. Das ist ein Witz, denn Trainingsdaten sind eigentlich mehrere Gigabyte oder gar Terrabyte groß. Dass mein LLM also nichts kann, ist nicht verwunderlich. Es ist Folge von zu wenig Training.
Der Lernprozess läuft immer gleich ab, in meinem Falle skizziere ich es mal im Training auf Char-Level (also einzelne Zeichen). Möglich ist ein Training aber auch auf Subword-, Word- oder Byte-Level, was alles seine Vor- und Nachteile hat und zu mehr oder minder großen Datenmengen führt. In meinem Falle verbleibt es allerdings in einer Skizze:
Der Text wird in kleine Teile zerlegt, in meinem Falle, wie gesagt, in einzelne Zeichen. Das Modell sieht also bspw. nicht „Hallo Welt“, sondern „H“, „a“, „l“, „l“, „o“, “ „, „W“, ….
Jedes Zeichen wird in Zahlen übersetzt. Das Modell arbeitet nicht mit Buchstaben, sondern mit Zahlenlisten, die diese Buchstaben repräsentieren.
Das Modell bekommt ein Stück Text und soll das nächste Zeichen vorhersagen. Zum Beispiel sieht es „Hall“ und soll raten, dass als nächstes „o“ kommt.
Es berechnet nun eine Wahrscheinlichkeitsliste. Es sagt nicht „Das nächste Zeichen ist o“, sondern: o: 60%, a: 5%, l: 10%, Leerzeichen: 20%, usw.
Das Modell vergleicht seine Vorhersage mit dem echten nächsten Zeichen.
Wenn es falsch lag, wird ein Fehlerwert berechnet. Auf dieser Grundlage passt das Modell seine inneren Zahlen minimal an, damit es beim nächsten Mal etwas besser liegt. Das passiert hunderttausende Male oder millionenfach.
So lernt das Modell nach und nach, welche Zeichen in welchen Situationen wahrscheinlich sind. Es versteht nicht, was es da lernt – es erkennt nur Muster. Gut oder schlecht? Das kann es im logischen Sinne nicht bewerten. Nur anhand der Zahlenwerte, die das Training verursacht hat.
Wenn das Modell fertig angelernt ist, kann es Text erzeugen. Auch das passiert rein statistisch. Du gibst einen Starttext ein, zum Beispiel: „Es war einmal ein“
Das Modell wandelt diesen Text wieder in Zahlen um und berechnet, wie wahrscheinlich jedes mögliche nächste Zeichen wäre. Es wählt ein Zeichen aus, entweder das wahrscheinlichste oder zufällig gewichtet nach Wahrscheinlichkeit. Dieses Zeichen wird an den Text angehängt.
Der neue Text wird wieder ins Modell gegeben, und der Prozess beginnt von vorne. So entsteht Zeichen für Zeichen ein Text, der oft erstaunlich sinnvoll wirkt – aber nur, weil die Statistik gut gelernt hat, wie Sprache typischerweise aussieht. Das Modell denkt nicht. Es versteht nicht. Es weiß nichts. Es berechnet nur Wahrscheinlichkeiten.
Aber halt, Thomas, wie kannst du das sagen. Dein LLM da in den Screenshots, das generiert ja gar keinen Text. Stimmt. Tut es nicht. Weil es ein Modell ist, was ich nur mit 75kb Daten trainiert habe. Ich meine, sorry, ich hab den Mist in PHP geschrieben. Um Datenmengen umzusetzen, wie es ein LLM normalerweise zum Training braucht, würde mein Script Jahrhunderte brauchen. Und selbst das Training auf PHP ist irgendwann Sackgang, so dass ich das Modell zu Trainingszwecken schließlich noch mal auf Python umgesattelt habe.
Das Geheimnis hinter jedem LLM ist nichts anderes als das Folgende: Du brauchst Unmengen (Unmengen!!!) von Daten, mit dem du es trainierst. Und du verteilst das Training auf Unmengen von gleichzeitigen Threads, die auf der Maschine ausgeführt werden. Im Training braucht allein mein Modell (was nahezu alles kann, was ein anderes LLM auch kann, nur halt auf meinem lokalen Rechner läuft) für 75kb Textdatei nicht weniger als 23 Milliarden Rechenoperationen pro Epoche, um diesen Text zu behandeln. Was eine Epoche ist? Ein Trainingslauf des LLMs. Davon hatte mein Modell 10. Normal sind 100 und aufwärts.
Also, rein technisch habe ich nun also ein Modell hergestellt, was alles kann, was große Modelle können. Aber es limitiert mich eins: Ich habe nur meinen Rechner. LLMs laufen im Training auf Supercomputern. Sie führen unglaublich viele Operationen pro Sekunde durch und werden so geschaffen. Und irgendwann kommt dann der Punkt, wenn ein neues Modell an den Markt gebracht wird, dass wir unfassbar beeindruckt sind von dem, was es leistet. Aber in Wirklichkeit liegt die ganze Wahrheit in ein paar Kilobyte Code und unfassbaren Datenmengen, die damit verarbeitet werden.
Warum aber das Ganze, warum schreibe ich das? Ein Sprachmodell ist keine Wahrheitsmaschine und kein denkendes Wesen. Es ist ein Werkzeug, das gelernt hat: „Wenn vorher X stand, ist Y statistisch wahrscheinlich.“ Es ist einfache Mathematik. Die Architektur meines LLM ist die gleiche wie bei großen Modellen – nur kleiner und mit weniger Daten.
Der Unterschied zwischen meinem Modell und einem riesigen LLM ist nicht die Technik, sondern nur: wie viele Daten es gesehen hat, wie viele Parameter es hat, wie lange es trainiert wurde. Mehr ist es nicht.
Und genau deshalb finde ich es extrem problematisch, wenn Menschen, die das System hinter einem LLM nicht verstanden haben, ihre Überzeugungen und Weltansichten mittlerweile auf Systemen aufbauen, die mit einfach reproduzierbaren Scripts von Statistik und Stochastik die vermeintliche Antwort liefern. Also bitte: Lasst das.
PS: Eines habe ich noch vergessen: Wenn alles auf Statistik und Stochastik beruht, dann ist der erste Fingerzeig für das System, in welche Richtung es antworten soll, deine Nutzereingabe. Du kommst bereits mit einer Bias zum LLM. Folglich wird es genau daran analysieren, wie es dir antworten soll. Erwartest du beispielsweise bereits in deiner Frage, dass ein Text zum Beispiel übersetzt worden ist, dann wird das LLM auf der Grundlage der ihm vorliegenden Daten mit hoher Wahrscheinlichkeit in genau diese Richtung antworten. Wenn du verhindern willst, dass ein LLM einseitig in eine Richtung arbeitet, musst du ihm Optionen anbieten. Und auch diese sind bereits biased, weil du selbstverständlich gedanklich eine Vorauswahl triffst. Nun ja. Es ist nicht einfach. Aber seien wir vorsichtig, uns auf solche Modelle zu verlassen.
PPS: Wenn man den Textkorpus übrigens vergrößert und bereinigt und dann in jedem Schritt noch ein paar mehr Badges mitgibt, dann rechnet das Modell zwar etwas länger im Training, aber dafür kriegt man sehr früh schon Fragmente, die irgendwie doch an die deutsche Sprache erinnern. In diesem Falle sieht das dann nach 96.000 Sequenzen so aus:

PPPS: Eines noch, damit das nicht missverstanden wird: Mein Modell verwendet die gleiche Architektur wie große LLMs. Es wird aber niemals in der Lage sein, gleiches zu generieren wie ein solches LLM. Es wird an natürlicher Sprache Scheitern, auch wenn es sich immer mehr dem annähert. Warum? Weil mein LLM „from scratch“ limitiert ist in den Ressourcen. Sowohl ist mein zugrunde gelegter Corpus viel zu klein, als auch sind die Rechenkapazitäten für mein Modell auf meinem Rechner begrenzt. Ich komme an das tote Ende, wenn ich lokal Folgendes versuche:
embed_size = 192
hidden_size = 768
num_blocks = 8
max_seq_len = 512
Mehr schafft mein Rechner nicht und das mit 32 gleichzeitigen Badges. Moderne LLMs skalieren komplett anders. Wir reden nicht über doppelt oder dreifach, wir reden über Faktoren. Damit steigt die Größe der Weightings-Parameter im Übrigen exorbitant an. Spielen wir nur leicht an den Zahlen, kann ein Vielfaches der Dateigröße herauskommen. Und damit können sich am Ende nur noch Serverfarmen beschäftigten. Die Frage ist also: Wie schaffen wir die Demokratisierung dieser Technologie? Die Produktionsressourcen zur Schaffung eines einzigen Modells werden wir nicht akkumulieren können auf kleinen Einheiten. Wir können nicht darauf vertrauen, fremde Modelle zu verwenden und diese umzutrainieren, denn das wird nicht aufgehen. Wie schaffen wir Modelle „from scratch“, die genau das tun, was wir von ihnen erwarten? Das ist die Frage der Zukunft und die Frage an die Open-Source-Community. Wir können uns auf alles, was wir bekommen, nicht verlassen. Wie schaffen wir also demokratisch Neues? Und diese Frage will ich mit euch beantworten. 🙂




