DeepSeek V4 Flash auf dem DGX Spark: unsere Einstellungen

Welche Flags wir für DeepSeek-V4-Flash im 3-Bit-Quant gesetzt haben — Kontext, KV-Cache, Sampler-Reihenfolge, DRY — und warum jede einzelne.

DeepSeek-V4-Flash hat 284 Milliarden Parameter, von denen bei jedem Token rund 13 Milliarden aktiv sind. Unsere Maschine ist ein DGX Spark mit 121 GB gemeinsamem Speicher. Das passt nicht — jedenfalls nicht in der Form, in der das Modell ausgeliefert wird. Wie wir es trotzdem betreiben, und welche Einstellung dabei am meisten ausgemacht hat, steht hier. Vorweg: Das ist ein Zwischenstand. Wir rechnen fest damit, dass wir in ein paar Wochen manches davon anders einstellen.

Der Quant: bewusst unterhalb des Auslegungspunkts

Wir fahren die Unsloth-Dynamic-Variante UD-IQ3_XXS, 97 GB in vier Teilen. Das ist eine bewusste Entscheidung gegen die Empfehlung des Herstellers — und wir halten sie trotzdem für richtig.

Der Grund für die Empfehlung: DeepSeek hat dieses Modell quantisierungsbewusst trainiert. Die gerouteten Experten liegen im offiziellen Checkpoint nativ in einem 4-Bit-Format vor. Auf Vier-Bit-Niveau ist eine Quantisierung deshalb praktisch verlustfrei; alles darunter komprimiert Gewichte, die kaum noch Spielraum haben.

Der Grund für unsere Entscheidung: Ein Q4-Build liegt bei rund 155 GB. Auf einer 121-GB-Maschine ist das keine Option, sondern eine Rechenaufgabe ohne Lösung. Wer das Modell auf einem einzelnen Spark betreibt, liegt zwangsläufig unterhalb des Punktes, für den es gebaut wurde. Diese Ehrlichkeit ist wichtig, weil sie erklärt, warum manche Probleme sich nicht wegkonfigurieren lassen — dazu am Schluss mehr.

Der Preis ist außerdem Zeit: Der Kaltstart dauert rund drei Minuten. Ein Modell, das zwischendurch entladen wird, ist damit für interaktive Nutzung unbrauchbar. Bei uns bleibt es deshalb resident, und ein Proxy davor sorgt dafür, dass alle Klienten dieselbe geladene Instanz benutzen, statt sich gegenseitig aus dem Speicher zu werfen.

Kontext: vier Slots à 96k statt eines großen Fensters

--ctx-size 393216 --parallel 4 --no-context-shift --ctx-checkpoints 32
--slot-prompt-similarity 0.5 --flash-attn on

Der gesamte Kontextspeicher wird auf vier gleichzeitige Slots aufgeteilt: rund 98.000 Token pro Slot. Das ist eine Abwägung, keine Optimierung. Wir haben mehrere Verbraucher — einen Assistenten im Dialog, eine nächtliche Schreib-Pipeline, mehrere Agenten —, und ein einzelnes riesiges Fenster hätte bedeutet, dass sie sich gegenseitig blockieren.

Wichtiger als die Zahl ist, was wir nicht gesetzt haben: Der KV-Cache läuft auf 16 Bit. Es ist verlockend, ihn zu quantisieren, weil er viel Speicher frisst — genau das ist bei diesem Modell aber eine bekannte Fehlerquelle und erzeugt verstümmelte Ausgaben. Die Regel, die wir daraus mitgenommen haben: Beim KV-Cache spart man nicht.

Sampling: die Werte des Herstellers, nicht die des Nachbarmodells

--temp 1.0 --top-p 0.95 --min-p 0.0

Das sind die Werte, die für dieses Modell empfohlen sind (top-p 0.95 ist die Variante für agentische Nutzung). Sie klingen unspektakulär, aber wir haben uns hier eine Lektion eingefangen: In unseren Klienten standen zunächst die Sampler-Werte eines anderen lokalen Modells — Temperatur 0,6, ein Top-K-Wert — schlicht deshalb, weil die Konfiguration von dort kopiert war. Eine niedrige Temperatur schadet dieser Architektur überproportional. Seitdem setzen wir die Werte in jedem Klienten ausdrücklich, damit keine Voreinstellung eines SDK die serverseitigen still überschreibt.

