Self-hosting artinya menjalankan model open-weight (model yang file bobotnya boleh diunduh) di mesinmu sendiri, bukan memanggil API provider. Ollama adalah program yang mengunduh model, menjalankannya, dan membuka API HTTP di localhost:11434. Bayangin masak di dapur sendiri dibanding pesan antar. Bahannya dibeli sekali, kompor dan gas kamu yang tanggung, gak ada ongkos per porsi, dan gak ada orang lain yang tahu kamu masak apa. Tapi dapurmu cuma punya satu kompor: kalau sepuluh tamu datang bersamaan, mereka antre.
🧪 Tebakan cepat:
qwen3:4b-instruct, model 4 miliar parameter, dijalankan Ollama di laptop M1 Pro 16 GB. Berapa memori yang dipakainya saat menjawab: sekitar 1 GB, sekitar 3 GB, atau sekitar 8 GB? Tebak dulu, jawabannya ada di bagian "Ukuran model: hitung memorinya".
Ollama dalam empat perintah
Versi terbaru di GitHub per Oktober 2026: Ollama 0.40.2 (rilis 8 Oktober 2026). Pasang dari ollama.com/download, lalu di terminal:
ollama pull qwen3:4b-instruct # unduh model, 2,5 GB
ollama run qwen3:4b-instruct "Halo" # coba langsung di terminal
ollama ps # model yang sedang dimuat, ukurannya, GPU atau CPU
ollama stop qwen3:4b-instruct # keluarkan dari memori
Model di library Ollama (ollama.com/library) yang populer: Llama (Meta, misalnya llama3.2), Mistral (Mistral AI, mistral 7B), Gemma (Google, gemma4), dan Qwen (qwen3). GPT dan Claude gak bisa di-self-host: bobotnya gak dibagikan, jadi cuma bisa dipakai lewat API. "Open-weight" belum tentu bebas dipakai apa saja; lisensinya beda per model (metadata qwen3:4b menulis apache-2.0), jadi cek sebelum dipakai untuk bisnis.
API-nya: /api/chat mengalirkan NDJSON
Server Toko Buku memanggil Ollama seperti memanggil API lain, tanpa API key. Bedanya dengan pelajaran Streaming: Ollama gak memakai SSE, tapi NDJSON (newline-delimited JSON): satu objek JSON utuh per baris. Ini respons asli yang direkam dari Ollama 0.40.2 di laptop M1 Pro 16 GB, 11 Oktober 2026, untuk pertanyaan stok dengan <data_stok> (yang sama yang diputar ulang di Lab):
{"model":"qwen3:4b-instruct","created_at":"2026-10-11T03:56:52.850956Z","message":{"role":"assistant","content":"Ya"},"done":false}
{"model":"qwen3:4b-instruct","created_at":"2026-10-11T03:56:52.876316Z","message":{"role":"assistant","content":","},"done":false}
... 16 baris lagi ...
{"model":"qwen3:4b-instruct","created_at":"2026-10-11T03:56:53.289062Z","message":{"role":"assistant","content":""},"done":true,"done_reason":"stop","total_duration":2356862167,"load_duration":1603703000,"prompt_eval_count":116,"prompt_eval_cached_count":0,"prompt_eval_duration":299435000,"eval_count":19,"eval_duration":439680000}
Gabungan isinya: "Ya, stok Laskar Pelangi masih ada sebanyak 12." Baris terakhir ("done": true) membawa hitungan dalam nanodetik: total 2,36 detik, 1,60 detik di antaranya memuat model, dan 19 token output dalam 0,44 detik = 43 token per detik.
const res = await fetch("http://localhost:11434/api/chat", {
method: "POST",
body: JSON.stringify({ model: "qwen3:4b-instruct", messages }),
});
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
let sisa = "";
for (;;) {
const { value, done } = await reader.read();
if (done) break;
sisa += value;
const baris = sisa.split("\n");
sisa = baris.pop(); // baris terakhir mungkin belum lengkap
for (const b of baris) {
if (!b.trim()) continue;
const potong = JSON.parse(b);
kirimKeBrowser(potong.message.content);
if (potong.done) console.log(potong.eval_count / (potong.eval_duration / 1e9), "token/detik");
}
}
- Satu potongan jaringan bisa berisi setengah baris, jadi sisa terakhir disimpan untuk dibaca bersama potongan berikutnya.
"stream": falsedi body membuat Ollama membalas satu JSON utuh.- Panggil dari server, bukan langsung dari browser pelanggan.
/api/embed dan endpoint yang kompatibel dengan OpenAI
Embedding untuk RAG juga bisa lokal. POST /api/embed dengan {"model":"all-minilm","input":["Stok Laskar Pelangi masih ada?","Ada novel tentang sekolah di Belitung?"]} membalas {"embeddings":[[...],[...]]}. Hasil ukur: tiap vector 384 angka dengan panjang 1, dan cosine kedua kalimat itu 0,5567.
Ollama juga membuka endpoint dengan bentuk OpenAI di /v1: /v1/chat/completions, /v1/responses (tanpa previous_response_id), dan /v1/embeddings. SDK openai tinggal diarahkan ke sana:
import OpenAI from "openai";
const ollama = new OpenAI({ baseURL: "http://localhost:11434/v1/", apiKey: "ollama" }); // wajib diisi, tapi diabaikan
const r = await ollama.chat.completions.create({ model: "qwen3:4b-instruct", messages });
// r.choices[0].message.content: "Tidak, Bumi Manusia tidak ada karena stoknya 0."
Ukuran model: hitung memorinya
Memori untuk bobot = jumlah parameter × bit per bobot ÷ 8. Kuantisasi artinya menyimpan bobot dengan bit lebih sedikit: lebih kecil dan lebih cepat, sedikit kurang akurat. README llama-quantize dari llama.cpp (diukur di Llama 3.1 8B): Q4_K_M 4,89 bit per bobot (sekitar 0,61 byte), Q8_0 8,50 bit, F16 16 bit (2 byte).
| Model | Q4_K_M | Q8_0 | F16 |
|---|---|---|---|
| 4B (4,02 miliar parameter) | 2,46 GB (library Ollama: 2,5 GB) | 4,27 GB (4,3 GB) | 8,04 GB (8,1 GB) |
| 12B | 7,34 GB | 12,75 GB | 24 GB |
Di atas bobot ada KV cache (simpanan perhitungan tiap token di context, makin panjang context makin besar) dan buffer. Hasil ukur qwen3:4b-instruct di laptop tadi, dari /api/ps: 3,18 GB, dengan context 4.096 token dan 100% di GPU. Itu jawaban tebakannya: 2,50 GB file bobot plus 0,68 GB KV cache dan buffer. KV cache-nya bisa dihitung dari metadata model: 36 layer × 8 kepala KV × 128 dimensi × 2 (key dan value) × 2 byte × 4.096 token = 0,60 GB.
Di laptop itu Ollama melihat 11,8 GiB dari 16 GiB yang bisa dipakai GPU. Jadi model 12B di Q4_K_M (sekitar 8 GB) muat, Q8_0 (13,4 GB) gak muat. Ollama memakai context 4.096 token kalau memori GPU di bawah 24 GiB. Context lebih panjang, atau OLLAMA_NUM_PARALLEL lebih dari 1, menambah KV cache. Cek kolom PROCESSOR di ollama ps: kalau sebagian pindah ke CPU, jawabannya jauh lebih lambat.
Kecepatan, diukur dengan jujur
Hasil ukur di laptop yang sama (sambil program lain jalan; ukur di mesinmu sendiri):
| Kejadian | Waktu |
|---|---|
| Request pertama, model dimuat dulu | 2,36 detik (1,60 detik memuat model) |
| Request berikutnya, model sudah di memori | 0,50 detik (115 dari 116 token prompt dari cache Ollama) |
| 4 request bersamaan | selesai di 0,61, 1,05, 1,50, 1,95 detik |
qwen3:4b versi thinking, pertanyaan sama |
30,9 detik: 938 token output untuk satu kalimat |
- Model tetap di memori 5 menit setelah dipakai (bisa diatur dengan
keep_alive), jadi request pertama setelah lama diam selalu lambat. OLLAMA_NUM_PARALLELbawaannya 1: request lain antre. Antrean penuh (bawaannya 512) dibalas503.- Model "thinking" menulis penalaran dulu. Untuk pertanyaan stok, pilih model instruct.
Privasi, dan kapan API hosted lebih murah
Keuntungan utama self-hosting: data tetap di server sendiri dan gak ada biaya per request ke pihak ketiga. Itu penting untuk data yang gak boleh keluar (catatan medis, dokumen internal), kerja offline, dan percobaan prompt ratusan kali tanpa tagihan. Sebagai pembanding, halaman "Your data" OpenAI (Oktober 2026): data API gak dipakai untuk melatih model kecuali kamu memilih ikut, log penyalahgunaan bisa disimpan sampai 30 hari, dan Responses API menyimpan respons 30 hari kecuali store: false.
Biaya gak otomatis lebih murah. Asisten Toko Buku dengan gpt-6-luna (400 token masuk, 40 keluar): 10.000 pertanyaan sehari = $0,60 sehari, $18 sebulan. Mesin GPU sendiri, listrik, dan waktu merawatnya jelas lebih dari $18 sebulan, dan model 4B belum tentu lolos eval set seperti gpt-6-luna. Self-host baru menang hitungan kalau volumenya besar dan stabil, atau kalau datanya memang gak boleh keluar.
⚠️ Jebakan yang sering ketemu
- Memilih model dari jumlah parameter saja. Hitung memorinya: bobot dari kuantisasi, ditambah KV cache. F16 12B butuh sekitar 25 GB.
- Mengukur kecepatan dari request pertama. Yang pertama ikut memuat model. Ukur request kedua, dan ukur juga beberapa request bersamaan.
- Membaca stream Ollama sebagai SSE. Formatnya NDJSON: pisahkan per baris, simpan sisa baris yang belum lengkap.
- Mengira self-host selalu gratis. Gak ada tagihan per token, tapi ada mesin, listrik, perawatan, dan antrean di jam ramai.
TL;DR: Ollama menjalankan model open-weight (Llama, Mistral, Gemma, Qwen) di mesinmu: ollama pull, ollama run, ollama ps, API di localhost:11434. /api/chat mengalirkan NDJSON, satu JSON per baris, dan baris "done": true membawa durasi dalam nanodetik; /api/embed membuat embedding; /v1 kompatibel dengan SDK OpenAI (baseURL: "http://localhost:11434/v1/", apiKey diisi apa saja). Memori ≈ parameter × bit per bobot ÷ 8 (Q4_K_M 4,89 bit, Q8_0 8,50, F16 16) plus KV cache: qwen3:4b-instruct memakai 3,18 GB di M1 Pro 16 GB, 12B di Q4_K_M sekitar 8 GB. Hasil ukur: 43 token per detik, request pertama 2,36 detik, berikutnya 0,50 detik, dan request bersamaan antre. Keuntungan utamanya data tetap di server sendiri tanpa biaya per request; untuk volume kecil seperti Toko Buku ($18 sebulan di gpt-6-luna), API hosted lebih murah.