Zum Inhalt springen

Technik

Eine Vorgabe, die zwischen zwei Dateien umgedreht ist

Erwähnt die Konfiguration eines Modells tie_word_embeddings nicht, nimmt phi3 false an und llama true. Übernehmen Sie eine der beiden, und Sie haben ein Modell, das bei der einen Familie stimmt und bei der anderen still danebenliegt.

Aktualisiert 2026-09-12Gemessen 2026-09-06

Hier ist ein Defekt, den man beim Testen eines einzigen Modells unmöglich findet und beim Testen von zweien mühelos.

Wenn in mlx-lm die config.json eines Modells tie_word_embeddings nicht erwähnt, unterscheidet sich die Vorgabe je Architekturdatei. phi3.py nimmt false an. llama.py nimmt true an. Beides ist richtig für die Modelle, für die es geschrieben wurde, und keines von beiden ist eine allgemeine Regel.

Wer also eine Architektur portiert und die Vorgabe aus derjenigen Datei übernimmt, die er zuerst gelesen hat, liegt bei dieser Familie richtig und bei der anderen falsch. Und «falsch» heißt hier keine Ausnahme.

Was das Kennzeichen tatsächlich steuert

Ein Sprachmodell hat eine Einbettungstabelle, die am Eingang Token-Kennungen in Vektoren verwandelt, und eine Projektion, die am Ausgang Vektoren zurück in Bewertungen über dem Vokabular verwandelt. Beide haben dieselbe Form, transponiert.

Gebunden heißt, es sind dieselben Gewichte: Die Ausgabeprojektion ist die Transponierte der Eingabeeinbettung, und die Datei enthält eine Matrix. Ungebunden heißt, sie sind getrennt, unabhängig gelernt, und die Datei enthält zwei — die zweite üblicherweise lm_head.weight genannt.

Das Binden spart bei einem kleinen Modell viel Speicher, weil die Vokabularmatrix dort einen erheblichen Anteil der Parameter ausmachen kann. Das Lösen gibt dem Modell mehr Kapazität. Verschiedene Familien haben verschieden entschieden, und deshalb gibt es dieses Kennzeichen.

Warum es leise falsch wird

Nehmen Sie Bindung an, wo das Modell ungebunden ist, dann benutzen Sie die Eingabeeinbettung als Ausgabeprojektion. Die Matrix hat die richtige Form. Die Multiplikation gelingt. Sie bekommen Logits.

Es sind Logits, die mit der falschen Matrix berechnet wurden, also ist die Ausgabeverteilung des Modells nicht die, auf die es trainiert wurde — aber Rauschen ist es auch nicht, denn in einem Modell, das mit getrennten Matrizen trainiert wurde, sind die beiden miteinander verwandt. Der Text bleibt flüssig. Er wird nur schlechter, und zwar auf eine Weise, die sich liest wie «diese Quantisierung verliert etwas» oder «dieses Modell ist nicht besonders gut».

Die umgekehrte Richtung ist lauter: Ungebundenheit anzunehmen, wo die Gewichte gebunden sind, heißt, nach lm_head.weight zu suchen und es nicht zu finden — was immerhin scheitert.

Die Behebung besteht darin, das Raten zu lassen

Die verlässliche Antwort ist keine bessere Vorgabe. Sie besteht darin, in die Gewichte zu sehen.

Ist lm_head.weight in den Safetensors vorhanden, sind die Einbettungen ungebunden — denn ein ungebundenes Modell muss diese Matrix ausliefern, und ein gebundenes hat keinen Grund dazu. Fehlt sie, sind sie gebunden.

Diese Prüfung ist keine Heuristik. Sie ist die Tatsache selbst: Das Vorhandensein des Tensors ist, was ungebunden auf Dateiebene bedeutet. Ein Konfigurationsfeld ist eine Behauptung über die Datei, und wo beide sich widersprechen, gewinnt die Datei.

Die Reihenfolge lautet also: das Konfigurationsfeld lesen, wenn es existiert, und wenn nicht, nach dem Tensor sehen. Niemals auf eine Konstante zurückfallen.

Ein Modell in dreißig Sekunden prüfen

Da die Antwort in den Gewichten steckt, hier das praktische Rezept, das kein Herunterladen verlangt.

Öffnen Sie das Modell auf Hugging Face und sehen Sie sich die Dateiliste an. Steht lm_head.weight in einem Safetensors-Index, oder gibt es eine Datei, deren Name darauf hindeutet, sind die Einbettungen ungebunden. Bei einem aufgeteilten Modell führt die Indexdatei — model.safetensors.index.json — in ihrer weight_map jeden Tensornamen auf, und es ist eine schlichte JSON-Datei, die Sie im Browser lesen können.

Öffnen Sie dann die config.json und suchen Sie tie_word_embeddings. Drei Ausgänge:

  • Es steht true da und es gibt kein lm_head.weight — stimmig, gebunden, nichts zu überlegen.
  • Es steht false da und lm_head.weight existiert — stimmig, ungebunden, ebenso.
  • Es steht nichts da — das ist der häufige Fall, und der, in dem die beiden Bibliotheken uneinig sind. Die Gewichte entscheiden.

