> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Panduan Penggunaan Cache Konteks Gemini

> Buat dan gunakan kembali cache konteks Gemini (Context Cache) melalui API Chat Completions yang kompatibel dengan OpenAI atau API native Gemini. Gunakan cache_control untuk menyimpan prefiks stabil ke cache dan mengurangi biaya token dari konten panjang yang berulang.

Panduan ini menjelaskan cara membuat dan menggunakan kembali cache konteks Gemini (Context Cache) melalui API Chat Completions yang kompatibel dengan OpenAI atau API native Gemini.

Sebelum memulai:

```bash theme={null}
export API_KEY="KUNCI_API_ANDA"
```

<Note>Contoh dalam panduan ini menggunakan `gemini-3.6-flash`. Untuk mengetahui apakah model lain mendukung Context Cache, lihat deskripsi model dan halaman harga di platform.</Note>

## Kasus penggunaan

Jika beberapa permintaan berulang kali menyertakan blok konten besar yang sama, Anda dapat menyimpan prefiks stabil ke cache, misalnya:

* System prompt yang sangat panjang
* Basis pengetahuan tetap atau dokumentasi produk
* Pesan riwayat yang stabil dalam percakapan multi-giliran
* Definisi dan petunjuk tool yang digunakan berulang kali

Context Cache cocok untuk permintaan dengan “konten awal yang tetap sama dan hanya pertanyaan terakhir yang terus berubah”.

## Penggunaan dasar

Tambahkan `cache_control` ke blok konten pada pesan terakhir dalam prefiks stabil:

```json theme={null}
{
  "type": "text",
  "text": "Ini adalah bagian konten terakhir dalam prefiks stabil",
  "cache_control": {
    "type": "ephemeral",
    "ttl": "5m"
  }
}
```

TTL yang didukung:

| TTL  | Arti                 |
| ---- | -------------------- |
| `5m` | Cache selama 5 menit |
| `1h` | Cache selama 1 jam   |

<Note>Jika `ttl` dihilangkan, nilai defaultnya adalah `5m`.</Note>

## Struktur pesan

Sebaiknya gunakan struktur berikut:

```text theme={null}
system
→ Teks panjang atau pesan riwayat yang stabil
→ Batas prefiks stabil dengan cache_control
→ Pertanyaan pengguna saat ini (tidak disimpan ke cache)
```

Pesan yang memuat `cache_control` dan semua pesan sebelumnya membentuk prefiks yang disimpan ke cache. Setidaknya harus ada satu pesan real-time setelahnya.

## Contoh permintaan yang kompatibel dengan OpenAI

```bash theme={null}
curl "https://api.apimart.ai/v1/chat/completions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.6-flash",
    "stream": false,
    "messages": [
      {
        "role": "system",
        "content": "Jawab pertanyaan hanya berdasarkan materi referensi yang diberikan."
      },
      {
        "role": "user",
        "content": "Tempatkan materi referensi panjang yang akan digunakan berulang kali di sini…"
      },
      {
        "role": "assistant",
        "content": [
          {
            "type": "text",
            "text": "Saya telah membaca dan memahami materi referensi di atas.",
            "cache_control": {
              "type": "ephemeral",
              "ttl": "5m"
            }
          }
        ]
      },
      {
        "role": "user",
        "content": "Ringkas tiga poin utama dalam materi referensi tersebut."
      }
    ]
  }'
```

Saat permintaan dikirim untuk pertama kalinya, sistem akan mencoba membuat cache dan menggunakannya untuk menyelesaikan permintaan saat ini.

<Note>Anda tidak perlu memanggil endpoint terpisah untuk membuat cache. `cache_control` sekaligus menetapkan “batas cache” dan “masa berlaku cache”.</Note>

## Contoh permintaan native Gemini

Endpoint native Gemini `generateContent` juga mendukung penambahan `cache_control` di dalam `contents[].parts[]`:

```bash theme={null}
curl "https://api.apimart.ai/v1beta/models/gemini-3.6-flash:generateContent" \
  -H "x-goog-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemInstruction": {
      "parts": [
        {
          "text": "Jawab pertanyaan hanya berdasarkan materi referensi yang diberikan."
        }
      ]
    },
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Tempatkan materi referensi panjang yang akan digunakan berulang kali di sini…"
          }
        ]
      },
      {
        "role": "model",
        "parts": [
          {
            "text": "Saya telah membaca dan memahami materi referensi di atas.",
            "cache_control": {
              "type": "ephemeral",
              "ttl": "5m"
            }
          }
        ]
      },
      {
        "role": "user",
        "parts": [
          {
            "text": "Ringkas tiga poin utama dalam materi referensi tersebut."
          }
        ]
      }
    ]
  }'
```

`cache_control` adalah kolom ekstensi platform dalam format permintaan Gemini. Setelah mengidentifikasi batas, platform menghapus kolom ini sebelum meneruskan permintaan, lalu secara otomatis membuat atau menggunakan kembali konten cache (`cachedContent`).

Antarmuka streaming menggunakan isi permintaan yang sama; Anda hanya perlu mengubah alamat menjadi:

