مدل‌های زبانی بزرگ (LLMها) وارد کد شما نمی‌شوند – آن‌ها یک درخواست به شما می‌دهند و شما تابع را اجرا می‌کنید. همین واقعیت ساده، این باور غلط را که «مدل به‌طور جادویی روتین پایتون من را فراخوانی می‌کند» از بین می‌برد و توسعه‌دهندگان را مجبور می‌کند در مورد عیب‌یابی (debugging) و امنیت بازنگری کنند.

چرخه اعزام (dispatch loop)، مرحله به مرحله

وقتی یک مدل زبانی بزرگ (LLM) به یک ابزار نیاز دارد، یک توالی قطعی را دنبال می‌کند:

  1. برنامه‌ریزی (Planning) – مدل تصمیم می‌گیرد که یک اقدام لازم است (مثلاً «بازگشت وجه پرداخت»).
  2. تولید درخواست (Generating a request) – مدل یک متن ساختاریافته — معمولاً JSON — تولید می‌کند که نام ابزار را مشخص کرده و آرگومان‌ها را ارائه می‌دهد.
  3. تجزیه (Parsing) – اپلیکیشن شما یا یک فریم‌ورک پشتیبان، آن متن را می‌خواند.
  4. تطبیق (Matching) – فریم‌ورک نام را در فهرست توابع واقعی که شما ارائه کرده‌اید، جستجو می‌کند.
  5. اعتبارسنجی (Validating) – بررسی می‌کند که آیا آرگومان‌ها با طرحواره (schema) تابع مطابقت دارند و آیا فراخواننده مجاز است یا خیر.
  6. اجرا (Executing) – تابع تطبیق‌یافته در محیط شما اجرا شده و کار را انجام می‌دهد.
  7. بازگرداندن (Returning) – نتیجه بسته‌بندی شده و برای استدلال بیشتر به مدل بازگردانده می‌شود.

LLM را به عنوان یک برنامه‌ریز، فریم‌ورک را به عنوان یک اعزام‌کننده (dispatcher) و تابع را به عنوان کارگری در نظر بگیرید که واقعاً داده‌ها یا پول را جابه‌جا می‌کند.

چرا باور غلط «جادو» همچنان پابرجاست

اکثر توسعه‌دهندگان تنها یک خط از خروجی مدل را می‌بینند که شبیه به فراخوانی یک تابع است و تصور می‌کنند که خودِ مدل عملیات را انجام داده است. اصطلاح «tool calling» در مستندات ارائه‌دهندگان (providers) به‌گونه‌ای به نظر می‌رسد که انگار مدل مستقیماً کد را فراخوانی می‌کند.

در واقعیت، مدل فقط متنی تولید می‌کند که یک فراخوانی را توصیف می‌کند. این فرآیند شماست که کارهای اصلی را انجام می‌دهد: جستجو، بررسی نوع (type checking)، اعمال مجوزها و مدیریت خطا.

فریم‌ورک‌هایی که جزئیات زیرساختی را پنهان می‌کنند

کتابخانه‌هایی مانند PydanticAI و LangChain این چرخه را انتزاعی (abstract) می‌کنند تا شما بتوانید بر منطق تجاری (business logic) تمرکز کنید. آن‌ها به‌طور خودکار:

  • اعتبارسنجی آرگومان‌ها بر اساس یک schema (مثلاً یک مدل Pydantic).
  • اعمال مجوزها، برای اطمینان از اینکه کاربر اجازه اجرای ابزار را دارد.
  • تلاش مجدد در صورت شکست، با بازگشت به مدل در زمانی که یک ابزار خطایی را برمی‌گرداند.
  • محافظت در برابر حلقه‌های بی‌انتها، با محدود کردن تعداد فراخوانی‌های متوالی ابزار.
  • حفظ وضعیت گفتگو، با گره زدن نتایج ابزار به دیالوگ.

حتی با وجود این کمک‌کننده‌ها، الگو ثابت می‌ماند: مدل هرگز کد را اجرا نمی‌کند.

پشتیبانی بومی از فراخوانی ابزار توسط ارائه‌دهندگان

