24 β Batch API va optimizatsiya¶
β¬ οΈ Oldingi: 23 β Observability va evals Β· π README Β· Keyingi: 25 β Deploy: serverless va edge β‘οΈ
Bu bobda: sizda ko'p so'rov bor, lekin ularning birortasi ham "darhol javob ber" demaydi β 10 000 ta sharhni tasniflash, butun datasetga xulosa/embedding generatsiya qilish, tungi ishlov. Mana shunday ish uchun Message Batches API bor: hammasini fonda asinxron ishlaydi va buning evaziga narxning yarmini (50% off) oladi. Avval nega batch β jonli chaqiruvdan farqi nimada, qachon to'g'ri, qachon noto'g'ri β keyin uni JavaScript'da qanday ishlatish:
createβcustom_idβprocessing_statusni poll qilish β natijalarni o'qib chiqish (har element xatosini alohida). So'ng kitob bo'ylab tarqalgan barcha narx/kechikish dastaklarini bitta to'plamga jamlaymiz β qaysi qachon, qaysi qaysi bobda β va ularni bitta bulk pipeline'da birlashtirib ~10Γ tejovni ko'ramiz. Yakunda: 1000 ta sharhni Batch + Haiku bilan, yarim narxda tasniflaydigan klassifikator + sample pipeline'ga qo'llangan "optimizatsiya nazorat ro'yxati".Halollik eslatmasi: bu bobdagi API shakllari β
client.messages.batches.create({ requests: [...] }),requestsichidagicustom_idvaparams,batches.retrieve(id)qaytaradiganprocessing_status("ended"bo'lguncha poll),batches.results(id)async-iterator va undagiresult.custom_id/result.result.type("succeeded"/"errored"/ ...) /result.result.messageβ@anthropic-ai/sdk0.104 va Anthropic hujjatiga muvofiq yozilgan. Cheklovlar: bitta batchda 100 000 gacha so'rov yoki 256 MB, natijalar 29 kun saqlanadi, odatda 1 soat ichida (maks 24 soat) tayyor. Narx ~50% β lekin aniq raqamlar va break-even sizning hajmingizga bog'liq, shuning uchun har doim haqiqiyusagebilan o'lchang (14/23-bob).
Nega kerak? β "darhol kerak emas" ishning yarim narxi¶
Tasavvur qiling, sizda 10 000 ta mahsulot sharhi bor va har birini "ijobiy / salbiy / neytral" deb tasniflashingiz kerak. Buni hisobot uchun bugun kechqurun qilsangiz kifoya β hech kim ekran oldida javob kutib turgani yo'q. Agar siz buni 10 000 ta alohida jonli messages.create() chaqiruvi bilan qilsangiz, ikki narsani to'lasiz: to'liq narx va rate limit bilan kurash (16-bob). Holbuki ishning o'zi shoshilinch emas.
Mana shu yerda Message Batches API keladi. Batch (to'plam, partiya) β bu ko'p so'rovni bitta yumaloqqa yig'ib, Anthropic'ga "buni fonda, navbatda ishlab, tayyor bo'lganda ber" deyish. Buning evaziga siz narxning 50% ini (yarmini) to'laysiz. Almashinuv aniq: javob darhol emas β odatda 1 soat ichida (kafolatli yuqori chegara 24 soat). Demak batch fon/bulk ish uchun mukammal, lekin jonli chat uchun noto'g'ri β u yerda foydalanuvchi kutib turadi.
Analogiya: jonli chaqiruv β bu taksi. Darhol keladi, lekin har safar to'liq haq to'laysiz. Batch β bu avtobus. Ketishini biroz kutasiz, lekin chiptasi yarim narx. Yo'lovchilaringiz ko'p va shoshilmasa β avtobus aqlli tanlov.
Batch qachon to'g'ri (kechikishga sezgir EMAS, ko'p so'rov):
- Bulk tasniflash β minglab sharh/tiket/xabarni teglash (bu bobning kapstoni).
- Dataset bo'yicha generatsiya β har bir hujjatga xulosa, tarjima yoki qayta yozish.
- Tungi/rejali ishlov β har kuni yangi ma'lumotni qayta hisoblash.
- Eval'larni ishga tushirish β yuzlab test holatini bir batchda baholash (23 β Observability va evals).
Batch qachon noto'g'ri (javob darhol kerak):
- Jonli chatbot, foydalanuvchi yozib kutadi β bu yerda streaming (04-bob) kerak, batch emas.
- Tugmaga bosgandan keyingi darhol javob, real-vaqt vositalar.
Batch'ni JavaScript'da ishlatish¶
Batch oqimi to'rt qadamdan iborat: yarat β poll qil β tugadi β natijalarni o'qib chiq. Har birini ko'rib chiqamiz.
1) Batchni yaratish β custom_id muhim¶
Har bir so'rov bitta obyekt: custom_id (siz beradigan noyob nom) va params (xuddi messages.create() ga beradigan narsangiz β model, max_tokens, messages, hatto tools, system, caching). custom_id β eng muhim qism: natijalar tartibsiz qaytishi mumkin, shuning uchun har natijani qaysi so'rovga tegishli ekanini aynan custom_id orqali topasiz.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic(); // ANTHROPIC_API_KEY .env dan (02-bob)
const sharhlar = [
"Mahsulot zo'r, tez yetkazishdi!",
"Sifati past, pulim afsus.",
"Yaxshi, lekin qadoq buzilgan edi.",
// ... 1000 ta sharh
];
const batch = await client.messages.batches.create({
requests: sharhlar.map((sharh, i) => ({
custom_id: `sharh-${i}`, // <- natijani shu so'rovga moslash uchun NOYOB id
params: {
model: "claude-haiku-4-5", // oddiy ish -> arzon model (14-bob)
max_tokens: 16, // javob qisqa -> kichik max_tokens (arzon)
messages: [
{
role: "user",
content: `Quyidagi sharhni faqat bitta so'z bilan tasnifla: `
+ `"ijobiy", "salbiy" yoki "neytral".\n\nSharh: ${sharh}`,
},
],
},
})),
});
console.log("Batch yaratildi:", batch.id); // msgbatch_...
console.log("Holat:", batch.processing_status); // "in_progress"
E'tibor bering: params ichida model, max_tokens, messages β bular oddiy messages.create() dagi bilan bir xil. Batch shunchaki ularni o'rab, "fonda, yarim narxda ishla" deydi. custom_id esa params dan tashqarida β u sizning ichki yorlig'ingiz, modelga ko'rinmaydi.
2) Holatni poll qilish β processing_status¶
Batch yaratilgandan keyin u darhol tayyor emas. Siz vaqti-vaqti bilan retrieve(id) chaqirib, processing_status ni tekshirasiz. U "ended" bo'lganda hamma so'rov ishlangan (muvaffaqiyatli yoki xato β har biri alohida).
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
let b;
do {
b = await client.messages.batches.retrieve(batch.id);
console.log("Holat:", b.processing_status,
"| tugadi:", b.request_counts.succeeded,
"| xato:", b.request_counts.errored);
if (b.processing_status !== "ended") await sleep(10_000); // 10 soniyada bir tekshir
} while (b.processing_status !== "ended");
console.log("Batch tugadi! Natijalar tayyor.");
Bu yerda biz har 10 soniyada bir poll qilamiz. Tez-tez poll qilmang β batch baribir asinxron, soniyada o'nlab tekshirish foydasiz va rate limit yeydi. Real ishlab chiqarishda buni ko'pincha alohida ishchi/cron qiladi: batchni yaratasiz, batch.id ni bazaga yozasiz, va keyinroq (masalan, har 5 daqiqada) yagona joyda tekshirasiz. request_counts esa progressni ko'rsatadi β necha so'rov bitdi, nechtasi xato.
3 va 4) Natijalarni o'qib chiqish β custom_id bo'yicha moslab¶
"ended" dan keyin batches.results(id) async-iterator qaytaradi. Har bir natijada custom_id (qaysi so'rov) va result.type ("succeeded" / "errored" / "canceled" / "expired") bor. Har elementning xatosini alohida boshqaring β batch'da bir element xato bo'lsa, qolganlari baribir muvaffaqiyatli bo'lishi mumkin.
const natijalar = {}; // custom_id -> javob
for await (const r of await client.messages.batches.results(batch.id)) {
if (r.result.type === "succeeded") {
// r.result.message β xuddi messages.create() qaytaradigan Message
const javob = r.result.message.content[0].text.trim();
natijalar[r.custom_id] = javob;
} else {
// har element xatosi ALOHIDA β bittasi yiqilsa, batch yiqilmaydi
console.warn(`${r.custom_id}: ${r.result.type}`,
r.result.error?.error?.message ?? "");
natijalar[r.custom_id] = null;
}
}
// custom_id orqali asl tartibga qaytaramiz
sharhlar.forEach((sharh, i) => {
console.log(`[${natijalar[`sharh-${i}`] ?? "XATO"}] ${sharh}`);
});
Asosiy g'oya: for await ... of orqali natijalarni oqim sifatida o'qiysiz (10 000 ta natijani xotiraga birdan yuklamaslik uchun), har birini custom_id orqali asl so'rovga bog'laysiz, va result.type bo'yicha muvaffaqiyat/xatoni ajratasiz. succeeded bo'lsa r.result.message β bu siz tanigan oddiy Message obyekti (xuddi jonli chaqiruvdagidek content, usage bilan).
To'liq optimizatsiya to'plami β qaysi dastak, qachon¶
Batch β narxni tushiradigan dastaklardan bittasi. Endi kitob bo'ylab tarqalgan barcha narx va kechikish dastaklarini bitta joyga jamlaymiz, toki keyingi loyihangizda "qayerda tejasam bo'ladi?" deganda butun ro'yxat ko'z oldingizda bo'lsin.
Narxni kamaytirish¶
| Dastak | Nima qiladi | Qachon | Bob |
|---|---|---|---|
| To'g'ri model | Oddiy ish uchun Haiku, qiyin ish uchun Opus | Vazifa oddiy bo'lsa (tasniflash, marshrutlash) | 14 |
| Prompt caching | Takror prefiksni ~0.1Γ narxda qayta ishlatish | Bir xil katta kontekst qayta yuborilsa | 15 |
| Batch API | Asinxron bulk = 50% (yarmi) | Ko'p so'rov, kechikish muhim emas | shu bob |
Kichik max_tokens |
Chiqishni cheklash β chiqish narxi qimmatroq | Javob qisqa bo'lishi kerak bo'lsa | 14 |
| Qisqa/aniq prompt | Kamroq kirish tokeni | Prompt shishib ketgan bo'lsa | har doim |
Past effort |
Kamroq fikrlash (thinking) tokeni | Vazifa chuqur fikrlashni talab qilmasa | 10-bob |
| Routing arzonβqimmat | Avval Haiku, faqat kerak bo'lsa Opus | Aralash qiyinlikdagi oqim | 21 |
Kechikishni (latency) kamaytirish¶
| Dastak | Nima qiladi | Qachon | Bob |
|---|---|---|---|
| Streaming | Token-token oqim β his etilgan tezlik | Foydalanuvchi javobni ko'rib turadi | 04-bob |
Promise.all parallel |
Mustaqil so'rovlarni bir vaqtda | Bir nechta so'rov bir-biriga bog'liq emas | 21 |
| Kichikroq model | Haiku Opus'dan tez javob qaytaradi | Tezlik va narx ikkalasi muhim | 14 |
| Keshlash (kesh hit) | Kesh natijasi qaytsa, API ga umuman bormaysiz | Bir xil so'rov takrorlansa | 15 |
Diqqat β ba'zi dastaklar ikkala tomonni ham yutadi. Kichikroq model ham arzon, ham tez. Prompt caching ham narxni tushiradi (o'qish ~0.1Γ), ham ishlanish vaqtini qisqartiradi (model keshlangan prefiksni qayta o'qimaydi). Shu sababli bu ikkitasi β eng "tekin" optimizatsiyalar: ko'pincha xarajat almashinuvisiz ikkala foydani ham beradi.
Eslatma β batch parallel EMAS. 21 β Multi-agent dagi
Promise.allham "ko'p so'rovni birga" qiladi, lekin maqsadi boshqa: u kechikishni kamaytiradi (javoblar darhol, parallel keladi), narxni emas. Batch esa narxni yarmiga tushiradi, lekin kechikishni oshiradi (asinxron). Ko'p so'rov darhol kerak bo'lsa βPromise.all. Ko'p so'rov shoshilmasa va arzon kerak bo'lsa β batch.
Dastaklarni birlashtirish β tejov ustma-ust¶
Eng katta kuch β dastaklarni birlashtirganda kelib chiqadi. Ular jamlanmaydi, ko'paytma bo'lib ishlaydi: har biri qolgan narxni yana bo'ladi.
Misol: 10 000 ta sharhni tasniflash uchun bulk pipeline quramiz va uchta dastakni ustma-ust qo'yamiz:
- To'g'ri model β bu oddiy ish, Opus shart emas. Haiku Opus'dan ~5Γ arzon β narx ~25% ga tushadi.
- Keshlangan system prompt β har sharhda bir xil yo'riqnoma (tasniflash qoidalari, misollar) takrorlanadi. Uni keshlasak, o'sha umumiy prefiks ~0.1Γ bo'ladi β narx yana tushadi.
- Batch API β hammasi shoshilinch emas, bulk. Batch qolgan narxni yana yarmiga bo'ladi (50%).
Yakuniy natija: sodda "Opus, jonli, har so'rov alohida" yondashuviga nisbatan taxminan 10Γ arzonroq. Va bu taxminiy raqamlar β sizning aniq tejouingiz prompt o'lchamiga, model tanloviga va keshlanadigan prefiks ulushiga bog'liq. Shuning uchun har doim o'lchang.
Halollik β raqamlar taxminiy. Yuqoridagi ~25% / ~14% / ~7% β dastaklar qanday ko'payishini ko'rsatish uchun illustratsiya, kafolatli aniq qiymat emas. Haqiqiy tejov sizning ish yukingizga bog'liq: agar keshlanadigan prefiks kichik bo'lsa, caching foydasi kam; agar sharhlar juda qisqa bo'lsa, model tanlovi foydasi katta. Doim haqiqiy
usagebilan tasdiqlang.
Kapston: bulk klassifikator (Batch + Haiku + kesh) + nazorat ro'yxati¶
Hammasini birlashtiramiz β 1000 ta sharhni Batch API bilan, Haiku'da, umumiy yo'riqnomani keshlab tasniflaydigan pipeline. So'ng pastda uni "optimizatsiya nazorat ro'yxati" bilan tekshiramiz.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// Har sharhda BIR XIL yo'riqnoma β keshlash uchun nomzod (15-bob).
const YORIQNOMA =
"Sen sharhlarni tasniflovchisan. Sharhni faqat bitta so'z bilan tasnifla: "
+ "'ijobiy', 'salbiy' yoki 'neytral'. Boshqa hech narsa yozma.\n"
+ "Misollar:\n"
+ "Sharh: 'Zo'r mahsulot!' -> ijobiy\n"
+ "Sharh: 'Umuman yoqmadi.' -> salbiy\n"
+ "Sharh: 'O'rtacha, shunchaki.' -> neytral\n"; // ... real holatda uzunroq
async function bulkTasnifla(sharhlar) {
// 1) Batch yaratamiz: Haiku + kichik max_tokens + keshlangan system
const batch = await client.messages.batches.create({
requests: sharhlar.map((sharh, i) => ({
custom_id: `sharh-${i}`,
params: {
model: "claude-haiku-4-5", // arzon model (14-bob)
max_tokens: 16, // qisqa javob (14-bob)
system: [
{ type: "text", text: YORIQNOMA,
cache_control: { type: "ephemeral" } }, // keshlangan prefiks (15-bob)
],
messages: [{ role: "user", content: `Sharh: ${sharh}` }],
},
})),
});
console.log("Batch:", batch.id, "| so'rovlar:", sharhlar.length);
// 2) Tugaguncha poll qilamiz
let b;
do {
b = await client.messages.batches.retrieve(batch.id);
if (b.processing_status !== "ended") await sleep(10_000);
} while (b.processing_status !== "ended");
// 3) Natijalarni custom_id bo'yicha yig'amiz + xatolarni alohida hisoblaymiz
const tasnif = {};
let xato = 0, kesh_oqildi = 0;
for await (const r of await client.messages.batches.results(batch.id)) {
if (r.result.type === "succeeded") {
tasnif[r.custom_id] = r.result.message.content[0].text.trim().toLowerCase();
kesh_oqildi += r.result.message.usage.cache_read_input_tokens ?? 0;
} else {
xato++;
tasnif[r.custom_id] = null;
}
}
console.log(`Tugadi. Xato: ${xato}. Keshdan o'qilgan token: ${kesh_oqildi}`);
return sharhlar.map((_, i) => tasnif[`sharh-${i}`]);
}
const sharhlar = [/* ... 1000 ta sharh ... */];
const teglar = await bulkTasnifla(sharhlar);
console.log(teglar.slice(0, 5)); // ["ijobiy", "salbiy", "neytral", ...]
Bu pipeline uchta dastakni birga ishlatadi: Batch (50% narx), Haiku (arzon model), kesh (umumiy yo'riqnoma ~0.1Γ). Va cache_read_input_tokens ni o'qib, keshning haqiqatan ishlayotganini tekshiramiz (15-bob).
Optimizatsiya nazorat ro'yxati β har bulk/AI pipeline uchun bosib o'ting:
- [ ] Vazifa darhol javob talab qiladimi? Yo'q β Batch API (50%). Ha β batch emas.
- [ ] Eng oddiy model yetadimi? Tasniflash/marshrutlash β Haiku (14-bob).
- [ ] Bir xil katta kontekst takrorlanadimi? Ha β prompt caching (15-bob),
cache_readni tekshir. - [ ]
max_tokenshaqiqiy ehtiyojga moslangmi? Qisqa javob β kichik limit. - [ ] Prompt shishib ketmaganmi? Keraksiz so'zlarni olib tashla;
effortni pasaytir (10-bob). - [ ] So'rovlar bir-biriga bog'liq emasmi? (jonli oqimda) β
Promise.allparallel (21-bob). - [ ] Har optimizatsiyani
cost()/usagebilan O'LCHADINGMI? (14/23-bob) β taxmin qilma.
O'lchamasdan optimallashtirmang¶
Bu butun bobning eng muhim qoidasi. Har bir optimizatsiya bir taxminga asoslanadi ("Haiku yetadi", "kesh ishlayapti", "batch arzonroq"). Taxmin noto'g'ri bo'lishi mumkin: ehtimol Haiku sifat berolmay, siz uni Opus bilan ikki marta chaqirib, qimmatroq qilib qo'ygansiz; ehtimol keshingiz har so'rovda buzilib, faqat yozish narxini behuda to'layapsiz (15-bob). Buni bilishning yagona yo'li β o'lchash.
14 β Token, narx va limitlar dagi cost(usage, model) va 23 β Observability va evals dagi logging'ni ishlating: optimizatsiyadan oldin va keyin narx/kechikishni yozib oling va solishtiring. Raqam tushdimi β yutdingiz. Tushmadi yoki sifat yomonlashdi β orqaga qayting.
import { cost } from "./narx.js"; // 14-bobdagi cost() funksiyasi
// Optimizatsiyadan OLDIN: Opus, jonli, keshsiz
const oldin = await client.messages.create({
model: "claude-opus-4-8", max_tokens: 16,
messages: [{ role: "user", content: `Sharhni tasnifla: ${sharh}` }],
});
console.log("Oldin (1 so'rov):", cost(oldin.usage, "claude-opus-4-8").toFixed(6), "$");
// KEYIN: Haiku, keshlangan system β bir so'rovning narxini solishtiring
const keyin = await client.messages.create({
model: "claude-haiku-4-5", max_tokens: 16,
system: [{ type: "text", text: YORIQNOMA, cache_control: { type: "ephemeral" } }],
messages: [{ role: "user", content: `Sharh: ${sharh}` }],
});
console.log("Keyin (1 so'rov):", cost(keyin.usage, "claude-haiku-4-5").toFixed(6), "$");
// + batchda yana 50% β lekin uni batch usage'ida ko'rasiz
Qachon umuman optimallashtirmaslik kerak¶
Erta optimizatsiya (premature optimization) β bu o'zining tuzog'i. Agar siz kuniga atigi 50 ta so'rov yuborsangiz, batch sozlash, caching breakpoint'lari va router ustida bosh qotirish β vaqt isrofi. Shunchaki Opus'ni jonli ishlating va ishingizni davom ettiring; oydagi farq bir piyola qahvadan kam bo'lishi mumkin.
Optimizatsiya og'rigan joyda ma'noli bo'ladi: hisob-faktura sezilarli, yoki kechikish foydalanuvchini bezovta qiladi. Avval o'lchang (qayerga pul/vaqt ketyapti?), keyin eng katta ulushni oling. "Hammasini optimallashtir" emas, "eng katta xarajatni optimallashtir".
Diqqat β sifatni qurbon qilmang. Eng arzon model va eng past effort doim "yaxshi" emas. Agar Haiku tasnifni xato qilsa va siz noto'g'ri hisobot bersangiz, bu sizga arzon modeldan ko'ra qimmatga tushadi. Har optimizatsiyadan keyin sifatni ham tekshiring β eval'lar bilan (23-bob). Narx va sifat orasidagi muvozanat β sizniki, modelniki emas.
Mashqlar¶
Quyidagi mashqlarning ko'pi haqiqiy ANTHROPIC_API_KEY va tarmoq talab qiladi (batch jonli ishlanadi). client β new Anthropic() (02-bob). Katta hajm uchun avval kichik (5β10 ta) so'rovli batch bilan sinab ko'ring.
Oson¶
- Birinchi batch. 5 ta qisqa so'rovni (masalan, "1+1 nechchi?", "Parij qaysi davlatda?" ...)
batches.create()bilan yuboring, har birigacustom_id: "q-0","q-1", ... bering.batch.idvabatch.processing_statusni log qiling. - Poll qilish. 1-mashqdagi batchni
retrieve(id)bilan 10 soniyada bir tekshiring,processing_status"ended"bo'lguncha. Har tekshirishdarequest_countsni log qiling. - Natijalarni o'qish.
batches.results(id)orqali natijalarni oqim sifatida o'qing. Har biridar.custom_idvar.result.typeni log qiling;succeededbo'lsa javob matnini ko'rsating.
O'rta¶
- Custom_id moslash. 1-mashqdagi natijalarni
custom_idorqali asl savollar bilan moslab chiqaring (natijalar[custom_id]lug'ati quring, keyin asl tartibda chop eting). Natijalar tartibsiz kelishi mumkinligini eslab, faqatcustom_idga tayaning. - Element xatosini boshqarish. Bitta so'rovni atayin buzuq qiling (masalan,
max_tokens: 0yoki noto'g'ri model), batchni yuboring. Natijalarda o'sha elementresult.type !== "succeeded"ekanini, lekin qolganlari"succeeded"bo'lganini ko'ring. Xato elementni alohida hisoblang. - Batch vs jonli narx. 10 ta bir xil so'rovni (a) 10 ta alohida jonli
messages.create()va (b) bitta batch bilan yuboring.cost()(14-bob) bilan jonli to'liq narxni hisoblang; batch ~50% ekanini eslatib, qancha tejaganingizni taxmin qiling.
Qiyin¶
- Bulk klassifikator. Kapstondagi pipeline'ni quring: 50 ta sharhni Haiku + keshlangan yo'riqnoma + batch bilan tasniflang.
cache_read_input_tokens(natijausage'ida) noldan katta ekanini β ya'ni kesh ishlaganini β tasdiqlang. - Optimizatsiya nazorat ro'yxati. O'zingizning biror AI pipeline'ingizni (yoki kitobdagi biror kapstonni) oling va bobdagi nazorat ro'yxatining har bandidan o'tkazing. Har band uchun: qo'llasa bo'ladimi? Qo'llasangiz,
cost()/usagebilan narx tushganini o'lchang. - Birlashtirilgan tejovni o'lchash. Bir vazifani to'rt usulda baholang va
cost()/usagebilan haqiqiy narxni solishtiring: (a) Opus jonli keshsiz, (b) Haiku jonli keshsiz, (c) Haiku jonli keshli, (d) Haiku batch keshli. Har qadamda narx necha barobar tushganini jadval qiling. Diagrammadagi ~10Γ ga yaqinlashdimi?
Yechimlar
Yechimlar
ANTHROPIC_API_KEY(.env) talab qiladi.clientβnew Anthropic()(02-bob),cost()β 14-bobdagi funksiya.sleep = (ms) => new Promise(r => setTimeout(r, ms)).
1-mashq yechimi¶
const savollar = ["1+1 nechchi?", "Parij qaysi davlatda?", "Suvning formulasi?",
"Yer Quyoshni necha kunda aylanadi?", "Eng katta okean?"];
const batch = await client.messages.batches.create({
requests: savollar.map((s, i) => ({
custom_id: `q-${i}`,
params: {
model: "claude-haiku-4-5",
max_tokens: 64,
messages: [{ role: "user", content: s }],
},
})),
});
console.log("Batch id:", batch.id);
console.log("Holat:", batch.processing_status); // "in_progress"
custom_id har so'rov uchun noyob (q-0 ... q-4). batch.id ni saqlang β keyingi qadamlar shunga tayanadi.
2-mashq yechimi¶
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
let b;
do {
b = await client.messages.batches.retrieve(batch.id);
console.log(b.processing_status, b.request_counts); // { processing, succeeded, errored, ... }
if (b.processing_status !== "ended") await sleep(10_000);
} while (b.processing_status !== "ended");
console.log("Tayyor!");
request_counts progressni ko'rsatadi: nechtasi ishlanmoqda, nechtasi tugadi, nechtasi xato. "ended" β hammasi (xato bo'lsa ham) yakunlangani.
3-mashq yechimi¶
for await (const r of await client.messages.batches.results(batch.id)) {
console.log(r.custom_id, "->", r.result.type);
if (r.result.type === "succeeded") {
console.log(" javob:", r.result.message.content[0].text.trim());
}
}
results() async-iterator β for await ... of bilan o'qiladi. r.result.message β oddiy Message obyekti (jonli chaqiruvdagidek).
4-mashq yechimi¶
const natijalar = {};
for await (const r of await client.messages.batches.results(batch.id)) {
natijalar[r.custom_id] =
r.result.type === "succeeded" ? r.result.message.content[0].text.trim() : null;
}
// Asl tartibda, custom_id orqali moslab
savollar.forEach((s, i) => {
console.log(`Q: ${s}\nA: ${natijalar[`q-${i}`] ?? "XATO"}\n`);
});
Natijalar tartibsiz kelishi mumkin, shuning uchun massiv indeksiga emas, custom_id ga (q-${i}) tayanamiz. Lug'at quramiz, keyin asl tartibda chop etamiz.
5-mashq yechimi¶
const batch = await client.messages.batches.create({
requests: [
{ custom_id: "ok-0", params: {
model: "claude-haiku-4-5", max_tokens: 32,
messages: [{ role: "user", content: "Salom de" }] } },
{ custom_id: "buzuq-1", params: {
model: "yoq-bunday-model", max_tokens: 32, // <- atayin xato model
messages: [{ role: "user", content: "Salom de" }] } },
],
});
// ... poll qilib "ended" kut ...
let xato = 0, ok = 0;
for await (const r of await client.messages.batches.results(batch.id)) {
if (r.result.type === "succeeded") { ok++; }
else { xato++; console.warn(r.custom_id, r.result.type, r.result.error?.error?.message); }
}
console.log("OK:", ok, "Xato:", xato); // OK: 1, Xato: 1
Muhim saboq: batch'da bir element yiqilsa, butun batch yiqilmaydi. Har element result.type ni alohida tekshiring va xatolarni alohida hisoblang/qayta yuboring.
6-mashq yechimi¶
import { cost } from "./narx.js";
const sorov = { model: "claude-haiku-4-5", max_tokens: 32,
messages: [{ role: "user", content: "Bu sharh ijobiymi? 'Zo'r mahsulot'" }] };
// (a) 10 ta jonli chaqiruv β to'liq narx
let jonliNarx = 0;
for (let i = 0; i < 10; i++) {
const m = await client.messages.create(sorov);
jonliNarx += cost(m.usage, "claude-haiku-4-5");
}
console.log("Jonli (10x, to'liq narx):", jonliNarx.toFixed(6), "$");
// (b) Batch β xuddi shu 10 so'rov, ~50%
const batch = await client.messages.batches.create({
requests: Array.from({ length: 10 }, (_, i) => ({ custom_id: `r-${i}`, params: sorov })),
});
// ... poll + results ...
console.log("Batch ~", (jonliNarx * 0.5).toFixed(6), "$ atrofida (50% off)");
Batch narxni ~yarmiga tushiradi. Aniq raqamni batch natijalarining usage yig'indisidan oling β taxmin emas, o'lchang.
7-mashq yechimi¶
const YORIQNOMA = "Sharhni faqat bitta so'z bilan tasnifla: 'ijobiy', 'salbiy', 'neytral'. "
+ "/* ... uzun, keshlanadigan yo'riqnoma + misollar ... */";
const sharhlar = [/* 50 ta sharh */];
const batch = await client.messages.batches.create({
requests: sharhlar.map((sh, i) => ({
custom_id: `sh-${i}`,
params: {
model: "claude-haiku-4-5", max_tokens: 16,
system: [{ type: "text", text: YORIQNOMA, cache_control: { type: "ephemeral" } }],
messages: [{ role: "user", content: `Sharh: ${sh}` }],
},
})),
});
// ... poll ...
let kesh = 0;
for await (const r of await client.messages.batches.results(batch.id)) {
if (r.result.type === "succeeded") kesh += r.result.message.usage.cache_read_input_tokens ?? 0;
}
console.log("Keshdan o'qilgan token (jami):", kesh); // > 0 bo'lsa kesh ishladi
Birinchi so'rov yo'riqnomani keshga yozadi, qolganlari o'qiydi β shuning uchun jami cache_read_input_tokens noldan katta. Eslatma: keshlash ishlashi uchun yo'riqnoma minimal prefiks o'lchamidan katta bo'lishi kerak (Haiku 4.5 da β 4096 token, 15-bob), aks holda jim keshlanmaydi.
8-mashq yechimi¶
Nazorat ro'yxatini pipeline'ga qo'llash β masalan, 18-bobdagi RAG javob generatori uchun:
[x] Darhol kerakmi? β RAG javobi foydalanuvchiga jonli -> batch EMAS, streaming (04-bob).
[x] Eng oddiy model? β javob sifatli bo'lishi kerak -> Opus qoldiramiz, lekin retrieval tasnifini Haiku ga (router, 21-bob).
[x] Takror kontekst? β system prompt + retrieval shabloni har so'rovda bir xil -> caching (15-bob).
[x] max_tokens? β javob 1-2 abzats -> max_tokens: 512 ga cheklaymiz.
[x] Prompt shishganmi? β retrieval'da top-3 -> top-8 emas, kamroq kontekst.
[x] Parallel? β bir foydalanuvchi bir savol -> parallel kerak emas; lekin embeddings'ni Promise.all bilan.
[x] O'lchadingmi? β har so'rovda cost(usage) log -> caching narxni 40% tushirdi (o'lchandi).
Asosiy g'oya: har bandni "ha/yo'q" bilan ko'rib chiqing va qo'llaganingizni o'lchang β taxmin emas.
9-mashq yechimi¶
import { cost } from "./narx.js";
const sh = "Mahsulot zo'r, lekin yetkazish sekin edi.";
const Y = "Sharhni bir so'z bilan tasnifla: ijobiy/salbiy/neytral. /* ... uzun yo'riqnoma ... */";
// (a) Opus jonli, keshsiz
const a = await client.messages.create({ model: "claude-opus-4-8", max_tokens: 16,
messages: [{ role: "user", content: `${Y}\nSharh: ${sh}` }] });
// (b) Haiku jonli, keshsiz
const b = await client.messages.create({ model: "claude-haiku-4-5", max_tokens: 16,
messages: [{ role: "user", content: `${Y}\nSharh: ${sh}` }] });
// (c) Haiku jonli, keshli (ikki marta yuborib o'qishni ko'ring)
const c = await client.messages.create({ model: "claude-haiku-4-5", max_tokens: 16,
system: [{ type: "text", text: Y, cache_control: { type: "ephemeral" } }],
messages: [{ role: "user", content: `Sharh: ${sh}` }] });
// (d) Haiku batch keshli -> batch usage'idan narx, keyin ~50% qo'llang
console.log("a Opus jonli :", cost(a.usage, "claude-opus-4-8").toFixed(6));
console.log("b Haiku jonli:", cost(b.usage, "claude-haiku-4-5").toFixed(6));
console.log("c Haiku kesh :", cost(c.usage, "claude-haiku-4-5").toFixed(6), "(2-so'rovda kesh o'qiladi)");
// d: c ning narxini batchda ~0.5x deb hisoblang -> jadval qiling
Har qadamda narx tushadi: OpusβHaiku (~5Γ), keshli (umumiy prefiks ~0.1Γ), batch (yana ~2Γ). Birlashtirilganda diagrammadagi ~10Γ ga yaqinlashadi β lekin aniq qiymat sizning prompt o'lchamingiz va keshlanadigan ulushga bog'liq, shuning uchun o'lchang, taxmin qilmang.
Keyingi qadam. Endi sizda to'liq optimizatsiya to'plami bor. Eng muhim ikki saboqni yodda tuting: (1) Batch API kechikishga sezgir bo'lmagan ko'p so'rov uchun narxni yarmiga tushiradi β
custom_idbilan yuborib,processing_statusni poll qilib, natijalarnicustom_idorqali moslab o'qiysiz; (2) dastaklar (to'g'ri model, caching, batch, kichikmax_tokens, past effort, routing, streaming, parallel) birlashganda ko'paytma bo'lib ishlaydi β bulk pipeline'da ~10Γ tejovga olib keladi. Va oltin qoida: o'lchamasdan optimallashtirmang β har o'zgarishnicost()/usage(14/23-bob) bilan tasdiqlang, va sifatni ham (23-bob) tekshiring. Keyingi bobda ilovangizni dunyoga chiqaramiz: serverless va edge muhitlarida AI ilovasini deploy qilishni β sovuq start, environment maxfiylari, streaming'ni edge'da uzatishni β o'rganamiz.
β¬ οΈ Oldingi: 23 β Observability va evals Β· π README Β· Keyingi: 25 β Deploy: serverless va edge β‘οΈ