```bash theme={null}
curl -N "https://api.apimart.ai/v1beta/models/gemini-3.6-flash:streamGenerateContent?alt=sse" \
  -H "x-goog-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Tempatkan materi referensi panjang yang akan digunakan berulang kali di sini…",
            "cache_control": {
              "type": "ephemeral",
              "ttl": "5m"
            }
          }
        ]
      },
      {
        "role": "user",
        "parts": [
          {
            "text": "Ringkas tiga poin utama dalam materi referensi tersebut."
          }
        ]
      }
    ]
  }'
```

Saat menggunakan kembali cache, pertahankan `systemInstruction`, `contents` sebelum batas, TTL, dan tools tanpa perubahan; ubah hanya konten real-time setelah batas.

## Alur pembuatan dan penggunaan kembali

Saat Anda mengirim permintaan dengan `cache_control` untuk pertama kalinya:

```text theme={null}
Identifikasi prefiks stabil
→ Buat Context Cache
→ Rujuk cache baru dalam permintaan saat ini
→ Kembalikan hasil model
```

Saat Anda mengirim kembali prefiks stabil yang sama:

```text theme={null}
Identifikasi prefiks stabil yang sama
→ Gunakan kembali Context Cache yang belum kedaluwarsa
→ Kirim hanya konten real-time saat ini
→ Kembalikan hasil model
```

Oleh karena itu, permintaan pertama juga dapat langsung mengembalikan token cache dalam jumlah besar. Ini adalah perilaku normal dan tidak mengharuskan Anda mengirim “permintaan pemanasan” terlebih dahulu.

## Menggunakan kembali cache

Pada permintaan berikutnya, pertahankan hal-hal berikut tanpa perubahan:

* Model
* Semua pesan sebelum `cache_control`
* `cache_control.ttl`
* Definisi tool (jika menggunakan tools)
* `systemInstruction` dalam permintaan native Gemini

Ubah hanya pertanyaan real-time setelah batas:

```json theme={null}
{
  "role": "user",
  "content": "Risiko apa saja yang disebutkan dalam materi referensi?"
}
```

Selama prefiks stabil tetap sama dan cache belum kedaluwarsa, sistem akan menggunakan kembali cache yang ada.

Perubahan berikut akan menghasilkan cache yang berbeda:

* Mengubah teks atau urutan pesan dalam prefiks stabil
* Mengganti model
* Mengubah `5m` menjadi `1h`
* Mengubah tools atau definisi parameter tool
* Menggunakan pengguna atau kanal API yang berbeda

## Contoh Python

```python theme={null}
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.apimart.ai/v1",
)

stable_messages = [
    {
        "role": "system",
        "content": "Jawab pertanyaan hanya berdasarkan materi referensi yang diberikan.",
    },
    {
        "role": "user",
        "content": "Tempatkan materi referensi panjang yang akan digunakan berulang kali di sini…",
    },
    {
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "Saya telah membaca dan memahami materi referensi di atas.",
                "cache_control": {
                    "type": "ephemeral",
                    "ttl": "5m",
                },
            }
        ],
    },
]

response = client.chat.completions.create(
    model="gemini-3.6-flash",
    messages=[
        *stable_messages,
        {
            "role": "user",
            "content": "Ringkas tiga poin utama dalam materi referensi tersebut.",
        },
    ],
)

print(response.choices[0].message.content)
print(response.usage)
```

Pada permintaan berikutnya, gunakan kembali `stable_messages` yang sama dan ganti hanya pesan user terakhir.

## Memeriksa apakah cache digunakan

### Respons yang kompatibel dengan OpenAI

Periksa kolom berikut dalam respons:

```json theme={null}
{
  "usage": {
    "prompt_tokens": 14430,
    "prompt_tokens_details": {
      "cached_tokens": 14420,
      "cache_write_tokens": 0
    }
  }
}
```

Keterangan kolom:

| Kolom                | Arti                                                    |
| -------------------- | ------------------------------------------------------- |
| `prompt_tokens`      | Total token input untuk permintaan ini                  |
| `cached_tokens`      | Token input yang dibaca dari cache untuk permintaan ini |
| `cache_write_tokens` | Token yang ditulis ke cache; nilai `0` adalah normal    |

Permintaan pertama juga dapat menampilkan nilai `cached_tokens` yang besar karena sistem dapat membuat cache, lalu merujuknya dalam panggilan model yang sama.

### Respons native Gemini

Periksa `usageMetadata.cachedContentTokenCount` dalam respons:

```json theme={null}
{
  "usageMetadata": {
    "promptTokenCount": 13926,
    "cachedContentTokenCount": 13916,
    "totalTokenCount": 13954
  }
}
```

Keterangan kolom:

| Kolom                     | Arti                                                    |
| ------------------------- | ------------------------------------------------------- |
| `promptTokenCount`        | Total token input untuk permintaan ini                  |
| `cachedContentTokenCount` | Token input yang dibaca dari cache untuk permintaan ini |
| `totalTokenCount`         | Total token input dan output untuk permintaan ini       |

`streamGenerateContent` mengembalikan `usageMetadata` yang sama dalam frame respons SSE. Klien harus membaca frame yang memuat kolom tersebut, bukan hanya memeriksa potongan teks pertama.

