← Kembali ke Blog

Benerin Context Length Ollama Sebelum Agent Lokal Kamu Mulai Lupa

Agent lokal jalan lancar sepuluh turn, lalu mulai ngulang-ngulang jawaban, lupa instruksi awal, atau jawab seolah separuh percakapan sebelumnya gak pernah ada. Modelnya yang sering disalahin. Padahal biasanya masalahnya di context window: Ollama cuma alokasi beberapa ribu token, percakapan tumbuh melewati batas itu, dan history-nya dipotong sebelum sampai ke model.

Kebingungannya datang dari dua angka berbeda yang dua-duanya kelihatan seperti "context length". ollama show nampilin maksimum yang dilatih ke model, seringnya 32k atau lebih. ollama ps nampilin yang beneran dialokasikan server di mesin ini, yang bisa cuma 4k. Selisih dua angka itulah tempat agent lokal kehilangan ingatan.

Panduan ini buat nutup selisih itu: baca alokasi asli, kunci budget per model, kecilin KV cache, dan buktiin tiap perubahan pakai angka dari hardware kamu sendiri.

Yang perlu disiapin

  • Ollama terpasang dan jalan (ollama --version)
  • Satu model yang support tool, misalnya qwen3:8b
  • curl dan Python 3
  • VRAM atau RAM yang cukup buat context yang mau kamu pakai

Langkah 1: Cek context yang beneran kamu dapat

Pull model, kirim satu request biar ke-load, lalu lihat apa yang dilakukan server:

ollama pull qwen3:8b
ollama run qwen3:8b "say hi" > /dev/null
ollama ps

Outputnya punya kolom CONTEXT dan PROCESSOR. Ini contoh dari dokumentasi Ollama, angka di mesin kamu bakal beda:

NAME             ID              SIZE      PROCESSOR    CONTEXT    UNTIL
gemma4:latest    c6eb396dbd59    9.6 GB    100% GPU     131072     2 minutes from now

CONTEXT itu alokasinya. PROCESSOR nunjukin apakah model dan cache-nya muat di GPU. Sekarang bandingin sama kartu model:

ollama show qwen3:8b

Perintah itu nampilin context length yang dipakai waktu model dilatih. Itu batas atas, bukan janji. Server milih angkanya sendiri berdasarkan VRAM yang tersedia. Menurut dokumentasi Ollama, default-nya bertingkat: di bawah 24 GiB VRAM dapat 4k, 24 sampai 48 GiB dapat 32k, dan 48 GiB ke atas dapat 256k. FAQ-nya masih nulis 4096 sebagai default, jadi dua halaman itu gak kompak. Percaya ollama ps aja, karena itu yang nggambarin proses yang sedang jalan.

Data yang sama bisa diambil lewat HTTP:

curl -s http://localhost:11434/api/ps | python3 -m json.tool

Tiap model yang ke-load melaporkan context_length, size, dan size_vram. Kalau size_vram lebih kecil dari size, sebagian model ada di RAM sistem dan generasinya bakal lambat banget.

Langkah 2: Naikin default server

Di Linux yang pakai service systemd, edit drop-in-nya, jangan file unit aslinya:

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

Kirim satu request, lalu cek /api/ps lagi. context_length harusnya 32768. Kalau masih 4096, environment variable-nya gak sampai ke proses:

systemctl show ollama -p Environment

Di macOS, aplikasinya baca variabel dari launchd. Set dulu, lalu tutup dan buka lagi Ollama:

launchctl setenv OLLAMA_CONTEXT_LENGTH 32768

Angka ini global. Model autocomplete 1B kamu juga kena, dan KV cache model itu di 32k adalah VRAM yang gak perlu kamu buang. Karena itu ada langkah berikutnya.

Langkah 3: Kunci budget per model

Modelfile bikin tiap model bawa default-nya sendiri, jadi setelan server yang dipakai bareng gak bisa diam-diam nurunin agent coding kamu.

