واحد محاسبه اشتباه است
بیشتر داشبوردهای هزینه برای سیستمهای LLM حول یک پرسش ساخته میشوند: هزینه این فراخوانی چقدر بود؟ این پرسش پاسخپذیر، دقیق و تقریباً بیفایده برای عاملهاست. یک اجرای عامل یک فراخوانی نیست. یک مسیر است: یک برنامه، دنبالهای از فراخوانی ابزارها، یک یا چند دور بازتاب، تلاش مجدد پس از آرگومانهای نامعتبر، و یک ترکیب نهایی. فراخوانی اتم است؛ مسیر مولکول. قیمتگذاری اتم و بودجهبندی مولکول باعث میشود تیمها به فاکتور ماهانهای برسند که هیچکس نمیتواند از لاگها توضیحش دهد.
این مقاله از کنترل هزینه در سطح مسیر دفاع میکند: سقفهای سطح اجرا بر توکن، زمان دیواری و فراخوانی ابزار، اعمالشده خارج از مدل، با تخریب پلهای و تشدید تعریفشده پیش از شروع اجرا. مکانیزم زرقوبرق ندارد. اما تفاوت بین یک سیستم عامل قابل بهرهبرداری و سیستمی است که فقط میتوان نمایشش داد.
چرا قیمتگذاری بهازای هر فراخوانی گمراهکننده است
یک فراخوانی هزینه کراندار دارد. یک مسیر ندارد، چون تعداد فراخوانیها تابعی از وظیفه، تصمیمات خود مدل و پاسخهای محیط است. سه عامل غالباند و هیچکدام در دفتر کل بهازای هر فراخوانی ظاهر نمیشوند.
تلاشهای مجدد. فراخوانی ابزاری که اعتبارسنجی طرحواره را رد کند، مهلت تمام شود یا خطای مبهم برگرداند، دوباره تلاش میشود. هر تلاش مجدد زمینه را دوباره میفرستد. زمینهای که در طول مسیر بهطور یکنوا رشد میکند یعنی تلاش مجدد nام بیشتر از اولی هزینه دارد، نه برابر آن. هزینه هر تلاش بالا میرود حتی وقتی تعداد تلاشها ثابت است.
پخششدگی ابزار. یک مرحله برنامهریزی میتواند تصمیم بگیرد از یک منبع پرسوجو کند یا دوازده. مدل اقتصاد واحد شما را نمیداند، پس دلیلی برای ترجیح یکی ندارد. پخششدگی جایی است که حالت میانه خوشرفتار و حالت دنباله بیمارگونه به اندازه یک مرتبه بزرگی واگرا میشوند، و این واگرایی ساختاری است، نه تصادفی.
دورهای بازتاب. حلقههای خودنقدی، راستیآزمایی و برنامهریزی مجدد بالاترین اهرم کیفیت در بیشتر طراحیهای عامل و بالاترین واریانس هزینه هستند. یک دور بازتاب که چیزی برای اصلاح پیدا نمیکند هنوز هزینه یک دور کامل زمینه را دارد. یک دور بازتاب که چیزی برای اصلاح پیدا میکند هزینه آن بهعلاوه اصلاح بهعلاوه راستیآزمایی مجدد را دارد.
نتیجه یک توزیع هزینه با دنباله سنگین است. اجرای میانه ارزان است و میانگین نه. تیمهایی که از میانه بودجهبندی میکنند بهطور سیستماتیک غافلگیر میشوند؛ تیمهایی که از میانگین بودجهبندی میکنند بیشازحد تأمین میکنند و باز هم از دنباله غافلگیر میشوند. دنباله نویز نیست. یک کلاس خاص از وظیفه است که عامل با حلقه زدن انجامش میدهد، و تکرار خواهد شد.
یک بُعد خارجی هم وجود دارد: با تکثیر چارچوبهای عامل و الگوهای ارکستراسیون، سطح هزینه یک سیستم مستقر سریعتر از هر برآورد ایستای بهازای هر فراخوانی تغییر میکند. یک انضباط مفید این است که مسیر را بهعنوان چیزی که قیمتگذاری، پایش و سقفگذاری میشود در نظر بگیریم، نه فراخوانی را.

ابتداییهای بودجه
بودجه اجرا مجموعهای از سقفهاست که به یک شناسه مسیر متصل و توسط ارکستراتور اعمال میشود، نه توسط مدل. اعمال خارج از مدل مهم است: مدلی که از او خواسته شده زیر بودجه بماند دارد یک وعده نرم میدهد، و وعدههای نرم دقیقاً همان چیزی است که در دنباله شکست میخورد. ارکستراتور میتواند بشمارد، و بودجهها به شمارش نیاز دارند.
سقفها
سه سقف بیشتر حالتهای شکست را پوشش میدهند:
- سقف توکن. مجموع توکنهای ورودی و خروجی در کل مسیر، نه بهازای هر فراخوانی. در مرز ارکستراتور شمرده میشود تا تلاشهای مجدد و دورهای بازتاب بهطور ساختاری شامل شوند.
- سقف زمان دیواری. یک مهلت برای مسیر. این حلقههایی را میگیرد که هر مرحلهشان ارزان است اما تعداد مراحلشان بیکران است، و تنها سقفی است که از یک حادثه تأخیر سمت ارائهدهنده جان سالم به در میبرد.
- سقف فراخوانی ابزار. محدودیتی بر تعداد فراخوانیهای خارجی، بهصورت اختیاری بهازای هر ابزار. این کنترل مستقیم پخششدگی و ارزانترین چیز برای استدلال است.
یک پیادهسازی عملی یک دفتر کل بهازای هر اجرا نگه میدارد که هر مرحله پیش از ارسال در آن مینویسد:
class RunLedger:
def __init__(self, limits):
self.limits = limits
self.tokens = 0
self.tools = 0
self.started = now()
def admit(self, est_tokens, tool_name=None):
if self.tokens + est_tokens > self.limits.tokens:
raise BudgetExceeded("tokens")
if tool_name and self.tools + 1 > self.limits.tools:
raise BudgetExceeded("tools")
if now() - self.started > self.limits.wall_clock:
raise BudgetExceeded("wall_clock")
self.tokens += est_tokens
if tool_name:
self.tools += 1
برآوردی که به admit داده میشود عمداً محافظهکارانه است: هزینه پیشبینیشده مرحله بهعلاوه ذخیرهای برای یک تلاش مجدد. ذخیره همان چیزی است که سقف
توقف سخت در سقف درست اما بیظرافت است. طراحی بهتر نردبانی از حالتهای تخریبشده تعریف میکند که ارکستراتور با نزدیک شدن اجرا به محدودیتهایش از آن پایین میرود:

