SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor

Ollama num_ctx setzen und Kontextlänge erhöhen

Lange Prompts werden bei Ollama standardmäßig abgeschnitten. Setzen Sie num_ctx pro Anfrage oder serverweit und prüfen Sie den KV-Cache-RAM vor einer Erhöhung.

Wofür num_ctx steht und warum Ihr langer Prompt abgeschnitten wurde

Die Ollama-Kontextlänge gibt an, wie viele Tokens ein geladenes Modell gleichzeitig im Speicher halten kann. num_ctx ist die Option, die diesen Wert festlegt. Ollama wählt standardmäßig einen Wert, der deutlich unter dem vom Modell angegebenen Maximum liegt. Deshalb wird ein längerer Prompt abgeschnitten, bevor das Modell ihn überhaupt liest. Die Antwort enthält keinen Hinweis darauf, dass dies geschehen ist.

Llama 3.1 8B wird in der Ollama-Modellbibliothek mit einem Kontextfenster von 128k angegeben. Ein Server mit Standardeinstellungen stellt diesen Wert nicht bereit. Die eigene Dokumentation von Ollama nennt auf verschiedenen Seiten unterschiedliche Standardwerte: Die FAQ nennt 4096 Tokens, die Modelfile-Referenz gibt für num_ctx den Standardwert 2048 an, und auf der Seite zur Kontextlänge heißt es, dass der Standardwert anhand des verfügbaren VRAM (Video-RAM) gewählt wird: 4k bei weniger als 24 GiB, 32k ab 24 GiB bis unter 48 GiB und 256k ab 48 GiB. Jeder dieser Werte war für bestimmte Builds korrekt. Die wichtige Schlussfolgerung aus dieser Abweichung lautet: Lesen Sie den Wert auf Ihrem eigenen laufenden Server aus, statt einer beliebigen Seite zu vertrauen, auch nicht dieser.

Das Abschneiden bleibt unbemerkt, weil das Modell weiterhin antwortet und die Antwort weiterhin schlüssig wirkt. Sie wurde jedoch nur aus dem Ende Ihrer Eingabe erstellt. Eine Zusammenfassung, in der die erste Hälfte eines Dokuments fehlt, wirkt wie die Ausgabe eines schwachen Modells. Meist ist stattdessen das Kontextfenster zu klein.

Prüfen, welche Kontextlänge der Server für Ollama tatsächlich verwendet

Die Prüfung, die mit jedem Build funktioniert, ist prompt_eval_count. Dabei handelt es sich um die Anzahl der Prompt-Tokens, deren Verarbeitung der Server meldet. Senden Sie mehr Text, als in den Kontext passt, bleibt diese Zahl am Limit stehen.

sudo apt update && sudo apt install -y jq
LONG=$(python3 -c "print('the quick brown fox jumps over the lazy dog. ' * 2000)")
jq -n --arg p "$LONG" '{model:"llama3.1:8b", prompt:$p, stream:false, options:{num_ctx:4096}}' |
  curl -s http://localhost:11434/api/generate -d @- |
  jq '{prompt_eval_count, prompt_eval_duration}'

Dieser Prompt umfasst etwa 18,000 Wörter und damit deutlich mehr als 4096 Tokens. prompt_eval_count gibt einen Wert nahe 4096 statt nahe der tatsächlichen Tokenanzahl zurück, weil der Server den restlichen Text verworfen hat. Führen Sie den Befehl mit "num_ctx":16384 erneut aus. Dann steigt die Anzahl. Gibt Ihr Build statt einer Kürzung einen Fehler zurück, ist das dieselbe Erkenntnis mit einem eindeutigeren Signal.

ollama ps

Die Spalte CONTEXT enthält bei Builds, die sie ausgeben, die Kontextlänge, mit der das geladene Modell aktuell läuft. Die danebenstehende Spalte PROCESSOR zeigt, wo sich das Modell befindet. 100% CPU ist auf einem VPS ohne GPU normal. Eine Aufteilung wie 30%/70% CPU/GPU auf einem GPU-Server bedeutet, dass die Gewichte und der Cache nicht mehr vollständig in den VRAM passen. Ein erhöhter Wert für num_ctx ist dafür normalerweise die Ursache.

journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5

Der Inference Runner gibt seine Kontextgröße in einer Zeile aus, die n_ctx enthält. Die genaue Formulierung ändert sich zwischen Releases. Interpretieren Sie daher eine fehlende Zeile als Umbenennung und nicht als Beleg für eine bestimmte Konfiguration.

