上下文缓存

在典型的 AI 工作流中,您可能会反复将相同的输入 token 传递给模型。Gemini API 提供两种不同的缓存机制:

  • 隐式缓存(在 Gemini 2.5 及更新型号上自动启用,不保证节省费用)
  • 显式缓存(可在大多数型号上手动启用,保证节省费用)

如果您想保证节省费用,但需要增加一些开发者工作,则显式缓存非常有用。

隐式缓存

对于所有 Gemini 2.5 及更新型号,隐式缓存默认处于启用状态。如果您的请求命中缓存,我们会自动为您节省费用。您无需执行任何操作即可启用此功能。下表列出了每种型号的上下文缓存的最小输入 token 数:

型号 最小 token 限制
Gemini 3 Flash 预览版 1024
Gemini 3 Pro 预览版 4096
Gemini 2.5 Flash 1024
Gemini 2.5 Pro 4096

如要提高隐式缓存命中的几率,可以:

  • 尝试将较大且常见的内容放置在提示的开头
  • 尝试在短时间内发送具有相似前缀的请求

您可以在响应对象的 usage_metadata 字段中查看缓存命中的 token 数。

显式缓存

借助 Gemini API 显式缓存功能,您可以将一些内容一次性传递给模型,缓存输入 token,然后在后续请求中引用缓存的 token。在达到一定数量时,使用缓存的 token 比重复传递相同的 token 语料库的费用更低。

缓存一组 token 时,您可以选择希望缓存存在多长时间,然后系统会自动删除这些 token。此缓存时长称为“存留时间”(TTL)。 如果未设置,TTL 默认为 1 小时。缓存费用取决于输入 token 大小以及您希望 token 保留多长时间。

本部分假定您已安装 Gemini SDK(或已安装 curl) 并且已配置 API 密钥,如 快速入门中所述。

使用缓存生成内容

Python

以下示例展示了如何使用缓存的系统指令和视频文件生成内容。

视频

import os
import pathlib
import requests
import time

from google import genai
from google.genai import types

client = genai.Client()

# Download a test video file and save it locally
url = 'https://storage.googleapis.com/generativeai-downloads/data/SherlockJr._10min.mp4'
path_to_video_file = pathlib.Path('SherlockJr._10min.mp4')
if not path_to_video_file.exists():
    path_to_video_file.write_bytes(requests.get(url).content)

# Upload the video using the Files API
video_file = client.files.upload(file=path_to_video_file)

# Wait for the file to finish processing
while video_file.state.name == 'PROCESSING':
    time.sleep(2.5)
    video_file = client.files.get(name=video_file.name)

print(f'Video processing complete: {video_file.uri}')

model='models/gemini-3-flash-preview'

# Create a cache with a 5 minute TTL (300 seconds)
cache = client.caches.create(
    model=model,
    config=types.CreateCachedContentConfig(
        display_name='sherlock jr movie', # used to identify the cache
        system_instruction=(
            'You are an expert video analyzer, and your job is to answer '
            'the user\'s query based on the video file you have access to.'
        ),
        contents=[video_file],
        ttl="300s",
    )
)

response = client.models.generate_content(
    model = model,
    contents= (
    'Introduce different characters in the movie by describing '
    'their personality, looks, and names. Also list the timestamps '
    'they were introduced for the first time.'),
    config=types.GenerateContentConfig(cached_content=cache.name)
)

print(response.usage_metadata)

print(response.text)

PDF

from google import genai
from google.genai import types
import io
import httpx

client = genai.Client()

long_context_pdf_path = "https://sma.nasa.gov/SignificantIncidents/assets/a11_missionreport.pdf"

# Retrieve and upload the PDF using the File API
doc_io = io.BytesIO(httpx.get(long_context_pdf_path).content)

document = client.files.upload(
  file=doc_io,
  config=dict(mime_type='application/pdf')
)

model_name = "gemini-3-flash-preview"
system_instruction = "You are an expert analyzing transcripts."

# Create a cached content object
cache = client.caches.create(
    model=model_name,
    config=types.CreateCachedContentConfig(
      system_instruction=system_instruction,
      contents=[document],
    )
)