- کاهش مجموعه ابزار. ابزارهای اختیاری یا پرتأخیر را حذف کن، آنهایی را نگه دار که وظیفه بدونشان کامل نمیشود.
- حذف دورهای بازتاب. خودنقدی و راستیآزمایی را رد کن، کیفیت پایینتر پاسخ را بپذیر، و ثبت کن که اجرا تخریب شده است.
- شکست بسته. یک شکست ساختاریافته با مسیر جزئی پیوستشده برگردان، بهجای تلاش بیکران برای موفقیت.
نردبان پیشاپیش تعریف میشود چون لحظه اتمام بدترین زمان ممکن برای طراحی یک جایگزین است. یک اجرای تخریبشده که پاسخ جزئی قابل استفاده و یک پرچم واضح برمیگرداند، عملیاتی بسیار بهتر از اجرایی است که یا بیصدا بودجه را میسوزاند یا با هیچ چیز خاتمه مییابد.
انتساب
بودجهها تنها در صورتی تشخیصی هستند که هزینه انتساب یابد. هر اجرا را با یک کلاس وظیفه، یک شناسه مستأجر یا کاربر در صورت لزوم، و نقطه ورودی که آن را تولید کرده برچسب بزن. سپس هزینه را بر اساس برچسب تجمیع کن، نه بر اساس مدل. نمای مفید یک توزیع بهازای هر کلاس وظیفه است: میانه، دنباله، و نسبت بین آنها. کلاس وظیفهای که دنبالهاش یک مرتبه بزرگی بالای میانهاش است، آسیبشناسی حلقه دارد، و برچسب به شما میگوید کجا را نگاه کنید.
پیامدهای عملیاتی
ناهنجاریهای هزینه آسیبشناسی حلقه هستند. وقتی یک کلاس وظیفه ناگهان گرانتر میشود، غریزه این است که ناکارآمدی پرامپت را سرزنش کنیم. معمولاً پرامپت بدون تغییر است و حلقه تغییر کرده: یک ابزار شروع به برگرداندن خطاهایی کرده که تلاش مجدد را تحریک میکنند، یک برنامهریز شروع به پخششدگی گستردهتر کرده، یک دور بازتاب از همگرایی بازمانده. بررسی ناهنجاری باید با شکل مسیر شروع شود، نه متن پرامپت. توزیع تعداد مراحل و فراخوانیهای ابزار بهازای هر اجرا آسیبشناسی را سریعتر از هر دیف پرامپت شناسایی میکند.
بودجهها ارزیابی را قابل مقایسه میکنند. بدون یک کران هزینه در سطح اجرا، مقایسه بنچمارک بین دو طراحی عامل مقایسه نیست. طراحی گرانتر میتواند فقط با بیشتر تلاش کردن در نرخ موفقیت برنده شود. با بودجههای ثابت در همان سقفها، یک مسیر ارزانتر با موفقیت برابر یک نتیجه واقعی است، و یک مسیر گرانتر با موفقیت برابر یک پسرفت است. این مبادله صادقانه کل رویکرد است: بودجههای سخت گاهی اجرایی را قطع میکنند که با فضای بیشتر موفق میشد. این هزینه عمداً پرداخت میشود، در ازای سیستمی که بدترین رفتارش پیش از استقرار شناخته شده است نه اینکه روی فاکتور کشف شود. تیمهایی که نمیتوانند هیچ قطعی را بپذیرند باید سقفها را بالا بگذارند و از تخریب بهجای شکست استفاده کنند، اما باز هم باید آنها را بگذارند.
مهلتها بخشی از قرارداد هستند. سقف زمان دیواری فقط کنترل هزینه نیست؛ تضمین تأخیر برای هر چیزی است که منتظر عامل است. اجراهایی که از آن فراتر میروند باید بسته شکست بخورند با یک نتیجه جزئی، چون فراخوانیکنندهای که قبلاً تسلیم شده از یک موفقیت دیرهنگام سودی نمیبرد.
اول چه بسازیم
حداقل نسخه قابل اجرا کوچک است. یک دفتر کل روی ارکستراتور بگذار، توکنها، فراخوانیهای ابزار و زمان سپریشده را بهازای هر مسیر بشمار، سه سقف را اعمال کن، و هر اجرا را با یک کلاس وظیفه برچسب بزن. پیش از افزودن حالت دوم، یک حالت تخریبشده اضافه کن. توزیع را ابزارگذاری کن، نه میانگین را. نمای بهازای هر فراخوانی میتواند بهعنوان کمک اشکالزدایی باقی بماند، اما نباید چیزی باشد که بودجه به آن متصل است. بودجه را به اجرا متصل کن، و اجرا چیزی میشود که میتوانی بهرهبرداری کنی.
