
Gemini Batch API memangkas biaya 50%—duplikasi job bisa menagih dua kali

Gemini Batch API memproses permintaan massal secara asinkron dengan tarif 50% dari standar dan target penyelesaian 24 jam; pembuatan job tidak idempoten, sehingga dua panggilan pembuatan yang sama menghasilkan dua job. Jika keduanya memproses permintaan yang sama dengan pemakaian token setara, keduanya dapat menimbulkan tagihan.
Untuk menjalankannya, tulis setiap permintaan sebagai satu baris JSONL dengan key unik, validasi file, unggah, lalu buat satu job dan simpan namanya. Setelah job selesai, unduh hasil dan cocokkan setiap baris dengan key masukan. Alur ini sesuai untuk evaluasi atau pra-pemrosesan data yang tidak memerlukan jawaban langsung.
Buat JSONL dengan key yang tetap
Setiap baris file memuat objek JSON dengan key dan request. Pilih key dari identitas data yang stabil, seperti ID produk, agar keluaran tetap dapat dikenali meskipun urutannya berbeda dari masukan. Dua baris berikut adalah contoh untuk file batch.jsonl; masing-masing ditulis pada baris tersendiri tanpa koma di antaranya.
{"key":"item-001","request":{"contents":[{"role":"user","parts":[{"text":"Ringkas deskripsi produk A dalam satu kalimat."}]}]}}
{"key":"item-002","request":{"contents":[{"role":"user","parts":[{"text":"Ringkas deskripsi produk B dalam satu kalimat."}]}]}}
Jangan memakai nomor baris sebagai satu-satunya identitas bila file mungkin disusun ulang. Simpan pula file masukan yang benar-benar dikirim, model yang dipilih, dan versi instruksinya. Saat satu baris perlu dicoba kembali, catatan itu memungkinkan Anda mengirim request asal dengan key yang sama tanpa menebak isi permintaan sebelumnya.
Validasi masukan sebelum unggah
Contoh Python berikut membaca file kecil tadi, menolak JSON yang rusak, key kosong atau ganda, serta request tanpa contents. Jalankan pernyataannya berurutan dalam sesi Python yang sama. Untuk file besar, baca dan periksa baris secara bertahap agar seluruh isi tidak harus berada di memori.
import json, time; from pathlib import Path; from google import genai; from google.genai import types
rows = [json.loads(line) for line in Path("batch.jsonl").read_text(encoding="utf-8").splitlines() if line.strip()]
keys = [row["key"] for row in rows]; assert rows and all(isinstance(key, str) and key for key in keys) and len(keys) == len(set(keys))
assert all(row["request"]["contents"] for row in rows)
Pemeriksaan ini menangkap masalah bentuk dasar, tetapi belum menjamin setiap request diterima model. Batasi ukuran file sesuai ketentuan layanan dan periksa pula parameter yang dipakai setiap request. Jika data berasal dari beberapa sumber, lakukan pemeriksaan key setelah semuanya digabung: key yang unik di masing-masing sumber belum tentu unik dalam satu batch.
Unggah file dan buat satu job
Setelah GEMINI_API_KEY tersedia di lingkungan, unggah JSONL melalui File API dan gunakan nama file hasil unggahan sebagai src. Contoh Python Google Developers Blog memakai urutan unggah file, pembuatan job, lalu pengunduhan hasil setelah job berhasil.
client = genai.Client(); uploaded = client.files.upload(file="batch.jsonl", config=types.UploadFileConfig(mime_type="jsonl"))
job = client.batches.create(model="gemini-2.5-flash", src=uploaded.name, config={"display_name": "batch-katalog-v1"})
Path("batch-job.txt").write_text(job.name, encoding="utf-8")
File batch-job.txt memudahkan contoh ini dilanjutkan pada sesi berikutnya. Dalam sistem produksi, catat hash isi JSONL bersama model dan konfigurasi pada penyimpanan dengan aturan keunikan, lalu kaitkan nama job yang dikembalikan dengan catatan itu. Nama tampilan membantu penelusuran, tetapi tidak mencegah job lain dibuat dengan nama yang sama.
Ada celah penting antara panggilan create dan penyimpanan responsnya: koneksi dapat terputus setelah layanan membuat job, sementara aplikasi belum menerima namanya. Tandai pengiriman yang masih belum pasti, telusuri daftar job dengan client.batches.list(), dan cocokkan catatan waktu serta nama tampilannya sebelum memutuskan tindakan. Pencarian itu membantu rekonsiliasi; jika hasilnya belum meyakinkan, jangan menganggap panggilan pertama gagal lalu otomatis membuat job baru.
Pantau nama job yang sudah tersimpan
Ambil status berdasarkan nama job, bukan dengan mengirim ulang file. Contoh berikut menambah jeda pemeriksaan secara bertahap hingga batas yang dipilih aplikasi. Angka jedanya merupakan pilihan untuk contoh, sedangkan status akhir menentukan apakah hasil boleh diunduh.
job_name = Path("batch-job.txt").read_text(encoding="utf-8"); done = {"JOB_STATE_SUCCEEDED", "JOB_STATE_FAILED", "JOB_STATE_CANCELLED", "JOB_STATE_EXPIRED"}; delay = 30; job = client.batches.get(name=job_name)
while job.state.name not in done: time.sleep(delay); delay = min(delay * 2, 300); job = client.batches.get(name=job_name)
Unduh keluaran hanya ketika statusnya JOB_STATE_SUCCEEDED. Pada JOB_STATE_FAILED, simpan rincian job.error untuk diagnosis; status dibatalkan atau kedaluwarsa juga perlu dicatat sebelum menentukan permintaan mana yang masih harus diproses. Target waktu penyelesaian bukan alasan untuk membuat salinan job selama status job lama masih dapat diperiksa.
Rekonsiliasi keluaran dan pilih retry per baris
Status job yang berhasil tidak berarti semua permintaan di dalamnya menghasilkan respons. Unduh file hasil, uraikan setiap baris JSONL, dan periksa key sebelum menyimpan respons. Pernyataan berikut melanjutkan sesi Python sebelumnya dan sengaja berhenti jika job belum berhasil atau file keluaran tidak lengkap.
assert job.state.name == "JOB_STATE_SUCCEEDED"
result = client.files.download(file=job.dest.file_name).decode("utf-8"); output = [json.loads(line) for line in result.splitlines() if line.strip()]
out_keys = [item["key"] for item in output]; assert len(out_keys) == len(set(out_keys)), "key keluaran ganda"
by_key = {item["key"]: item for item in output}; missing = set(keys) - set(by_key); unexpected = set(by_key) - set(keys); assert not missing and not unexpected, (missing, unexpected)
Setelah jumlah dan identitas key sesuai, pisahkan baris yang memuat response dari baris yang memuat error. Simpan respons bersama key dan nama job asalnya; simpan rincian error bersama request asal. Hitungan kegagalan pada statistik job berguna sebagai pemeriksaan tambahan, tetapi tidak menunjukkan sendiri baris mana yang harus ditangani.
failed = [row for row in rows if by_key[row["key"]].get("error")]
Daftar failed adalah calon retry, bukan perintah untuk langsung mengirim semuanya. Perbaiki request yang tidak valid; untuk kegagalan yang layak dicoba kembali, tulis JSONL baru hanya dari baris tersebut. Pertahankan key asal dan simpan nomor percobaan dalam catatan aplikasi, sehingga hasil retry dapat dipasangkan dengan kegagalan sebelumnya tanpa menimpa respons yang sudah berhasil. Key yang hilang dari file keluaran atau muncul ganda memerlukan penyelidikan tersendiri sebelum pengiriman ulang.
Perkirakan biaya dari token, bukan jumlah baris
Untuk Gemini 2.5 Flash pada paket berbayar, daftar harga Gemini API mencantumkan tarif batch USD 0,15 per sejuta token input teks dan USD 1,25 per sejuta token output, dibandingkan USD 0,30 dan USD 2,50 pada tarif standar. Token output mencakup token pemikiran; pemakaian cache dan alat dapat memiliki komponen harga tersendiri.
Sebagai ilustrasi bersyarat, 10 juta token input teks dan 1 juta token output untuk model itu berbiaya sekitar USD 2,75 dalam satu batch, dibandingkan USD 5,50 pada tarif standar, sebelum komponen lain yang mungkin berlaku. Jika dua job identik sama-sama selesai dengan pemakaian tersebut, gabungan biaya batch menjadi sekitar USD 5,50. Karena biaya mengikuti pemakaian, jumlah baris yang sama belum tentu menghasilkan tagihan yang sama ketika panjang input atau output berbeda.
Baca juga:
Artikel terkait


GitLab CVSS 10 dieksploitasi—cek log untuk memastikan data benar-benar keluar

Google AI Studio bukan Gemini biasa—mulai dari petunjuk sistem

Kunci Gemini API bocor di GitHub? Simpan di environment sebelum kode berjalan

Server Vite terbuka sedang dipindai—rahasia .env ikut menjadi sasaran

Databricks membeli Row Zero—spreadsheet menjadi pintu masuk agen AI
Berlangganan buletin kami
Dapatkan berita Web3, AI, dan kripto terbaru langsung di kotak masuk Anda.