10 β Tool runner va ko'p tool¶
β¬ οΈ Oldingi: 09 β Function calling Β· π Kitob boshi Β· Keyingi: 11 β Agentlar β‘οΈ
Bu bobda: 09-bobda tool'ni qo'lda boshqargandik β har tool natijasini o'zimiz qaytarib, loopni o'zimiz yozgandik. Bu charchatadi, ayniqsa bir nechta tool yoki ko'p qadam bo'lsa. Bu bobda tool runner bilan tanishamiz: u loopni avtomatik boshqaradi. SDK'dagi
BetaRunnableToolvatoolRunneryordamida bir nechta tool'ni model o'zi tanlab, ketma-ket chaqiradigan "do'kon yordamchisi" yasaymiz. Hammasiphp -lbilan tekshirilgan jonli kod.
1. Muammo: qo'lda loop charchatadi¶
09-bobni eslang. Model tool chaqirishni xohlaganda biz quyidagilarni o'z qo'limiz bilan qildik:
- Javobni tekshirdik β
stopReason === 'tool_use'ekanmi? tool_useblokidan tool nomi, ID va kirish argumentlarini ajratib oldik.- Tegishli PHP funksiyani qidirib topdik va chaqirdik.
- Natijani
tool_resultblokiga o'rab, suhbatga qo'shdik. - Modelga qaytadan so'rov yubordik.
- Model yana tool so'rasa β 1-qadamdan takrorladik (
whileloop bilan).
Bu bitta tool va bitta qadam uchun ham anchagina kod edi. Endi tasavvur qiling: foydalanuvchi "Toshkentdagi ob-havoni ayt, keyin haroratni Farengeytga aylantir va menga bugungi sanani ham qo'sh" desa. Bu uchta tool va kamida uch-to'rt qadamli loop. Har qadamda yuqoridagi 6 ta ishni qo'lda yozish β xato qilish oson, kodni o'qish qiyin.
Hayotiy o'xshatish. Tasavvur qiling, siz oshpazsiz va sizda yordamchi bor. Qo'lda loop β bu yordamchiga har bir ingredientni alohida-alohida o'zingiz uzatib turish: "mana piyoz, to'g'ra... endi mana sabzi, to'g'ra... endi menga qaytar...". Tool runner esa β yordamchiga butun retseptni berib: "kerakli ingredientlarni o'zing olib, ketma-ket tayyorla, oxirida tayyor taomni ber" deyish. Siz faqat boshida va oxirida ishtirok etasiz.
Yechim: SDK'da tayyor tool runner bor. Siz unga tool'lar ro'yxati va boshlang'ich savolni berasiz β u esa yuqoridagi 1β6 qadamlarni avtomatik, model tugatgunicha takrorlaydi. Sizga faqat tool'ning o'zini (funksiyasi bilan) ta'riflash qoladi.
Eslatma
Tool runner β bu sehr emas. U ichida aynan 09-bobdagi loopni bajaradi: model tool so'raydi β runner funksiyani chaqiradi β natijani qaytaradi β takrorlaydi. Farqi shundaki, bu kodni siz emas, SDK yozadi. Tushuncha har provayderda bir xil (OpenAI'da ham "tool/function calling loop" deyiladi), faqat klass nomlari farq qiladi.
2. BetaRunnableTool β funksiya bilan birga tool¶
09-bobda tool ta'rifi (JSON-schema) va uni bajaradigan PHP funksiya alohida edi: ta'rif tools massivida, funksiya esa match yoki if ichida. Tool runner ishlashi uchun bu ikkalasini bir joyda bog'lashimiz kerak β toki runner "qaysi tool chaqirilsa, qaysi funksiyani ishga tushirish"ni bilsin.
Buning uchun SDK'da Anthropic\Lib\Tools\BetaRunnableTool klassi bor. Bu β "ishga tushiriladigan tool", ya'ni ta'rif + funksiya birga.
use Anthropic\Lib\Tools\BetaRunnableTool;
$obHavo = new BetaRunnableTool(
// 1-argument: tool TA'RIFI (xuddi 09-bobdagi kabi JSON-schema massiv)
[
'name' => 'ob_havo',
'description' => 'Berilgan shahar uchun joriy ob-havoni qaytaradi. '
. 'Foydalanuvchi ob-havo haqida so\'rasa shu tool\'ni chaqir.',
'input_schema' => [
'type' => 'object',
'properties' => [
'shahar' => ['type' => 'string', 'description' => 'Shahar nomi'],
],
'required' => ['shahar'],
],
],
// 2-argument: FUNKSIYA (closure) β model tool'ni chaqirsa shu ishlaydi
function (array $input): string {
$shahar = $input['shahar'] ?? 'noma\'lum';
// Haqiqiy loyihada bu yerda ob-havo API'ga so'rov yuborardingiz:
return "$shahar: 25 daraja, quyoshli";
},
);
BetaRunnableTool konstruktori ikki argument oladi:
| Argument | Nima | Misol |
|---|---|---|
| ta'rif (1-o'rin) | tool nomi + tavsifi + input_schema (model o'qiydigan JSON-schema massiv) |
['name' => ..., 'description' => ..., 'input_schema' => ...] |
| funksiya (2-o'rin) | array $input qabul qiladi, string yoki array qaytaradi |
fn (array $in) => "..." |
Ehtiyot bo'ling β argumentlar TARTIBI
BetaRunnableTool konstruktori pozitsion (tartibli) argument oladi: avval ta'rif massivi, keyin funksiya. name: yoki run: kabi nomli argument bilan chaqirib bo'lmaydi. Ta'rif ichidagi kalit aynan input_schema (pastki chiziq bilan, JSON-schema standartidagidek) β inputSchema emas.
Funksiya nimani qaytaradi? Ikki variant bor:
stringβ oddiy matn natija (eng ko'p ishlatiladi):"Toshkent: 25 daraja".arrayβ bloklar massivi (masalan, model'ga rasm yoki tuzilgan ma'lumot qaytarish kerak bo'lsa). Oddiy hollarda string yetadi.
Maslahat β description muhim
Tool'ning description maydoni β modelga "bu tool qachon kerakligini" tushuntiradigan yagona yo'l. Aniq yozing: "Foydalanuvchi ob-havo so'rasa chaqir". Yomon tavsif β model tool'ni noto'g'ri paytda chaqiradi yoki umuman chaqirmaydi. (09-bobda batafsil aytgandik.)
3. toolRunner β loopni boshqaruvchi¶
Tool tayyor. Endi loopni boshqaradigan runnerni yaratamiz. Buning uchun $client->beta->messages->toolRunner(...) metodi bor β u BetaToolRunner obyektini qaytaradi.
$runner = $client->beta->messages->toolRunner(
model: 'claude-opus-4-8',
maxTokens: 1024,
tools: [$obHavo], // BetaRunnableTool obyektlari ro'yxati
messages: [
['role' => 'user', 'content' => 'Toshkentda ob-havo qanday?'],
],
);
toolRunner β bu create ga o'xshaydi (model, maxTokens, messages, tools), lekin so'rov yubormaydi. U faqat "boshqaruvchi"ni tayyorlaydi. Loopni ishga tushirish uchun runUntilDone() chaqiramiz:
$final = $runner->runUntilDone(); // BetaMessage β loop tugagach YAKUNIY javob
// Yakuniy matnni o'qiymiz (xuddi oddiy create kabi):
foreach ($final->content as $block) {
if ($block->type === 'text') {
echo $block->text;
}
}
runUntilDone() quyidagilarni avtomatik bajaradi:
- Modelga so'rov yuboradi.
- Model tool so'rasa β tegishli
BetaRunnableToolfunksiyasini chaqiradi. - Natijani
tool_resultqilib suhbatga qo'shadi. - Modelga qaytadan yuboradi.
- Model yana tool so'rasa β 2-qadamga qaytadi; so'ramasa, to'xtaydi.
- Yakuniy
BetaMessageni qaytaradi.
Ya'ni 09-bobdagi butun while loop β bitta runUntilDone() chaqiruviga aylandi.
Boshqa provayderda
OpenAI SDK'sida bunday tayyor runner yo'q β odatda loopni qo'lda yozasiz yoki LLPhant/Neuron AI kabi framework ishlatasiz (17-bob). Anthropic PHP SDK'ning toolRunner'i β bu ishni o'rnatib qo'yilgan qulaylik. G'oya esa universal: "model tool so'raydi, kod bajaradi, takrorlanadi".
4. To'liq ishlaydigan misol β bitta tool¶
Hammasini bir joyga yig'amiz. Quyidagi to'liq fayl β bitta ob_havo tool bilan tool runner. API kalit muhit o'zgaruvchisidan olinadi (hech qachon kodga yozmaymiz).
<?php
require __DIR__ . '/vendor/autoload.php';
use Anthropic\Client;
use Anthropic\Lib\Tools\BetaRunnableTool;
$client = new Client(apiKey: getenv('ANTHROPIC_API_KEY'));
// 1) Tool'ni ta'rif + funksiya bilan yaratamiz
$obHavo = new BetaRunnableTool(
[
'name' => 'ob_havo',
'description' => 'Berilgan shahar uchun joriy ob-havoni qaytaradi.',
'input_schema' => [
'type' => 'object',
'properties' => [
'shahar' => ['type' => 'string', 'description' => 'Shahar nomi'],
],
'required' => ['shahar'],
],
],
function (array $input): string {
$shahar = $input['shahar'] ?? 'noma\'lum';
// Haqiqiy loyihada: ob-havo API chaqiruvi. Bu yerda namuna:
return "$shahar: 25 daraja, quyoshli, shamol 3 m/s";
},
);
// 2) Runner yaratamiz va loopni avtomatik ishga tushiramiz
$runner = $client->beta->messages->toolRunner(
model: 'claude-opus-4-8',
maxTokens: 1024,
tools: [$obHavo],
messages: [
['role' => 'user', 'content' => 'Toshkentda hozir ob-havo qanday?'],
],
);
$final = $runner->runUntilDone();
// 3) Yakuniy javobni chiqaramiz
foreach ($final->content as $block) {
if ($block->type === 'text') {
echo $block->text . PHP_EOL;
}
}
Ishga tushirsangiz, model ob_havo tool'ni o'zi chaqiradi, bizning funksiya "Toshkent: 25 daraja..." qaytaradi, model esa buni odamga tushunarli jumlaga aylantiradi: "Toshkentda hozir 25 daraja, ob-havo quyoshli, shamol kuchsiz." Bularning hammasi bitta runUntilDone() ichida sodir bo'ladi.
Tekshirib ko'ring
Yuqoridagi koddan tools: [$obHavo] qatorini olib tashlasangiz nima bo'ladi? (Model ob_havo tool haqida bilmaydi β uning o'rniga "Men real vaqtdagi ob-havoni bilolmayman" deb javob beradi.)
5. Bir nechta tool β model o'zi tanlaydi¶
Tool runner'ning asl kuchi β bir nechta toolda ko'rinadi. Siz bir necha tool berasiz, model esa savolga qarab qaysi biri (yoki bir nechtasi) kerakligini o'zi hal qiladi va ketma-ket chaqiradi.
Quyida uchta tool yaratamiz: ob-havo, kalkulyator va joriy vaqt.
<?php
require __DIR__ . '/vendor/autoload.php';
use Anthropic\Client;
use Anthropic\Lib\Tools\BetaRunnableTool;
$client = new Client(apiKey: getenv('ANTHROPIC_API_KEY'));
// --- Tool 1: ob-havo ---
$obHavo = new BetaRunnableTool(
[
'name' => 'ob_havo',
'description' => 'Shahar uchun joriy ob-havoni qaytaradi.',
'input_schema' => [
'type' => 'object',
'properties' => ['shahar' => ['type' => 'string']],
'required' => ['shahar'],
],
],
fn (array $in): string => ($in['shahar'] ?? '?') . ': 25 daraja, quyoshli',
);
// --- Tool 2: kalkulyator ---
$kalkulyator = new BetaRunnableTool(
[
'name' => 'kalkulyator',
'description' => 'Ikki son ustida arifmetik amal bajaradi.',
'input_schema' => [
'type' => 'object',
'properties' => [
'amal' => [
'type' => 'string',
'enum' => ['qoshish', 'ayirish', 'kopaytirish', 'bolish'],
],
'a' => ['type' => 'number'],
'b' => ['type' => 'number'],
],
'required' => ['amal', 'a', 'b'],
],
],
fn (array $in): string => (string) match ($in['amal']) {
'qoshish' => $in['a'] + $in['b'],
'ayirish' => $in['a'] - $in['b'],
'kopaytirish' => $in['a'] * $in['b'],
'bolish' => $in['b'] != 0 ? $in['a'] / $in['b'] : 'nolga bo\'linmaydi',
},
);
// --- Tool 3: joriy vaqt ---
$vaqt = new BetaRunnableTool(
[
'name' => 'joriy_vaqt',
'description' => 'Joriy sana va vaqtni qaytaradi.',
// argument kerak emas: bo'sh xususiyatlar
'input_schema' => ['type' => 'object', 'properties' => (object) []],
],
fn (array $in): string => date('Y-m-d H:i'),
);
// --- Runner: uchta tool bilan ---
$runner = $client->beta->messages->toolRunner(
model: 'claude-opus-4-8',
maxTokens: 1024,
tools: [$obHavo, $kalkulyator, $vaqt],
messages: [[
'role' => 'user',
'content' => 'Bugungi sanani ayt va 240 ni 4 ga bo\'l.',
]],
);
$final = $runner->runUntilDone();
echo $final->content[0]->text . PHP_EOL;
Bu savolda model ikkita tool'ni chaqiradi: joriy_vaqt (sana uchun) va kalkulyator (bo'lish uchun). Ob-havo so'ralmagani uchun ob_havo tegilmaydi. Runner ikkala tool'ni ham bajaradi va natijalarni bitta yakuniy javobga jamlaydi: "Bugun 2026-06-15. 240 ni 4 ga bo'lsak β 60."
Eslatma
'properties' => (object) [] β bu bo'sh JSON obyekti ({}) bo'lib serializatsiya bo'lishi uchun. Agar [] (bo'sh massiv) yozsangiz, JSON'da [] chiqadi va schema noto'g'ri bo'ladi. Argument talab qilmaydigan tool'larda shu yo'lni ishlating.
6. Real, foydali tool'lar¶
O'yinchoq misollar tushunarli, lekin amalda tool'lar tashqi dunyo bilan ishlaydi: ma'lumotlar bazasi, hisob-kitob, joriy vaqt, tashqi API. Mana bir nechta real namuna.
6.1 Ma'lumotlar bazasiga so'rov (mahsulot qidirish)¶
Eng foydali tool β bu modelga sizning bazangizdan ma'lumot olib berish. Model bazani bilmaydi; tool orqali u "ko'zoynak taqib" sizning ma'lumotingizni ko'radi.
use Anthropic\Lib\Tools\BetaRunnableTool;
// PDO ulanishi avval tayyorlangan deb hisoblaymiz (PHP kitobiga qarang)
$mahsulotQidir = new BetaRunnableTool(
[
'name' => 'mahsulot_qidir',
'description' => 'Do\'kon bazasidan nom bo\'yicha mahsulotlarni qidiradi. '
. 'Narx va qoldiqni qaytaradi.',
'input_schema' => [
'type' => 'object',
'properties' => [
'nom' => ['type' => 'string', 'description' => 'Qidiriladigan mahsulot nomi'],
],
'required' => ['nom'],
],
],
function (array $input) use ($pdo): string {
// Parametrli so'rov β SQL-injection xavfsiz (PHP kitobida tushuntirilgan)
$stmt = $pdo->prepare(
'SELECT nom, narx, qoldiq FROM mahsulotlar WHERE nom LIKE :q LIMIT 5'
);
$stmt->execute([':q' => '%' . $input['nom'] . '%']);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!$rows) {
return 'Bunday mahsulot topilmadi.';
}
// Natijani modelga matn ko'rinishida qaytaramiz
return json_encode($rows, JSON_UNESCAPED_UNICODE);
},
);
Xavfsizlik β SQL
Bazaga so'rov yozayotganda doim parametrli so'rov (prepare + execute) ishlating β model bergan matnni to'g'ridan-to'g'ri SQL'ga qo'shmang. Model "halol" bo'lsa ham, foydalanuvchi unga zararli matn yuborishi mumkin (prompt injection β 20-bob). Tool funksiyasi β bu sizning himoya devoringiz.
6.2 Hisob-kitob, sana va valyuta kursi¶
Boshqa foydali tool'lar:
// Valyuta kursi (mock β real loyihada API chaqiruvi)
$valyuta = new BetaRunnableTool(
[
'name' => 'valyuta_kursi',
'description' => 'Bir valyutadan boshqasiga konvertatsiya summasini hisoblaydi.',
'input_schema' => [
'type' => 'object',
'properties' => [
'miqdor' => ['type' => 'number'],
'dan' => ['type' => 'string', 'description' => 'masalan USD'],
'ga' => ['type' => 'string', 'description' => 'masalan UZS'],
],
'required' => ['miqdor', 'dan', 'ga'],
],
],
function (array $in): string {
// Real loyihada: kursni API yoki bazadan oling
$kurslar = ['USD_UZS' => 12600, 'EUR_UZS' => 13700];
$kalit = "{$in['dan']}_{$in['ga']}";
if (!isset($kurslar[$kalit])) {
return 'Bu valyuta juftligi mavjud emas.';
}
$natija = $in['miqdor'] * $kurslar[$kalit];
return "{$in['miqdor']} {$in['dan']} = {$natija} {$in['ga']}";
},
);
Maslahat β tool nimaga yaxshi
LLM matn bilan kuchli, lekin aniq hisob-kitob, joriy sana, real ma'lumot β uning kuchsiz tomoni. Shu ishlarni tool'ga topshiring: model "240 / 4" ni o'zi yechmasin, kalkulyator chaqirsin. Shunda javob har doim aniq bo'ladi.
7. Iteratsiya β oraliq qadamlarni kuzatish¶
runUntilDone() faqat yakuniy javobni beradi β oraliqda nima bo'lganini ko'rsatmaydi. Lekin ba'zan har qadamni kuzatish kerak bo'ladi: qaysi tool chaqirildi, model nima dedi (debug, log, foydalanuvchiga "qidiryapman..." ko'rsatish uchun).
BetaToolRunner β iterable. Ya'ni uni foreach bilan aylanish mumkin; har takrorlanishda bitta BetaMessage (model javobi) qaytadi.
$runner = $client->beta->messages->toolRunner(
model: 'claude-opus-4-8',
maxTokens: 1024,
tools: [$obHavo, $kalkulyator],
messages: [[
'role' => 'user',
'content' => 'Toshkentdagi haroratni 2 ga ko\'paytir.',
]],
);
$qadam = 0;
foreach ($runner as $message) {
$qadam++;
echo "--- Qadam {$qadam} (stopReason: {$message->stopReason}) ---" . PHP_EOL;
foreach ($message->content as $block) {
if ($block->type === 'text') {
echo "Model: {$block->text}" . PHP_EOL;
} elseif ($block->type === 'tool_use') {
// Qaysi tool, qanday argument bilan chaqirildi
echo "Tool chaqirildi: {$block->name}" . PHP_EOL;
echo "Argumentlar: " . json_encode($block->input, JSON_UNESCAPED_UNICODE) . PHP_EOL;
}
}
}
// Loop tugaganda oxirgi $message β yakuniy javob
Bu yerda foreach runner'ni qadam-baqadam aylanadi. runUntilDone() esa β aslida shu foreachning ichida oxirgi xabarni qaytaradigan qisqa yo'li (xohlasangiz manbasiga qarang). Iteratsiya β debug va kuzatish uchun; oddiy holatda runUntilDone() qulayroq.
Eslatma
Bir BetaToolRunnerni faqat bir marta aylanish mumkin. foreach qilib bo'lgach yoki runUntilDone() chaqirgach, u "iste'mol qilingan" hisoblanadi β qayta aylansangiz xato beradi. Yangidan kerak bo'lsa, yangi runner yarating.
8. Qo'lda loop vs tool runner β qachon qaysi¶
Endi 09-bobning qo'lda usuli va bu bobning runner'i o'rtasidagi farqni aniq ko'raylik:
| Jihat | Qo'lda loop (09-bob) | Tool runner (10-bob) |
|---|---|---|
| Kod hajmi | Ko'p (while, blok ajratish, qaytarish) |
Oz (toolRunner + runUntilDone) |
| Loop boshqaruvi | Siz yozasiz | SDK avtomatik |
| Tool va funksiya | Alohida (tools + match) |
Birga (BetaRunnableTool) |
| Har qadamni nazorat | To'liq (har bosqichni boshqarasiz) | Faqat foreach orqali kuzatish |
| Inson-tasdiqlash | Oson (qadam orasiga qo'shasiz) | Qiyinroq (avtomatik bajariladi) |
| Shartli/murakkab mantiq | To'liq erkinlik | Cheklangan |
| Qachon | Maxsus nazorat, tasdiqlash, murakkab oqim | Oddiy, tez, ko'p hollarda default |
Qisqasi:
- Tool runner β kundalik, oddiy holatlar uchun birinchi tanlov. Tez yoziladi, kam xato.
- Qo'lda loop β sizga to'liq nazorat kerak bo'lganda: masalan, xavfli tool bajarilishidan oldin insondan tasdiq so'rash, yoki tool natijasiga qarab oqimni o'zgartirish. Bu mavzu 11-bobda (agentlar) chuqurroq ochiladi.
11-bobga ko'prik
Agent β bu aslida "maqsadga yetgunicha tool'larni o'zi tanlab chaqiradigan" tizim. Tool runner β agentning yuragi. 11-bobda runner ustiga maqsad, xotira va to'xtash shartlarini qo'shib, to'laqonli agent yasaymiz.
9. Xavfsizlik β runner tool'larni AVTOMATIK bajaradi¶
Bu eng muhim ogohlantirish. Tool runner tool funksiyalarini so'rovsiz, avtomatik bajaradi β model "shu tool'ni chaqir" desa, kodingiz darhol ishga tushadi.
Bu o'qish/qidirish tool'lari uchun yaxshi. Lekin o'zgartiruvchi yoki xavfli tool'larda jiddiy xavf:
- Buyurtmani o'chiradigan tool
- Pul o'tkazadigan yoki to'lov qiladigan tool
- Fayl yozadigan/o'chiradigan tool
- Tashqariga email/SMS yuboradigan tool
Hayotiy o'xshatish. Tool runner β bu sizning nomingizdan ish qiladigan ishonchli, lekin tajribasiz yordamchi. "Buni qil" desa qiladi β hatto "barcha fayllarni o'chir" bo'lsa ham. Shuning uchun yordamchiga faqat xavfsiz vazifalarni ishonib topshirasiz; pul yoki o'chirish kabi ishlarni β o'zingiz tasdiqlaganingizdan keyin.
Xavfsizlik qoidalari
- Xavfli tool'larni runner'ga avtomatik bermang. O'chirish/to'lov kabi amallar uchun qo'lda loop ishlating va bajarishdan oldin insondan tasdiq oling.
- Har bir tool funksiyasida tekshiruv qo'ying β model bergan argumentni ishonchsiz deb biling: turlarini, chegaralarni, ruxsatlarni tekshiring.
- Eng kam ruxsat tamoyili β tool faqat o'ziga kerakli ishni qila olsin (masalan, faqat o'qish huquqi bilan ulangan baza).
- Loop uzunligini cheklang β
toolRunnergamaxIterationsbering, toki cheksiz loopga tushib qolmasin.
// maxIterations β eng ko'pi bilan necha marta API chaqiruvi (xavfsizlik to'sig'i)
$runner = $client->beta->messages->toolRunner(
model: 'claude-opus-4-8',
maxTokens: 1024,
tools: [$obHavo, $mahsulotQidir],
messages: [['role' => 'user', 'content' => $savol]],
maxIterations: 5, // 5 qadamdan keyin majburan to'xtaydi
);
To'liq xavfsizlik mavzusi β prompt injection, ruxsatlar, audit β 20-bobda.
10. To'liq misol β "do'kon yordamchisi"¶
Endi hammasini birlashtiramiz: ikkita tool bilan haqiqiy do'kon yordamchisi. Birinchi tool bazadan mahsulot qidiradi, ikkinchisi umumiy narxni hisoblaydi. Foydalanuvchi savol beradi β model tool'larni o'zi chaqirib, to'liq javob beradi.
<?php
require __DIR__ . '/vendor/autoload.php';
use Anthropic\Client;
use Anthropic\Lib\Tools\BetaRunnableTool;
$client = new Client(apiKey: getenv('ANTHROPIC_API_KEY'));
// Namuna "baza" (real loyihada β PDO bilan MySQL/PostgreSQL)
$mahsulotlar = [
['nom' => 'Klaviatura', 'narx' => 250000, 'qoldiq' => 12],
['nom' => 'Sichqoncha', 'narx' => 90000, 'qoldiq' => 30],
['nom' => 'Monitor', 'narx' => 1800000, 'qoldiq' => 5],
];
// --- Tool 1: mahsulot qidirish ---
$mahsulotQidir = new BetaRunnableTool(
[
'name' => 'mahsulot_qidir',
'description' => 'Do\'kon bazasidan nom bo\'yicha mahsulot qidiradi. '
. 'Narx (so\'mda) va qoldiq sonini qaytaradi.',
'input_schema' => [
'type' => 'object',
'properties' => ['nom' => ['type' => 'string']],
'required' => ['nom'],
],
],
function (array $input) use ($mahsulotlar): string {
$topildi = array_values(array_filter(
$mahsulotlar,
fn ($m) => str_contains(
mb_strtolower($m['nom']),
mb_strtolower($input['nom'] ?? ''),
),
));
return $topildi
? json_encode($topildi, JSON_UNESCAPED_UNICODE)
: 'Mahsulot topilmadi.';
},
);
// --- Tool 2: umumiy narx hisoblash ---
$narxHisobla = new BetaRunnableTool(
[
'name' => 'narx_hisobla',
'description' => 'Birlik narxini soniga ko\'paytirib, umumiy summani qaytaradi.',
'input_schema' => [
'type' => 'object',
'properties' => [
'birlik_narx' => ['type' => 'number'],
'soni' => ['type' => 'integer'],
],
'required' => ['birlik_narx', 'soni'],
],
],
function (array $in): string {
$umumiy = $in['birlik_narx'] * $in['soni'];
return "Umumiy: {$umumiy} so'm";
},
);
// --- Runner: ikkala tool bilan ---
$runner = $client->beta->messages->toolRunner(
model: 'claude-opus-4-8',
maxTokens: 1024,
tools: [$mahsulotQidir, $narxHisobla],
messages: [[
'role' => 'user',
'content' => 'Menga 3 ta klaviatura kerak. Bormi? Hammasi qancha bo\'ladi?',
]],
maxIterations: 6, // xavfsizlik to'sig'i
);
$final = $runner->runUntilDone();
foreach ($final->content as $block) {
if ($block->type === 'text') {
echo $block->text . PHP_EOL;
}
}
Bu yerda model ikki qadamda ishlaydi: avval mahsulot_qidir bilan klaviaturani topadi (narx 250000, qoldiq 12 β yetarli), keyin narx_hisobla bilan 250000 Γ 3 ni hisoblaydi. Yakuniy javob: "Ha, klaviatura bor (omborda 12 ta). 3 tasi 750 000 so'm bo'ladi." Biz faqat ikki tool va bitta runUntilDone() yozdik β qolganini runner qildi.
Hayotiy o'xshatish. Bu β do'kondagi tajribali sotuvchi kabi: mijoz savolini eshitadi, omborni tekshiradi, narxni hisoblaydi va bitta tushunarli javob beradi. Siz unga faqat "ombor"ni (qidirish tool) va "kalkulyator"ni (hisoblash tool) berdingiz.
Kengaytirish g'oyasi
Bu yordamchiga savatga_qoshish, buyurtma_yaratish kabi tool'lar qo'shsangiz β to'liq savdo botiga aylanadi. Lekin buyurtma_yaratish β o'zgartiruvchi tool, shuning uchun (9-bo'limni eslang) uni avtomatik runner'ga bermay, insondan tasdiq so'rab qo'lda bajargan ma'qul.
Xulosa¶
- Qo'lda loop charchatadi: har tool natijasini qaytarish va loop yozish β ko'p kod, oson xato. Tool runner bu loopni avtomatlashtiradi.
BetaRunnableToolβ tool ta'rifini (JSON-schema massiv) va uni bajaradigan funksiyani (closure) birga bog'laydi. Konstruktor pozitsion: avval ta'rif, keyin funksiya. Funksiyastringyokiarrayqaytaradi.$client->beta->messages->toolRunner(...)BetaToolRunnerqaytaradi;runUntilDone()loopni model tugatgunicha avtomatik aylantirib, yakuniyBetaMessageni beradi.- Bir nechta toolda model savolga qarab keraklisini (yoki bir nechtasini) o'zi tanlab, ketma-ket chaqiradi. Foydali tool'lar: baza qidiruvi, hisob-kitob, joriy vaqt, valyuta kursi.
BetaToolRunneriterable βforeachbilan har qadamni (qaysi tool, qanday argument) kuzatish mumkin (debug, log). Bir runner faqat bir marta aylanadi.- Runner default, qo'lda loop β nazorat uchun. Inson-tasdiqlash yoki murakkab shartli oqim kerak bo'lsa qo'lda loop ishlating.
- Xavfsizlik: runner tool'larni avtomatik bajaradi β o'chirish/to'lov kabi xavfli tool'larda ehtiyot bo'ling, argumentlarni tekshiring,
maxIterationsbilan loopni cheklang (batafsil β 20-bob).
Amaliy mashqlar¶
- Bitta tool runner. Bir
tasodifiy_sontool yarating (min va max argumentlarini olib, oraliqdagi tasodifiy sonni qaytaradi).toolRunner+runUntilDone()bilan modeldan "1 dan 100 gacha tasodifiy son ber" deb so'rang. - Ko'p tool tanlovi. Uchta tool (
ob_havo,kalkulyator,joriy_vaqt) bilan runner yozing. Modelga "Bugungi sana qanaqa va 15 ni 3 ga ko'paytir" deb savol bering β qaysi tool'lar chaqirilishini kuzating. - DB qidiruv tool. PDO (yoki namuna massiv) bilan
kitob_qidirtool yozing: nom bo'yicha kitob qidirib, sarlavha va narxni qaytarsin. Runner orqali "Dasturlash haqida kitob bormi?" deb so'rang. Funksiyada parametrli so'rov ishlatganingizga ishonch hosil qiling. - Iteratsiyani kuzatish. 2-mashqdagi runner'ni
runUntilDone()o'rnigaforeachbilan aylanib chiqing. Har qadamda qaysi tool chaqirilganini va uning argumentlarini ekranga chiqaring. - Xavfsizlik to'sig'i. Bir runner'ga
maxIterations: 2bering va modelni ko'p qadam talab qiladigan savol bilan sinab ko'ring. Nima bo'ldi? NegamaxIterationsxavfsizlik uchun muhim?
β¬ οΈ Oldingi: 09 β Function calling Β· π Kitob boshi Β· Keyingi: 11 β Agentlar β‘οΈ