Knaph

ابزارها و حلقه16 از 375 دقیقه مطالعه

درخواستِ یک ابزار

در درس «مدلی با دست»، لیلا به این نتیجه رسید که مدلِ یک عامل درخواست‌هایی مثل «این فرمان را اجرا کن» می‌نویسد و برنامه‌ی دورِ آن اجرایشان می‌کند. فکرِ درستی است. این درس دقیق نشان می‌دهد این کار چطور انجام می‌شود، چون وقتی آن را دیدید، خیلی چیزها درباره‌ی عامل‌ها دیگر رازآلود نیستند.


لیلا چیزی که هنوز ذهنم را مشغول کرده این است: مدل متن می‌نویسد. برنامه از کجا می‌فهمد که یک تکه متن درخواستِ انجامِ کاری است، نه بخشی از یک پاسخ؟

امید سؤالِ خوبی است. فرض کن خودت آن برنامه را می‌نوشتی. چطور مطمئن می‌شدی که این دو را از هم تشخیص می‌دهی؟

لیلا با مدل سرِ یک قالبِ خاص توافق می‌کردم. مثلاً: «اگر می‌خواهی کاری بکنم، دقیقاً همین‌طور بنویسش و هیچ چیزِ دیگر ننویس».

امید دقیقاً همین اتفاق می‌افتد. و مدل باید بداند چه کارهایی را می‌تواند درخواست کند. از کجا می‌داند؟

لیلا به او می‌گفتم. لابد در درخواست، چون فقط همان را می‌بیند. یک فهرست: «این کارها را می‌توانی بخواهی».

امید باز هم درست است. پس: فهرستی از کارها در درخواست، و یک قالبِ ثابت برای خواستن. کلِ سازوکار همین است.


شرحِ ابزارها

به کاری که مدل می‌تواند درخواست کند ابزار (tool) می‌گویند. برنامه فهرستی از ابزارها را در هر درخواست، به‌عنوانِ بخشی از زمینه، می‌فرستد. هر ابزار سه بخش دارد:

  • یک نام، مثل get_weather؛
  • یک شرح به زبانِ ساده: چه می‌کند و کی باید از آن استفاده کرد؛
  • ورودی‌هایی که لازم دارد، و نوعِ هر کدام.

کارتِ شرحِ یک ابزار. نام: get_weather. شرح: هوای همین حالای یک شهر را می‌دهد؛ وقتی کاربر درباره‌ی هوای همین حالا می‌پرسد، از آن استفاده کن. ورودی: city، نامِ شهر، به صورتِ متن.

مدل این شرح‌ها را هم مثل هر چیزِ دیگری در زمینه‌اش می‌خواند. وقتی به این نتیجه برسد که ابزاری کمک می‌کند، با کلمه‌ها پاسخ نمی‌دهد. به‌جایش یک فراخوانی ابزار (tool call) می‌نویسد: نامِ ابزار و ورودی‌هایش، در قالبی ثابت، و بعد می‌ایستد. در Claude شکلش این است:

{
  "type": "tool_use",
  "name": "get_weather",
  "input": { "city": "Tabriz" }
}
JSON

به سه چیز دقت کنید: name می‌گوید کدام ابزار؛ input مقدارها را دارد، دقیقاً به همان شکلی که شرحِ ابزار خواسته بود؛ و هنوز هیچ پاسخی برای لیلا نیست، چون مدل ایستاده و منتظر است.

تبادل، گام‌به‌گام

وقتی لیلا می‌پرسد «امروز در تبریز چتر ببرم؟»، کلِ تبادل این‌طور است:

  1. برنامه درخواست را می‌فرستد: پرامپت سیستمی، فهرستِ ابزارها و پرسشِ لیلا.
  2. مدل یک فراخوانی ابزار می‌نویسد، get_weather با city: Tabriz، و می‌ایستد.
  3. برنامه فراخوانی را می‌بیند و کدِ واقعیِ پشتِ get_weather را اجرا می‌کند: شاید از یک سرویسِ هواشناسی در اینترنت بپرسد.
  4. برنامه پاسخ را به‌عنوانِ یک نتیجه‌ی ابزار (tool result) به گفت‌وگو اضافه می‌کند: «بارانِ سبک، ۹ درجه». بعد درخواستی تازه با همه‌ی چیزهای تا اینجا می‌فرستد.
  5. مدل نتیجه را می‌خواند و پاسخش را می‌نویسد: «بله، چتر ببرید: بارانِ سبک پیش‌بینی شده است.»

این تبادل به ترتیب: مدل یک فراخوانیِ ابزار می‌نویسد؛ برنامه ابزار را اجرا می‌کند و نتیجه را برمی‌گرداند؛ سپس مدل پاسخِ لیلا را می‌نویسد.

مدل در هیچ لحظه‌ای به اینترنت دست نزد. یک درخواست نوشت و بعدتر یک نتیجه را خواند. هر چه در دنیای بیرون اتفاق افتاد کارِ برنامه بود. به این کار فراخوانی تابع (function calling) هم می‌گویند، چون هر ابزار معمولاً یک تابع در کدِ برنامه است.