Vier Stellen zum Setzen von num_ctx

In der Anfrage. Senden Sie "options": {"num_ctx": 16384} an /api/generate oder /api/chat. Diese Einstellung hat Vorrang vor allen anderen und gilt nur für diesen Aufruf. Wenn der Wert von der Context-Größe abweicht, mit der das geladene Modell ausgeführt wird, lädt der Server das Modell zuerst neu. Das sehen Sie in load_duration der Antwort: Der Wert steigt von nahezu null auf ganze Sekunden. Dieselbe Wartezeit tritt auf, wenn das Modell lange genug inaktiv war und entladen wurde. Sobald Sie eine Context-Größe festgelegt haben, empfiehlt es sich daher, das Modell mit keep_alive resident zu halten.

In der interaktiven Sitzung. Geben Sie innerhalb von ollama run /set parameter num_ctx 16384 ein. Die Einstellung gilt für diese Sitzung.

In einer Modelfile. Dadurch wird der Wert in ein benanntes Modell übernommen. Jeder Client erhält ihn dann ohne Änderung auf Client-Seite.

FROM llama3.1:8b
PARAMETER num_ctx 16384
ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16k

Auf dem Server. OLLAMA_CONTEXT_LENGTH legt den Standardwert für jede Anfrage fest, die kein eigenes num_ctx enthält. Unter systemd fügen Sie ein Drop-in hinzu, statt die Unit-Datei zu bearbeiten.

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"
sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama ps

Die Priorität ist besonders wichtig, wenn Sie den Client einer anderen Person debuggen. Eine Anfrage mit num_ctx hat Vorrang vor dem Serverstandard. Ein Chat-Frontend oder ein Agent, der selbst einen kleinen Wert sendet, macht Ihre systemd-Änderung dadurch unbemerkt rückgängig. Wenn Sie einen Coding-Agent auf Ihren Ollama-Server verweisen, prüfen Sie, was der Client sendet, bevor Sie den Server als Ursache vermuten.

Warum Sie num_ctx nicht einfach auf das maximale Kontextfenster des Modells setzen können

Bei der Attention sieht jedes Token alle vorherigen Tokens. Die für frühere Tokens berechneten Keys und Values werden gespeichert, damit sie für jedes neue Token nicht erneut berechnet werden müssen. Dieser Speicher ist der KV-Cache (Key/Value-Cache). Er wird beim Laden des Modells für die gesamte Größe von num_ctx reserviert und wächst nicht mit der Unterhaltung. Ein großer Kontext belegt den Speicher daher auch bei einer einzeiligen Eingabe.

Jede Schicht speichert für jedes Token einen Key-Vektor und einen Value-Vektor pro Key/Value-Head. Die Berechnung passt daher in eine Zeile:

kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_value

Die 2 zählt Keys und Values getrennt. Die übrigen Zahlen können Sie aus Ihrem eigenen Modell ablesen.

curl -s http://localhost:11434/api/show -d '{"model":"llama3.1:8b"}' |
  jq '.model_info | {ctx: ."llama.context_length", layers: ."llama.block_count", heads: ."llama.attention.head_count", kv_heads: ."llama.attention.head_count_kv", embed: ."llama.embedding_length"}'

Llama 3.1 8B verwendet 32 Schichten und 8 Key/Value-Heads. Die Head-Dimension ergibt sich aus embed geteilt durch heads, also hier 4096 / 32 = 128. Einige Modelle geben diesen Wert direkt als llama.attention.key_length an. Der Standard-Cache verwendet f16-Werte, daher ist bytes_per_value gleich 2. Die Rechnung 2 32 8 128 2 ergibt 131,072 Byte. Das entspricht 128 KiB Cache für jedes einzelne Kontext-Token. Multipliziert mit der Kontextlänge werden die Kosten konkret.

DiagrammLlama 3.1 8B at f16: KV cache and total RAM by context length, in GiB
Die Daten hinter diesem Diagramm
[
  {
    "label": "4k",
    "kv_cache_gib": 0.5,
    "total_ram_gib": 5.1
  },
  {
    "label": "8k",
    "kv_cache_gib": 1,
    "total_ram_gib": 5.6
  },
  {
    "label": "16k",
    "kv_cache_gib": 2,
    "total_ram_gib": 6.6
  },
  {
    "label": "32k",
    "kv_cache_gib": 4,
    "total_ram_gib": 8.6
  },
  {
    "label": "64k",
    "kv_cache_gib": 8,
    "total_ram_gib": 12.6
  },
  {
    "label": "128k",
    "kv_cache_gib": 16,
    "total_ram_gib": 20.6
  }
]