print(f'{cache=}')

response = client.models.generate_content(
  model=model_name,
  contents="Please summarize this transcript",
  config=types.GenerateContentConfig(
    cached_content=cache.name
  ))

print(f'{response.usage_metadata=}')

print('\n\n', response.text)

JavaScript

以下示例展示了如何使用缓存的系统指令和文本文件生成内容。

import {
  GoogleGenAI,
  createUserContent,
  createPartFromUri,
} from "@google/genai";

const ai = new GoogleGenAI({ apiKey: "GEMINI_API_KEY" });

async function main() {
  const doc = await ai.files.upload({
    file: "path/to/file.txt",
    config: { mimeType: "text/plain" },
  });
  console.log("Uploaded file name:", doc.name);

  const modelName = "gemini-3-flash-preview";
  const cache = await ai.caches.create({
    model: modelName,
    config: {
      contents: createUserContent(createPartFromUri(doc.uri, doc.mimeType)),
      systemInstruction: "You are an expert analyzing transcripts.",
    },
  });
  console.log("Cache created:", cache);

  const response = await ai.models.generateContent({
    model: modelName,
    contents: "Please summarize this transcript",
    config: { cachedContent: cache.name },
  });
  console.log("Response text:", response.text);
}

await main();

Go

以下示例展示了如何使用缓存生成内容。

package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, &genai.ClientConfig{
        APIKey: "GOOGLE_API_KEY",
        Backend: genai.BackendGeminiAPI,
    })
    if err != nil {
        log.Fatal(err)
    }

    modelName := "gemini-3-flash-preview"
    document, err := client.Files.UploadFromPath(
        ctx,
        "media/a11.txt",
        &genai.UploadFileConfig{
          MIMEType: "text/plain",
        },
    )
    if err != nil {
        log.Fatal(err)
    }
    parts := []*genai.Part{
        genai.NewPartFromURI(document.URI, document.MIMEType),
    }
    contents := []*genai.Content{
        genai.NewContentFromParts(parts, genai.RoleUser),
    }
    cache, err := client.Caches.Create(ctx, modelName, &genai.CreateCachedContentConfig{
        Contents: contents,
        SystemInstruction: genai.NewContentFromText(
          "You are an expert analyzing transcripts.", genai.RoleUser,
        ),
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Cache created:")
    fmt.Println(cache)

    // Use the cache for generating content.
    response, err := client.Models.GenerateContent(
        ctx,
        modelName,
        genai.Text("Please summarize this transcript"),
        &genai.GenerateContentConfig{
          CachedContent: cache.Name,
        },
    )
    if err != nil {
        log.Fatal(err)
    }
    printResponse(response) // helper for printing response parts
}

REST

以下示例展示了如何创建缓存,然后使用该缓存生成内容。

视频

wget https://storage.googleapis.com/generativeai-downloads/data/a11.txt
echo '{
  "model": "models/gemini-3-flash-preview",
  "contents":[
    {
      "parts":[
        {
          "inline_data": {
            "mime_type":"text/plain",
            "data": "'$(base64 $B64FLAGS a11.txt)'"
          }
        }
      ],
    "role": "user"
    }
  ],
  "systemInstruction": {
    "parts": [
      {
        "text": "You are an expert at analyzing transcripts."
      }
    ]
  },
  "ttl": "300s"
}' > request.json

curl -X POST "https://generativelanguage.googleapis.com/v1beta/cachedContents?key=$GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d @request.json \
> cache.json

CACHE_NAME=$(cat cache.json | grep '"name":' | cut -d '"' -f 4 | head -n 1)

curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent?key=$GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
      "contents": [
        {
          "parts":[{
            "text": "Please summarize this transcript"
          }],
          "role": "user"
        },
      ],
      "cachedContent": "'$CACHE_NAME'"
    }'

PDF

DOC_URL="https://sma.nasa.gov/SignificantIncidents/assets/a11_missionreport.pdf"
DISPLAY_NAME="A11_Mission_Report"
SYSTEM_INSTRUCTION="You are an expert at analyzing transcripts."
PROMPT="Please summarize this transcript"
MODEL="models/gemini-3-flash-preview"
TTL="300s"

