import anthropic
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request
client = anthropic.Anthropic()
reviews = [
"配送が早くて満足しています",
"梱包が雑で商品が傷んでいた",
"可もなく不可もなくといった印象",
]
batch = client.messages.batches.create(
requests=[
Request(
custom_id=f"review-{i}",
params=MessageCreateParamsNonStreaming(
model="claude-haiku-4-5",
max_tokens=50,
messages=[
{
"role": "user",
"content": f"次のレビューをポジティブ・ネガティブ・中立のいずれかで分類して: {text}",
}
],
),
)
for i, text in enumerate(reviews)
]
)
print(batch.id)
print(batch.processing_status)
custom_idは結果とリクエストを突き合わせるための識別子なので、重複しない値を付けます。
いずみ
例ではレビュー3件ですが、数万件を一度に投げても書き方は同じです。
処理状況をポーリングする
バッチIDを使って、処理が終わったかどうかを確認します。
import time
while True:
batch = client.messages.batches.retrieve(batch.id)
if batch.processing_status == "ended":
break
print(batch.request_counts)
time.sleep(60)
processing_statusがendedになれば、全リクエストの処理が完了しています。
request_countsには、処理中・成功・失敗・キャンセル・期限切れの件数が入ります。
結果を取得する
処理が終わったら、resultsで結果をストリーミング取得します。
for result in client.messages.batches.results(batch.id):
match result.result.type:
case "succeeded":
message = result.result.message
text = next((b.text for b in message.content if b.type == "text"), "")
print(result.custom_id, text)
case "errored":
print(result.custom_id, "エラー:", result.result.error)
case "expired":
print(result.custom_id, "期限切れ。再投入が必要")
結果はリクエストを投げた順番では返りません。
custom_idをキーにして、元のデータと突き合わせる作りにします。
いずみ
順番に依存したコードを書くとバグるので、custom_id管理は必須です。
バッチのキャンセルと一覧取得
投入済みのバッチは、処理完了前ならキャンセルできます。
client.messages.batches.cancel(batch.id)
過去に投入したバッチの一覧は、listで取得できます。
for b in client.messages.batches.list(limit=20):
print(b.id, b.processing_status)