โ† Semua pembelajaran / Python untuk AI Engineer
Fase 4 ยท Bicara dengan LLM

Prompt Caching

Prompt caching bisa memangkas biaya input sampai 90%. Kuncinya satu: cache bekerja dengan mencocokkan awalan prompt.

Intisari

  • Satu aturan yang menjelaskan semuanya: cache adalah prefix match. Satu byte berubah di depan, semua cache setelahnya hangus.
  • Urutan render prompt: tools โ†’ system โ†’ messages. Taruh yang stabil di depan.
  • Baca cache โ‰ˆ 0,1ร— harga input. Tulis cache โ‰ˆ 1,25ร— (TTL 5 menit) atau 2ร— (TTL 1 jam).
  • Pembatal senyap yang paling sering: timestamp di system prompt, UUID, json.dumps tanpa sort_keys.
  • Verifikasi dengan usage.cache_read_input_tokens. Kalau selalu 0, ada yang membatalkan cache.

Satu invarian yang menjelaskan semuanya

Prompt caching adalah pencocokan awalan (prefix match). Kunci cache dihitung dari byte prompt yang sudah dirender, sampai ke titik cache_control. Perubahan satu byte di posisi ke-N membatalkan cache untuk semua titik pada posisi โ‰ฅ N.

Urutan render:

tools  โ†’  system  โ†’  messages

Jadi menandai blok system terakhir dengan cache_control akan meng-cache tools dan system sekaligus. Dan mengubah satu tool membatalkan seluruhnya, karena tools berada di posisi paling depan.

Cara memakainya

Otomatis โ€” paling sederhana

response = client.messages.create(
    model="claude-opus-5",
    max_tokens=16000,
    cache_control={"type": "ephemeral"},    # cache blok terakhir yang bisa di-cache
    system=dokumen_besar,
    messages=[{"role": "user", "content": "Ringkas poin utamanya"}],
)

Manual โ€” kendali penuh

response = client.messages.create(
    model="claude-opus-5",
    max_tokens=16000,
    system=[
        {"type": "text", "text": INSTRUKSI_TETAP},
        {
            "type": "text",
            "text": dokumen_besar,
            "cache_control": {"type": "ephemeral"},     # titik potong di sini
        },
    ],
    messages=[{"role": "user", "content": pertanyaan}],  # bagian yang berubah-ubah
)
{"type": "ephemeral"}                 # TTL 5 menit (default)
{"type": "ephemeral", "ttl": "1h"}    # TTL 1 jam

Ekonominya

OperasiBiaya relatif
Input biasa1ร—
Tulis cache, TTL 5 menit1,25ร—
Tulis cache, TTL 1 jam2ร—
Baca cache0,1ร—

Titik impasnya:

Batas minimum yang bisa di-cache

ModelMinimum
Claude Opus 5512 token
Opus 4.8, Sonnet 5, Sonnet 4.61.024 token
Opus 4.72.048 token
Opus 4.6, Haiku 4.54.096 token

Prompt di bawah batas ini tidak akan di-cache โ€” tanpa error apa pun. Kamu hanya akan melihat cache_creation_input_tokens: 0. Perhatikan bahwa angkanya tidak berurutan antar generasi model, jadi cek tabelnya, jangan mengira-ira.

Pembatal senyap

Saat meninjau kode, cari pola berikut di bagian yang menyusun awalan prompt:

PolaKenapa merusak
datetime.now() di system promptAwalan berubah tiap request
uuid4() atau request ID di awal kontenSama โ€” selalu unik
json.dumps(d) tanpa sort_keys=TrueUrutan key bisa berubah
Iterasi atas setUrutannya tidak dijamin
ID pengguna di-interpolasi ke system promptTiap pengguna punya awalan sendiri
System prompt dirakit dengan if flag:Tiap kombinasi flag = awalan berbeda
tools=build_tools(user)Tools di posisi 0 โ€” tidak ada yang ter-cache

Prinsip arsitektur

1. Bekukan system prompt

# โŒ awalan berubah tiap request
system = f"Kamu asisten. Tanggal hari ini: {datetime.now():%Y-%m-%d}"

# โœ… konteks dinamis ditaruh di messages, jauh di belakang
system = "Kamu asisten."
messages = [
    *riwayat,
    {"role": "user", "content": f"[tanggal: {hari_ini}]\n\n{pertanyaan}"},
]

2. Jangan ubah tools atau model di tengah percakapan

Tools berada di posisi 0. Menambah, menghapus, atau mengubah urutannya membatalkan seluruh cache. Serialisasikan daftar tool secara deterministik (urutkan berdasarkan nama). Berganti model juga membatalkan cache โ€” cache bersifat per-model.

3. Untuk instruksi yang datang di tengah

messages = [
    *riwayat,
    {"role": "user", "content": pesan_pengguna},
    {"role": "system", "content": "Mode ringkas aktif โ€” jawab di bawah 40 kata."},
]

Pesan role: "system" di dalam messages (didukung Claude Opus 5 dan Opus 4.8) menambahkan instruksi operator tanpa mengubah awalan. Mengedit system tingkat atas akan membuat seluruh riwayat percakapan diproses ulang dengan harga penuh.

Verifikasi

u = response.usage
print(f"tulis cache : {u.cache_creation_input_tokens}")
print(f"baca cache  : {u.cache_read_input_tokens}")
print(f"tanpa cache : {u.input_tokens}")

Kalau cache_read_input_tokens selalu 0 pada request berulang dengan awalan yang seharusnya sama, ada pembatal senyap. Cara menemukannya: rakit prompt untuk dua request berturut-turut, simpan ke file, lalu diff byte-nya.

Perhatikan juga: input_tokens hanya menghitung sisa yang tidak ter-cache.

total = u.input_tokens + u.cache_creation_input_tokens + u.cache_read_input_tokens

Hierarki pembatalan

Yang berubahCache toolsCache systemCache messages
Definisi toolโŒโŒโŒ
Ganti modelโŒโŒโŒ
Isi system promptโœ…โŒโŒ
tool_choice, aktif/nonaktif thinkingโœ…โœ…โŒ
Isi pesanโœ…โœ…โŒ

Jadi mengubah tool_choice per request itu aman โ€” cache tools dan system tetap terpakai.

Batas teknis

Di mana ini paling berdampak

KasusYang di-cachePenghematan
Chatbot RAGSystem prompt + definisi toolBesar โ€” dipakai tiap giliran
Tanya jawab atas satu dokumen besarIsi dokumenSangat besar
Loop agenticRiwayat percakapan yang tumbuhSangat besar
Klasifikasi batchInstruksi + contoh few-shotBesar
Panggilan sekali, prompt pendekโ€”Tidak ada; jangan pakai cache

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.