# Download the PDF
wget -O "${DISPLAY_NAME}.pdf" "${DOC_URL}"

MIME_TYPE=$(file -b --mime-type "${DISPLAY_NAME}.pdf")
NUM_BYTES=$(wc -c < "${DISPLAY_NAME}.pdf")

echo "MIME_TYPE: ${MIME_TYPE}"
echo "NUM_BYTES: ${NUM_BYTES}"

tmp_header_file=upload-header.tmp

# Initial resumable request defining metadata.
# The upload url is in the response headers dump them to a file.
curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \
  -D upload-header.tmp \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
  -H "Content-Type: application/json" \
  -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null

upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file}"

# Upload the actual bytes.
curl "${upload_url}" \
  -H "Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary "@${DISPLAY_NAME}.pdf" 2> /dev/null > file_info.json

file_uri=$(jq ".file.uri" file_info.json)
echo "file_uri: ${file_uri}"

# Clean up the downloaded PDF
rm "${DISPLAY_NAME}.pdf"

# Create the cached content request
echo '{
  "model": "'$MODEL'",
  "contents":[
    {
      "parts":[
        {"file_data": {"mime_type": "'$MIME_TYPE'", "file_uri": '$file_uri'}}
      ],
    "role": "user"
    }
  ],
  "system_instruction": {
    "parts": [
      {
        "text": "'$SYSTEM_INSTRUCTION'"
      }
    ],
    "role": "system"
  },
  "ttl": "'$TTL'"
}' > request.json

# Send the cached content request
curl -X POST "${BASE_URL}/v1beta/cachedContents?key=$GOOGLE_API_KEY" \
-H 'Content-Type: application/json' \
-d @request.json \
> cache.json

CACHE_NAME=$(cat cache.json | grep '"name":' | cut -d '"' -f 4 | head -n 1)
echo "CACHE_NAME: ${CACHE_NAME}"
# Send the generateContent request using the cached content
curl -X POST "${BASE_URL}/${MODEL}:generateContent?key=$GOOGLE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
      "contents": [
        {
          "parts":[{
            "text": "'$PROMPT'"
          }],
          "role": "user"
        }
      ],
      "cachedContent": "'$CACHE_NAME'"
    }' > response.json

cat response.json

echo jq ".candidates[].content.parts[].text" response.json

列出缓存

您无法检索或查看缓存的内容,但可以检索 缓存元数据(namemodeldisplay_nameusage_metadatacreate_timeupdate_timeexpire_time)。

Python

如需列出所有已上传缓存的元数据,请使用 CachedContent.list()

for cache in client.caches.list():
  print(cache)

如需提取一个缓存对象的元数据(如果您知道其名称),请使用 get

client.caches.get(name=name)

JavaScript

如需列出所有已上传缓存的元数据,请使用 GoogleGenAI.caches.list()

console.log("My caches:");
const pager = await ai.caches.list({ config: { pageSize: 10 } });
let page = pager.page;
while (true) {
  for (const c of page) {
    console.log("    ", c.name);
  }
  if (!pager.hasNextPage()) break;
  page = await pager.nextPage();
}

Go

以下示例列出了所有缓存。

caches, err := client.Caches.All(ctx)
if err != nil {
    log.Fatal(err)
}
fmt.Println("Listing all caches:")
for _, item := range caches {
    fmt.Println("   ", item.Name)
}

以下示例列出了缓存,页面大小为 2。

page, err := client.Caches.List(ctx, &genai.ListCachedContentsConfig{PageSize: 2})
if err != nil {
    log.Fatal(err)
}

pageIndex := 1
for {
    fmt.Printf("Listing caches (page %d):\n", pageIndex)
    for _, item := range page.Items {
        fmt.Println("   ", item.Name)
    }
    if page.NextPageToken == "" {
        break
    }
    page, err = page.Next(ctx)
    if err == genai.ErrPageDone {
        break
    } else if err != nil {
        return err
    }
    pageIndex++
}

REST

curl "https://generativelanguage.googleapis.com/v1beta/cachedContents?key=$GEMINI_API_KEY"

更新缓存