Die 6 Zeilen sind aus der obigen Formel berechnet und keine Messwerte. Die Spalte „Gesamt“ addiert den 4.9-GB-Download, den die Ollama-Bibliothek im Oktober 2026 für llama3.1:8b angegeben hat. Das entspricht 4.6 GiB. Rechenpuffer und der Serverprozess selbst sind nicht enthalten. Betrachten Sie den Wert als Untergrenze.

Entscheidend ist die Größenordnung. Bei 8k belegt der Cache 1 GiB. Das fällt gegenüber den Gewichten kaum ins Gewicht. Beim vollständigen Kontext von 128k belegt er 16 GiB. Das ist mehr als das Dreifache der Gewichte. Insgesamt werden nahezu 20.6 GiB benötigt. Ein VPS mit 4 GB kann dieses Modell daher mit keinem praktisch nutzbaren Kontext laden. Ein VPS mit 8 GB bietet bei 8k ausreichend Spielraum. Ein VPS mit 16 GB erreicht 32k und lässt noch Speicher für die übrigen Dienste des Systems. Mit den Gewichten steigen alle diese Grenzwerte. Wenn Sie ein größeres Modell mit diesem 8B-Modell vergleichen, zeigt die gleiche Berechnung für Qwens 27B-Tag auf einem VPS ohne GPU wie wenig Speicher zwischen 8 und 64 GB für den Kontext übrig bleibt.

Was geschieht, wenn der KV-Cache nicht in den Arbeitsspeicher passt

Auf einer CPU-only-VPS wächst der Prozess einfach weiter. Überwachen Sie ihn während des Modell-Ladevorgangs und während eine lange Anfrage ausgeführt wird.

free -m
ps -eo rss,comm --sort=-rss | head -n 5

RSS (resident set size) wird in Kilobyte ausgegeben. Wenn der verwendete Swap in free -m ansteigt, reduzieren Sie den Kontext. Ein KV-Cache im Swap lässt die Generierung auf mehrere Sekunden pro Token abbremsen, weil jeder neue Token den gesamten Cache liest.

Wenn der Arbeitsspeicher des Systems vollständig erschöpft ist, wählt der Kernel einen Prozess zum Beenden aus, normalerweise den Prozess mit dem höchsten Speicherverbrauch.

sudo dmesg | grep -i "killed process"

Eine Zeile mit Out of memory: Killed process 1234 (ollama) bedeutet, dass Ollama der vom Kernel ausgewählte Prozess war. Das bedeutet nicht unbedingt, dass Ollama den Speicherverbrauch verursacht hat. Wenn Ollama der einzige Prozess mit hohem Speicherverbrauch auf dem System ist, ist ein zu großer Kontext die übliche Ursache. Prüfen Sie, was vor dem Abschneiden von num_ctx noch ausgeführt wurde. Ollama bricht häufig bereits vorher ab. Die Anfrage schlägt dann mit einer Meldung fehl, die den benötigten Speicher dem freien Speicher gegenüberstellt.

Auf einem System mit GPU ist der Fehler weniger offensichtlich. Layer werden in den System-RAM ausgelagert, ollama ps zeigt die Aufteilung zwischen CPU und GPU, und der Durchsatz sinkt stark. Wie stark er sinkt, hängt von Ihrer Hardware ab. Messen Sie daher die Tokens pro Sekunde auf Ihrem eigenen System bei jeder Kontexteinstellung, statt einem Wert von einem anderen System zu vertrauen.

Prefill-Zeit steigt schneller als die Prompt-Länge

Prefill bezeichnet die Verarbeitung Ihrer Eingabe, bevor das erste Ausgabetoken erscheint. Jedes Prompt-Token berücksichtigt alle vorhergehenden Tokens. Daher steigt der Gesamtaufwand quadratisch mit der Eingabelänge. Wenn Sie den Prompt verdoppeln, dauert es bis zum ersten Token mehr als doppelt so lange.

Die Antwort enthält die Messwerte. Sie müssen diese daher nicht ungeprüft übernehmen.