لیلا پس اگر شرحِ ابزار بد باشد، ممکن است مدل آن را در وقتِ نادرست به کار ببرد.

امید یا اصلاً به کار نبرد. شرح تنها چیزی است که مدل درباره‌ی ابزار می‌داند. ابزاری که شرحش فقط «هوا» است بد به کار می‌رود. ابزاری با شرحِ «هوای همین حالای یک شهر را می‌دهد؛ وقتی کاربر درباره‌ی هوای همین حالا می‌پرسد از آن استفاده کن، نه برای پیش‌بینی» خوب به کار می‌رود.

لیلا و شرحِ همه‌ی ابزارها در همه‌ی درخواست‌ها هست؟

امید در همه‌ی درخواست‌ها. عاملی با پنجاه ابزار، پنجاه شرح را همیشه در زمینه‌اش دارد. این هم توکن خرج می‌کند و هم توجه، برای همین عامل‌های خوب فهرستِ ابزارهایشان را مرتب و کوتاه نگه می‌دارند.


ابزارهای یک عاملِ کدنویسی

عامل‌های کدنویسی مثل Claude Code با چند ابزار می‌آیند که تقریباً همه‌چیز را پوشش می‌دهند:

  • خواندنِ یک فایل (یا بخشی از آن)؛
  • ویرایشِ یک فایل، یا نوشتنِ فایلی تازه؛
  • جست‌وجو در فایل‌ها برای یک کلمه یا الگو؛
  • اجرای یک فرمانِ پوسته (shell): هر برنامه‌ای روی کامپیوتر، از فهرست کردنِ یک پوشه تا اجرای تست‌ها؛
  • گرفتنِ یک صفحه‌ی وب، یا جست‌وجو در وب.

ابزارِ فرمانِ پوسته همان ابزارِ قدرتمند است: عامل از راهِ آن می‌تواند هر برنامه‌ای را که شما می‌توانید به کار ببرد. درس‌های بعدی درباره‌ی این است که این قدرت را چطور در اختیار نگه دارید.

امتحان کنید

اگر عاملی دارید، چیزی از آن بپرسید که ابزار لازم دارد، مثلاً «در این پوشه چند فایل هست؟»، و صفحه را نگاه کنید. بیشترِ عامل‌ها هر فراخوانی ابزار را همان لحظه نشان می‌دهند (در Claude Code خطی مثل Bash(ls | wc -l) می‌بینید) و بعد نتیجه‌اش را. در یک دستیار گفت‌وگو، درباره‌ی خبرهای امروز بپرسید: اگر جست‌وجو کند، معمولاً پیش از پاسخ یک مرحله‌ی «در حال جست‌وجو» می‌بینید.

درست به کار بردن

  1. فراخوانی‌های ابزار را بخوانید، نه فقط پاسخِ نهایی را. نشان می‌دهند عامل واقعاً چه کرد، که اغلب گویاتر از چیزی است که می‌گوید کرده است.
  2. انتظار داشته باشید ابزارها گاهی شکست بخورند. یک نامِ فایلِ اشتباه، فرمانی که خطا می‌دهد: خطا در قالبِ نتیجه‌ی ابزار برمی‌گردد و یک عاملِ خوب آن را می‌خواند و دوباره تلاش می‌کند.
  3. اگر ابزاری می‌سازید یا اضافه می‌کنید، شرحش را با دقت بنویسید. بگویید ابزار چه می‌کند، کی باید از آن استفاده کرد و کی نه. مدل هیچ چیزِ دیگری درباره‌اش نمی‌بیند.

واژه‌های این درس

  • ابزار (tool) - کاری که برنامه در اختیارِ مدل می‌گذارد، با یک نام، یک شرح و ورودی‌هایش
  • فراخوانی ابزار (tool call) - متنی در قالبی ثابت که مدل با آن می‌خواهد ابزاری با ورودی‌هایش اجرا شود
  • نتیجه‌ی ابزار (tool result) - آنچه برنامه بعد از اجرای یک ابزار به مدل برمی‌گرداند: خروجی، یا یک خطا
  • فراخوانی تابع (function calling) - نامِ دیگرِ استفاده از ابزار، چون ابزارها معمولاً تابع‌هایی در کدِ برنامه‌اند

ایده‌ی اصلی

مدل هرگز خودش کاری نمی‌کند. شرحِ ابزارها را می‌خواند، یک فراخوانی ابزار می‌نویسد و می‌ایستد؛ برنامه ابزار را اجرا می‌کند و نتیجه را برمی‌گرداند تا مدل بخواند. هر کاری که یک عامل در دنیا انجام می‌دهد از همین تبادل می‌گذرد.

دانش خود را بسنجید

ورود برای سنجش دانش خود از این درس و پیگیری پیشرفتتان.