FROM qwen3:8b
PARAMETER num_ctx 32768
PARAMETER temperature 0.7
PARAMETER repeat_penalty 1.05
SYSTEM """You are a coding assistant. Answer with patches, not essays."""
ollama create qwen3-agent -f Modelfile
ollama run qwen3-agent "list three uses of a ring buffer"
ollama ps

ollama ps sekarang harusnya nunjukin 32768 buat model turunan itu. Isi Modelfile-nya selalu bisa dicek:

ollama show --modelfile qwen3-agent | head -20

Pisahin model sesuai kerjaannya. Model chat di 8k, model coding di 32k, model embedding yang context budget-nya gak perlu dipikirin. Satu angka global maksa semua workload masuk ke amplop yang sama.

Satu catatan: client yang ngirim options.num_ctx eksplisit di /api/chat atau /api/generate bakal menang atas Modelfile. Kalau framework agent kamu set nilainya sendiri, Modelfile-nya cuma hiasan. Cek request yang dia kirim sebelum nyalahin server.

Langkah 4: Kecilin cache, bukan context-nya

Ukuran KV cache tumbuh seiring panjang context. Flash attention plus cache terkuantisasi adalah cara paling murah buat mempertahankan context panjang tanpa beli GPU baru. Dua-duanya environment variable di level server:

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"
sudo systemctl daemon-reload
sudo systemctl restart ollama
journalctl -u ollama -n 50 --no-pager | grep -iE "flash attention|kv_cache_type"

Log-nya harus nyebut flash attention dan tipe cache-nya. Kalau gak ada, setelannya gak kepasang.

Menurut dokumentasi, q8_0 makan memori sekitar setengah dari f16 dengan kehilangan presisi yang sangat kecil, dan q4_0 sekitar seperempat dengan kehilangan yang mulai kelihatan di context panjang. Cache terkuantisasi butuh flash attention; tanpa itu Ollama balik ke f16. Setelan ini juga global buat semua model yang di-load server, jadi kamu gak bisa campur tipe cache dalam satu proses.

Dampaknya ke kualitas tergantung model. Dokumentasi nyebut model dengan GQA tinggi, Qwen2 salah satunya, lebih sensitif ke kuantisasi cache. Kalau kamu mau q4_0 buat nambah headroom, jalankan prompt eval kamu di dua setelan itu sebelum dipakai serius.

Langkah 5: Hitung matematika paralelismenya

Request paralel mengalikan alokasi context. Dokumentasi kasih contohnya langsung: context 2K dengan 4 request paralel jadi context 8K, plus memori yang mengikuti. Kebutuhan memori skala dengan OLLAMA_NUM_PARALLEL kali OLLAMA_CONTEXT_LENGTH.

Jadi context 32k dengan empat slot paralel berarti 128k cache yang harus dialokasikan. Di kartu 12 GB itu biasanya berakhir jadi split CPU, dan split CPU lebih lambat daripada antrean.

Buat agent lokal single user:

[Service]
Environment="OLLAMA_CONTEXT_LENGTH=32768"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"

Kalau satu mesin dipakai beberapa orang, naikin OLLAMA_NUM_PARALLEL ke 2 atau 4 setelah cek sisa memori. Request di luar kapasitas antre sampai OLLAMA_MAX_QUEUE (default 512), lalu API balikin 503, yang setidaknya error jujur daripada timeout.

Langkah 6: Berhenti bayar biaya load

Model di-unload setelah 5 menit idle secara default. Agent yang jalan tiap 15 menit bayar harga load di setiap run, dan harganya kelihatan di load_duration tiap response.