## Rekomendasi penggunaan

<Tip>
  1. Simpan ke cache hanya konten panjang yang benar-benar stabil dan akan digunakan kembali beberapa kali.
  2. Tempatkan pertanyaan yang berubah pada setiap permintaan setelah batas `cache_control`.
  3. Jangan sertakan timestamp, ID acak, atau informasi pengguna yang dinamis dalam prefiks stabil.
  4. Gunakan `5m` jika Anda memperkirakan panggilan akan diulang dalam waktu singkat.
  5. Gunakan `1h` jika Anda memerlukan jangka waktu penggunaan kembali yang lebih panjang.
  6. Jika prefiks terlalu pendek, model tidak mendukung cache, atau cache sedang tidak tersedia, permintaan dapat diproses secara otomatis dengan cara biasa.
  7. Dalam format native Gemini, batas cache harus ditempatkan di `contents[].parts[]`, bukan di `systemInstruction`.
</Tip>

## Pertanyaan umum

<AccordionGroup>
  <Accordion title="Apakah format permintaan native Gemini dapat membuat cache secara otomatis?">
    Ya. `generateContent` dan `streamGenerateContent` menggunakan struktur `cache_control` yang sama. Batas harus ditempatkan di `contents[].parts[]`, dan setidaknya harus ada satu content real-time setelah content yang memuat batas.

    Jika permintaan sudah secara eksplisit menyediakan nama resource `cachedContent` native, platform akan memprioritaskan resource yang diberikan pengguna dan tidak lagi membuat cache secara otomatis.
  </Accordion>

  <Accordion title="Mengapa cache tidak digunakan?">
    Penyebab yang umum meliputi:

    * Prefiks stabil tidak sama persis dengan permintaan sebelumnya
    * TTL telah kedaluwarsa
    * Model atau tools telah diubah
    * Konten cache tidak mencapai jumlah minimum token yang diwajibkan oleh model
    * `cache_control` ditempatkan pada pesan terakhir sehingga tidak ada pertanyaan real-time yang tersisa
  </Accordion>

  <Accordion title="Apakah cache_control dapat ditempatkan pada pesan terakhir?">
    Tidak disarankan. Pesan terakhir biasanya merupakan pertanyaan real-time saat ini dan tidak seharusnya disimpan ke cache. Jika tidak ada pesan real-time setelah batas, permintaan akan diproses dengan cara biasa.
  </Accordion>

  <Accordion title="Apakah saya dapat menetapkan TTL lain?">
    Tidak. Saat ini hanya `5m` dan `1h` yang didukung. Nilai lain akan menghasilkan error HTTP 400.
  </Accordion>

  <Accordion title="Apakah saya dapat menetapkan beberapa batas cache?">
    Ya, tetapi semua batas harus menggunakan TTL yang sama dan sistem akan menggunakan batas terakhir. Secara umum, sebaiknya tetapkan hanya satu batas per permintaan agar strukturnya lebih jelas.
  </Accordion>

  <Accordion title="Apakah permintaan akan gagal jika cache tidak tersedia?">
    Biasanya tidak. Jika syarat untuk membuat atau menggunakan kembali cache tidak terpenuhi, sistem akan memproses permintaan secara otomatis dengan cara biasa. Pengecualiannya adalah error parameter, seperti TTL yang tidak valid atau penggunaan beberapa TTL yang berbeda.
  </Accordion>

  <Accordion title="Apa yang terjadi jika Context Cache tidak diaktifkan untuk model?">
    Permintaan akan diproses secara otomatis dengan cara biasa tanpa membuat cache eksplisit atau menimbulkan biaya penyimpanan cache. Input dan output biasa, serta kemungkinan hit pada cache implisit, akan tetap ditagih berdasarkan aturan model yang berlaku.
  </Accordion>

  <Accordion title="Mengapa cache_write_tokens bernilai 0?">
    Ini adalah perilaku normal cache konteks Gemini. Biaya pembuatan dicatat sebagai biaya penyimpanan cache tersendiri; `cache_write_tokens` dengan gaya OpenAI atau Claude tidak digunakan untuk menunjukkan jumlah token yang ditulis ke cache.
  </Accordion>

  <Accordion title="Apakah cached_tokens yang lebih besar dari 0 berarti cache eksplisit pasti telah dibuat?">
    Belum tentu. Sistem juga dapat menghasilkan hit pada cache implisit. Bagi pengguna biasa, token yang dibaca dari cache dapat digunakan untuk menentukan apakah permintaan memperoleh manfaat dari pembacaan cache. Jika Anda perlu memeriksa biaya pembuatan cache eksplisit, lihat catatan penggunaan Context Cache storage di platform.
  </Accordion>

  <Accordion title="Bagaimana biaya cache dihitung?">
    Saat cache dibuat, biaya penyimpanan cache satu kali mungkin dikenakan. Saat cache digunakan, token yang cocok dikenai harga pembacaan cache. Untuk harga spesifik, lihat halaman harga model di platform.
  </Accordion>
</AccordionGroup>
