چیتشیت
فراخوانی ابزار و خروجیهای ساختاریافته
Tool Calling and Structured Outputs
تعریف ابزارها، خواندن فراخوانیها، بازگرداندن نتایج، اجرای موازی فراخوانیها، استریمینگ آرگومانها و اجبار به تولید JSON معتبر.
فهرست مطالب
وظایف فراخوانی تابع
کار و کد| وظیفه | کد |
|---|---|
| تعریف یک ابزار، OpenAI | {"type": "function", "function": {...}} |
| تعریف یک ابزار، Anthropic | {"name": ..., "input_schema": {...}} |
| واگذاری تصمیم به مدل | tool_choice="auto" |
| اجبار به فراخوانی ابزار | tool_choice="required" |
| اجبار به یک ابزار خاص | tool_choice={"type":"function", ...} |
| خواندن فراخوانیهای OpenAI | message.tool_calls |
| یافتن فراخوانی Anthropic | b.type == "tool_use" |
| بازگرداندن نتیجهی Anthropic | {"type": "tool_result", "tool_use_id": ...} |
وظایف خروجی ساختاریافته
کار و کد| وظیفه | کد |
|---|---|
| JSON معتبر، بدون اسک Schema | { type: "json_object" } |
| JSON منطبق بر اسکیمای JSON | {type: "json_schema", strict: true} |
| پارس کردن به مدل Pydantic | response_format=Product |
| خواندن نتیجهی تایپشده | message.parsed |
| تلاش مجدد در خطاهای اعتبارسنجی | instructor.from_openai(OpenAI()) |
حلقهی ابزار
معمارییک فراخوانی ابزار
گامبهگام- میزباننام، توضیحات و اسکیمای ورودی را تعریف میکند.
- مدلپاسخ میدهد، ابزارها را فراخوانی میکند، یا امتناع میکند.
- مدلهر فراخوانی دارای
id،nameوargumentsاست. - میزبانآرگومانها را بر اساس اسکیمای JSON اعتبارسنجی میکند.
- مجریکد را اجرا کرده و نتیجهای قابل سریالسازی برمیگرداند.
- میزبانیک پیام
toolبا همان شناسه ضمیمه میکند. - میزباناین روند را تا نبود فراخوانی جدید یا رسیدن به
MAX_TURNSتکرار میکند.
رفتوبرگشت کامل در OpenAI
کدpython
response = client.chat.completions.create(
model="gpt-4o", messages=messages,
tools=tools, tool_choice="auto", # مدل ابزار یا متن را انتخاب میکند
)
tool_call = response.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments) # آرگومانها از جنس رشته هستند
result = get_weather(**args) # کد شما اجرا میشود
messages += [
response.choices[0].message, # حفظ نوبت گفتوگوی assistant
{"role": "tool", "tool_call_id": tool_call.id, # همان شناسه مشابه فراخوانی
"content": json.dumps(result)},
]
final = client.chat.completions.create(model="gpt-4o", messages=messages)
اعتبارسنجی، سپس اصلاح یا امتناع
کدpython
def process_model_output(raw: str, schema: dict) -> ParsedResult:
if raw.startswith("__REFUSAL__"): # امتناع مدل: بدون تلاش مجدد
return ParsedResult("refusal", raw.removeprefix("__REFUSAL__").strip(), [])
try:
parsed = json.loads(raw)
except json.JSONDecodeError as e: # خطای 1: داده JSON نیست
return ParsedResult("parse_error", None, [ValidationError("$", str(e))])
errs = validate(schema, parsed) # فهرستی از مسیر و پیام خطا
if errs:
return ParsedResult("violation", parsed, errs) # تزریق خطاها، تلاش مجدد
return ParsedResult("ok", parsed, [])
ساختارها بر اساس ارائهدهنده
مفهومها- فیلد اسکیمای JSON
parameters،input_schema، و در Gemini فیلدparameters.- فراخوانی
tool_calls[]، یک بلوکtool_use، یک بخشfunctionCall.- آرگومانها
- OpenAI رشته میفرستد. بقیه یک شیء ارسال میکنند.
- پیوند نتیجه
tool_call_id،tool_use_id، شناسهیfunctionResponse.- ممنوعیت ابزارها
tool_choice: "none"،{type: "none"}،mode: "NONE".- حالت سختگیرانه
strict: true، همیشه روشن،responseSchema.
فراخوانیهای موازی و استریمینگ
مفهومها- فعالسازی
parallel_tool_calls: trueحالت پیشفرض OpenAI است.- ترتیبی
- در صورت وابستگی فراخوانیها به یکدیگر، آن را خاموش کنید.
- تطبیق
- هر نتیجه شناسهی فراخوانی خود را دارد. ترتیب اختیاری است.
- استریمینگ OpenAI
- تکهها را بر اساس
indexمتصل کنید تا بهfinish_reason = "tool_calls"برسید. - استریمینگ Anthropic
- تکههای
input_json_deltaتا رسیدن بهcontent_block_stop. - پارس با تاخیر
- JSON ناقص خطا میدهد. در سیگنال پایانی پارس کنید.
- تاخیر
- 400، 600، 800 میلیثانیه: 1800 میلیثانیه ترتیبی، 800 میلیثانیه موازی.
قوانین طراحی اسکیمای JSON
مفهومها- نام
snake_case، فعل و سپس اسم:get_weather. بدون آرگومان در نام.- توضیحات
- "زمانی استفاده شود که {شرط}. برای {موارد-مشابه-اما-غلط} استفاده نشود."
- Enumها
- هر مجموعهی بستهای را در یک
enumقرار دهید. - ابزارهای تجزیهناپذیر
- اگر
actionبیش از 3 مقدار دارد، ابزار را تفکیک کنید. - حالت سختگیرانه
- همهی خصوصیات در
required، مقدارadditionalProperties: false، بدون$ref.
محدودیتها و پیشفرضها
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
OpenAI tools per request | 128 | محدودیت قطعی |
Anthropic tools per request | 64 | محدودیت قطعی |
OpenAI schema depth | 5 | حالت سختگیرانه |
OpenAI argument string | 8192 bytes | حداکثر اندازه |
Description length | 1024 characters | متنهای طولانیتر بریده میشوند |
MAX_TURNS | 5 | سقف حلقهی درس |
Repair retries | 3x | تعداد بیشتر یعنی اسکیمای نامناسب |
timeout_ms | 30_000 | به ازای هر رکورد ابزار |
عیبیابی
عیبیابیخطای
json.loadsاواسط استریمینگ- علت
- آرگومانها JSON ناقص هستند
- راهحل
- پارس کردن پس از سیگنال پایان فراخوانی
خطای 400 در زمان درخواست، حالت سختگیرانه
- علت
- نقض قوانین حالت سختگیرانه در اسکیمای JSON
- راهحل
- همه در
required، بدون$ref
انتخاب ابزار اشتباه
- علت
- همپوشانی توضیحات دو ابزار
- راهحل
- افزودن خط "استفاده نشود برای"
مقدار خارج از
enum- علت
- خروجی مبتنی بر پرامپت
- راهحل
- استفاده از رمزگشایی مقید
refusalدر پاسخ- علت
- ورودی با اسکیمای JSON همخوانی ندارد
- راهحل
- مدیریت آن به عنوان یک پیامد تایپشده
فیلدهای اضافی در
input- علت
- اسکیمای Anthropic صرفاً مشورتی است
- راهحل
- اعتبارسنجی سمت سرور
تلاش مجدد روی خطاهای اسکیمای JSON
- علت
- خطاها قطعی هستند
- راهحل
- اصلاح آرگومانها، بدون تلاش مجدد
ارسال نتایج به فراخوانی اشتباه
- علت
- تطبیق بر اساس نام به جای شناسه
- راهحل
- بازگرداندن هر نتیجه به همراه شناسهی آن
پرسش و پاسخ
پرسش و پاسخ- خروجی ساختاریافته یا فراخوانی ابزار؟
- خروجی دادهی نهایی است. فراخوانی درخواست اقدام است.
- چرا پرامپت ساده برای JSON مناسب نیست؟
- بین 5 تا 15 درصد مواقع ناموفق است.
- چرا شناسهی فراخوانی نیاز است؟
- نتایج موازی بدون ترتیب بازمیگردند.
- آیا اسکیمای JSON میتواند مقدار غلط را تشخیص دهد؟
- خیر. نوع داده درست است، اما مقدار ساختگی است.
نکات
نکتهها- خطاها را به عنوان نتیجه برگردانید:
{"error": true, "code": "CITY_NOT_FOUND"}. - خطاها را برای مدل بنویسید: "'city' is required."
- گزارش خطاها در قالب مسیرهای اشارهگر جیسان:
/user/email. - فیلدهای کلیدی را اجباری کنید. مدل در صورت نیاز
nullمینویسد. - فقط توابعی را افشا کنید که کاربر به آنها نیاز دارد.