[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"

Bisa juga diatur per request, dan itu menang atas default server:

curl http://localhost:11434/api/generate -d '{"model": "qwen3-agent", "keep_alive": "30m"}'
curl http://localhost:11434/api/generate -d '{"model": "qwen3-agent", "keep_alive": -1}'

Prompt kosong bikin model ke-preload. Nilai negatif bikin model tetap di memori sampai kamu lepas sendiri:

ollama stop qwen3-agent

Keep-alive panjang bagus di workstation dan jelek di host GPU bersama yang dipakai job lain. Pilih per mesin, bukan per tutorial.

Langkah 7: Ukur pakai API, bukan pakai feeling

Tiap response dari /api/generate bawa load_duration, prompt_eval_count, prompt_eval_duration, eval_count, dan eval_duration, semuanya dalam nanodetik. Itu cukup buat ngitung tiga angka yang penting: waktu load, kecepatan prefill, dan kecepatan decode.

# bench.py
import json
import sys
import urllib.request

model = sys.argv[1] if len(sys.argv) > 1 else "qwen3-agent"
payload = {
    "model": model,
    "prompt": "Explain the CAP theorem in three sentences.",
    "stream": False,
}
req = urllib.request.Request(
    "http://localhost:11434/api/generate",
    data=json.dumps(payload).encode(),
    headers={"Content-Type": "application/json"},
)
d = json.load(urllib.request.urlopen(req))

print(f"load     {d['load_duration'] / 1e9:6.2f} s")
print(f"prefill  {d['prompt_eval_count'] / (d['prompt_eval_duration'] / 1e9):6.1f} tok/s")
print(f"decode   {d['eval_count'] / (d['eval_duration'] / 1e9):6.1f} tok/s")
print(f"total    {d['total_duration'] / 1e9:6.2f} s")

Jalankan, ubah satu variabel, jalankan lagi. Kecepatan decode itu yang kamu rasain waktu baca jawaban. Kecepatan prefill itu yang dirasain agent kamu waktu dia nyodorin 20k token output tool ke prompt.

Buat nemuin plafon praktis, kirim prompt panjang dan pantau prefill:

# long_context.py
import json
import urllib.request

filler = "Latency is a distribution, not a number. " * 3000
payload = {
    "model": "qwen3-agent",
    "prompt": filler + "

In one sentence: what is the main idea above?",
    "stream": False,
}
req = urllib.request.Request(
    "http://localhost:11434/api/generate",
    data=json.dumps(payload).encode(),
    headers={"Content-Type": "application/json"},
)
d = json.load(urllib.request.urlopen(req))
print(d["prompt_eval_count"], "prompt tokens")
print(round(d["prompt_eval_count"] / (d["prompt_eval_duration"] / 1e9), 1), "prefill tok/s")

Jaga filler-nya tetap di bawah num_ctx kamu. Kalau prefill jatuh di 24k padahal kartu modelnya ngiklankan 128k, 24k itu plafon asli di kartu tersebut, dan sehebat apa pun prompt engineering-nya gak bakal ngubah itu.

Kalau ada yang aneh

  • Context masih 4096 setelah diubah: service belum di-restart, atau variabelnya masuk ke file unit bukan ke drop-in. Cek systemctl show ollama -p Environment.
  • PROCESSOR nunjukin split CPU/GPU: bobot plus cache-nya gak muat. Turunin num_ctx, ganti cache ke q8_0, atau pakai kuantisasi yang lebih kecil.
  • Jawaban berhenti di tengah kalimat: itu num_predict, bukan context. Bandingin eval_count sama limit yang kamu set.
  • API balikin 503: antreannya penuh. Tambah paralelisme cuma kalau memori cukup, kalau nggak ya serialisasi kerjanya.
  • Kualitas turun setelah pindah ke q4_0: wajar di beberapa model. Balik ke q8_0 dan pertahankan context-nya.

Loop yang layak dipertahankan

Baca context_length dari /api/ps. Kunci angkanya di Modelfile buat tiap jenis pekerjaan. Kuantisasi cache sebelum beli hardware. Jaga model tetap hangat di mesin yang sanggup. Lalu ukur load, prefill, dan decode setelah tiap perubahan.

Tiga angka dan satu file config per model jauh lebih berguna daripada nebak-nebak kenapa agent lupa instruksi ketiga lagi.

Referensi

Butuh Bantuan Implementasi?

Saya membantu tim mendesain dan membangun infrastruktur cloud scalable, pipeline DevOps, dan sistem production-grade.

Konsultasi Gratis