NVIDIA rilis Dory 1.0 4B, model reasoning yang blok tengahnya bisa di-loop 1 sampai 4 kali per token. Kita coba bangun llama.cpp versi pinned, ukur memori KV, tes kecepatan decode, dan evaluasi GSM8K biar tau naik loop beneran bikin pintar atau cuma makan waktu.
NVIDIA baru ngeluarin Dory 1.0 4B, model reasoning kecil dari Nemotron Labs yang punya trik unik: blok lapisan tengahnya dibagi jadi grup input, recurrent, dan output. Yang bikin beda, blok recurrent ini bisa diaplikasiin sekali, dua, tiga, atau empat kali untuk setiap token yang dihasilin. Artinya, dari satu file checkpoint 3.7 GB GGUF, kamu bisa dapet empat 'model' dengan budget komputasi beda-beda tanpa perlu retraining atau download file baru. Kita ikutin tutorial lengkap dari MarkTechPost yang bangun llama.cpp dari commit pinned NVIDIA, download GGUF Q5_K_M, terus analisis arsitekturnya langsung dari header file biar tau persis tiap loop makan parameter dan cache berapa.
Langkah pertama, kita harus build llama-server dari fork llama.cpp yang masih draft PR, jadi belum ada di release resmi. Commit yang dipin NVIDIA adalah 98a74c9, dan kita compile dengan flag khusus: Metal di Mac, CUDA kernels untuk GPU yang ada di Colab (misal T4 compute 7.5), dan matiin flash-attention soalnya card NVIDIA nyuruh --flash-attn off. Build-nya butuh waktu beberapa menit, tapi hasilnya binary yang pasti cocok sama arsitektur Dory. Setelah server jalan, kita cek header GGUF dan nemu fakta menarik: model punya 16 lapisan input, 40 lapisan recurrent (shared block), dan 16 lapisan output. Total parameter 3.98 miliar, dengan 1.84 miliar di blok recurrent. Header juga nyimpen default num_loops = 4, padahal model card NVIDIA merekomendasikan 2. Ini berarti kalau kamu jalanin server tanpa override, dia diam-diam pakai setting paling mahal.
Kenapa override loop wajib diset manual
Kita tes tujuh konfigurasi: 1-4 loop dengan mode cache per_loop dan last_loop. Mode per_loop nyimpen cache KV terpisah untuk setiap loop di setiap lapisan attention recurrent, jadi memori KV tumbuh linear: dari 306 MiB di 1 loop jadi 816 MiB di 4 loop (context 4096 token). Mode last_loop cuma nyimpen cache loop terakhir, jadi footprint KV tetap 306 MiB berapa pun jumlah loop. Tapi ada jebakannya: last_loop baru sama hasilnya sama per_loop kalau prompt muat dalam satu micro-batch (default 512 token). Kalau prompt panjang dan dipotong chunk 16 token, cache loop sebelumnya ketimpa dan distribusi next-token beda signifikan. Kita buktiin lewat 50 soal GSM8K sebagai prompt mentah, minta top-20 logprob, bandingin total-variation distance. Hasilnya: satu chunk, last_loop = per_loop persis; pecah chunk, last_loop diverge di 2 dan 4 loop.
Loop lebih banyak, decode lebih lambat tapi parameter per token naik
Kita ukur kecepatan decode dengan prompt tetap, generate 192 token greedy tiga kali ambil median. Di 1 loop per_loop: ~45 tok/s. Di 4 loop per_loop: ~18 tok/s. Slowdown measured 2.5x, sedangkan rasio parameter per token dari prediksi 2.51x. Berarti decode behaves hampir compute-bound, weight bytes read ratio 2.28x. Prefill speed relatif stabil karena input block dan output block cuma dilewati sekali. Ini penting buat kamu yang mau trade-off latency vs reasoning depth: naik loop bikin model 'pikir' lebih lama per token, tapi gak nambah parameter model. File GGUF tetap 3.7 GB, cuma komputasi inference yang naik.
Evaluasi GSM8K: akurasi naik tipis, panjang jawab turun, waktu per soal naik
Kita jalanin evaluasi paired GSM8K 30 soal, seed tetap per soal, sampling settings dari model card (temp 1.0, top-p 0.95), reasoning on, max 2048 token. Bandingin 5 setting: 1 loop, 2 loop per/last, 4 loop per/last. Akurasi 1 loop 63%, 2 loop per_loop 70%, 4 loop per_loop 73%. Wilson 95% CI tumpang tindih luas soalnya sample cuma 30, jadi beda kecil belum signifikan statistik. McNemar exact test: 4 loop vs 1 loop only-A 3 soal, only-B 1 soal, p=0.625. Median token per jawaban turun dari 1 loop (1.120 token) ke 4 loop (780 token), bootstrap CI [0.58, 0.82], konsisten sama klaim card kalau lebih banyak loop butuh token reasoning lebih sedikit. Tapi wall-time per soal terpecahkan naik drastis: 1 loop ~45 detik, 4 loop ~110 detik, karena decode lambat dan akurasi naik gak sebanding.
Dari seluruh eksperimen, dua pelajaran praktis yang hold apa pun hardware kamu: pertama, selalu set --override-kv dory.num_loops=int:N,dory.recurrent_kv_cache_mode=str:per_loop|last_loop saat start server, karena default GGUF adalah 4 loop (paling mahal) dan mode per_loop. Kedua, pin commit llama.cpp ke 98a74c9, jangan pakai main branch atau release terbaru, soalnya support Dory masih draft PR dan bisa breaking kapan aja. Kalau kamu cuma butuh reasoning ringan, 1 atau 2 loop last_loop hemat VRAM dan cepet. Kalau mau reasoning maksimal dan punya waktu, 4 loop per_loop. File GGUF sama, cuma angka loop yang beda, inilah test-time compute jadi load-time setting.
Catatan redaksi
Kalau lo cuma ambil satu hal dari artikel ini
NVIDIA rilis Dory 1.0 4B, model reasoning yang blok tengahnya bisa di-loop 1 sampai 4 kali per token. Kita coba bangun llama.cpp versi pinned, ukur memori KV, tes kecepatan decode, dan evaluasi GSM8K biar tau naik loop beneran bikin pintar atau cuma makan waktu.


