11 β Tool calling chuqur va ko'p qadamli¶
β¬ οΈ Oldingi: 10 β Function/tool calling asoslari Β· π Kitob boshi Β· Keyingi: 12 β Multimodal: rasm va ovoz β‘οΈ
Bu bobda: 10-bobda bitta tool bilan tanishdik; endi bir nechta tool beramiz va modelning qaysi birini (yoki bir nechtasini) tanlashini ko'ramiz. Parallel tool calls β bitta javobda bir nechta
tool_callskelganda hammasini bajarib, natijalarni qaytarishni o'rganamiz. Eng muhimi β ko'p qadamliwhileloop quramiz: model tool chaqiradi -> biz bajaramiz -> model yana chaqirishi mumkin -> ... -> nihoyat yakuniy matn. Tartibli bajarish uchun tool registry (lug'at) ishlatamiz, xavfsiz kalkulyator (evalISHLATMASDAN), soxta DB va HTTP API misollarini yozamiz,tool_choiceni boshqaramiz va tool xatosini modelga natija sifatida qaytarishni ko'ramiz.
Muammodan boshlaymiz: bitta tool yetmaydi¶
10-bobda modelga bitta ob_havo tool berdik va u shu toolni chaqirdi. Lekin haqiqiy yordamchi bitta ish bilan cheklanmaydi. Foydalanuvchi shunday yozishi mumkin:
"Toshkentda ob-havo qanday va 12500 so'mni dollarga aylantirsang qancha bo'ladi?"
Bu yerda model ikkita har xil ishni qilishi kerak: ob-havoni olish va valyuta hisoblash. Yoki boshqa savol:
"Toshkent va Samarqandda ob-havo qanday?"
Bu β bitta tool (ob_havo), lekin ikki marta chaqirilishi kerak. An'anaviy "bitta so'rov -> bitta tool -> bitta javob" sxemasi buni qoplay olmaydi. Bizga kerak:
- Modelga bir nechta tool berish va u o'zi tanlashi.
- Parallel chaqiruvlarni qo'llab-quvvatlash (bitta javobda bir nechta tool).
- Ko'p qadamli loop β model tool natijasini ko'rib, yana tool chaqirishi mumkin (masalan, avval shaharni topadi, keyin o'sha shahar ob-havosini so'raydi).
Hayotiy o'xshatish. Bitta tool bergan model β bitta tugmasi bor pultga o'xshaydi. Ko'p tool + loop bergan model esa β to'la asboblar yashigi bor usta: u qaysi asbobni, qachon, necha marta ishlatishni o'zi qaror qiladi va oxirida sizga tayyor natijani beradi.
Bir nechta tool: model qaysini tanlaydi¶
Modelga tool ro'yxatini berasiz β u har bir so'rovda qaysi biri(lari) mosligini o'zi hal qiladi. Keling, uchta tool tasvirini tayyorlaymiz: ob-havo, valyuta, soatni bilish.
tools = [
{
"type": "function",
"function": {
"name": "ob_havo",
"description": "Berilgan shahar uchun joriy ob-havoni qaytaradi.",
"parameters": {
"type": "object",
"properties": {
"shahar": {"type": "string", "description": "Shahar nomi, masalan 'Toshkent'"}
},
"required": ["shahar"],
},
},
},
{
"type": "function",
"function": {
"name": "valyuta_aylantir",
"description": "Summani bir valyutadan boshqasiga aylantiradi.",
"parameters": {
"type": "object",
"properties": {
"summa": {"type": "number", "description": "Aylantiriladigan miqdor"},
"dan": {"type": "string", "description": "Manba valyuta kodi, masalan 'UZS'"},
"ga": {"type": "string", "description": "Maqsad valyuta kodi, masalan 'USD'"},
},
"required": ["summa", "dan", "ga"],
},
},
},
{
"type": "function",
"function": {
"name": "joriy_vaqt",
"description": "Hozirgi sana va vaqtni qaytaradi.",
"parameters": {"type": "object", "properties": {}},
},
},
]
Modelga "Toshkentda ob-havo qanday?" desangiz β u faqat ob_havoni tanlaydi; "soat necha?" desangiz β joriy_vaqtni; "qanaqasan?" desangiz β hech qaysi toolni tanlamay, oddiy matn bilan javob beradi. Tanlovni model tavsiflar (description) asosida qiladi β shuning uchun tavsifni aniq yozing.
Hayotiy o'xshatish. Tool ro'yxati β restoran menyusi: model (mijoz) menyuni ko'radi va buyurtmasiga mos taom(lar)ni tanlaydi.
descriptionβ menyudagi taom tavsifi; u qancha aniq bo'lsa, mijoz shuncha to'g'ri tanlaydi.
description β bu modelning ko'zi
Model tool kodini ko'rmaydi β u faqat nom, description va parameters sxemasini ko'radi. "Berilgan shahar uchun joriy ob-havoni qaytaradi" kabi aniq tavsif β to'g'ri tanlovning kalitidir. "ob-havo" kabi quruq tavsif modelni adashtiradi.
Tool registry: nom -> funksiya lug'ati¶
Model bizga ob_havo degan matnli nom qaytaradi. Biz uni haqiqiy Python funksiyasiga bog'lashimiz kerak. Buni if/elif zanjiri bilan qilish mumkin, lekin tool ko'paysa β chigallashadi. Toza yo'l β registry (lug'at):
import json
import datetime
# --- Haqiqiy funksiyalar ---
def ob_havo(shahar: str) -> dict:
# Demo: haqiqiy loyihada bu yerda HTTP API chaqiriladi
soxta = {"Toshkent": 24, "Samarqand": 21, "Buxoro": 27}
return {"shahar": shahar, "harorat_c": soxta.get(shahar, 20), "holat": "ochiq"}
def valyuta_aylantir(summa: float, dan: str, ga: str) -> dict:
kurslar = {("UZS", "USD"): 1 / 12600, ("USD", "UZS"): 12600}
kurs = kurslar.get((dan, ga))
if kurs is None:
return {"xato": f"{dan}->{ga} kursi mavjud emas"}
return {"natija": round(summa * kurs, 2), "valyuta": ga}
def joriy_vaqt() -> dict:
return {"vaqt": datetime.datetime.now().strftime("%Y-%m-%d %H:%M")}
# --- Registry: model qaytaradigan NOM -> haqiqiy funksiya ---
REGISTRY = {
"ob_havo": ob_havo,
"valyuta_aylantir": valyuta_aylantir,
"joriy_vaqt": joriy_vaqt,
}
Endi modeldan kelgan har qanday tool chaqiruvini bitta umumiy kod bilan bajaramiz β nom bo'yicha registry'dan funksiyani topamiz:
def tool_ni_bajar(tool_call) -> str:
"""Bitta tool_call'ni bajaradi va natijani JSON-matn qaytaradi."""
nom = tool_call.function.name
funksiya = REGISTRY.get(nom)
if funksiya is None:
return json.dumps({"xato": f"noma'lum tool: {nom}"})
try:
args = json.loads(tool_call.function.arguments)
natija = funksiya(**args)
except Exception as e:
# Xatoni model ko'rishi uchun NATIJA sifatida qaytaramiz (pastda batafsil)
natija = {"xato": str(e)}
return json.dumps(natija, ensure_ascii=False)
Hayotiy o'xshatish. Registry β telefon kitobchasi: model ism (
"ob_havo") aytadi, siz kitobchadan raqamni (funksiyani) topib, qo'ng'iroq qilasiz. Yangi tool qo'shish β kitobchaga bitta qator qo'shishdek oson.
Nega registry, if/elif emas?
if nom == "ob_havo": ... elif nom == "valyuta_aylantir": ... β 3 ta toolda ishlaydi, lekin 15 ta tool bilan o'qib bo'lmaydigan zanjirga aylanadi. Registry lug'ati esa ma'lumot β yangi tool = bitta funksiya + bitta lug'at yozuvi. Bajarish kodi (tool_ni_bajar) hech qachon o'zgarmaydi.
Parallel tool calls: bitta javobda bir nechta¶
"Toshkent va Samarqandda ob-havo qanday?" so'raganda zamonaviy modellar bitta javobda ikkita tool_call qaytaradi β har biri alohida shahar uchun. Bu parallel tool calls deyiladi. Muhim qoida: javobda nechta tool_call bo'lsa, hammasini bajarib, har biri uchun alohida tool xabarini (o'sha tool_call_id bilan) tarixga qo'shishingiz shart. Bittasini tashlab ketsangiz β model "javobsiz qoldi" deb xato beradi.
msg = resp.choices[0].message
if msg.tool_calls:
msgs.append(msg) # assistant navbati β BARCHA tool_calls bilan, bir marta
# Javobdagi HAR BIR tool_call'ni bajaramiz (parallel chaqiruvlar)
for tc in msg.tool_calls:
natija = tool_ni_bajar(tc)
msgs.append({
"role": "tool",
"tool_call_id": tc.id, # qaysi chaqiruvga javob ekanini bog'laydi
"content": natija,
})
# Endi natijalar bilan modelni qayta chaqiramiz
resp = client.chat.completions.create(model=MODEL, messages=msgs, tools=tools)
Har tool_call uchun ALOHIDA javob shart
Eng keng tarqalgan xato β model 2 ta tool chaqirgan, siz faqat 1 tasini bajarib javob qaytargansiz. Natijada tool_call_idlardan biri javobsiz qoladi va API 400 xato beradi. Qoida: for tc in msg.tool_calls: bilan hammasini aylanib chiqing va har biriga tool xabari qaytaring.
Parallelni o'chirish
Agar toollaringiz bir-biriga bog'liq bo'lsa (biri ikkinchisining natijasiga muhtoj) va parallel chaqiruv chalkashlik tug'dirsa, parallel_tool_calls=False parametri bilan modelni bir vaqtda bitta tool chaqirishga majburlash mumkin. Odatda kerak emas β ko'pchilik holatda parallel tezroq.
Ko'p qadamli loop: agentning yuragi¶
Hozir biz ikki qadam qildik: (1) model tool chaqirdi, (2) natijani berib qayta chaqirdik. Lekin model ikkinchi chaqiruvda yana tool so'rashi mumkin! Masalan: avval joriy_vaqtni so'rab, keyin o'sha sanaga qarab ob_havoni chaqiradi. Demak, bizga qat'iy "ikki qadam" emas, sikl kerak: model tool chaqirsa β bajaramiz va qaytaramiz; tool chaqirmasa (oddiy matn bersa) β to'xtaymiz.
def agent_javobi(savol: str, maks_qadam: int = 5) -> str:
msgs = [
{"role": "system", "content": "Sen yordamchisan. Kerak bo'lsa toollardan foydalan."},
{"role": "user", "content": savol},
]
for qadam in range(maks_qadam): # QADAM LIMITI β cheksiz siklga qarshi
resp = client.chat.completions.create(
model=MODEL, messages=msgs, tools=tools,
)
msg = resp.choices[0].message
# TO'XTASH SHARTI: tool chaqirilmadi -> bu yakuniy javob
if not msg.tool_calls:
return msg.content
# Aks holda: barcha tool_call'larni bajaramiz
msgs.append(msg)
for tc in msg.tool_calls:
natija = tool_ni_bajar(tc)
msgs.append({"role": "tool", "tool_call_id": tc.id, "content": natija})
# Sikl yana boshiga qaytadi -> model natijalarni ko'rib davom etadi
return "Qadam limiti tugadi (model yakunlay olmadi)."
Ishlatish:
print(agent_javobi("Toshkent va Samarqandda ob-havo qanday? Hozir soat necha?"))
# Model: ob_havo(Toshkent) + ob_havo(Samarqand) + joriy_vaqt ni chaqiradi (parallel),
# natijalarni oladi, keyin hammasini birlashtirib o'zbekcha matn yozadi -> loop tugaydi
Bu 20 qatordan kichik kod β aslida eng sodda agent. 18-bobda buni ReAct nuqtai nazaridan kengaytiramiz, lekin yadrosi aynan shu: model -> tool -> natija -> model -> ... -> javob.
Hayotiy o'xshatish. Loop β oshpaz bilan suhbat. Siz "palov qil" deysiz; oshpaz "guruch bormi?" (tool) so'raydi, siz javob berasiz; u "go'sht qancha?" (yana tool) so'raydi, siz aytasiz; nihoyat u "tayyor!" (yakuniy javob) deydi. Har savol oldingi javobga tayanadi β shuning uchun qat'iy ikki qadam emas, sikl kerak.
Qadam limitisiz β cheksiz sikl xavfi
Agar model (yoki tool xatosi) doimo tool chaqiraversa, limitisiz loop cheksiz ishlaydi va pulingizni yeydi. Doim maks_qadam qo'ying (odatda 5-10 yetarli). Limitga yetganda chiroyli to'xtang, foydalanuvchiga xabar bering.
Real tool misol: xavfsiz kalkulyator (eval ISHLATMANG)¶
Model matematikada xato qiladi (1-bob), shuning uchun hisob-kitobni toolga topshiramiz. Vasvasaga uchib eval(ifoda) yozmang β bu xavfli: model (yoki foydalanuvchi orqali) __import__('os').system('rm -rf ...') kabi zararli matn yuborsa, kodingiz uni bajaradi. To'g'ri yo'l β ast moduli bilan faqat ruxsat etilgan amallarni baholash:
import ast
import operator
# Ruxsat etilgan amallar β boshqa hech narsa bajarilmaydi
AMALLAR = {
ast.Add: operator.add, ast.Sub: operator.sub,
ast.Mult: operator.mul, ast.Div: operator.truediv,
ast.Pow: operator.pow, ast.USub: operator.neg,
}
def _bahola(tugun):
if isinstance(tugun, ast.Constant): # son
if not isinstance(tugun.value, (int, float)):
raise ValueError("faqat sonlar")
return tugun.value
if isinstance(tugun, ast.BinOp): # a + b, a * b ...
return AMALLAR[type(tugun.op)](_bahola(tugun.left), _bahola(tugun.right))
if isinstance(tugun, ast.UnaryOp): # -a
return AMALLAR[type(tugun.op)](_bahola(tugun.operand))
raise ValueError("ruxsat etilmagan ifoda")
def kalkulyator(ifoda: str) -> dict:
"""'2 + 3 * 4' kabi matematik ifodani XAVFSIZ hisoblaydi."""
try:
natija = _bahola(ast.parse(ifoda, mode="eval").body)
return {"natija": natija}
except Exception as e:
return {"xato": f"hisoblab bo'lmadi: {e}"}
Bu funksiya faqat + - * / ** - amallarini biladi; har qanday boshqa narsa (funksiya chaqiruvi, import, o'zgaruvchi) ValueError beradi. Registryga qo'shish β bir qator: REGISTRY["kalkulyator"] = kalkulyator (va tools ro'yxatiga mos tasvir).
eval/exec β tool ichida HECH QACHON
Modeldan kelgan matnni eval(), exec() yoki os.system()ga to'g'ridan-to'g'ri uzatish β eng xavfli xatolardan biri. Model "ishonchli" emas: u foydalanuvchi matnini takrorlashi yoki manipulyatsiya qilinishi mumkin. Doim aniq, cheklangan amallar (ast, oq ro'yxat) ishlating. Xavfsizlikni 24-bobda chuqur ko'ramiz.
Real tool misol: soxta DB va HTTP API¶
Toollar tashqi dunyoga "ko'prik" β ular bazaga so'rov yuboradi yoki API chaqiradi. Mana ikki amaliy shakl. Avval soxta DB so'rovi (haqiqiy loyihada SQL bo'ladi):
# Demo "baza" β haqiqiy loyihada bu SQLite/Postgres so'rovi bo'ladi
_MIJOZLAR = {
"1001": {"ism": "Ali", "buyurtmalar": 3, "shahar": "Toshkent"},
"1002": {"ism": "Vali", "buyurtmalar": 0, "shahar": "Buxoro"},
}
def mijoz_malumoti(mijoz_id: str) -> dict:
"""ID bo'yicha mijoz ma'lumotini bazadan oladi."""
mijoz = _MIJOZLAR.get(mijoz_id)
if mijoz is None:
return {"xato": f"{mijoz_id} ID'li mijoz topilmadi"} # xatoni qaytaramiz
return mijoz
Endi HTTP API chaqiradigan tool (requests bilan, qisqa). E'tibor bering: tarmoq xatosini ham natija sifatida qaytaramiz, modelni "yiqitmaymiz":
import requests
def valyuta_kursi(dan: str, ga: str) -> dict:
"""Ochiq API'dan real valyuta kursini oladi."""
url = f"https://api.exchangerate.host/convert?from={dan}&to={ga}"
try:
r = requests.get(url, timeout=10)
r.raise_for_status()
return {"kurs": r.json().get("result")}
except requests.RequestException as e:
return {"xato": f"tarmoq xatosi: {e}"}
Hayotiy o'xshatish. Tool β modelning "qo'li": LLM o'zi bazaga kira olmaydi, internetga chiqa olmaydi, hisoblay olmaydi (aniq emas). Tool bu qo'lni beradi β model "nima qilishni" aytadi, qo'l (sizning kodingiz) "qilib beradi".
Tool ichida har doim timeout va xato boshqaruvi
HTTP/DB toollarida timeout qo'ying va xatoni try/except bilan ushlang. Tashqi xizmat ishlamay qolsa, tool exception otmasligi, balki {"xato": ...} qaytarishi kerak β shunda model muammoni ko'rib, foydalanuvchiga chiroyli xabar beradi (pastda batafsil).
tool_choice: model tool ishlatishini boshqarish¶
Standart holatda tool_choice="auto" β model o'zi hal qiladi: tool kerakmi yoki oddiy matnmi. Lekin ba'zan boshqacha xulq kerak:
# 1) auto (standart): model o'zi tanlaydi β tool YOKI matn
resp = client.chat.completions.create(model=MODEL, messages=msgs,
tools=tools, tool_choice="auto")
# 2) required: model SHART tool chaqirsin (matn javob berolmaydi)
resp = client.chat.completions.create(model=MODEL, messages=msgs,
tools=tools, tool_choice="required")
# 3) aniq tool: aynan SHU tool chaqirilsin
resp = client.chat.completions.create(model=MODEL, messages=msgs, tools=tools,
tool_choice={"type": "function", "function": {"name": "ob_havo"}})
# 4) none: tool umuman ishlatilmasin (faqat matn)
resp = client.chat.completions.create(model=MODEL, messages=msgs,
tools=tools, tool_choice="none")
Qachon ishlatiladi? required β ma'lumotni doim bazadan olishni xohlasangiz (model "o'zidan to'qib" qo'ymasin). Aniq tool β bitta qat'iy qadamni majburlash (masalan, formani har doim saqla tooli bilan yozdirish). none β modelni vaqtincha "tool'siz" rejimga o'tkazish.
auto β eng ko'p ishlatiladigani
Ko'pchilik holatda auto to'g'ri: model "qanaqasan?"ga matn, "soat necha?"ga joriy_vaqt bilan javob beradi. requiredni faqat haqiqatan kerak bo'lganda ishlating β aks holda model "salom"ga ham toolni zo'rlab chaqirib, g'alati ishlaydi.
Tool xatosini natija sifatida qaytarish¶
Diqqat qiling: yuqoridagi barcha toollarda xato yuz berganda biz exception otmadik, balki {"xato": "..."} lug'atini qaytardik. Bu β ataylab. Sababi: modelga xatoni natija sifatida bersangiz, u xatoni o'qiydi va qayta urinadi yoki foydalanuvchiga tushuntiradi. Agar funksiya exception otib loopni yiqitsa β model bunday "o'rganish" imkonidan mahrum bo'ladi.
# YOMON: exception loop'ni yiqitadi, model xatoni ko'rmaydi
def ob_havo(shahar):
return TASHQI_API[shahar] # KeyError -> butun loop qulaydi
# YAXSHI: xatoni model ko'radigan NATIJA qilib qaytaramiz
def ob_havo(shahar):
if shahar not in TASHQI_API:
return {"xato": f"'{shahar}' shahri topilmadi. To'g'ri nom yuboring."}
return TASHQI_API[shahar]
Misol oqimi: foydalanuvchi shahar nomini xato yozsa ("Toshkennt"), tool {"xato": "... topilmadi"} qaytaradi; model buni ko'rib, o'zi to'g'rilab ob_havo("Toshkent")ni qayta chaqiradi yoki foydalanuvchidan aniqlik so'raydi. Loop davom etadi β chunki tool_ni_bajar ichidagi try/except ham xatoni JSON qilib qaytaradi.
Hayotiy o'xshatish. Xatoni natija qilib qaytarish β ustaga "bu vint mos kelmadi" deb aytishdek: usta boshqa vintni sinab ko'radi. Agar siz unga baqirsangiz (exception) va ustaxonani yopib qo'ysangiz β ish to'xtaydi.
Xato xabarini foydali yozing
{"xato": "xato"} emas β {"xato": "'Toshkennt' topilmadi. To'g'ri yozing, masalan: Toshkent"} kabi modelga nima qilishni aytadigan xabar yozing. Model bu maslahatni o'qib, o'zini to'g'rilaydi. Xato xabari ham β promptning bir qismi.
Xavfsizlik: tool argumentlarini validatsiya qilish¶
Model argumentsni o'zi to'qiydi β ya'ni ular foydalanuvchi (yoki manipulyatsiya) ta'sirida bo'lishi mumkin. Shuning uchun toolni bajarishdan oldin argumentlarni tekshiring. Bir nechta qatlam:
def fayl_oqi(yol: str) -> dict:
import os
RUXSAT_PAPKA = os.path.abspath("hujjatlar") # faqat shu papka
toliq = os.path.abspath(os.path.join(RUXSAT_PAPKA, yol))
# Validatsiya: papkadan tashqariga chiqishga yo'l qo'ymaymiz (path traversal)
if not toliq.startswith(RUXSAT_PAPKA + os.sep):
return {"xato": "ruxsat etilmagan yo'l"}
if not os.path.isfile(toliq):
return {"xato": "fayl topilmadi"}
with open(toliq, encoding="utf-8") as f:
return {"matn": f.read()[:2000]} # uzunlikni cheklash
Asosiy qoidalar: (1) toollarni eng kam imtiyoz bilan yozing β faqat zarur ishni qilsin; (2) destruktiv amallar (o'chirish, to'lov, email yuborish) uchun model qaroriga ko'r-ko'rona ishonmang, kerak bo'lsa inson tasdig'i so'rang; (3) summa < 0, mavjud bo'lmagan ID kabi noto'g'ri argumentlarni rad eting (natija sifatida xato qaytaring).
Model argumentlari β ishonchsiz kirish (untrusted input)
Tool argumentlarini xuddi foydalanuvchi formasidan kelgan ma'lumotdek ko'ring: hech qachon ishonmang, doim validatsiya qiling. SQL toolda β parametrli so'rov (SQL injection'dan himoya), fayl toolda β yo'lni tekshirish, summa toolda β chegara. Bularning hammasini 24-bobda (xavfsizlik) batafsil ko'rib chiqamiz.
Boshqa provayderlar: bir xil g'oya¶
Yuqoridagi kod OpenAI-mos (OpenAI, Groq, DeepSeek, Ollama...) uchun. Claude va Geminida format biroz farq qiladi, lekin g'oya bir xil: ko'p tool berasiz, model bir nechtasini (parallel) chaqirishi mumkin, siz natijalarni qaytarib loopda davom etasiz.
# Claude (Anthropic) β tool natijasini user navbatida, tool_result blok bilan qaytarasiz:
import anthropic
client = anthropic.Anthropic()
resp = client.messages.create(
model="claude-sonnet-4-6", max_tokens=1024,
tools=[{"name": "ob_havo", "description": "...",
"input_schema": {"type": "object",
"properties": {"shahar": {"type": "string"}}, "required": ["shahar"]}}],
messages=msgs,
)
# Javobda block.type == "tool_use" bloklarini topib bajarasiz, keyin
# {"role": "user", "content": [{"type": "tool_result", "tool_use_id": ..., "content": ...}]}
Model nomlari o'zgaradi
Bu kitobdagi model nomlari (gpt-5.4-mini, claude-sonnet-4-6, gemini-2.5-flash...) β yozilish paytidagi holat. Nomlar tez-tez yangilanadi; loyiha boshlashdan oldin provayderning joriy model ro'yxatini tekshiring. Tool calling g'oyasi esa o'zgarmaydi.
Xulosa¶
- Modelga bir nechta tool berasiz; u har bir so'rovga qarab birini, bir nechtasini yoki hech qaysisini
descriptionasosida tanlaydi β tavsifni aniq yozing. - Tool registry (
{"nom": funksiya}lug'ati) modeldan kelgan matnli nomni haqiqiy funksiyaga bog'laydi; yangi tool = bitta funksiya + bitta lug'at yozuvi, bajarish kodi o'zgarmaydi. - Parallel tool calls: bitta javobda bir nechta
tool_callskelishi mumkin β hammasini bajaring va har biriga o'ztool_call_idbilan alohidatoolxabari qaytaring (bittasini tashlasangiz β400xato). - Ko'p qadamli
while/forloop β agentning yuragi: model tool chaqiradi -> bajarasiz -> qaytarasiz -> model yana chaqirishi mumkin -> ... To'xtash sharti:tool_callsyo'q (yakuniy matn) yoki qadam limitiga yetish. - Qadam limiti (
maks_qadam) shart β cheksiz sikl va keraksiz xarajatning oldini oladi. - Real toollar: xavfsiz kalkulyator (
evalemas,ast+ oq ro'yxat), DB so'rovi, HTTP API (timeout +try/exceptbilan). tool_choice:auto(standart, model hal qiladi),required(shart tool), aniq tool (majburlash),none(faqat matn).- Tool xatosini exception emas,
{"xato": "..."}natija sifatida qaytaring β model uni o'qib qayta urinadi yoki tushuntiradi. Xato xabarini foydali yozing. - Model argumentlari β ishonchsiz kirish: bajarishdan oldin validatsiya qiling (eng kam imtiyoz, destruktiv amalga inson tasdig'i). Batafsil β 24-bob.
Amaliy mashqlar¶
-
(Oson) 3 ta tool (
ob_havo,valyuta_aylantir,joriy_vaqt) va ularningREGISTRYlug'atini yozing. "Soat necha?" deb so'rang va modelning faqatjoriy_vaqtni tanlaganini, "qanaqasan?"ga esa hech qaysi toolni chaqirmay matn bilan javob berganini kuzating. -
(Oson) "Toshkent va Samarqandda ob-havo qanday?" deb so'rang. Modelning bitta javobda nechta
tool_callqaytarganini chop eting (len(msg.tool_calls)). Har biriningfunction.argumentsini ham ko'ring. -
(O'rtacha) Bobdagi
agent_javobiloopini yozing vamaks_qadam=5qo'ying. Har qadamda qaysi tool(lar) chaqirilganini va argumentlariniprintqiling β model qanday "fikrlayotganini" kuzating. -
(O'rtacha)
astasosidagi xavfsizkalkulyatortoolini yozing. Uni registry vatoolsga qo'shing. "(125 + 75) * 3 necha bo'ladi?" deb so'rang. Keyin atayin__import__('os')kabi xavfli ifoda yuborib, toolingiz uni rad etganini ({"xato": ...}) tekshiring. -
(Qiyin)
mijoz_malumoti(soxta DB) toolini yozib, mavjud bo'lmagan ID uchun{"xato": "topilmadi"}qaytaring. Loopda shunday savol bering: "1001 va 9999 ID'li mijozlarni solishtir." Model topilmagan ID xatosini ko'rib, javobida buni qanday tushuntirganini kuzating. So'ngtool_choice="required"ga o'zgartirib, xulqning qanday o'zgarganini yozing.
β¬ οΈ Oldingi: 10 β Function/tool calling asoslari Β· π Kitob boshi Β· Keyingi: 12 β Multimodal: rasm va ovoz β‘οΈ