تعریفِ یک ابزار
mini تا اینجا میتواند گفتوگو کند، ولی کاری از دستش برنمیآید. لیلا از آن میپرسد «در notes.txt چه نوشته است؟» و mini با صداقت جواب میدهد که فایلهای او را نمیبیند. از استفاده از ابزار میدانید چه چیزی کم است: درخواست باید به مدل بگوید چه کارهایی را میتواند بخواهد. این درس همین بخشِ درخواست را با پایتون مینویسد.
لیلا پس یک تابع به مدل میدهم و مدل صدایش میزند؟
امید مدل هیچ وقت چیزی را صدا نمیزند. برای اینکه بتواند کاری را بخواهد، واقعاً چه چیزی از ما لازم دارد؟
لیلا اسمش را، تا بتواند بگوید کدام را میخواهد. و اینکه چه میکند، تا بداند کی سراغش برود.
امید خوب است. وقتی میخواهد فایلی را بخواند، چه چیزی را باید به ما بگوید؟
لیلا کدام فایل. پس باید بداند چه ورودیهایی هست.
امید و از کجا مطمئن شویم درخواستش شکلی دارد که کدِ ما بتواند با آن کار کند؟ اگر بنویسد «لطفاً فایلِ یادداشتها را بخوان»، با آن چه کنیم؟
لیلا هیچ کار، راستش. چیزی مثلِ یک فرم لازم داریم، با خانههایی که اسم دارند. خانهای به اسمِ path که باید متن باشد.
امید دقیقاً همین را میفرستیم: یک نام، یک شرح به زبانِ ساده، و یک فرم برای ورودیها. این فرم با استانداردی به اسمِ JSON Schema نوشته میشود.
ابزار، به شکلِ یک دیکشنری
تعریفِ ابزار (tool definition) یک دیکشنری با سه کلید است. این اولین ابزارِ mini است:
read_file_tool = {
"name": "read_file",
"description": "Read a text file in the project. Use before changing a file.",
"input_schema": {
"type": "object",
"properties": {
"path": {"type": "string", "description": "path relative to the project folder"},
},
"required": ["path"],
},
}به اینها دقت کنید:
nameاسمی است که مدل با آن به ابزار اشاره میکند. کوتاه، با حروفِ کوچک، و یک فعل همراهِ یک اسم:read_file،run_command.descriptionبرای خواندنِ مدل است. میگوید ابزار چه میکند و کی باید از آن استفاده کرد.input_schemaهمان فرم است."type": "object"یعنی «ورودیها مجموعهای از خانههای نامدار است»؛propertiesهر خانه را با نوع و شرحِ خودش فهرست میکند؛ وrequiredخانههایی را میگوید که همیشه باید پر شوند.
اسکیمای ورودی (input schema) با JSON Schema نوشته میشود، استانداردی رایج برای توصیفِ شکلِ دادهها. فقط چند کلمه از آن لازمتان میشود: "string" برای متن، "integer" و "number" برای عدد، "boolean" برای درست یا نادرست، "array" برای فهرست، و "enum" برای خانهای که باید یکی از چند مقدارِ ثابت باشد، مثلِ "enum": ["celsius", "fahrenheit"].
فرستادنِ آن
ابزارها به شکلِ یک فهرست، کنارِ پیامها، در درخواست میروند:
response = client.messages.create(
model=MODEL,
max_tokens=16000,
system=SYSTEM,
tools=[read_file_tool],
messages=[{"role": "user", "content": "What's in notes.txt?"}],
)
print(response.stop_reason)
for block in response.content:
print(block.type, getattr(block, "name", ""), getattr(block, "input", ""))اگر مدل به این نتیجه برسد که ابزار کمک میکند، جواب نمیدهد. یک بلوکِ tool_use مینویسد و میایستد، و stop_reason (دلیلِ ایستادن) میگوید چرا ایستاد: "tool_use". چیزی که چاپ میشود کموبیش این است:
tool_use
thinking
tool_use read_file {'path': 'notes.txt'}بلوکِ اول فکر کردنِ مدل است (Opus 5.5 همیشه فکر میکند، و متنِ فکرش بهطور پیشفرض نمیآید). دومی خودِ درخواست است و سه بخش دارد: block.name ابزار است؛ block.input یک دیکشنریِ پایتون است که از قبل به شکلِ اسکیمای شما درآمده؛ و block.id، رشتهای مثلِ "toolu_01A..."، این درخواست را نشانهگذاری میکند تا پاسخ را بشود به آن ربط داد. این موضوعِ درسِ بعد است.
اینکه از ابزار استفاده کند یا نه، انتخابِ خودِ مدل است و شما نمیتوانید مجبورش کنید. (مدلهای قدیمیتر تنظیمی را میپذیرفتند که فراخوانیِ ابزار را اجباری میکرد؛ تازهترین مدلهای Claude آن را رد میکنند.) اگر کاری حتماً باید از ابزارِ خاصی استفاده کند، در پیام یا پرامپت سیستمی بگویید: «پیش از جواب دادن، با read_file فایل را نگاه کن.»
لیلا اگر هر ابزار یک دیکشنری مثلِ این باشد، mini آخرش فهرستِ بلندی از آنها خواهد داشت.
امید و پشتِ هر کدام هم یک تابع هست. این دو را کجا نگه میداری که از هم جدا نیفتند؟
لیلا کنارِ هم. یک جدول: نام، تابع، شرح و ورودیها.
جدولِ ابزارهای mini
mini همهی ابزارهایش را در یک دیکشنری به اسمِ TOOLS نگه میدارد و تعریفها را از روی آن میسازد. هر ابزار یعنی تابعش، شرحش و ورودیهایش:
TOOLS = { # name -> (function, description, inputs)
"read_file": (read_file, "Read a text file in the project. Use before changing a file.",
{"path": "path relative to the project folder"}),
}
def tool_schemas(names): # the descriptions the model reads
return [{
"name": name,
"description": TOOLS[name][1],
"input_schema": {
"type": "object",
"properties": {k: {"type": "string", "description": d} for k, d in TOOLS[name][2].items()},
"required": list(TOOLS[name][2]),
},
} for name in names]tool_schemas(["read_file"]) دقیقاً همان دیکشنریِ بالا را میسازد. همهی ورودیهای ابزارهای mini متناند و الزامی، و همین جدول را کوتاه نگه میدارد؛ یک عاملِ بزرگتر به هر ورودی نوعِ خودش را میدهد. حالا اضافه کردنِ یک ابزار فقط یک خط در TOOLS است. بخشِ بعد سه ابزارِ دیگر اضافه میکند.
شرحهایی که مدل خوب به کار میبرد
شرح تنها چیزی است که مدل دربارهی ابزار میداند، و فقط از روی همین تصمیم میگیرد. یک شرحِ خوب اینها را میگوید:
- ابزار چه میکند، در یک جمله: «یک فایلِ متنی در پروژه را میخواند.»
- کی از آن استفاده کنیم و کی نه: «پیش از تغییر دادنِ فایل از آن استفاده کن.» «برای پوشه نیست: از list_files استفاده کن.»
- ورودیها چه شکلی دارند، با یک نمونه اگر کمک میکند: «مسیر نسبت به پوشهی پروژه، مثلِ reports/march.md».
- چه برمیگردد، اگر روشن نیست: «کدِ خروج و خروجی را برمیگرداند.»
شرحِ همهی ابزارها در هر درخواست فرستاده میشود، پس یکی دو جمله برای هر کدام کافی است، و ده ابزارِ دقیق بهتر از چهل ابزارِ همپوشان کار میکند.
امتحان کنید
اگر کلیدتان را تنظیم کردهاید، درخواستِ بالا را در پوشهای که یک
notes.txtدارد اجرا کنید و بلوکها را چاپ کنید. هزینهاش خیلی کمتر از یک سنت است. بعد شرح را فقط"Files."کنید و چند بار بپرسید «در notes.txt چه نوشته است؟»: آیا مدل باز هم از ابزار استفاده میکند؟ بدونِ کلید: تعریفِ ابزاری را که برای کارِ خودتان میخواهید به شکلِ یک دیکشنری بنویسید. آیا شرحش میگوید کی باید از آن استفاده کرد؟
درست به کار بردن
- اسمِ ابزار را یک فعل و یک اسم بگذارید.
read_file،send_email،list_orders: مدل بینِ اسمها انتخاب میکند، پس اسم باید بگوید ابزار چه میکند. - شرح را برای لحظهی انتخاب بنویسید. «وقتی ... از آن استفاده کن» و «برای ... نیست» بیشتر از یک فهرستِ بلندِ قابلیتها کار میکنند.
- تعریف را کنارِ تابع نگه دارید. یک جدول برای هر دو یعنی اگر اسمِ ورودیای عوض شود، شرح جا نمیماند.
- وقتی مهم است، ابزار را در پرامپت بخواهید. نمیتوانید فراخوانیِ ابزار را اجباری کنید، ولی میتوانید بگویید کار به کدام ابزار نیاز دارد.
واژههای این درس
- تعریفِ ابزار (tool definition) - دیکشنریای که ابزاری را به مدل پیشنهاد میکند: نام، شرح و اسکیمای ورودیاش
- اسکیمای ورودی (input schema) - بخشی از تعریفِ ابزار که ورودیهای ابزار را توصیف میکند: اسمشان، نوعشان و اینکه کدامها الزامیاند
- JSON Schema - روشی استاندارد برای توصیفِ شکلِ دادهها، که برای ورودیهای ابزار به کار میرود
- stop_reason (دلیلِ ایستادن) - خانهای از پاسخ که میگوید مدل چرا از نوشتن ایستاد؛
"tool_use"یعنی منتظر است ابزاری اجرا شود
ایدهی اصلی
ابزار از نگاهِ مدل یک نام است، یک شرح و یک فرم برای ورودیها، که با هر درخواست فرستاده میشود. وقتی مدل آن را بخواهد، با یک بلوکِ
tool_useمیایستد: نام، فرمِ پرشده و یک شناسه. بقیهاش با کدِ شماست.