Die wichtigste Einstellung: die Reihenfolge der Sampler

--samplers top_k;top_p;min_p;temperature;dry;typ_p;xtc
--dry-multiplier 0.8 --dry-base 1.75 --dry-allowed-length 2 --dry-penalty-last-n 4096

Das ist die Änderung, die am meisten gebracht hat. Unser Problem waren ausufernde Generierungen: Das Modell schrieb tausende Token, ohne zum Ende zu kommen, teils in reine Wiederholung degenerierend.

Zwei Erkenntnisse haben das gelöst. Erstens gibt es einen Sampler, der genau dagegen gebaut ist: DRY bestraft nicht einzelne Tokens wie die klassische Repetition-Penalty, sondern erkennt wiederholte Sequenzen und bestraft deren Fortsetzung. Er ist in llama.cpp enthalten und standardmäßig deaktiviert.

Zweitens — und das ist der unintuitive Teil — entscheidet die Reihenfolge. Die Standardkette setzt die Strafen ganz nach vorn. Unsloth hat bei einem anderen Modell dokumentiert, dass eine naiv hinzugefügte Wiederholungsstrafe Endlosschleifen erzeugt statt sie zu verhindern; die Lösung war nicht ein anderer Wert, sondern eine andere Reihenfolge. Erst die Verteilung formen, dann bestrafen. Genau so ist unsere Kette aufgebaut.

Die allgemeine Lehre daraus haben wir uns notiert: Bei einem entgleisenden Modell ist die erste Frage nicht „welchen Wert drehe ich", sondern „welche Sampler laufen in welcher Reihenfolge" — und die zweite, ob der Quant überhaupt der ist, den der Hersteller für diese Maschine empfiehlt. Beide Fragen kosten Minuten. In unserer ursprünglichen Abwägung kamen sie nicht vor.

Was wir dabei gemessen haben

Zwei Zahlen, die man nicht in Datenblättern findet und die unsere Planung mehr verändert haben als jede Flag-Änderung.

Die Grundlast eines Agenten. Ein Assistent auf Basis einer Agenten-CLI startet jede Anfrage mit rund 25.000 bis 31.000 Token, bevor der Nutzer ein Wort gesagt hat — Systemprompt, Werkzeugbeschreibungen, Arbeitsanweisungen. Bei 98.000 Token pro Slot ist damit ein Drittel weg. Wer Kontextprobleme beurteilt, sollte zuerst die leere Anfrage messen.

Der Preis der Gleichzeitigkeit. Dieselbe Aufgabe brauchte 360 Sekunden, während ein zweiter Verbraucher mitrechnete, und 59 Sekunden, als die Maschine ihr allein gehörte. Faktor sechs. Vier parallele Slots bedeuten nicht vierfachen Durchsatz — sie bedeuten, dass vier Anfragen gleichzeitig stattfinden können. Für uns heißt das: Arbeit entzerren, nicht Slots erhöhen.

Was offen bleibt

Wir sind nicht fertig, und ein paar Dinge lassen sich mit Einstellungen grundsätzlich nicht lösen. Der Abstand zum Vier-Bit-Auslegungspunkt bleibt, solange die Maschine 121 GB hat — das ist eine Hardware-Frage, keine Konfigurationsfrage. Der KV-Cache dieses Modells hat nativ ein Format, das llama.cpp derzeit nicht abbilden kann; es gibt Forks, die das angehen, mit gemischten Berichten. Und die spekulative Dekodierung über ein Entwurfsmodell haben wir vorbereitet, aber noch nicht sauber vermessen.

Kurz: Der Stand oben ist das, was heute läuft, mit Begründung. In vier Wochen steht hier vermutlich etwas anderes — und dann schreiben wir auf, warum. Wie beim A/B-Test lokaler Dev-Modelle und bei drei Sprachmodellen auf einer Maschine gilt: Die Zahlen aus dem eigenen Betrieb sind mehr wert als jede Empfehlung, die man ungeprüft übernimmt.

Zurück zur Übersicht