Dávkové zpracování přes Batch API
Popisky k tisícům produktů, štítky ke starým článkům, překlad celého webu – úlohy, na jejichž výsledek nikdo nečeká u obrazovky. Batch API je zpracuje najednou za polovinu běžné ceny. Jak dávku v PHP odeslat, hlídat a vyzvednout. Popis API odpovídá stavu k říjnu 2026.
Jak to funguje
- Pošlete dávku požadavků – každý má vlastní identifikátor custom_id a stejné parametry jako běžný dotaz.
- API dávku zpracuje na pozadí. Většina dávek je hotová do hodiny, nejpozději do 24 hodin (pak nezpracované požadavky vyprší).
- Stav kontrolujete dotazem na dávku. Když je processing_status "ended", stáhnete výsledky.
Dávka se platí za polovinu běžné ceny tokenů a může mít až 100 000 požadavků nebo 256 MB.
Pomocná funkce
Batch API má vlastní adresy, proto se hodí obecná funkce pro GET i POST:
// zavolá adresu Claude API, vrátí stavový kód a tělo odpovědi
function claude_api($klic, $adresa, ?array $data = null)
{
$ch = curl_init("https://api.anthropic.com" . $adresa);
$volby = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => array(
"content-type: application/json",
"x-api-key: " . $klic,
"anthropic-version: 2023-06-01",
),
);
if ($data !== null) {
$volby[CURLOPT_POST] = true;
$volby[CURLOPT_POSTFIELDS] = json_encode($data);
}
curl_setopt_array($ch, $volby);
$telo = curl_exec($ch);
if ($telo === false) {
throw new RuntimeException("Spojení se nezdařilo: " . curl_error($ch));
}
return array(curl_getinfo($ch, CURLINFO_HTTP_CODE), $telo);
}
Odeslání dávky
Skript vybere produkty bez popisku a pro každý připraví požadavek. Identifikátor custom_id smí obsahovat jen písmena bez diakritiky, číslice, podtržítko a pomlčku (nejvýš 64 znaků) a v dávce musí být jedinečný. Číslo dávky se uloží do databáze, ať ji další skript najde.
$pozadavky = array();
$vysledek = mysqli_query($db, "SELECT id, nazev, parametry FROM produkty WHERE popis = '' LIMIT 1000");
while ($p = mysqli_fetch_assoc($vysledek)) {
$pozadavky[] = array(
"custom_id" => "produkt-" . $p["id"],
"params" => array(
"model" => "claude-sonnet-5-5",
"max_tokens" => 400,
"system" => "Píšeš krátké a věcné popisky produktů pro český e-shop. Žádné superlativy.",
"messages" => array(array("role" => "user", "content" => "Produkt: " . $p["nazev"] . "\nParametry: " . $p["parametry"])),
),
);
}
if ($pozadavky) {
list($kod, $telo) = claude_api($klic, "/v1/messages/batches", array("requests" => $pozadavky));
$davka = json_decode($telo, true);
if ($kod !== 200) {
throw new RuntimeException("Dávku se nepodařilo odeslat: HTTP " . $kod . " " . $telo);
}
$stmt = mysqli_prepare($db, "INSERT INTO ai_davky (id_davky, stav, vytvoreno) VALUES (?, 'odeslano', NOW())");
mysqli_stmt_bind_param($stmt, "s", $davka["id"]);
mysqli_stmt_execute($stmt);
}
Kontrola a výsledky
Druhý skript spouští cron třeba každých deset minut. Výsledky přicházejí jako soubor JSONL (na každém řádku jeden JSON) a nemusí být ve stejném pořadí jako požadavky – k produktu se přiřazují podle custom_id. Každý výsledek má typ succeeded, errored, canceled nebo expired.
$davky = mysqli_query($db, "SELECT id_davky FROM ai_davky WHERE stav = 'odeslano'");
while ($d = mysqli_fetch_assoc($davky)) {
list($kod, $telo) = claude_api($klic, "/v1/messages/batches/" . rawurlencode($d["id_davky"]));
$stav = json_decode($telo, true);
if ($kod !== 200 || $stav["processing_status"] !== "ended") {
continue;
}
// results_url je adresa na api.anthropic.com, stačí z ní cesta
list($kod, $jsonl) = claude_api($klic, parse_url($stav["results_url"], PHP_URL_PATH));
$ulozit = mysqli_prepare($db, "UPDATE produkty SET popis = ? WHERE id = ?");
foreach (explode("\n", trim($jsonl)) as $radek) {
$r = json_decode($radek, true);
if (!is_array($r) || $r["result"]["type"] !== "succeeded" || strpos($r["custom_id"], "produkt-") !== 0) {
continue;
}
$text = "";
foreach ($r["result"]["message"]["content"] as $blok) {
if ($blok["type"] === "text") {
$text .= $blok["text"];
}
}
$id = (int) substr($r["custom_id"], 8);
mysqli_stmt_bind_param($ulozit, "si", $text, $id);
mysqli_stmt_execute($ulozit);
}
$hotovo = mysqli_prepare($db, "UPDATE ai_davky SET stav = 'hotovo' WHERE id_davky = ?");
mysqli_stmt_bind_param($hotovo, "s", $d["id_davky"]);
mysqli_stmt_execute($hotovo);
}
Na co si dát pozor
- Stav dávky má hodnoty in_progress, canceling a ended. Počty v request_counts (processing, succeeded, errored, canceled, expired) se doplní až po dokončení celé dávky.
- Chybné požadavky (errored, expired) se v ukázce přeskočí a produkty zůstanou bez popisku – při dalším běhu se pošlou znovu. Jen pozor, ať se do nové dávky nedostanou produkty, které ještě čekají v rozpracované dávce.
- Výsledky jsou dostupné omezenou dobu, pak se dávka archivuje. Stahujte je hned po dokončení.
- Kontrola textu. Popisky od AI před zveřejněním aspoň namátkou přečtěte. Mohou obsahovat nepravdivé údaje o produktu.
- S dávkou jde kombinovat i mezipaměť (prompt caching) – stejné instrukce v parametru system pak vyjdou ještě levněji.
- Na dotazy, na které někdo čeká (chat, formulář), se dávka nehodí – použijte běžné volání, případně streamování.
Související články:
Prompt caching: levnější opakované dotazy
Chyby a opakování dotazů na Claude API
Bezpečné a úsporné použití AI API na webu
parse_url()