فکر می‌کردم کار هوشمندانه‌ای انجام می‌دهم. یک تابع کمکی (helper function) نوشته بودم که دقیقاً سی درصد از پنجره بافت (context window) را به عنوان بودجه‌ی تفکر (thinking budget) برای خط لوله (pipeline) هوش مصنوعی ما رزرو می‌کرد. کد تمیز و قابل پیش‌بینی بود و روی Opus 4.5 به زیبایی کار می‌کرد. اما وقتی به Opus 4.8 سوئیچ کردم، تک‌تک درخواست‌ها با خطای 400 از کار افتادند. محاسبات توکن که با دقت طراحی کرده بودم، یک‌شبه تبدیل به زباله شد.

الگوی قدیمی ساده بود. شما یک مقدار برای budget_tokens تعیین می‌کردید و مدل تفکر خود را طوری مدیریت می‌کرد که در آن سقف محدود شود. اگر من یک بافت ۱۲۸ کیلوبایتی (128K context) تحویل می‌دادم، کد من تقریباً ۳۸,۰۰۰ توکن را برای استدلال کنار می‌گذاشت و بقیه را برای پاسخ باقی می‌گذاشت. این کار مسئولانه به نظر می‌رسید؛ مثل رعایت کردن محدودیت سرعت خودرو.

آن مدل دیگر وجود ندارد. نسخه‌های جدیدتر مانند Opus 4.7 و 4.8 از تفکر تطبیقی (adaptive thinking) استفاده می‌کنند. شما دیگر یک عدد انتخاب نمی‌کنید، بلکه در عوض، یک «پیچ تنظیم تلاش» (effort knob) را ارسال می‌کنید. این ممکن است فقط یک تغییر نام به نظر برسد، اما این دو کنترل با هم تفاوت‌های بنیادی دارند. budget_tokens یک سقف سخت برای میزان تفکر مدل تعیین می‌کرد، اما Effort (میزان تلاش) نحوه تفکر و عمل مدل را از همان ابتدا کنترل می‌کند. یکی مثل کنتور پمپ بنزین است و دیگری مثل نقشه‌ی موتور (engine map).

نگاشت میزان تلاش به کار واقعی

وقتی کنترل‌ها تغییر کردند، شهود قدیمی من دیگر کار نمی‌کرد. مجبور شدم دوباره یاد بگیرم که هر تنظیم در عمل چه چیزی را برای من می‌خرد. من تست‌هایی را روی ترافیک داخلی خودمان اجرا کردم تا بفهمم هر سطح از تلاش در عمل کجا قرار می‌گیرد.

طبقه‌بندی و مسیریابی (Classification and routing) تقریباً همیشه باید از تلاش کم (low) استفاده کنند. این کارها تصمیمات سریعی هستند. آیا این یک درخواست بازگشت وجه است یا یک سوال فروش؟ آیا این ورودیِ لاگ نیاز به ارجاع دارد؟ شما به یک تک‌گویی طولانی نیاز ندارید. تلاش کم، تأخیر (latency) را پایین نگه می‌دارد و هزینه را به حداقل می‌رساند.

بیشتر ترافیک اپلیکیشن، یعنی کارهای روزمره‌ای مثل خلاصه‌سازی، بازنویسی، پاسخ‌های پشتیبانی و استخراج محتوا، در بازه‌ی تلاش متوسط تا بالا (medium to high) قرار می‌گیرند. این نقطه تعادل است. مدل فضای کافی برای حل ابهامات واقعی پیدا می‌کند بدون اینکه برای کاری که نیاز به زنجیره تفکر طولانی ندارد، توکن‌های زیادی مصرف کند.

کدنویسی و حلقه‌های عامل‌محور (agentic loops) به تلاش بسیار بالا (xhigh) نیاز دارند. اینجاست که اشتباهات به صورت تصاعدی زیاد می‌شوند. اگر مدل در اولین دور از یک حلقه‌ی فراخوانی ابزار (tool-calling loop)، برنامه‌ی بدی بنویسد، سه مرحله‌ی بعدی را صرف جبران خسارت خواهد کرد. یا بدتر از آن، ابزارهای اشتباه را فراخوانی می‌کند، در پارامترها دچار توهم (hallucinate) می‌شود و کاربر را با یک گردش کار خراب تنها می‌گذارد. استدلال بهتر در همان ابتدا، از این مارپیچ اشتباه جلوگیری می‌کند.

وظایف حیاتی باید از حداکثر تلاش (max) بهره‌مند شوند. از این حالت برای همه چیز استفاده نکنید. آن را برای لحظاتی رزرو کنید که یک پاسخ اشتباه، هزینه‌ای بسیار بیشتر از هر صورت‌حساب توکنی دارد. تطبیق‌های مالی، بررسی‌های امنیتی، تصمیمات معماری و تریاژ پزشکی گزینه‌های مناسبی هستند. اگر یک خطا به این معناست که یک انسان باید ساعت‌ها برای باز کردن گره‌های آن کار کند، هزینه تفکر اضافی را بپردازید.

غافلگیری هزینه‌ها

