AI 기능의 경우 동일한 입력 토큰 (콘텐츠)을 모델에 반복해서 전달할 수 있습니다. 이러한 사용 사례의 경우 이 콘텐츠를 캐시할 수 있습니다. 즉, 콘텐츠를 모델에 한 번 전달하고 저장한 후 후속 요청에서 참조할 수 있습니다.
컨텍스트 캐싱은 대량의 콘텐츠(예: 대량의 텍스트, 오디오 파일 또는 동영상 파일)가 포함된 반복적인 작업의 지연 시간과 비용을 크게 줄일 수 있습니다. 캐시된 콘텐츠의 일반적인 사용 사례에는 상세한 페르소나 문서, 코드베이스, 매뉴얼이 있습니다.
Gemini 모델은 두 가지 캐싱 메커니즘을 제공합니다.
암시적 캐싱: 대부분의 모델에서 자동으로 사용 설정되며 비용 절감 효과가 보장되지 않음
명시적 캐싱: 대부분의 모델에서 선택적으로 수동으로 사용 설정할 수 있으며, 일반적으로 비용 절감 효과가 있습니다.
명시적 캐싱은 비용 절감을 보장할 가능성을 높이되 개발자 작업을 추가하려는 경우에 유용합니다.
암시적 캐싱과 명시적 캐싱 모두에서 응답 메타데이터의 cachedContentTokenCount 필드는 입력 중 캐싱된 부분의 토큰 수를 나타냅니다. 명시적 캐싱의 경우 이 페이지 하단의 가격 책정 정보를 검토하세요.
지원되는 모델
다음 모델을 사용할 때 캐싱이 지원됩니다.
gemini-3.1-pro-previewgemini-3-flash-previewgemini-3.1-flash-litegemini-2.5-progemini-2.5-flashgemini-2.5-flash-lite
미디어 생성 모델 (예: gemini-3.1-flash-image-preview와 같은 Nana Banana 모델)은 컨텍스트 캐싱을 지원하지 않습니다.
캐시된 콘텐츠 크기 제한
각 모델에는 캐시된 콘텐츠에 대한 최소 토큰 수 요구사항이 있습니다. 최댓값은 모델의 컨텍스트 윈도우에 따라 결정됩니다.
- Gemini Pro 모델: 최소 4,096개 토큰
- Gemini Flash 모델: 최소 1,024개 토큰
또한 Blob 또는 텍스트를 사용하여 캐시할 수 있는 콘텐츠의 최대 크기는 10MB입니다.
암시적 캐싱
암시적 캐싱은 기본적으로 사용 설정되며 대부분의 Gemini 모델에서 사용할 수 있습니다.
요청이 캐시된 콘텐츠에 도달하면 Google에서 비용 절감을 자동으로 전달합니다. 요청에서 암시적 캐싱을 사용할 가능성을 높이는 방법은 다음과 같습니다.
- 프롬프트 시작 부분에 크고 공통적인 콘텐츠를 배치해 보세요.
- 짧은 시간 내에 유사한 프리픽스를 가진 요청을 전송합니다.
입력 중 캐싱된 부분의 토큰 수는 응답 메타데이터의 cachedContentTokenCount 필드에 제공됩니다.
명시적 캐싱
명시적 캐싱은 기본적으로 사용 설정되어 있지 않으며 Gemini 모델의 선택적 기능입니다.
또한 Firebase AI Logic의 경우 명시적 콘텐츠 캐시를 Vertex AI Gemini API에서만 사용하여 명시적 콘텐츠 캐시를 만들고 관리할 때 Gemini API 키를 사용하거나 실수로 노출하는 것에 대해 걱정하지 않아도 되도록 하는 것이 좋습니다.
Firebase AI Logic에서는 명시적 캐싱 워크플로를 개선하기 위해 노력하고 있습니다. 이 기능에 관심이 있다면 기존 User Voice 항목에 찬성표를 던져 Google에서 리소스를 집중해야 하는 영역임을 알려주세요.
과도한 콘텐츠 캐시를 설정하고 사용하는 방법은 다음과 같습니다.
다음과 같은 명시적 캐시를 관리합니다.
명시적 콘텐츠 캐시는 암시적 캐시와 상호작용하므로 명시적으로 캐시된 콘텐츠 외에 추가 캐싱이 발생할 수 있습니다. 암시적 캐싱을 사용 중지하고 명시적 캐시를 만들지 않으면 캐시 데이터 보관을 방지할 수 있습니다. 자세한 내용은 캐싱 사용 설정 및 사용 중지를 참고하세요.
명시적 캐시 만들기 및 사용
명시적 콘텐츠 캐시를 만들고 사용하려면 다음이 필요합니다.
명시적 캐시 생성 및 사용에 관한 중요 정보
캐시는 앱의 프롬프트 요청 및 서버 프롬프트 템플릿과 일치해야 합니다.
캐시는 Gemini API 제공업체에 따라 다릅니다. 앱의 프롬프트 요청은 동일한 제공업체를 사용해야 합니다.
Firebase AI Logic의 경우 Vertex AI Gemini API에서만 명시적 콘텐츠 캐시를 사용하는 것이 좋습니다. 이 페이지의 모든 정보와 예시는 해당 Gemini API 제공업체에만 적용됩니다.캐시는 Gemini 모델에 따라 다릅니다. 앱의 프롬프트 요청은 동일한 모델을 사용해야 합니다.
Vertex AI Gemini API를 사용하는 경우 캐시는 위치에 따라 다릅니다.
명시적 캐시의 위치는 앱의 프롬프트 요청에 있는 서버 프롬프트 템플릿의 위치 및 모델에 액세스하는 위치와 일치해야 합니다.
명시적 캐싱에는 다음과 같은 제한사항과 요구사항도 있습니다.
명시적 캐시를 만든 후에는 TTL 또는 만료 시간을 제외한 캐시에 관한 어떤 것도 변경할 수 없습니다.
지원되는 입력 파일 MIME 유형 또는 캐시 생성 요청 내에 제공된 텍스트를 캐시할 수 있습니다.
캐시에 파일을 포함하려면 파일을 Cloud Storage URI로 제공해야 합니다. 브라우저 URL 또는 YouTube URL일 수 없습니다.
또한 파일에 대한 액세스 제한은 캐시 생성 시간에 확인되며 액세스 제한은 사용자 요청 시간에 다시 확인되지 않습니다. 따라서 명시적 캐시에 포함된 데이터는 해당 캐시를 포함하는 요청을 하는 모든 사용자에게 적합해야 합니다.
시스템 안내나 도구 (예: 코드 실행, URL 컨텍스트,
Google Search 를 사용한 그라운딩)를 사용하려면 캐시에 해당 구성이 포함되어야 합니다. 서버 프롬프트 템플릿이나 앱의 프롬프트 요청에서는 구성할 수 없습니다. 서버 프롬프트 템플릿은 아직 함수 호출 (또는 채팅)을 지원하지 않습니다. 캐시에서 시스템 지침과 도구를 구성하는 방법에 관한 자세한 내용은 Vertex AI Gemini API의 REST API를 참고하세요.
1단계: 캐시 만들기
Vertex AI Gemini API의 REST API를 직접 사용하여 캐시를 만듭니다.
다음은 PDF 파일의 명시적 캐시를 콘텐츠로 만드는 예입니다.
구문:
PROJECT_ID="PROJECT_ID"
MODEL_ID="GEMINI_MODEL" # for example, gemini-3-flash-preview
LOCATION="LOCATION" # location for both the cache and the model
MIME_TYPE="MIME_TYPE"
CACHED_CONTENT_URI="CLOUD_STORAGE_FILE_URI" # must be a Cloud Storage URI
CACHE_DISPLAY_NAME="CACHE_DISPLAY_NAME" # optional
TTL="CACHE_TIME_TO_LIVE" # optional (if not specified, defaults to 3600s)
curl \
-X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${LOCATION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/${LOCATION}/cachedContents \
-d @- <<EOF
{
"model":"projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}",
"contents": [
{
"role": "user",
"parts": [
{
"fileData": {
"mimeType": "${MIME_TYPE}",
"fileUri": "${CACHED_CONTENT_URI}"
}
}
]
}
],
"displayName": "${CACHE_DISPLAY_NAME}",
"ttl": "${TTL}"
}
EOF
요청 예시:
PROJECT_ID="my-amazing-app"
MODEL_ID="gemini-3-flash-preview"
LOCATION="global"
MIME_TYPE="application/pdf"
CACHED_CONTENT_URI="gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf"
CACHE_DISPLAY_NAME="Gemini - A Family of Highly Capable Multimodal Model (PDF)"
TTL="7200s"
curl \
-X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${LOCATION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/${LOCATION}/cachedContents \
-d @- <<EOF
{
"model":"projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}",
"contents": [
{
"role": "user",
"parts": [
{
"fileData": {
"mimeType": "${MIME_TYPE}",
"fileUri": "${CACHED_CONTENT_URI}"
}
}
]
}
],
"displayName": "${CACHE_DISPLAY_NAME}",
"ttl": "${TTL}"
}
EOF
응답 예시:
응답에는 캐시에 대해 전역적으로 고유한 정규화된 리소스 name가 포함됩니다 (마지막 세그먼트는 캐시 ID임). 워크플로의 다음 단계에서 이 전체 name 값을 사용합니다.
{
"name": "projects/861083271981/locations/global/cachedContents/4545031458888089601",
"model": "projects/my-amazing-app/locations/global/publishers/google/models/gemini-3-flash-preview",
"createTime": "2024-06-04T01:11:50.808236Z",
"updateTime": "2024-06-04T01:11:50.808236Z",
"expireTime": "2024-06-04T02:11:50.794542Z"
}
2단계: 서버 프롬프트 템플릿에서 캐시 참조
캐시를 만든 후 서버 프롬프트 템플릿의 cachedContent 속성 내에서 name로 참조합니다.
서버 프롬프트 템플릿을 만들 때 다음 요구사항을 따라야 합니다.
캐시를 만들 때 응답에서 정규화된 리소스
name를 사용합니다. 이는 요청에 지정한 선택적 표시 이름이 아닙니다.서버 프롬프트 템플릿의 위치는 캐시의 위치와 일치해야 합니다.
시스템 지침이나 도구를 사용하려면 캐시의 일부로 구성해야 하며 서버 프롬프트 템플릿의 일부로 구성하면 안 됩니다.
구문:
{{cachedContent name="YOUR_CACHE_RESOURCE_NAME"}}
{{role "user"}}
{{userPrompt}}
예:
{{cachedContent name="projects/861083271981/locations/global/cachedContents/4545031458888089601"}}
{{role "user"}}
{{userPrompt}}
또는 서버 프롬프트 템플릿의 name 매개변수 값이 동적 입력 변수일 수 있습니다.
예를 들어 {{cachedContent name=someVariable}}name를 포함할 수 있습니다.
3단계: 앱의 요청에서 서버 프롬프트 템플릿 참조
요청을 작성할 때는 다음 사항에 각별히 주의하세요.
캐시가 해당 Gemini API 제공자로 생성되었으므로 Vertex AI Gemini API를 사용합니다.
앱의 프롬프트 요청에 있는 모델에 액세스하는 위치가 서버 프롬프트 템플릿 및 캐시의 위치와 일치해야 합니다.
Swift
// ...
// Initialize the Vertex AI Gemini API backend service
// Create a `TemplateGenerativeModel` instance
// Make sure to specify the same location as the server prompt template and the cache
let model = FirebaseAI.firebaseAI(backend: .vertexAI(location: "LOCATION"))
.templateGenerativeModel()
do {
let response = try await model.generateContent(
// Specify your template ID
templateID: "TEMPLATE_ID"
)
if let text = response.text {
print("Response Text: \(text)")
}
} catch {
print("An error occurred: \(error)")
}
print("\n")
Kotlin
// ...
// Initialize the Vertex AI Gemini API backend service
// Create a `TemplateGenerativeModel` instance
// Make sure to specify the same location as the server prompt template and the cache
val model = Firebase.ai(backend = GenerativeBackend.vertexAI(location = "LOCATION"))
.templateGenerativeModel()
val response = model.generateContent(
// Specify your template ID
"TEMPLATE_ID",
)
val text = response.text
println(text)
Java
// ...
// Initialize the Vertex AI Gemini API backend service
// Create a `TemplateGenerativeModel` instance
// Make sure to specify the same location as the server prompt template and the cache
TemplateGenerativeModel generativeModel = FirebaseAI.getInstance().templateGenerativeModel();
TemplateGenerativeModelFutures model = TemplateGenerativeModelFutures.from(generativeModel);
Future<GenerateContentResponse> response = model.generateContent(
// Specify your template ID
"TEMPLATE_ID"
);
addCallback(response,
new FutureCallback<GenerateContentResponse>() {
public void onSuccess(GenerateContentResponse result) {
System.out.println(result.getText());
}
public void onFailure(Throwable t) {
reportError(t);
}
}
executor);
Web
// ...
// Initialize the Vertex AI Gemini API backend service
// Make sure to specify the same location as the server prompt template and the cache
const ai = getAI(app, { backend: new VertexAIBackend('LOCATION') });
// Create a `TemplateGenerativeModel` instance
const model = getTemplateGenerativeModel(ai);
const result = await model.generateContent(
// Specify your template ID
'TEMPLATE_ID'
);
const response = result.response;
const text = response.text();
Dart
// ...
// Initialize the Vertex AI Gemini API backend service
// Create a `TemplateGenerativeModel` instance
// Make sure to specify the same location as the server prompt template and the cache
var _model = FirebaseAI.vertexAI(location: 'LOCATION').templateGenerativeModel()
var response = await _model.generateContent(
// Specify your template ID
'TEMPLATE_ID',
);
var text = response?.text;
print(text);
Unity
// ...
// Initialize the Vertex AI Gemini API backend service
// Make sure to specify the same location as the server prompt template and the cache
var firebaseAI = FirebaseAI.GetInstance(FirebaseAI.Backend.VertexAI(location: "LOCATION"));
// Create a `TemplateGenerativeModel` instance
var model = firebaseAI.GetTemplateGenerativeModel();
try
{
var response = await model.GenerateContentAsync(
// Specify your template ID
"TEMPLATE_ID"
);
Debug.Log($"Response Text: {response.Text}");
}
catch (Exception e) {
Debug.LogError($"An error occurred: {e.Message}");
}
명시적 캐시 관리
이 섹션에서는 모든 캐시를 나열하고, 캐시에 관한 메타데이터를 가져오며, 캐시의 TTL 또는 만료 시간을 업데이트하고, 캐시를 삭제하는 등 명시적 콘텐츠 캐시를 관리하는 방법을 설명합니다.
Vertex AI Gemini API의 REST API를 사용하여 명시적 캐시를 관리합니다.
명시적 콘텐츠 캐시가 생성되면 TTL 또는 만료 시간을 제외한 캐시에 관한 어떤 것도 변경할 수 없습니다.
모든 캐시 나열
프로젝트에 사용할 수 있는 모든 명시적 캐시를 나열할 수 있습니다. 이 명령어는 지정된 위치의 캐시만 반환합니다.
PROJECT_ID="PROJECT_ID"
LOCATION="LOCATION"
curl \
-X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://${LOCATION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/${LOCATION}/cachedContents
캐시에 관한 메타데이터 가져오기
실제 캐시된 콘텐츠를 가져오거나 볼 수는 없습니다. 하지만 name, model, display_name, usage_metadata, create_time, update_time, expire_time을 비롯한 명시적 캐시에 관한 메타데이터를 검색할 수 있습니다.
캐시의 정규화된 리소스 name의 마지막 세그먼트인 CACHE_ID를 제공해야 합니다.
PROJECT_ID="PROJECT_ID"
LOCATION="LOCATION"
CACHE_ID="CACHE_ID" # the final segment in the `name` of the cache
curl \
-X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://${LOCATION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/${LOCATION}/cachedContents/${CACHE_ID}
캐시의 TTL 또는 만료 시간 업데이트
명시적 캐시를 만들 때 선택적으로 ttl 또는 expire_time을 설정할 수 있습니다.
ttl: 캐시의 TTL(수명)입니다. 구체적으로 캐시가 생성된 후 또는ttl이 만료되기 전에 업데이트된 후 캐시가 유지되는 시간(초 및 나노초)입니다.ttl을 설정하면 캐시의expireTime이 자동으로 업데이트됩니다.expire_time: 캐시가 만료되는 절대 날짜와 시간을 지정하는Timestamp(예:2024-06-30T09:00:00.000000Z)입니다.
이러한 값을 설정하지 않으면 기본 TTL은 1시간입니다. TTL에는 최소 또는 최대 경계가 없습니다.
기존 명시적 캐시의 경우 ttl 또는 expire_time를 추가하거나 업데이트할 수 있습니다.
캐시의 정규화된 리소스 name의 마지막 세그먼트인 CACHE_ID를 제공해야 합니다.
ttl 업데이트
PROJECT_ID="PROJECT_ID"
LOCATION="LOCATION"
CACHE_ID="CACHE_ID" # the final segment in the `name` of the cache
TTL="CACHE_TIME_TO_LIVE"
curl \
-X PATCH \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
https://${LOCATION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/${LOCATION}/cachedContents/${CACHE_ID} -d \
'{
"ttl": "'$TTL'"
}'
expire_time 업데이트
PROJECT_ID="PROJECT_ID"
LOCATION="LOCATION"
CACHE_ID="CACHE_ID" # the final segment in the `name` of the cache
EXPIRE_TIME="ABSOLUTE_TIME_CACHE_EXPIRES"
curl \
-X PATCH \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
https://${LOCATION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/${LOCATION}/cachedContents/${CACHE_ID} -d \
'{
"expire_time": "'$EXPIRE_TIME'"
}'
캐시 삭제
명시적 캐시가 더 이상 필요하지 않으면 삭제할 수 있습니다.
캐시의 정규화된 리소스 name의 마지막 세그먼트인 CACHE_ID를 제공해야 합니다.
PROJECT_ID="PROJECT_ID"
LOCATION="LOCATION"
CACHE_ID="CACHE_ID" # the final segment in the `name` of the cache
curl \
-X DELETE \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://${LOCATION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/${LOCATION}/cachedContents/${CACHE_ID}
명시적 캐싱 가격 책정
명시적 캐싱은 비용을 절감하기 위해 설계된 유료 기능입니다. 가격은 다음 요소를 기준으로 합니다.
캐시 생성용 입력 토큰: 암시적 캐싱과 명시적 캐싱 모두 캐시를 만드는 데 사용된 입력 토큰에 대해 표준 입력 토큰 가격으로 요금이 청구됩니다.
캐시 저장: 명시적 캐싱의 경우 캐시 저장 기간에 따라 스토리지 비용이 청구됩니다. 암시적 캐싱에는 스토리지 비용이 발생하지 않습니다. 자세한 내용은 Vertex AI Gemini API 가격 책정을 참고하세요.
캐시된 콘텐츠 사용: 명시적 캐싱은 명시적 캐시가 참조될 때 할인을 보장합니다. 즉, 기존 캐시를 참조할 때 입력 토큰에 할인이 적용됩니다. Gemini 2.5 이상 모델의 경우 이 할인은 90%입니다.
입력 중 캐싱된 부분의 토큰 수는 응답 메타데이터의 cachedContentTokenCount 필드에 제공됩니다.