컨텍스트 캐싱

일반적인 AI 워크플로에서는 동일한 입력 토큰을 모델에 반복해서 전달할 수 있습니다. Gemini API 컨텍스트 캐싱 기능을 사용하면 일부 콘텐츠를 모델에 한 번 전달하고 입력 토큰을 캐시한 다음 후속 요청에 캐시된 토큰을 참조할 수 있습니다. 특정 볼륨에서는 캐시된 토큰을 사용하면 동일한 토큰 코퍼스를 반복적으로 전달하는 것보다 비용이 적게 듭니다.

토큰 세트를 캐시할 때 토큰이 자동으로 삭제되기 전에 캐시가 존재할 시간을 선택할 수 있습니다. 이 캐싱 기간을 TTL(수명)이라고 합니다. 설정하지 않으면 TTL 기본값은 1시간입니다. 캐싱 비용은 입력 토큰 크기와 토큰 유지 기간에 따라 다릅니다.

컨텍스트 캐싱은 Gemini 1.5 Pro와 Gemini 1.5 Flash를 모두 지원합니다.

컨텍스트 캐싱을 사용해야 하는 경우

컨텍스트 캐싱은 상당한 양의 초기 컨텍스트가 더 짧은 요청에 의해 반복적으로 참조되는 시나리오에 특히 적합합니다. 다음과 같은 사용 사례에 문맥 캐싱을 사용하는 것이 좋습니다.

  • 광범위한 시스템 안내가 포함된 챗봇
  • 긴 동영상 파일에 대한 반복적인 분석
  • 대규모 문서 집합에 대한 반복 쿼리
  • 빈번한 코드 저장소 분석 또는 버그 수정

캐싱으로 비용을 절감하는 방법

컨텍스트 캐싱은 전반적인 운영 비용을 줄이기 위해 설계된 유료 기능입니다. 결제는 다음 요소를 기준으로 합니다.

  1. 캐시 토큰 수: 캐시된 입력 토큰 수로, 후속 프롬프트에 포함될 경우 할인된 요율로 청구됩니다.
  2. 저장 기간: 캐시된 토큰이 저장되는 시간(TTL)으로, 캐시된 토큰 수의 TTL 기간을 기준으로 청구됩니다. TTL에는 최소 또는 최대 경계가 없습니다.
  3. 기타 요인: 캐시되지 않은 입력 토큰 및 출력 토큰과 같은 기타 요금이 적용됩니다.

최신 가격 책정에 관한 자세한 내용은 Gemini API 가격 책정 페이지를 참고하세요. 토큰 수를 집계하는 방법을 알아보려면 토큰 가이드를 참고하세요.

컨텍스트 캐싱을 사용하는 방법

이 섹션에서는 빠른 시작의 설명에 따라 Gemini SDK를 설치했거나 curl이 설치되어 있고 API 키를 구성했다고 가정합니다.

캐시를 사용하여 콘텐츠 생성

다음 예에서는 캐시된 시스템 안내 및 동영상 파일을 사용하여 콘텐츠를 생성하는 방법을 보여줍니다.

import { GoogleGenerativeAI } from '@google/generative-ai';
import {
  FileState,
  GoogleAICacheManager,
  GoogleAIFileManager,
} from '@google/generative-ai/server';

// A helper function that uploads the video to be cached.
async function uploadMp4Video(filePath, displayName) {
  const fileManager = new GoogleAIFileManager(process.env.API_KEY);
  const fileResult = await fileManager.uploadFile(filePath, {
    displayName,
    mimeType: 'video/mp4',
  });

  const { name, uri } = fileResult.file;

  // Poll getFile() on a set interval (2 seconds here) to check file state.
  let file = await fileManager.getFile(name);
  while (file.state === FileState.PROCESSING) {
    console.log('Waiting for video to be processed.');
    // Sleep for 2 seconds
    await new Promise((resolve) => setTimeout(resolve, 2_000));
    file = await fileManager.getFile(name);
  }

  console.log(`Video processing complete: ${uri}`);

  return fileResult;
}