این همان بخشی است که مدل ذهنی مرا به هم ریخت. من فرض می‌کردم که حداکثر تلاش (max effort) همیشه هزینه‌های مرا به شدت بالا می‌برد. در یک مرحله‌ی واحد، همین‌طور است؛ ردپای استدلال (reasoning trace) طولانی‌تر می‌شود. اما در وظایف عامل‌محور چند مرحله‌ای، کل هزینه اغلب کاهش یافت.

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

چگونه بدون از کار انداختن بقیه موارد، مهاجرت کنیم

اگر هنوز budget_tokens در کدهای خود دارید، این مسیر دقیق برای خروج است. از مراحل سه و پنج نگذرید. من این کار را کردم و تمام یک بعدازظهر را صرف عیب‌یابی (debugging) کردم.

در کد خود به دنبال budget_tokens بگردید. تمام موارد باید حذف شوند. این پارامتر در مدل‌های جدید مرده است و باعث خطای 400 می‌شود.

شیء بودجه را با یک بلوک تفکر تطبیقی جایگزین کنید. از thinking: { type: "adaptive" } استفاده کنید.

یک output_config با سطح تلاش مشخص برای هر فراخوانی اضافه کنید. اگر ترافیک شما ترکیبی است، این مورد را به یک مقدار پیش‌فرض جهانی واگذار نکنید. نقطه پایانیِ سبکِ طبقه‌بندی شما نباید به طور تصادفی همان تنظیمات تلاشِ عامل کدنویسی شما را به ارث ببرد. در محل فراخوانی، صریح عمل کنید.

تابع کمکی محاسبه بودجه خود را حذف کنید. می‌دانم، احتمالاً تست‌های واحد (unit tests) دارد. کد من داشت. اما الان دیگر فقط یک بار اضافی است. پلتفرم نیازی به محاسبات توکن شما ندارد. مدل خودش سرعت و روند کار را مدیریت می‌کند.

پارامترهای temperature ،top_p و top_k را حذف کنید. در مدل‌های Opus 4.7 و 4.8، این پارامترهای نمونه‌برداری (sampling) باعث خطای 400 می‌شوند. پلتفرم آن‌ها را از این نسل حذف کرده است. ترفندهای قدیمی شما برای تنظیم دما (temperature-tuning) در اینجا کاربردی ندارند و باقی گذاشتن آن‌ها باعث شکست بی‌صدای فرآیند مهاجرت شما خواهد شد.

هر مدل را به صورت جداگانه تست کنید. Opus 4.5 و 4.8 کاملاً با هم متفاوت هستند. تنظیماتی (config) که روی یکی کار می‌کند، لزوماً روی دیگری کار نخواهد کرد. اگر از چندین نسخه پشتیبانی می‌کنید، منطق خود را شاخه‌بندی کنید یا با آن‌ها به عنوان بک‌اندهای (backends) مجزا برخورد کنید.

رفع مشکل فریز شدن UI

یک رفتار در حالت استریمینگ (streaming) وجود دارد که اگر آن را مدیریت نکنید، کاربران شما را گیج خواهد کرد. در مدل‌های جدید، بلوک‌های تفکر (thinking blocks) استریم می‌شوند اما متن به طور پیش‌فرض خالی است. در رابط کاربری شما، این حالت شبیه به یک وقفه طولانی و ناخوشایند بدون پیشرفت قابل مشاهده به نظر می‌رسد. کاربران تصور می‌کنند که برنامه هنگ کرده است.

برای رفع این مشکل، مقدار thinking: { type: "adaptive", display: "summarized" } را ارسال کنید. این کار بدون ریختن جریان خامِ افکار در پنجره چت، یک نشانگر پیشرفت قابل مشاهده به شما می‌دهد. فرانت‌اند (frontend) شما پاسخگو باقی می‌ماند و کاربران متوجه می‌شوند که در پس‌زمینه اتفاقی در حال رخ دادن است.

درس واقعی

من یک لایه انتزاعی (abstraction layer) کامل بر پایه پارامتری ساختم که فروشنده هرگز قصد نداشت ماندگار باشد. من تنظیمات آن‌ها را در منطق خودم پیچیدم چون فکر می‌کردم موازنه (tradeoff) را بهتر از پلتفرم درک می‌کنم. اما اشتباه می‌کردم. تفکر تطبیقی (Adaptive thinking) گزینه بهتری است، زیرا مدل واقعاً تصمیم می‌گیرد چه زمانی نیاز به استدلال عمیق دارد و چه زمانی می‌تواند به راحتی پیش برود. اکنون کد من کوچک‌تر شده و نتایج دقیق‌تر شده‌اند. گاهی اوقات حرکت مهندسی درست این است که کدهای هوشمندانه را حذف کنید و اجازه دهید پلتفرم کار خودش را انجام دهد.

اگر می‌خواهید یادداشت‌های اصلی مهاجرت را بخوانید، می‌توانید آن‌ها را اینجا پیدا کنید. برای بحث‌های عملی بیشتر از این دست، به جامعه GyaanSetu AI در تلگرام بپیوندید.