您可以为缓存设置新的 ttlexpire_time。不支持更改缓存的其他任何内容。

Python

以下示例展示了如何使用 client.caches.update() 更新缓存的 ttl

from google import genai
from google.genai import types

client.caches.update(
  name = cache.name,
  config  = types.UpdateCachedContentConfig(
      ttl='300s'
  )
)

如需设置过期时间,它将接受 datetime 对象 或 ISO 格式的 datetime 字符串(dt.isoformat(),例如 2025-01-27T16:02:36.473528+00:00)。您的时间必须包含时区 (datetime.utcnow() 不会附加时区, datetime.now(datetime.timezone.utc) 会附加时区)。

from google import genai
from google.genai import types
import datetime

# You must use a time zone-aware time.
in10min = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=10)

client.caches.update(
  name = cache.name,
  config  = types.UpdateCachedContentConfig(
      expire_time=in10min
  )
)

JavaScript

以下示例展示了如何使用 GoogleGenAI.caches.update() 更新缓存的 ttl

const ttl = `${2 * 3600}s`; // 2 hours in seconds
const updatedCache = await ai.caches.update({
  name: cache.name,
  config: { ttl },
});
console.log("After update (TTL):", updatedCache);

Go

以下示例展示了如何更新缓存的 TTL

// Update the TTL (2 hours).
cache, err = client.Caches.Update(ctx, cache.Name, &genai.UpdateCachedContentConfig{
    TTL: 7200 * time.Second,
})
if err != nil {
    log.Fatal(err)
}
fmt.Println("After update:")
fmt.Println(cache)

REST

以下示例展示了如何更新缓存的 ttl

curl -X PATCH "https://generativelanguage.googleapis.com/v1beta/$CACHE_NAME?key=$GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"ttl": "600s"}'

删除缓存

缓存服务提供删除操作,用于手动从缓存中移除内容。以下示例展示了如何删除缓存:

Python

client.caches.delete(cache.name)

JavaScript

await ai.caches.delete({ name: cache.name });

Go

_, err = client.Caches.Delete(ctx, cache.Name, &genai.DeleteCachedContentConfig{})
if err != nil {
    log.Fatal(err)
}
fmt.Println("Cache deleted:", cache.Name)

REST

curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/$CACHE_NAME?key=$GEMINI_API_KEY"

使用 OpenAI 库进行显式缓存

如果您使用的是 OpenAI 库,则可以使用 cached_content 上的 extra_body 属性启用显式缓存。

何时使用显式缓存

上下文缓存特别适合较短的请求重复引用大量初始上下文的场景。例如,对于以下使用场景,可以考虑使用上下文缓存:

  • 有大量系统指令的聊天机器人
  • 对较长的视频文件进行的重复分析
  • 针对大型文档集的定期查询
  • 频繁的代码库分析或 bug 修复

显式缓存如何降低费用

虽然上下文缓存是一项付费功能,但它的目的是为了降低费用。结算取决于以下因素:

  1. 缓存 token 数: 缓存的输入 token 数,如果相同的 token 在后续提示中被重复使用,则按折扣费率计费。
  2. 存储时长: 所缓存 token 的存储时长 (TTL),根据缓存 token 数的 TTL 时长计费。TTL 没有下限或上限。
  3. 其他因素: 可能还会产生其他费用,例如非缓存输入 token 和输出 token 的费用。

如需了解最新的价格详情,请参阅 Gemini API 价格 页面。如需了解如何计算 token 数,请参阅 Token 指南

其他注意事项

使用上下文缓存时,请注意以下事项:

  • 上下文缓存的最小输入 token 数因模型而异。 最大输入 token 数与给定模型的最大输入 token 数相同。(如需详细了解如何计算 token 数, 请参阅token 指南)。
  • 模型不会区分缓存的 token 和常规输入 token。缓存的内容是提示的前缀。
  • 上下文缓存没有特殊费率或使用限制;GenerateContent 的标准速率限制适用,token 限制包括缓存的 token。
  • 缓存的 token 数在缓存服务的创建、获取和列出操作的 usage_metadata 中返回,在使用缓存时也会在 GenerateContent 中返回。