// Download video file
// curl -O https://storage.googleapis.com/generativeai-downloads/data/Sherlock_Jr_FullMovie.mp4
const pathToVideoFile = 'Sherlock_Jr_FullMovie.mp4';

// Upload the video.
const fileResult = await uploadMp4Video(pathToVideoFile, 'Sherlock Jr. video');

// Construct a GoogleAICacheManager using your API key.
const cacheManager = new GoogleAICacheManager(process.env.API_KEY);

// Create a cache with a 5 minute TTL.
const displayName = 'sherlock jr movie';
const model = 'models/gemini-1.5-flash-001';
const systemInstruction =
  '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.";
let ttlSeconds = 300;
const cache = await cacheManager.create({
  model,
  displayName,
  systemInstruction,
  contents: [
    {
      role: 'user',
      parts: [
        {
          fileData: {
            mimeType: fileResult.file.mimeType,
            fileUri: fileResult.file.uri,
          },
        },
      ],
    },
  ],
  ttlSeconds,
});

// Get your API key from https://aistudio.google.com/app/apikey
// Access your API key as an environment variable.
const genAI = new GoogleGenerativeAI(process.env.API_KEY);

// Construct a `GenerativeModel` which uses the cache object.
const genModel = genAI.getGenerativeModelFromCachedContent(cache);

// Query the model.
const result = await genModel.generateContent({
  contents: [
    {
      role: 'user',
      parts: [
        {
          text:
            'Introduce different characters in the movie by describing ' +
            'their personality, looks, and names. Also list the ' +
            'timestamps they were introduced for the first time.',
        },
      ],
    },
  ],
});

console.log(result.response.usageMetadata);

// The output should look something like this:
//
// {
//   promptTokenCount: 696220,
//   candidatesTokenCount: 270,
//   totalTokenCount: 696490,
//   cachedContentTokenCount: 696191
// }

console.log(result.response.text());

캐시 목록

캐시된 콘텐츠를 검색하거나 볼 수는 없지만 캐시 메타데이터 (name, model, displayName, usageMetadata, createTime, updateTime, expireTime)를 검색할 수는 있습니다.

업로드된 모든 캐시의 메타데이터를 나열하려면 GoogleAICacheManager.list()를 사용합니다.

const listResult = await cacheManager.list();
listResult.cachedContents.forEach((cache) => {
  console.log(cache);
});

캐시 업데이트

캐시에 새 ttl 또는 expireTime를 설정할 수 있습니다. 캐시의 다른 사항은 변경할 수 없습니다.

다음 예는 GoogleAICacheManager.update()를 사용하여 캐시의 ttl를 업데이트하는 방법을 보여줍니다.

const ttlSeconds = 2 * 60 * 60;
const updateParams = { cachedContent: { ttlSeconds } };
const updatedCache = await cacheManager.update(cacheName, updateParams);

캐시 삭제

캐싱 서비스는 캐시에서 콘텐츠를 수동으로 삭제하는 삭제 작업을 제공합니다. 다음 예시에서는 GoogleAICacheManager.delete()를 사용하여 캐시를 삭제하는 방법을 보여줍니다.

await cacheManager.delete(cacheName);

추가 고려사항

컨텍스트 캐싱을 사용할 때 다음 고려사항에 유의하세요.

  • 컨텍스트 캐싱의 최소 입력 토큰 수는 32,768개이고, 최댓값은 지정된 모델의 최댓값과 동일합니다. 토큰 집계에 관한 자세한 내용은 토큰 가이드를 참고하세요.
  • 모델은 캐시된 토큰과 일반 입력 토큰을 구별하지 않습니다. 캐시된 콘텐츠는 단순히 프롬프트의 접두사입니다.
  • 컨텍스트 캐싱에는 특별한 비율 또는 사용량 제한이 없습니다. GenerateContent의 표준 비율 제한이 적용되며 토큰 한도에는 캐시된 토큰이 포함됩니다.
  • 캐시된 토큰 수는 캐시 서비스의 생성, 가져오기, 목록 작업에서 usage_metadata로 반환되며 캐시를 사용할 때는 GenerateContent에서도 반환됩니다.