jq -n --arg p "$LONG" '{model:"llama3.1:8b", prompt:$p, stream:false, options:{num_ctx:16384}}' |
  curl -s http://localhost:11434/api/generate -d @- |
  jq '{tokens: .prompt_eval_count, prefill_seconds: (.prompt_eval_duration/1000000000)}'

Führen Sie den Vorgang mit einem kurzen Prompt und anschließend mit einem langen Prompt aus. Teilen Sie die Tokenanzahl jeweils durch die benötigte Zeit in Sekunden. Auf einer VPS nur mit CPU ist das Prefill bei einer Anfrage mit langem Kontext meist der langsamste Teil. Ein für einen kurzen Prompt ermittelter Wert in Token pro Sekunde lässt sich daher nicht auf lange Prompts übertragen. Dauert das Prefill länger als das davorliegende Timeout, wird ein langer Prompt normalerweise als Kontext-Deadline überschritten statt mit einer Antwort zurückgegeben. Ermitteln Sie daher, welche Schicht den Vorgang vorzeitig abgebrochen hat, bevor Sie den Kontext verkürzen.

Bei gleichzeitiger Verarbeitung mehrerer Anfragen ist dieser Effekt besonders problematisch. Jede verarbeitete Anfrage benötigt einen eigenen Cache. Der Speicherbedarf in der obigen Grafik gilt daher pro Anfrage und nicht pro Server. Eine einzige lange Anfrage kann den Server auslasten, während kurze Anfragen dahinter warten. Setzen Sie OLLAMA_NUM_PARALLEL bewusst. Lesen Sie wie viele gleichzeitige Benutzer ein selbst gehostetes LLM bedienen kann, bevor Sie beide Werte gemeinsam erhöhen.

Mit einem kleineren Cache Kontext zurückgewinnen

bytes_per_value in der Formel ist eine Einstellung, die Sie steuern können. Die FAQ von Ollama dokumentiert OLLAMA_KV_CACHE_TYPE, wobei f16 der Standardwert ist, q8_0 ungefähr die Hälfte des Speichers von f16 benötigt und q4_0 ungefähr ein Viertel. Der genaue Wert für q8_0 liegt etwas über der Hälfte: llama.cpp speichert jeden Block aus 32 Werten als 32 Ein-Byte-Werte plus eine Zwei-Byte-Skalierung. Das ergibt 34 Byte, während f16 64 Byte benötigt. Durch den Wechsel zu q8_0 sinkt die 32k-Zeile daher auf etwa 2.1 GiB statt 4 GiB. Die Quantisierung der Gewichte gibt auf der anderen Seite desselben Budgets Speicher frei. Der GLM-Tag, der tatsächlich auf einen VPS passt, wird dabei Quantisierung für Quantisierung behandelt, falls Sie diesen Kompromiss bevorzugen. Dieselbe FAQ weist darauf hin, dass der Cache nur bei aktiviertem Flash Attention quantisiert wird, und dokumentiert OLLAMA_FLASH_ATTENTION=1, um die Funktion zu erzwingen.