Die vierte Kombination, in der Konfiguration und Gewichte einander widersprechen, ist selten und sollte man als kaputtes Repository behandeln statt als Rätsel. In aller Regel steckt dahinter eine Umwandlung, bei der jemand die Gewichte neu geschrieben und die Konfiguration von vorher übernommen hat, und dann ist das Repository selbst die Sache, die repariert gehört.

Das allgemeine Muster

Dies ist ein Fall von etwas, das man erkennen sollte, weil es sich über jede Laufzeitumgebung für Modelle hinweg wiederholt.

Referenzimplementierungen werden je Familie geschrieben, und ihre Vorgaben sind örtliches Wissen. Ein Wert in llama.py ist keine Aussage über Sprachmodelle; er ist eine Aussage über llama. Eine Datei zu lesen und daraus zu verallgemeinern ist der Weg, eine Annahme zu erben, die nie zum Reisen gedacht war.

Dieselbe Form taucht anderswo in derselben Codebasis auf. Aufmerksamkeitsverzerrungen zum Beispiel: qwen2 hat sie auf den Projektionen für Anfrage, Schlüssel und Wert und erklärt sie nirgends, weil sie in mlx-lm in der Architektur wohnen und nicht in der Konfiguration. Llama macht sie über attention_bias optional. Eine Portierung, die nur die Konfiguration liest, macht qwen2 falsch; eine, die immer Verzerrungen hinzufügt, macht llama falsch. Nachzusehen, ob der Tensor existiert, beantwortet beides.

Was dieselbe Regel wie vorhin ist, und sie verallgemeinert sich:

Wenn Konfiguration und Gewichte darüber uneinig sind, was ein Modell ist, dann sind die Gewichte das Modell.

Wie man es vor der Auslieferung fängt

Der einzige Grund, warum das gefunden und nicht ausgeliefert wurde, ist, dass Richtigkeit hier gegen eine Referenz geprüft wird und nicht durch Lesen der Ausgabe.

mlx-lm erzeugt Orakel: für ein gegebenes Modell und einen Prompt die genaue Tokenfolge und die rohen Logits. Eine Portierung muss sie reproduzieren. Eine falsche Ausgabeprojektion verändert die Logits sofort und sichtbar — in Zahlen, nicht in Eindrücken —, und der Test scheitert beim ersten Token.

Wer Architekturen portiert und das nicht hat, baut es besser vor der zweiten Familie als nach der zehnten. Die Alternative ist, erzeugten Text zu lesen und sich einen Eindruck zu bilden, und ein Eindruck kann «falsche Matrix» nicht von «kleines Modell» unterscheiden.

Ein Vorbehalt zum Vergleich von Logits, denn es ist dieselbe Nachmittagsarbeit: Die Toleranz kann nicht unter einen Schritt des Logit-Typs gehen. Qwen3 erzeugt Logits in bfloat16, wo bei einer Größenordnung von 16 ein Schritt 0,125 beträgt — 0,05 zu verlangen heißt also, bitgenaue Gleichheit zu verlangen und sie Toleranz zu nennen.

Was es kostet, wenn es stimmt

Einen Absatz wert, denn das Kennzeichen ist in keiner Richtung umsonst, und der Tausch ist echt.

Bei einem kleinen Modell ist die Vokabularmatrix ein großer Anteil von allem. Ein Modell mit einem Vokabular von 128.000 Token und einer verborgenen Größe von 2.048 trägt allein in dieser Matrix rund 262 Millionen Parameter — bei einem Modell mit einer Milliarde Parametern also etwa ein Viertel davon. Binden halbiert diese Kosten, und bei einem so kleinen Modell ist der gesparte Speicher der Unterschied zwischen bequem hineinpassen und nicht.

Bei einem großen Modell ist dieselbe Matrix ein Rundungsfehler, und die zusätzliche Kapazität durch das Lösen ist mehr wert als der Speicher. Deshalb hängt die Wahl mit der Größe zusammen, und deshalb ist eine Vorgabe, die für die eine Familie richtig war, für die andere falsch — die beiden Bibliotheken waren nicht nachlässig. Jede beschrieb ihre eigenen Modelle.

Die Kurzfassung

  • tie_word_embeddings hat als Vorgabe false in phi3 und true in llama, in derselben Bibliothek.
  • Es falsch zu haben erzeugt flüssigen, schlechteren Text, keinen Fehler.
  • Wählen Sie keine Vorgabe: prüfen Sie, ob lm_head.weight in den Gewichten steht.
  • Dieselbe Regel gilt für Aufmerksamkeitsverzerrungen und für alles andere, was die Konfiguration weglassen kann.

Noch eines, weil es die Frage ist, die das immer aufwirft: Nein, am Namen des Modells, an seiner Parameterzahl oder an seiner Familie können Sie es nicht erkennen. Zwei Modelle desselben Herausgebers, einen Monat auseinander veröffentlicht, können sich unterscheiden. Die Dateiliste ist der einzige Ort, an dem die Antwort wohnt.

Geprüft gegen mlx-lm 0.31.3 am 6. September 2026.