Vertex batch embeddings (gemini-embedding-001): no way to attach billing labels; job and row labels never reach Cloud Billing
メンテナーはふだん 1 日以内に返信
@Venkaiahbabuneelam がすでに取り組んでいます。
2026年10月5日 から。
評価
この issue はまだ評価されていません。
説明
Billing labels on Vertex AI batch embedding jobs never reach Cloud Billing
Environment: google-genai 2.22.0, Python 3.13, Vertex AI (vertexai=True), us-central1, model gemini-embedding-001
What you're trying to do
We split our Vertex AI costs by custom metadata labels.
- Real-time calls work:
generateContentwithGenerateContentConfig(labels=...), andgemini-embedding-001embed_content(which the SDK sends to:predict) with labels added throughhttp_options.extra_body. Both labels show up in Cloud Billing. - Batch embeddings don't: for the same model through
client.batches.create(...), no label has ever appeared in billing, whether set on the job or in the JSONL rows.
Questions:
- Is there a supported way to attach billing labels to a Vertex batch embedding job?
- Batch rows accept
request.labels, while every other unknown key fails the row. Is that intended, and should it reach billing? - Could
CreateBatchJobConfigandEmbedContentConfigget alabelsfield, asGenerateContentConfigandGenerateImagesConfighave? CouldBatchJobkeeplabelswhen reading a job back? Today it drops them.
What code you've already tried
1. Real-time embedding: works
The label shows in billing.
await client.aio.models.embed_content(
model='gemini-embedding-001',
contents='...',
config=types.EmbedContentConfig(
task_type='RETRIEVAL_DOCUMENT',
output_dimensionality=768,
http_options=types.HttpOptions(extra_body={'labels': {'testing': 'rt_predict'}}),
),
)
Request as sent (intercepted):
POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/PROJECT/locations/us-central1/publishers/google/models/gemini-embedding-001:predict
{"instances": [{"content": "...", "task_type": "RETRIEVAL_DOCUMENT"}],
"parameters": {"outputDimensionality": 768},
"labels": {"testing": "rt_predict"}}
-> 200
Note:
PredictRequest.labelsis documented as "for Imagen billing usage only", but these labels do reach billing for this model.
2. Batch job labels: the job stores them, billing doesn't show them
CreateBatchJobConfig has no labels field, so we add them through extra_body:
await client.aio.batches.create(
model='gemini-embedding-001',
src=types.BatchJobSource(gcs_uri=['gs://BUCKET/input.jsonl'], format='jsonl'),
config=types.CreateBatchJobConfig(
display_name='label_test',
dest='gs://BUCKET/outputs/',
http_options=types.HttpOptions(extra_body={'labels': {'testing': 'j_labels'}}),
),
)
The job is created, a REST GET on the job returns "labels": {"testing": "j_labels"}, and the rows embed fine. No testing label appears on the cost.
3. Per-row labels
We tried every placement we could think of, one job per placement. Rows look like this:
{"key": "1", "request": {"content": {"parts": [{"text": "..."}]}, "output_dimensionality": 768, "task_type": "RETRIEVAL_DOCUMENT", "labels": {"testing": "r_request"}}}
| Label placement in the JSONL line | Result |
|---|---|
request.labels |
row embeds fine (accepted), not in billing |
request.content.labels |
row error: no such field: 'labels' (Content) |
request.content.parts[0].labels |
row error: no such field: 'labels' (Part) |
request.embed_content_config.labels / request.embedContentConfig.labels |
row error: no such field: 'labels' (EmbedContentConfig) |
request.metadata.labels |
row error: no such field: 'metadata' |
request.request_labels |
row error: no such field: 'request_labels' |
labels object beside request |
job fails (see errors below) |
labels as a JSON string beside request |
accepted as a pass-through column, not in billing |
flat request.content string (:predict-style) |
row error: can't parse into EmbedContentRequest |
Job-level placements:
| Placement on the job | Result |
|---|---|
labels |
stored on the job, not in billing |
modelParameters.labels |
stored, not in billing |
inputConfig.labels, outputConfig.labels, instanceConfig.labels |
400 at creation |
4. Real-time embedContent with labels
This is the request type batch rows are parsed into. It is rejected on both v1 and v1beta1:
POST .../publishers/google/models/gemini-embedding-001:embedContent
{"content": {"parts": [{"text": "..."}]}, "taskType": "RETRIEVAL_DOCUMENT", "outputDimensionality": 768, "labels": {"testing": "rt_embed_content"}}
-> 400
Any error messages you're getting
No error where it matters: request.labels and job labels are accepted and the jobs succeed, but the labels never reach Cloud Billing.
Errors from the other placements:
Failed to parse JSON into proto: google.cloud.aiplatform.master.EmbedContentRequest with status: invalid JSON in google.cloud.aiplatform.master.EmbedContentRequest @ content: message google.cloud.aiplatform.master.Content, near 1:22 (offset 21): no such field: 'labels'
Failed to parse JSON into proto: google.cloud.aiplatform.master.EmbedContentRequest with status: invalid JSON in google.cloud.aiplatform.master.EmbedContentRequest, near 1:86 (offset 85): no such field: 'metadata'
The column or property "labels" in the specified input data is of unsupported type. Supported types for this column are: [STRING, INTEGER, FLOAT, BOOLEAN, TIMESTAMP, DATE, DATETIME, NUMERIC].
400 INVALID_ARGUMENT. Invalid JSON payload received. Unknown name "labels" at 'batch_prediction_job.input_config': Cannot find field.
400 INVALID_ARGUMENT. Invalid JSON payload received. Unknown name "labels": Cannot find field. (real-time :embedContent, v1 and v1beta1)
- 主要言語
- Python
- スター
- 4k
- フォーク
- 1k
- 平均マージ
- 1日 17時間
- マージ済み PR(30日)
- 52
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
googleapis/python-genai のほかの issue
-
priority: p2 status:awaiting user response type: bug
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
googleapis/python-genai#3051 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
[Bug]: Unsubscripted typing.List and typing.Dict crash convert_if_exist_pydantic_model in AFC対応中かも @chauvuusvn が 3 日前に担当しました。 オープンpriority: p2 type: bug
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
googleapis/python-genai#3044 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
Name collision in google.genai.interactions: triggers.Interaction shadows response model Interaction in static type checkers対応中かも @Venkaiahbabuneelam が 8 日前に担当しました。 オープンpriority: p2 type: bug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
googleapis/python-genai#3013 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 74/100
googleapis/python-genai#3056 ·
メンテナーはふだん 1 日以内に返信
-
priority: p2 type: bug
難易度 3/5 1〜2日 初心者へのやさしさ 78/100
googleapis/python-genai#3031 · コメント 3 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
googleapis/python-genai の issue をすべて見る
似ている issue
-
needs-human needs-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
gke-labs/kube-agents#2400 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Device Details tables: FS/SF columns contradict each other (nfet_01v8 Vt row, pfet_01v8 Idsat row)オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
google/skywater-pdk#450 ·
-
Drained trajectory arrays are overwritten when the sequence buffer is reused対応中かも @sylvesterkaczmarek が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
google-deepmind/bsuite#56 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
LearningCircuit/local-deep-research#7206 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
chingu-voyages/V62-tier3-team-33#285 ·
メンテナーはふだん 1 日以内に返信