Cara Tetapkan num_ctx Ollama untuk Prompt Panjang
Ollama memotong prompt panjang kerana had lalai yang rendah. Pelajari cara menetapkan num_ctx melalui Modelfile atau API serta pengiraan RAM yang diperlukan untuk model anda.
Fungsi num_ctx dan sebab prompt panjang anda dipotong
Panjang konteks Ollama ialah bilangan token yang boleh ditampung oleh model yang dimuatkan dalam memori pada satu-satu masa, dan num_ctx ialah pilihan yang menetapkannya. Ollama memilih nilai lalai yang jauh lebih rendah daripada maksimum yang diiklankan oleh model, jadi prompt yang lebih panjang akan dipotong sebelum model sempat membacanya. Tiada apa-apa dalam respons yang memberitahu anda bahawa perkara ini berlaku.
Llama 3.1 8B disenaraikan dengan tetingkap konteks 128k pada pustaka model Ollama. Pelayan standard tidak akan memberikan anda nilai tersebut. Dokumentasi Ollama sendiri mempunyai nilai lalai yang berbeza pada halaman yang berlainan: FAQ menyatakan 4096 token, rujukan Modelfile menyatakan num_ctx secara lalai ialah 2048, dan halaman panjang konteks menyatakan nilai lalai dipilih berdasarkan VRAM (video RAM) yang tersedia, iaitu 4k untuk bawah 24 GiB, 32k untuk 24 hingga 48 GiB, dan 256k untuk melebihi nilai tersebut. Setiap satu pernah benar pada binaan tertentu. Percanggahan itu adalah pengajaran yang berguna di sini: baca nilai daripada pelayan anda sendiri yang sedang berjalan dan jangan mempercayai mana-mana halaman, termasuk halaman ini.
Pemotongan berlaku secara senyap kerana model masih memberikan jawapan, dan jawapan tersebut masih boleh dibaca dengan baik. Ia ditulis berdasarkan bahagian akhir input anda. Ringkasan yang tertinggal separuh pertama dokumen kelihatan seperti model yang lemah. Biasanya, ini berpunca daripada tetingkap konteks yang kecil.
Semak panjang konteks Ollama yang sebenarnya digunakan oleh pelayan anda
Semakan yang berkesan pada mana-mana binaan ialah prompt_eval_count, iaitu kiraan token prompt yang dilaporkan oleh pelayan telah diproses. Hantar lebih banyak daripada yang boleh ditampung oleh konteks dan nombor tersebut akan terhenti pada hadnya.
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}'Prompt tersebut mengandungi kira-kira 18,000 perkataan, jadi ia jauh melebihi 4096 token. prompt_eval_count kembali dengan nilai hampir 4096 dan bukannya hampir dengan kiraan token sebenar, kerana pelayan telah membuang bahagian selebihnya. Jalankan semula dengan "num_ctx":16384 dan kiraan tersebut akan meningkat. Jika binaan anda memaparkan ralat dan bukannya memotong data, itu adalah penemuan yang sama dengan isyarat yang lebih jelas.
ollama psLajur CONTEXT, pada binaan yang memaparkannya, mengandungi panjang konteks yang sedang dijalankan oleh model yang dimuatkan pada masa ini. Lajur PROCESSOR di sebelahnya menunjukkan kedudukan model tersebut. 100% CPU adalah normal pada VPS tanpa GPU. Pembahagian seperti 30%/70% CPU/GPU pada kotak GPU bermakna pemberat (weights) berserta cache tidak lagi muat dalam VRAM, dan num_ctx yang tinggi biasanya menjadi puncanya.
journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5Pelari inferens (inference runner) mencetak saiz konteksnya dalam satu baris yang mengandungi n_ctx. Perkataan tepatnya berubah antara keluaran, jadi anggap baris yang hilang sebagai penamaan semula dan bukannya bukti bagi apa-apa perkara.
Empat lokasi untuk menetapkan num_ctx
Dalam permintaan. Hantar "options": {"num_ctx": 16384} kepada /api/generate atau /api/chat. Nilai ini mengatasi semua tetapan lain dan hanya terpakai untuk panggilan tersebut. Jika nilainya berbeza daripada apa yang sedang dijalankan oleh model yang dimuatkan, pelayan akan memuatkan semula model tersebut terlebih dahulu. Anda boleh melihatnya dalam load_duration pada respons: nilainya melonjak daripada hampir sifar kepada beberapa saat.
Dalam sesi interaktif. Di dalam ollama run, taip /set parameter num_ctx 16384. Tetapan ini kekal untuk sesi tersebut sahaja.
Dalam Modelfile. Ini membakar nilai tersebut ke dalam model yang dinamakan, supaya setiap klien mendapatkannya tanpa sebarang perubahan pada bahagian klien.
FROM llama3.1:8b
PARAMETER num_ctx 16384ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16kPada pelayan. OLLAMA_CONTEXT_LENGTH menetapkan nilai lalai bagi setiap permintaan yang tidak membawa num_ctx sendiri. Di bawah systemd, tambahkan fail drop-in dan bukannya menyunting fail unit.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama psKeutamaan (precedence) adalah perkara paling penting apabila anda menyahpepijat klien orang lain. Permintaan yang membawa num_ctx mengatasi nilai lalai pelayan. Oleh itu, front-end sembang atau ejen yang menghantar nilai kecilnya sendiri akan membatalkan perubahan systemd anda secara senyap. Apabila anda menghalakan ejen pengekodan ke pelayan Ollama anda, periksa perkara yang dihantar oleh klien sebelum anda menyalahkan pelayan.
Mengapa anda tidak boleh menetapkan num_ctx kepada maksimum model
Mekanisme attention menyebabkan setiap token melihat setiap token sebelumnya. Key dan value yang dikira untuk token terdahulu disimpan supaya ia tidak perlu dikira semula bagi setiap token baharu, dan storan ini dikenali sebagai KV cache (key/value cache). Ia diperuntukkan untuk keseluruhan num_ctx apabila model dimuatkan, bukan mengikut pertumbuhan perbualan, jadi konteks yang besar akan menggunakan memori tersebut walaupun untuk prompt satu baris.
Tutorial kos inferens DigitalOcean menyatakan pengiraan tersebut dalam satu baris:
kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_valueAngka 2 mengira key dan value secara berasingan. Dapatkan nombor lain daripada model anda sendiri.
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 melaporkan 32 layer dan 8 key/value head. Dimensi head ialah embed dibahagikan dengan heads, jadi 4096 / 32 = 128 di sini, dan sesetengah model menerbitkannya secara terus sebagai llama.attention.key_length. Cache lalai menyimpan nilai f16, jadi bytes_per_value ialah 2, dan 2 32 8 128 2 menghasilkan 131,072 bait. Ini adalah 128 KiB cache untuk setiap satu token konteks. Darabkan dengan panjang konteks dan kos tersebut tidak lagi menjadi abstrak.
The data behind this chart
[
{
"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
}
]6 baris tersebut adalah hasil aritmetik daripada formula di atas, bukan ukuran sebenar. Lajur jumlah menambah muat turun 4.9 GB yang disenaraikan oleh pustaka Ollama untuk llama3.1:8b pada Ogos 2026, iaitu 4.6 GiB, dan ia tidak termasuk compute buffer serta proses pelayan itu sendiri. Anggap ia sebagai nilai minimum.
Bentuknya adalah perkara utama. Pada 8k, kos cache ialah 1 GiB, yang merupakan jumlah kecil berbanding berat model (weights). Pada kapasiti penuh 128k model tersebut, kosnya ialah 16 GiB, lebih tiga kali ganda daripada berat model, dengan jumlah keseluruhan hampir 20.6 GiB. Jadi, VPS 4 GB tidak boleh memuatkan model ini pada mana-mana konteks yang berguna. VPS 8 GB selesa pada 8k. VPS 16 GB mencapai 32k dengan ruang yang masih berbaki untuk kegunaan sistem lain. Setiap ambang tersebut meningkat mengikut berat model, jadi jika anda menimbang model yang lebih besar berbanding 8B ini, pengiraan yang sama seperti yang dilakukan untuk tag Qwen 27B pada VPS CPU sahaja menunjukkan betapa sedikit ruang yang ditinggalkan oleh berat model untuk konteks antara 8 dan 64 GB.
Apa yang berlaku apabila KV cache tidak mencukupi
Pada VPS yang hanya menggunakan CPU, saiz proses akan terus meningkat. Pantau proses tersebut semasa model dimuatkan dan semasa permintaan panjang sedang dijalankan.
free -m
ps -eo rss,comm --sort=-rss | head -n 5RSS (resident set size) dipaparkan dalam unit kilobyte. Jika penggunaan swap dalam free -m mula meningkat, kurangkan tetapan konteks. KV cache yang berada dalam swap akan menyebabkan penjanaan terhenti selama beberapa saat bagi setiap token, kerana setiap token baharu perlu membaca keseluruhan cache tersebut.
Jika pelayan kehabisan memori sepenuhnya, kernel akan memilih proses yang paling besar dan menamatkannya.
sudo dmesg | grep -i "killed process"Baris yang memaparkan Out of memory: Killed process 1234 (ollama) bermaksud konteks yang diminta tidak mencukupi. Ollama sering menolak permintaan sebelum mencapai tahap tersebut, dan permintaan akan gagal dengan mesej yang menyatakan jumlah memori yang diperlukan berbanding memori yang tersedia.
Pada pelayan yang menggunakan GPU, kegagalan berlaku dengan cara yang lebih senyap. Layer akan melimpah ke dalam RAM sistem, ollama ps akan menunjukkan pembahagian antara CPU dan GPU, dan kadar throughput akan merosot dengan ketara. Tahap kemerosotan bergantung pada perkakasan anda, jadi ukur token sesaat pada pelayan anda sendiri bagi setiap tetapan konteks dan jangan hanya bergantung pada angka daripada mesin orang lain.
Masa prefill meningkat lebih pantas daripada prompt
Prefill ialah kerja yang dilakukan pada input anda sebelum token output pertama muncul. Setiap token prompt memberikan perhatian kepada setiap token sebelumnya, jadi jumlah kerja meningkat mengikut kuasa dua panjang input. Menggandakan prompt akan meningkatkan masa menunggu untuk token pertama lebih daripada dua kali ganda.
Respons tersebut membawa ukuran berkenaan, jadi anda tidak perlu mempercayainya secara membuta tuli.
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)}'Jalankan arahan tersebut dengan prompt yang pendek dan sekali lagi dengan prompt yang panjang, kemudian bahagikan jumlah token dengan saat bagi setiap kes. Pada VPS yang hanya menggunakan CPU, prefill biasanya merupakan bahagian paling perlahan bagi permintaan konteks panjang, dan angka token sesaat yang diambil daripada prompt pendek tidak akan dapat meramalkannya.
Konkurensi adalah bahagian yang paling terkesan dengan masalah ini. Setiap permintaan yang dilayan memerlukan cache tersendiri, jadi memori dalam carta di atas adalah bagi setiap permintaan dan bukannya bagi setiap pelayan, dan satu permintaan yang panjang boleh menahan pelayan sementara permintaan pendek beratur di belakangnya. Tetapkan OLLAMA_NUM_PARALLEL dengan sengaja, dan baca berapa ramai pengguna serentak yang boleh dilayan oleh satu LLM yang dihoskan sendiri sebelum anda meningkatkan kedua-dua angka tersebut secara serentak.
Dapatkan semula konteks dengan cache yang lebih kecil
bytes_per_value dalam formula tersebut ialah tetapan yang anda kawal. FAQ Ollama mendokumentasikan OLLAMA_KV_CACHE_TYPE, dengan f16 sebagai lalai pada 2 bait, ditambah q8_0 pada 1 bait dan q4_0 di bawah nilai tersebut. Beralih kepada q8_0 akan mengurangkan saiz cache kepada separuh, jadi baris 32k akan menggunakan 2 GiB dan bukannya 4 GiB. FAQ yang sama mendokumentasikan OLLAMA_FLASH_ATTENTION=1, yang diperlukan oleh sesetengah binaan sebelum cache terkuantisasi (quantised cache) berkuat kuasa.
[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"Sahkan dan jangan buat andaian: mulakan semula servis, muatkan model pada num_ctx yang sama seperti sebelumnya, dan bandingkan RSS. Sokongan bergantung pada model dan backend, jadi tetapan yang tidak mengubah apa-apa bermakna kombinasi anda tidak disokong. Dokumentasi menyenaraikan pilihan ini tanpa menjamin hasil yang berkualiti, jadi uji q4_0 dengan prompt anda sendiri sebelum anda bergantung padanya. Jika parameter ini adalah sebab anda berada di sini, Ollama dan llama.cpp mendedahkannya secara berbeza.
Resipi untuk memilih num_ctx
- Baca konteks maksimum model, jumlah lapisan, dan jumlah head key/value daripada
/api/show. - Kira bait bagi setiap token menggunakan formula tersebut, kemudian darabkan dengan konteks yang anda inginkan.
- Tambahkan saiz berat (weight), bandingkan dengan RAM yang bebas, dan pastikan sekurang-kurangnya 1 GiB dikhaskan untuk kegunaan sistem yang lain.
- Tetapkan nilai tersebut, muatkan model, kemudian sahkan nilai yang digunakan dengan
ollama psdanprompt_eval_count. - Jalankan beban kerja sebenar anda sambil memantau
free -m, dan kurangkan konteks kepada separuh jika swap mula aktif.
Kebanyakan tugasan memerlukan konteks yang lebih kecil daripada jangkaan pengguna. Meringkaskan laporan panjang memadai dengan 16k. Antara muka perolehan (retrieval front end) yang menampal lima cebisan dokumen jarang melebihi 8k. Ejen pengekodan yang membaca keseluruhan fail adalah kes yang benar-benar memerlukan 64k atau lebih, dan ini juga merupakan kes di mana anda perlu menyesuaikan saiz mesin mengikut konteks dan bukannya sebaliknya. Jika pelayan masih baharu, mulakan daripada pemasangan Ollama yang berfungsi pada VPS dan laraskan konteks sebaik sahaja model dimuatkan dengan lancar.
FAQ
Apakah panjang konteks lalai dalam Ollama?
Ia bergantung pada binaan dan perkakasan, jadi semak dahulu dan jangan membuat andaian. FAQ Ollama mendokumentasikan 4096 token, rujukan Modelfile mendokumentasikan num_ctx lalai sebanyak 2048, dan halaman panjang konteks mendokumentasikan nilai lalai yang dipilih berdasarkan VRAM yang tersedia: 4k untuk bawah 24 GiB, 32k untuk 24 hingga 48 GiB, dan 256k untuk ke atas. VPS yang hanya menggunakan CPU akan mendapat nilai yang rendah. ollama ps mencetak konteks yang digunakan pada binaan yang menyertakan lajur tersebut, dan prompt_eval_count dalam respons API membuktikannya pada setiap binaan.
Mengapa Ollama mengabaikan bahagian awal prompt saya yang panjang?
Ini kerana prompt tersebut lebih panjang daripada tetingkap konteks, jadi pelayan memotongnya sebelum model melihatnya, dan tiada ralat dikembalikan. Hantar semula prompt yang sama dengan num_ctx yang lebih besar dan perhatikan prompt_eval_count dalam respons meningkat. Jika nombor tersebut tidak berubah, sesuatu antara anda dan pelayan sedang menetapkan num_ctx itu sendiri, yang merupakan perkara biasa pada antaramuka sembang dan rangka kerja ejen.
Berapa banyak RAM tambahan yang diperlukan oleh num_ctx yang lebih besar?
Darabkan panjang konteks dengan kos cache bagi setiap token, iaitu 2 * layers * kv_heads * head_dim * bytes_per_value. Untuk Llama 3.1 8B pada f16, nilainya ialah 128 KiB bagi setiap token, jadi 32k token menelan kos 4 GiB dan 128k penuh menelan kos 16 GiB sebagai tambahan kepada berat model. Cache diperuntukkan apabila model dimuatkan, jadi num_ctx yang besar akan menggunakan memori tersebut walaupun prompt anda kekal pendek.
Adakah tetingkap konteks yang lebih besar menjadikan Ollama lebih perlahan?
Ya, dalam dua cara. Kerja pra-isi (prefill) meningkat mengikut kuasa dua panjang prompt, jadi input yang panjang melambatkan token pertama lebih daripada yang dijangkakan berdasarkan panjangnya. Cache yang lebih besar juga bersaing untuk mendapatkan memori: pada mesin GPU, ia menolak lapisan model ke dalam RAM sistem, dan pada mesin CPU, ia menolak mesin ke arah swap. num_ctx yang besar yang tidak pernah anda penuhi masih menelan kos memori, walaupun ia tidak menjejaskan masa pra-isi.
Bolehkah saya menetapkan num_ctx secara kekal untuk satu model?
Ya. Tulis Modelfile yang mengandungi FROM llama3.1:8b dan PARAMETER num_ctx 16384, kemudian jalankan ollama create llama3.1-16k -f ./Modelfile. Setiap klien yang meminta llama3.1-16k akan mendapat konteks tersebut tanpa perlu menghantar sebarang pilihan. Permintaan yang membawa num_ctx sendiri masih akan diutamakan, jadi ini menetapkan nilai lalai dan bukannya had maksimum.