מצב באצ'

מצב האצווה של Gemini API נועד לעבד נפחים גדולים של בקשות באופן אסינכרוני ב50% מהעלות הרגילה. זמן הטיפול הממוצע הוא 24 שעות, אבל ברוב המקרים הוא קצר יותר.

כדאי להשתמש במצב אצווה למשימות גדולות ולא דחופות, כמו עיבוד מוקדם של נתונים או הפעלת הערכות שלא נדרשת לגביהן תגובה מיידית.

יצירת עבודה באצווה

יש שתי דרכים לשלוח בקשות במצב אצווה:

  • בקשות מוטבעות: רשימה של אובייקטים מסוג GenerateContentRequest שנכללים ישירות בבקשה ליצירת קבוצה. האפשרות הזו מתאימה לאצוות קטנות יותר שבהן הגודל הכולל של הבקשה הוא פחות מ-20MB. הפלט שמוחזר מהמודל הוא רשימה של אובייקטים מסוג inlineResponse.
  • קובץ קלט: קובץ JSON Lines (JSONL) שבו כל שורה מכילה אובייקט GenerateContentRequest שלם. השיטה הזו מומלצת לבקשות גדולות יותר. הפלט שמוחזר מהמודל הוא קובץ JSONL שבו כל שורה היא GenerateContentResponse או אובייקט סטטוס.

בקשות בתוך הדף

אם יש לכם מספר קטן של בקשות, אתם יכולים להטמיע ישירות את האובייקטים GenerateContentRequest בתוך BatchGenerateContentRequest. בדוגמה הבאה מופעלת השיטה 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, התשובה תסומן באותו שם מפתח.

הקובץ הזה מועלה באמצעות File 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)

בדוגמה הבאה מופעלת השיטה BatchGenerateContent עם קובץ הקלט שהועלה באמצעות File API:

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.state.name}. Waiting 30 seconds...")
    time.sleep(30)

print(f"Job finished with state: {batch_job.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 האינטראקטיבי (או במצב שאינו אצווה).
  • תמחור: השימוש במצב אצווה מתומחר ב-50% מעלות ה-API האינטראקטיבי הרגיל של הדגם המקביל. פרטים נוספים מופיעים בדף התמחור. פרטים על מגבלות הקצב של התכונה הזו מופיעים בדף בנושא מגבלות קצב.
  • יעד למדידת רמת השירות (SLO): משימות באצווה נועדו להסתיים תוך 24 שעות. יכול להיות שהרבה משימות יסתיימו הרבה יותר מהר, בהתאם לגודל שלהן ולעומס הנוכחי על המערכת.
  • שמירה במטמון: שמירת הקשר במטמון מופעלת לבקשות batch. אם בקשה בחבילה שלכם מניבה פגיעה במטמון, המחיר של הטוקנים שנשמרו במטמון זהה למחיר של תנועה במצב שאינו חבילה.

שיטות מומלצות

  • שימוש בקובצי קלט לבקשות גדולות: כשמדובר במספר גדול של בקשות, תמיד כדאי להשתמש בשיטת הקלט של קובץ כדי לשפר את יכולת הניהול ולמנוע חריגה ממגבלות הגודל של הבקשה עבור הקריאה BatchGenerateContent עצמה. חשוב לזכור שיש מגבלת גודל של 2GB לכל קובץ קלט.
  • טיפול בשגיאות: אחרי השלמת העבודה, בודקים את batchStats אם יש failedRequestCount. אם משתמשים בפלט קובץ, צריך לנתח כל שורה כדי לבדוק אם היא GenerateContentResponse או אובייקט סטטוס שמציין שגיאה בבקשה הספציפית הזו. במדריך לפתרון בעיות מופיעה רשימה מלאה של קודי שגיאה.
  • שליחת משימות פעם אחת: יצירת משימת אצווה היא לא אידמפוטנטית. אם תשלחו את אותה בקשת יצירה פעמיים, ייווצרו שני תהליכי אצווה נפרדים.
  • פיצול של קבוצות גדולות מאוד: אמנם יעד הזמן לטיפול הוא 24 שעות, אבל זמן הטיפול בפועל עשוי להשתנות בהתאם לעומס המערכת ולגודל המשימה. במשימות גדולות, כדאי לחלק אותן למנות קטנות יותר אם צריך לקבל תוצאות ביניים מוקדם יותר.

המאמרים הבאים

דוגמאות נוספות זמינות במחברת של מצב אצווה.