برخی از ارائه‌دهندگان یک رابط کاربری «بومی» (native) برای فراخوانی ابزار ارائه می‌دهند که تعاریف ابزار و قالب‌های درخواست را استاندارد می‌کند. این کار یکپارچه‌سازی را تسهیل می‌کند اما مرحله اعزام (dispatch) را حذف نمی‌کند. شما همچنان کدی را که واقعاً عملیات درخواستی را اجرا می‌کند، می‌نویسید (یا وارد می‌کنید).

عیب‌یابی با تغییر نام مشکل، آسان‌تر می‌شود

به جای مقصر دانستن یک «عامل گیج شده» (confused agent)، بگویید مشکل این است که «پاسخ مدل شامل هیچ فراخوانی ابزاری نبود». این تمایز بسیار مهم است:

  • عدم فراخوانی ابزار (No tool call) – مدل مستقیماً پاسخ داده یا در تولید یک درخواست با قالب صحیح شکست خورده است.
  • درخواست بدشکل (Malformed request) – ساختار JSON از نظر سینتکس اشتباه است یا فیلدهای مورد نیاز را ندارد، بنابراین اعزام‌کننده آن را رد می‌کند.
  • شکست در اعتبارسنجی (Validation failure) – آرگومان‌ها با schema مطابقت ندارند و قبل از اجرا باعث بروز خطا می‌شوند.

دسته‌بندی خطاها به شما اجازه می‌دهد هر مرحله از چرخه را ثبت (log) کنید و دقیقاً مشخص کنید که مشکل از کجا شروع شده است.

نکات کاربردی برای یک خط لوله (pipeline) قابل اعتماد

  • با خروجی مدل مانند یک ورودی غیرقابل اعتماد رفتار کنید. هر درخواست را قبل از فراخوانی هرگونه کد دارای اثر جانبی (side-effecting)، از یک اعتبارسنجی قطعی (deterministic) عبور دهید.
  • درخواست خام و نتیجه هر مرحله از اعتبارسنجی را ثبت کنید. این کار یک ردپای قابل بازپخش (replayable) در صورت بروز مشکل ایجاد می‌کند.
  • محدودیت‌های صریح تعیین کنید؛ فراخوانی‌های متوالی ابزار می‌تواند باعث اتمام منابع یا برخورد با محدودیت نرخ (rate limits) شود.
  • هر تابع را در یک بلوک try/except قرار دهید که یک شیء خطای ساختاریافته قابل فهم برای مدل برگرداند تا باعث تلاش مجدد یا بازگشت به حالت ایمن (graceful fallback) شود.
  • بررسی مجوزها را از منطق تجاری جدا کنید. قبل از اجرای تابع، حقوق فراخواننده را تأیید کنید، به‌ویژه برای اقدامات حساس مانند «حذف کاربر».
  • از تعاریف مبتنی بر schema استفاده کنید (مثلاً مدل‌های Pydantic) تا فریم‌ورک بتواند JSON schema مورد نیاز مدل را به‌طور خودکار تولید کند.

آنچه باید در آینده زیر نظر داشته باشید

با بهبود APIهای بومی فراخوانی ابزار توسط ارائه‌دهندگان، انتظار قراردادهای سخت‌گیرانه‌تر در مورد قالب‌های درخواست و کدهای خطای غنی‌تر را داشته باشید. این تغییرات اعتبارسنجی را آسان‌تر کرده و به توسعه‌دهندگان اجازه می‌دهد حصارهای امنیتی سخت‌گیرانه‌تری بسازند. اخبار به‌روزرسانی کتابخانه‌ها را دنبال کنید؛ بسیاری از آن‌ها در حال افزودن پشتیبانی داخلی برای جدیدترین ویژگی‌های ارائه‌دهندگان هستند.

نکته کلیدی

LLM یک تولیدکننده متن پیشرفته است، نه یک اجراکننده. کد شما همچنان تنها مرجعی است که اقدامات را انجام می‌دهد، و دیسپچری که می‌سازید (یا وارد می‌کنید) دروازه‌بانی است که آن اقدامات را اعتبارسنجی، تأیید و اجرا می‌کند. بازتعریف جریان کاری، افسانه «جادو» را از بین می‌برد، عیب‌یابی را دقیق‌تر می‌کند و انضباط امنیتی مورد نیاز هر سیستم عملیاتی را اعمال می‌کند.