일괄 모드

Gemini API의 일괄 모드는 표준 비용의 50%로 대량의 요청을 비동기식으로 처리하도록 설계되었습니다. 목표 처리 시간은 24시간이지만 대부분의 경우 훨씬 빠릅니다.

데이터 사전 처리 또는 평가 실행과 같이 즉각적인 응답이 필요하지 않은 대규모의 긴급하지 않은 작업에는 일괄 모드를 사용하세요.

일괄 작업 만들기

일괄 모드에서 요청을 제출하는 방법에는 두 가지가 있습니다.

  • 인라인 요청: 일괄 생성 요청에 직접 포함된 GenerateContentRequest 객체 목록입니다. 이는 총 요청 크기가 20MB 미만인 소규모 배치에 적합합니다. 모델에서 반환된 출력inlineResponse 객체 목록입니다.
  • 입력 파일: 각 줄에 완전한 GenerateContentRequest 객체가 포함된 JSON Lines (JSONL) 파일입니다. 이 방법은 더 큰 요청에 권장됩니다. 모델에서 반환된 출력은 각 줄이 GenerateContentResponse 또는 상태 객체인 JSONL 파일입니다.

인라인 요청

요청 수가 적은 경우 BatchGenerateContentRequest 내에 GenerateContentRequest 객체를 직접 삽입할 수 있습니다. 다음 예에서는 인라인 요청을 사용하여 BatchGenerateContent 메서드를 호출합니다.

Python


from google import genai
from google.genai import types

client = genai.Client()

# A list of dictionaries, where each is a GenerateContentRequest
inline_requests = [
    {
        'contents': [{
            'parts': [{'text': 'Tell me a one-sentence joke.'}],
            'role': 'user'
        }]
    },
    {
        'contents': [{
            'parts': [{'text': 'Why is the sky blue?'}],
            'role': 'user'
        }]
    }
]

inline_batch_job = client.batches.create(
    model="models/gemini-2.5-flash",
    src=inline_requests,
    config={
        'display_name': "inlined-requests-job-1",
    },
)

print(f"Created batch job: {inline_batch_job.name}")

REST

curl https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:batchGenerateContent \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-X POST \
-H "Content-Type:application/json" \
-d '{
    "batch": {
        "display_name": "my-batch-requests",
        "input_config": {
            "requests": {
                "requests": [
                    {
                        "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]},
                        "metadata": {
                            "key": "request-1"
                        }
                    },
                    {
                        "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]},
                        "metadata": {
                            "key": "request-2"
                        }
                    }
                ]
            }
        }
    }
}'

입력 파일

요청이 많은 경우 JSON Lines (JSONL) 파일을 준비합니다. 이 파일의 각 줄은 사용자 정의 키와 요청 객체를 포함하는 JSON 객체여야 합니다. 여기서 요청은 유효한 GenerateContentRequest 객체입니다. 사용자 정의 키는 응답에서 어떤 출력이 어떤 요청의 결과인지 나타내는 데 사용됩니다. 예를 들어 키가 request-1로 정의된 요청의 응답에는 동일한 키 이름이 주석으로 표시됩니다.

이 파일은 파일 API를 사용하여 업로드됩니다. 입력 파일의 최대 허용 파일 크기는 2GB입니다.

다음은 JSONL 파일의 예입니다. my-batch-requests.json이라는 파일에 저장할 수 있습니다.