[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"

Prüfen Sie das Ergebnis, statt es anzunehmen: Starten Sie den Dienst neu, laden Sie das Modell mit demselben num_ctx wie zuvor und vergleichen Sie den RSS-Wert. Die Unterstützung hängt vom Modell und vom Backend ab. Eine Einstellung, die nichts ändert, wird von Ihrer Kombination daher nicht unterstützt. Der Cache-Typ ist eine globale Option. Daher verwenden alle Modelle auf dem Server diese Einstellung. Zur Qualität sagt die FAQ, dass q8_0 normalerweise keinen wahrnehmbaren Effekt hat. q4_0 verliert dagegen mehr Genauigkeit, besonders bei größeren Kontextgrößen. Testen Sie daher q4_0 mit Ihren eigenen Prompts, bevor Sie sich darauf verlassen. Falls diese Optionen der Grund für Ihre Suche sind, stellen Ollama und llama.cpp sie unterschiedlich bereit.

Vorgehensweise zur Auswahl von num_ctx

  1. Lesen Sie den maximalen Kontext des Modells, die Anzahl seiner Layer und die Anzahl seiner Key/Value-Heads aus /api/show.
  2. Berechnen Sie mit der Formel die Byte-Anzahl pro Token und multiplizieren Sie sie anschließend mit dem gewünschten Kontext.
  3. Addieren Sie die Größe der Gewichte, vergleichen Sie das Ergebnis mit dem freien RAM und reservieren Sie mindestens 1 GiB für die übrigen Aufgaben des Servers.
  4. Setzen Sie den Wert, laden Sie das Modell und prüfen Sie anschließend mit ollama ps und prompt_eval_count, welcher Wert angewendet wurde.
  5. Führen Sie Ihre tatsächliche Arbeitslast aus und beobachten Sie dabei free -m. Halbieren Sie den Kontext, sobald Swap-Aktivität einsetzt.

Die meisten Aufgaben benötigen weniger Kontext, als häufig vorgegeben wird. Zum Zusammenfassen eines langen Berichts reichen 16k. Ein Retrieval-Frontend, das fünf Dokumentabschnitte einfügt, überschreitet selten 8k. Ein Coding-Agent, der vollständige Dateien einliest, ist der Anwendungsfall, der tatsächlich 64k oder mehr benötigt. In diesem Fall sollten Sie die Hardware anhand des Kontexts dimensionieren und nicht umgekehrt. Wenn der Server selbst noch neu ist, beginnen Sie mit einer funktionierenden Ollama-Installation auf einem VPS und optimieren Sie den Kontext, sobald die Modelle fehlerfrei geladen werden.

FAQ

Welcher ist der standardmäßige Kontextumfang in Ollama?

Das hängt vom Build und von der Hardware ab. Prüfen Sie den Wert daher, statt ihn vorauszusetzen. Die Ollama-FAQ nennt 4096 Token, die Modelfile-Referenz dokumentiert einen num_ctx-Standardwert von 2048, und die Seite zum Kontextumfang dokumentiert einen Standardwert, der anhand des verfügbaren VRAM ausgewählt wird: 4k unter 24 GiB, 32k ab 24 GiB bis unter 48 GiB und 256k ab 48 GiB. Eine CPU-only-VPS liegt am unteren Ende. ollama ps gibt den angewendeten Kontextumfang in Builds aus, die diese Spalte enthalten, und prompt_eval_count in einer API-Antwort bestätigt ihn in jedem Build.

Warum ignoriert Ollama den Anfang meines langen Prompts?

Weil der Prompt länger als das Kontextfenster war. Der Server hat ihn daher gekürzt, bevor das Modell ihn gesehen hat, ohne einen Fehler zurückzugeben. Senden Sie denselben Prompt erneut mit einem größeren num_ctx und beobachten Sie, ob prompt_eval_count in der Antwort zunimmt. Wenn sich dieser Wert nicht ändert, setzt etwas zwischen Ihnen und dem Server num_ctx selbst. Das ist bei Chat-Frontends und Agent-Frameworks häufig der Fall.

Wie viel zusätzlichen RAM benötigt ein größerer num_ctx?

Multiplizieren Sie den Kontextumfang mit den Cache-Kosten pro Token. Diese betragen 2 * layers * kv_heads * head_dim * bytes_per_value. Bei Llama 3.1 8B mit f16 sind das 128 KiB pro Token. 32k Token benötigen daher 4 GiB, und die vollständigen 128k benötigen zusätzlich zu den Gewichten 16 GiB. Der Cache wird beim Laden des Modells reserviert. Ein großer num_ctx belegt diesen Speicher daher auch dann, wenn Ihre Prompts kurz bleiben.

Macht ein größeres Kontextfenster Ollama langsamer?

Ja, und zwar auf zwei Arten. Der Prefill-Aufwand wächst mit dem Quadrat der Prompt-Länge. Eine lange Eingabe verzögert das erste Token daher stärker, als es ihre Länge vermuten lässt. Der größere Cache konkurriert außerdem um Speicher: Auf einem GPU-System verschiebt er Layer in den System-RAM, und auf einem CPU-System bringt er den Rechner näher an den Swap. Ein großer num_ctx, den Sie nie vollständig nutzen, belegt den Speicher trotzdem. Die Prefill-Zeit steigt dadurch jedoch nicht.

Kann ich num_ctx dauerhaft für ein Modell festlegen?

Ja. Schreiben Sie ein Modelfile mit FROM llama3.1:8b und PARAMETER num_ctx 16384 und führen Sie anschließend ollama create llama3.1-16k -f ./Modelfile aus. Jeder Client, der llama3.1-16k anfordert, erhält diesen Kontextumfang, ohne Optionen zu übergeben. Eine Anfrage mit einem eigenen num_ctx hat weiterhin Vorrang. Damit legen Sie einen Standardwert fest, aber keine Obergrenze.