{"key": "request-1", "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}], "generation_config": {"temperature": 0.7}}}
{"key": "request-2", "request": {"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}}

인라인 요청과 마찬가지로 각 요청 JSON에서 시스템 지침, 도구 또는 기타 구성과 같은 다른 매개변수를 지정할 수 있습니다.

다음 예와 같이 File API를 사용하여 이 파일을 업로드할 수 있습니다. 멀티모달 입력을 사용하는 경우 JSONL 파일 내에서 업로드된 다른 파일을 참조할 수 있습니다.

Python


from google import genai
from google.genai import types

client = genai.Client()

# Create a sample JSONL file
with open("my-batch-requests.jsonl", "w") as f:
    requests = [
        {"key": "request-1", "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]}},
        {"key": "request-2", "request": {"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}}
    ]
    for req in requests:
        f.write(json.dumps(req) + "\n")

# Upload the file to the File API
uploaded_file = client.files.upload(
    file='my-batch-requests.jsonl',
    config=types.UploadFileConfig(display_name='my-batch-requests', mime_type='jsonl')
)

print(f"Uploaded file: {uploaded_file.name}")

REST

tmp_batch_input_file=batch_input.tmp
echo -e '{"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}], "generationConfig": {"temperature": 0.7}}\n{"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}' > batch_input.tmp
MIME_TYPE=$(file -b --mime-type "${tmp_batch_input_file}")
NUM_BYTES=$(wc -c < "${tmp_batch_input_file}")
DISPLAY_NAME=BatchInput

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 "https://generativelanguage.googleapis.com/upload/v1beta/files \
-D "${tmp_header_file}" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-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/jsonl" \
-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 "@${tmp_batch_input_file}" 2> /dev/null > file_info.json

file_uri=$(jq ".file.uri" file_info.json)

다음 예시에서는 File API를 사용하여 업로드된 입력 파일로 BatchGenerateContent 메서드를 호출합니다.

Python


# Assumes `uploaded_file` is the file object from the previous step
file_batch_job = client.batches.create(
    model="gemini-2.5-flash",
    src=uploaded_file.name,
    config={
        'display_name': "file-upload-job-1",
    },
)

print(f"Created batch job: {file_batch_job.name}")

REST

BATCH_INPUT_FILE='files/123456' # File ID
curl https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:batchGenerateContent \
-X POST \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" \
-d "{
    'batch': {
        'display_name': 'my-batch-requests',
        'input_config': {
            'requests': {
                'file_name': ${BATCH_INPUT_FILE}
            }
        }
    }
}"

일괄 작업을 만들면 작업 이름이 반환됩니다. 작업이 완료되면 이 이름을 사용하여 작업 상태를 모니터링하고 결과를 검색합니다.

다음은 작업 이름을 포함하는 출력의 예입니다.


Created batch job from file: batches/123456789

요청 구성

표준 비일괄 요청에서 사용할 요청 구성을 포함할 수 있습니다. 예를 들어 온도, 시스템 안내를 지정하거나 다른 모달리티를 전달할 수 있습니다. 다음 예시에서는 요청 중 하나의 시스템 안내가 포함된 인라인 요청의 예를 보여줍니다.

inline_requests_list = [
    {'contents': [{'parts': [{'text': 'Write a short poem about a cloud.'}]}]},
    {'contents': [{'parts': [{'text': 'Write a short poem about a cat.'}]}], 'system_instructions': {'parts': [{'text': 'You are a cat. Your name is Neko.'}]}}
]

마찬가지로 요청에 사용할 도구를 지정할 수 있습니다. 다음 예시는 Google 검색 도구를 사용 설정하는 요청을 보여줍니다.

inline_requests_list = [
    {'contents': [{'parts': [{'text': 'Who won the euro 1998?'}]}]},
    {'contents': [{'parts': [{'text': 'Who won the euro 2025?'}]}], 'tools': [{'google_search ': {}}]}
]

구조화된 출력을 지정할 수도 있습니다. 다음 예시에서는 일괄 요청을 지정하는 방법을 보여줍니다.

from google import genai
from pydantic import BaseModel, TypeAdapter

class Recipe(BaseModel):
    recipe_name: str
    ingredients: list[str]

client = genai.Client()

# A list of dictionaries, where each is a GenerateContentRequest
inline_requests = [
    {
        'contents': [{
            'parts': [{'text': 'List a few popular cookie recipes, and include the amounts of ingredients.'}],
            'role': 'user'
        }],
        'config': {
            'response_mime_type': 'application/json',
            'response_schema': list[Recipe]
        }
    },
    {
        'contents': [{
            'parts': [{'text': 'List a few popular gluten free cookie recipes, and include the amounts of ingredients.'}],
            'role': 'user'
        }],
        'config': {
            'response_mime_type': 'application/json',
            'response_schema': list[Recipe]
        }
    }
]

inline_batch_job = client.batches.create(
    model="models/gemini-2.5-flash",
    src=inline_requests,
    config={
        'display_name': "structured-output-job-1"
    },
)

# wait for the job to finish
job_name = inline_batch_job.name
print(f"Polling status for job: {job_name}")

while True:
    batch_job_inline = client.batches.get(name=job_name)
    if batch_job_inline.state.name in ('JOB_STATE_SUCCEEDED', 'JOB_STATE_FAILED', 'JOB_STATE_CANCELLED'):
        break
    print(f"Job not finished. Current state: {batch_job_inline.state.name}. Waiting 30 seconds...")
    time.sleep(30)

print(f"Job finished with state: {batch_job_inline.state.name}")

# print the response
for i, inline_response in enumerate(batch_job_inline.dest.inlined_responses):
    print(f"\n--- Response {i+1} ---")

    # Check for a successful response
    if inline_response.response:
        # The .text property is a shortcut to the generated text.
        print(inline_response.response.text)

작업 상태 모니터링

일괄 작업을 만들 때 획득한 작업 이름을 사용하여 상태를 폴링합니다. 일괄 작업의 상태 필드에 현재 상태가 표시됩니다. 일괄 작업은 다음 상태 중 하나일 수 있습니다.

  • JOB_STATE_PENDING: 작업이 생성되었으며 서비스에서 처리되기를 기다리고 있습니다.
  • JOB_STATE_SUCCEEDED: 작업이 성공적으로 완료되었습니다. 이제 결과를 가져올 수 있습니다.
  • JOB_STATE_FAILED: 작업이 실패했습니다. 자세한 내용은 오류 세부정보를 확인하세요.
  • JOB_STATE_CANCELLED: 사용자가 작업을 취소했습니다.

작업 상태를 주기적으로 폴링하여 완료 여부를 확인할 수 있습니다.

Python


# Use the name of the job you want to check
# e.g., inline_batch_job.name from the previous step
job_name = "YOUR_BATCH_JOB_NAME"  # (e.g. 'batches/your-batch-id')
batch_job = client.batches.get(name=job_name)

completed_states = set([
    'JOB_STATE_SUCCEEDED',
    'JOB_STATE_FAILED',
    'JOB_STATE_CANCELLED',
])

print(f"Polling status for job: {job_name}")
batch_job = client.batches.get(name=job_name) # Initial get
while batch_job.state.name not in completed_states:
  print(f"Current state: {batch_job.state.name}")
  time.sleep(30) # Wait for 30 seconds before polling again
  batch_job = client.batches.get(name=job_name)

print(f"Job finished with state: {batch_job.state.name}")
if batch_job.state.name == 'JOB_STATE_FAILED':
    print(f"Error: {batch_job.error}")

결과 가져오기

작업 상태가 일괄 작업이 성공했음을 나타내면 response 필드에서 결과를 확인할 수 있습니다.

Python

import json

# Use the name of the job you want to check
# e.g., inline_batch_job.name from the previous step
job_name = "YOUR_BATCH_JOB_NAME"
batch_job = client.batches.get(name=job_name)

if batch_job.state.name == 'JOB_STATE_SUCCEEDED':

    # If batch job was created with a file
    if batch_job.dest and batch_job.dest.file_name:
        # Results are in a file
        result_file_name = batch_job.dest.file_name
        print(f"Results are in file: {result_file_name}")

        print("Downloading result file content...")
        file_content = client.files.download(file=result_file_name)
        # Process file_content (bytes) as needed
        print(file_content.decode('utf-8'))

    # If batch job was created with inline request
    elif batch_job.dest and batch_job.dest.inlined_responses:
        # Results are inline
        print("Results are inline:")
        for i, inline_response in enumerate(batch_job.dest.inlined_responses):
            print(f"Response {i+1}:")
            if inline_response.response:
                # Accessing response, structure may vary.
                try:
                    print(inline_response.response.text)
                except AttributeError:
                    print(inline_response.response) # Fallback
            elif inline_response.error:
                print(f"Error: {inline_response.error}")
    else:
        print("No results found (neither file nor inline).")
else:
    print(f"Job did not succeed. Final state: {batch_job.state.name}")
    if batch_job.error:
        print(f"Error: {batch_job.error}")

REST

BATCH_NAME="batches/123456" # Your batch job name

curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" 2> /dev/null > batch_status.json

if jq -r '.done' batch_status.json | grep -q "false"; then
    echo "Batch has not finished processing"
fi

batch_state=$(jq -r '.metadata.state' batch_status.json)
if [[ $batch_state = "JOB_STATE_SUCCEEDED" ]]; then
    if [[ $(jq '.response | has("inlinedResponses")' batch_status.json) = "true" ]]; then
        jq -r '.response.inlinedResponses' batch_status.json
        exit
    fi
    responses_file_name=$(jq -r '.response.responsesFile' batch_status.json)
    curl https://generativelanguage.googleapis.com/download/v1beta/$responses_file_name:download?alt=media \
    -H "x-goog-api-key: $GEMINI_API_KEY" 2> /dev/null
elif [[ $batch_state = "JOB_STATE_FAILED" ]]; then
    jq '.error' batch_status.json
elif [[ $batch_state == "JOB_STATE_CANCELLED" ]]; then
    echo "Batch was cancelled by the user"
fi

일괄 작업 취소

이름을 사용하여 진행 중인 일괄 작업을 취소할 수 있습니다. 작업이 취소되면 새 요청 처리가 중지됩니다.

Python

# Cancel a batch job
client.batches.cancel(name=batch_job_to_cancel.name)

REST

BATCH_NAME="batches/123456" # Your batch job name

# Cancel the batch
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME:cancel \
-H "x-goog-api-key: $GEMINI_API_KEY" \

# Confirm that the status of the batch after cancellation is JOB_STATE_CANCELLED
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" 2> /dev/null | jq -r '.metadata.state'

일괄 작업 삭제

이름을 사용하여 기존 일괄 작업을 삭제할 수 있습니다. 작업이 삭제되면 새 요청 처리가 중지되고 일괄 작업 목록에서 삭제됩니다.

Python

# Delete a batch job
client.batches.delete(name=batch_job_to_delete.name)

REST

BATCH_NAME="batches/123456" # Your batch job name

# Cancel the batch
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME:delete \
-H "x-goog-api-key: $GEMINI_API_KEY" \

기술 세부정보

  • 지원되는 모델: 배치 모드는 다양한 Gemini 모델을 지원합니다. 각 모델의 배치 모드 지원은 모델 페이지를 참고하세요. 일괄 모드에서 지원되는 모달리티는 대화형 (또는 비일괄 모드) API에서 지원되는 모달리티와 동일합니다.
  • 가격: 일괄 모드 사용량은 동급 모델의 표준 대화형 API 비용의 50% 로 가격이 책정됩니다. 자세한 내용은 가격 책정 페이지를 참고하세요. 이 기능의 비율 제한에 대한 자세한 내용은 비율 제한 페이지를 참고하세요.
  • 서비스 수준 목표 (SLO): 배치 작업은 24시간 이내에 완료되도록 설계되었습니다. 크기와 현재 시스템 부하에 따라 많은 작업이 훨씬 빠르게 완료될 수 있습니다.
  • 캐싱: 일괄 요청에 컨텍스트 캐싱이 사용 설정됩니다. 배치의 요청으로 인해 캐시 적중이 발생하면 캐시된 토큰의 가격은 배치 모드가 아닌 트래픽과 동일합니다.

권장사항

  • 대규모 요청에 입력 파일 사용: 요청이 많은 경우 관리 용이성을 높이고 BatchGenerateContent 호출 자체의 요청 크기 제한을 피하기 위해 항상 파일 입력 방법을 사용하세요. 입력 파일당 2GB의 파일 크기 제한이 있습니다.
  • 오류 처리: 작업이 완료된 후 batchStats에서 failedRequestCount를 확인합니다. 파일 출력을 사용하는 경우 각 줄을 파싱하여 해당 특정 요청의 오류를 나타내는 GenerateContentResponse인지 상태 객체인지 확인합니다. 전체 오류 코드 목록은 문제 해결 가이드를 참고하세요.
  • 작업을 한 번 제출: 일괄 작업 생성은 멱등성이 없습니다. 동일한 생성 요청을 두 번 보내면 별도의 일괄 작업이 두 개 생성됩니다.
  • 매우 큰 배치 분할: 목표 처리 시간은 24시간이지만 실제 처리 시간은 시스템 부하 및 작업 크기에 따라 달라질 수 있습니다. 대규모 작업의 경우 중간 결과가 더 빨리 필요한 경우 작은 배치로 나누는 것이 좋습니다.

다음 단계

자세한 예는 일괄 모드 노트북을 참고하세요.