اگر از مدلهای زبانی کوچک روی سختافزار شخصی استفاده میکنید، میدانید که اعتماد به آنها برای انتخاب ابزار درست از میان یک لیست طولانی، تقریباً غیرممکن است. مشکل اصلی نه در هوش مدل، بلکه در مکانیزم محدود کردن خروجی است؛ جایی که یک مدل ۱۴ میلیارد پارامتری نمیتواند تنها با دستورات متنی، تفاوت ابزارهای مشابه را درک کند. جان پل دالکی (Jan Paul Dahlke)، خالق پروژه Eris، دریافت که گلوگاه واقعی، روشی است که برای محدود کردن خروجی به کار میرود. او متوجه شد که نمیتوان از یک مدل محلی ۱۴ میلیاردی انتظار داشت که تنها با استفاده از نثر (Prose)، ابزار صحیح را از میان لیستی شامل ۵۰ گزینه انتخاب کند.
به نقل از مستندات پروژه، دالکی دریافت که تکیه بر پرامپتهای سیستمی برای رعایت فرمت JSON در مدلهای محلی، باعث اشغال حافظه VRAM و کاهش تمرکز مدل میشود. این رویکرد در سختافزارهای محلی شکست میخورد زیرا اسکیماهای بزرگ، بودجه محدود VRAM و پنجره متنی را میبلعند. وقتی پرامپت بیش از حد حجیم میشود، مدلهای کوچک تمرکز خود را از دست میدهند و شروع به توهم در آرگومانها میکنند یا قرارداد ابزار را بهطور کامل نادیده میگیرند. این وضعیت منجر به ایجاد یک شکاف قابلیت اطمینان میشود که نمیتوان آن را صرفاً با «پرامپتنویسی سختگیرانهتر» حل کرد.
همانطور که در تحلیلهای پیشین ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، کنترل دقیق روی لایه خروجی، کلید تبدیل یک مدل آزمایشی به یک ابزار کاربردی است. این چالش دقیقاً همان نقطهای است که در بررسیهای ما پیرامون جایگزینی زیرساختهای سختگیرانه با مهندسی پرامپت در عاملهای هوش به آن پرداختیم و دیدیم که چرا تکیه صرف بر دستورات متنی در سیستمهای پیچیده شکست میخورد. دالکی برای حل این چالش، مسیر تکاملی را طی کرد که او آن را به سه «زندگی» مجزا تقسیم میکند؛ مسیری که از پارس کردن ساده متن شروع شد و به یک لایه سیاستگذاری پیچیده رسید که بر انتخاب ابزار حاکم است.
سفر او با پروژهای به نام FUCKUP (مخفف First Universal Cybernetic-Kinetic Ultramicro-Programmer) آغاز شد. این نام از ابرکامپیوتر هاگبار سلین در سهگانه Illuminatus! گرفته شده بود و به عنوان یک گزارش وضعیت از کد یا یک «easterfuck» عمل میکرد. معماری این دوران که او آن را «عصر grep» مینامد، بر پایه پشتهای متشکل از اولاما (Ollama)، یک خزانه Obsidian, Redis و یک پل ارتباطی شبیه به Bash بنا شده بود. در آن دوران، مدل متنی مانند API: healthcheck چاپ میکرد و یک حلقه در شل با استفاده از Regex (عبارات منظم) آن را شناسایی میکرد، با یک لیست مجاز (Allowlist) تطبیق میداد و سپس آن را از طریق یک پل در میزبان اجرا میکرد.
این دوران واقعیِ grep بود: مدل متن را چاپ میکرد، یک حلقه خطوط API: را grep میکرد و نتیجه در نوبت بعدی به مدل بازگردانده میشد. اگرچه این روش برای دموها میکرد، اما برای استفاده در دنیای واقعی بیش از حد شکننده بود. او سپس تلاش کرد تا فراخوانی ابزار ساختاریافته را با استفاده از یک فورک اصلاحشده از یک ارکستراتور TypeScript در فرمت OpenAI function-call پیاده کند. این تلاش نیز شکست خورد زیرا مدلهای محلی که از طریق اولاما اجرا میشدند، اغلب در استریم کردن فراخوانیهای ابزار دچار خطا میشدند، بهجای دادههای ساختاریافته، متن خام برمیگرداندند یا در انتقال ابزارهای سفارشی از طریق پرامپت سیستمی ناتوان بودند.
درس آموخته شده روشن بود: قابلیت اطمینان باید از طریق محدود کردن نمونهگیر (Sampler) حاصل شود، نه با خواهش مؤدبانه از یک API استریم برای رفتار درست. این درک منجر به خلق Eris شد. دالکی بهجای قرار دادن تمام توصیفات ابزارها در ابتدای پرامپت به صورت متنی، به لاماسیپلاسپلاس (llama.cpp) نقل مکان کرد تا نمونهگیر را مستقیماً محدود کند و در هر نوبت، تنها ابزارهایی را به مدل ارائه دهد که برای آن لحظه اهمیت داشتند. او از رویکرد «بارگذاری پیشین» (Front-loading) بخش ساختاریافته به سمت رویکرد JIT (در لحظه) تغییر مسیر داد تا اطمینان حاصل کند مدل فقط قرارداد ابزار ضروری برای آن نوبت خاص را دریافت میکند.
قبل از رسیدن به سیستم فعلی، Eris از یک تطبیقدهنده لغوی (Lexical Matcher) استفاده میکرد که ورودی کاربر را به حروف کوچک تبدیل کرده و بررسیهای contains انجام میداد (مثلاً اگر کلمه «weather» در رشته بود، ابزار آبوهوا پیشنهاد میشد). اما این روش در برابر چهار فشار خاص شکست خورد:
- مترادفها: اگر کاربر میپرسید «بیرون چقدر گرم است؟» (how warm is it outside)، توکن «weather» بهطور کامل نادیده گرفته میشد.
- زبان: عبارات آلمانی مانند «wie spät ist es» (ساعت چند است) را فعال نمیکرد چون کلمه کلیدی «time» را نمییافت.
- اشارات: جملاتی مثل «دوباره همان کار را بکن» یا «آن را باز کن» هیچ کلمه کلیدی از هیچ لیستی نداشتند.
- تداخلات: کلمه «open» ممکن بود هم با «open the file» (باز کردن فایل) و هم با یک جمله شاعرانه مانند «you will open the way for future AIs» (راه را برای هوشهای مصنوعی آینده باز خواهی کرد) با اطمینان یکسانی تطبیق یابد.
دالکی اشاره میکند که تلاش برای وصله کردن این مشکلات با افزودن کلمات کلیدی بیشتر، منجر به ایجاد یک «تطبیقدهنده لغوی ۴۰۰ خطی میشود که هیچکس جرأت دست زدن به آن را ندارد» و باز هم اولین عبارت جدید کاربر را از دست میدهد.
برای حل این بحران، Eris یک پشته مسیریابی چهارلایه را پیاده کرد تا تضمین کند مدل فقط ابزارهایی را میبیند که واقعاً برای یک نوبت خاص به آنها نیاز دارد:
- لایه بردار معنایی (Embeddings Layer): سیستم از nomic-embed-text استفاده میکند تا ورودی کاربر را با بردارهای پیشمحاسبهشده برای هر ابزار مقایسه کند. در هنگام شروع،
ToolRouterمتن غنیشدهای را برای هر ابزار بردارسازی کرده و آنها را در حافظه نگه میدارد. در هر نوبت، شباهت کسینوسی (Cosine Similarity) بین «فکر» کاربر و بردارهای ابزار محاسبه میشود و مواردی که از آستانهtool_match_threshold(پیشفرض ۰.۵۰) عبور کنند، حفظ میشوند. - لایه سیاست (Policy Layer): این لایه به عنوان یک مکانیزم وتو یا گسترش عمل میکند. این لایه از «قفل شدن در GBNF» جلوگیری میکند؛ به این صورت که نتایج ضعیف تکنفره (امتیازات زیر ۰.۵۸) را تضعیف کرده و تساویهای نزدیک را به «خوشههای نزدیکی» (Affinity Clusters) تبدیل میکند (مثلاً گروهبندی ابزارهای ساعت، دستور کار و تقویم با هم). این لایه تضمین میکند که یک حدس تک و کماطمینان، مدل را بهطور ساختاری در یک پاسخ اشتباه قفل نکند.
- لایه پرامپت سبک (Slim Prompt): بهجای یک اسکیمای کامل JSON، مدل یک «نقشه عبارات» در قالب Markdown دریافت میکند که شامل توصیفات کوتاه و محرکهای رایج است. این کار باعث میشود پنجره متنی (Context Window) سبک بماند و از غرق شدن مدل در ۵۰ روش مختلف برای اشتباه کردن جلوگیری شود.
- لایه گرامر GBNF: در نهایت، لیست ابزارهای پیشنهاد شده به یک گرامر GBNF در llama.cpp تبدیل میشود. این لایه بهصورت فیزیکی هر توکنی را که منجر به فراخوانی نامعتبر ابزار شود ماسک (مسدود) میکند و توهم را از نظر ریاضی غیرممکن میسازد.
برای اینکه بردارها مؤثر باشند، دالکی لیستهای قدیمی کلمات کلیدی را به «عبارات مسیریابی» تبدیل کرد. بهجای استفاده از آنها برای بررسیهای contains ساده، اکنون این عبارات به عنوان متن بذر (Seed text) برای بردارها عمل میکنند.
ترتیب تفکیک (Resolution Order): سیستم متن بردار را از طریق enrich_for_routing تعیین میکند. ابتدا routing_hints را در توصیفگر TOML بررسی میکند (مثلاً agenda:remind_at از عبارات «به من یادآوری کن در» یا «به من یادآوری کن تا» استفاده میکند). اگر موجود نباشد، به سراغ جایگزین در routing_phrases.rs میرود (مثلاً clock:now از عبارات «ساعت چند است، زمان فعلی، منطقه زمانی، تاریخ اکنون، زمان محلی» و weather:current از «آبوهوای اکنون، دمای بیرون، آیا باران میبارد، بارش، آفتابی یا ابری، شرایط امروز، شرایط فعلی، هوا چطور است» استفاده میکند). اگر هر دو غایب باشند، به توصیف پیشفرض ابزار رجوع میکند.
گاردهای لغوی (Lexical Guards): توکنهایی با سیگنال بالا همچنان از بازنویسیهای سختافزاری (Hard-coded) استفاده میکنند. اگر has_web_lexical_intent یک URL یا دامنه را شناسایی کند، سیستم ابزار web:fetch را با امتیاز ۱.۰ تحمیل میکند. این نشانگر «با من بحث نکن» تضمین میکند که ابزار فارغ از امتیاز بردارساز، پیشنهاد شود. این گاردها تکامل یافتهاند؛ برای مثال، فعل تنها «open» دیگر باعث تطبیق نمیشود، اما عباراتی مانند «open page»، «open the website» یا «visit the page» باعث فعال شدن آن میشوند.
کفهای معنایی (Semantic Floors): برخی ابزارها برای جلوگیری از مثبتهای کاذب به آستانههای بالاتری نیاز دارند. ابزارهای Moltbook (یک سیستم اجتماعی فدرال) اغلب امتیازی بین ۰.۵۰ و ۰.۵۶ در برابر عبارات چت عمومی و بازیابی حافظه کسب میکنند. بنابراین، نتایج Moltbook زیر ۰.۵۸ حذف میشوند، مگر اینکه کاربر صراحتاً از کلمات «moltbook» یا «submolt» استفاده کند.
گروههای نزدیکی (Affinity Groups): وقتی نتایج برتر در محدوده match_margin (۰.۰۵) باشند، سیستم پیشنهاد را به یک خوشه دامنه مرتبط گسترش میدهد. برای مثال، نزدیکی «زمان» شامل agenda، clock و calendar است. گروههای دیگر شامل «وب» (web, news, wiki) و «دانش» (doc, vault, memory, media) هستند. این کار مانع از آن میشود که مدل مجبور شود بین دو قصد تقریباً یکسان یکی را انتخاب کند. تساویهای نزدیک اما نامرتبط (مثلاً ترکیبی از moltbook، وب و دیتابیس) به صورت یک زیرمجموعه رتبهبندی شده کسینوسی باقی میمانند تا از ریختن «محتوای نامفهوم» در گرامر جلوگیری شود.
گاردهای ورودی: برای صرفهجویی در منابع، یک گارد ورودی ارزانقیمت برای ورودیهای کوتاه، عملیات بردارسازی را برای سلام و احوالپرسی یا عبارات بسیار کوچک مانند «hey» یا «thanks» رد میکند، مگر اینکه حاوی توکن ابزار واضحی مانند URL یا «list my documents» باشند.
با وجود انتقال به مسیریابی معنایی، دالکی «پوششهای پیشنهادی» (Offer Overlays) را از طریق تابع apply_offer_overlays پیاده کرد تا جفتشدن منطقی ابزارها را تضمین کند. این جفتشدگیهای کاربردی بر اساس الگوهای واقعی استفاده است:
- جفتشدگی وب: اگر
web:fetchیاweb:searchپیشنهاد شود،web:findبهطور خودکار اضافه میشود تا مدل بتواند محتوای واکشی شده را جستوجو کند. - جفتشدگی دانش: اگر
doc:readپیشنهاد شود، سیستم آن را باvault:writeجفت میکند (به شرطی که وضعیت اجازه دهد)، زیرا خواندن یک سند معمولاً به نوشتن یک خلاصه منجر میشود. - قفل Moltbook: هنگامی که یک نوبت بهطور واضح شناسایی شود که مربوط به Moltbook است، کل خانواده ابزارهای Moltbook بهجای یک نقطه انتهایی (Endpoint) واحد پیشنهاد میشوند.
- حافظه دیالوگ: سیستم یک حافظه در سطح جلسه از آخرین ابزارهای موفق نگه میدارد. این اجازه میدهد دستوری مانند «آن ایمیل را پاک کن» پس از فراخوانی
mail:checkبا ابزارmail:deleteجفت شود، بهجای اینکه به عنوان یک «پاک کن» بدون مفعول خوانده شود. در این جفتشدگیها، Agenda برای مطابقت با الگوهای گفتار طبیعی، اولویت بیشتری نسبت به ایمیل و تقویم دارد.
یک حالت شکست بحرانی در طراحی عاملها، «انحراف» (Drift) است؛ جایی که پرامپت به مدل میگوید ابزاری در دسترس است، اما گرامر آن را منع میکند. این باعث میشود مدل «گیر کند» (Wedge) زیرا میخواهد توکنی را صادر کند که نمونهگیر آن را ماسک کرده است. Eris با استفاده از یک تابع واحد به نام slim_offered_tool_names برای تولید لیست ابزارهای پیشنهادی، از این اتفاق جلوگیری میکند. این لیست بهطور همزمان هم به مونتاژ پرامپت سبک و هم به گرامر GBNF تغذیه میشود.
پرامپت سبک شامل یک جدول Markdown (| Tool | Description (short) | Typical phrasing / triggers |) و تعاریف ابزارها با پارامترهای حذف شده است. مدل میبیند که vault:write وجود دارد و هدف کلی آن چیست، اما اسکیمای کامل آرگومانها را نمیبیند. اگر مدل بعداً آرگومانها را اشتباه وارد کند، یک «بازیابی اسکیمای دروازهبان» (Gatekeeper schema recovery) اسکیمای واقعی را در صورت نیاز ارائه میدهد.
این معماری تضمین میکند که مدل هرگز مجبور به فراخوانی «اشتباه» ابزار نشود. با محدود کردن انتخابها به یک مجموعه کوچک و از نظر ساختاری معتبر، یک مدل ۱۴ میلیاردی میتواند با قابلیت اطمینان یک سیستم بسیار بزرگتر عمل کند. گرامر GBNF پیشنهاد را از یک «توصیه» به یک «محدودیت سخت» تبدیل میکند؛ اگر مسیریاب برای یک نوبت چت لیستی خالی ارائه دهد، مدل نمیتواند توهم بزند و فراخوانی ابزار انجام دهد، زیرا گرامر آن را ممنوع کرده است.
این تغییر، فرض بنیادی طراحی عاملها را تغییر میدهد: مسیریابی یک مسئله رتبهبندی نیست، بلکه یک مسئله «اعتماد» است. هدف یافتن «بهترین» ابزار نیست، بلکه تعیین این است که چقدر به یک رتبهبندی اعتماد کنید پیش از آنکه اجازه دهید یک گرامر سخت، مدل را در یک انتخاب قفل کند.
توسعهدهندگانی که عاملهای محلی میسازند باید از قراردادهای ابزار مبتنی بر نثر فاصله گرفته و به سمت محدودیتهای سطح نمونهگیر حرکت کنند. این رویکرد در واقع پاسخی به نیاز برای ارزیابیهای دقیقتر است؛ همانطور که تستهای محلی کدنویسی اکنون در حال جایگزینی بنچمارکهای عمومی هستند تا عملکرد واقعی مدل در محیطهای بسته سنجیده شود. مرز بعدی برای این سیستمها احتمالاً ادغام مسیریابی پویا و آگاه از وضعیت (State-aware) خواهد بود که لایه سیاستگذاری را بر اساس حافظه بلندمدت جلسه تنظیم میکند.
گام بعدی شما
- اگر از llama.cpp استفاده میکنید، بررسی کنید که آیا میتوانید محدودیتهای GBNF را برای خروجیهای ساختاریافته جایگزین پرامپتهای طولانی کنید.
- برای کاهش هزینه استنتاج، لایهای از بردار معنایی را قبل از ارسال درخواست به مدل قرار دهید تا فقط ابزارهای مرتبط در پرامپت قرار گیرند.
- معماری Eris را برای مدیریت ابزارهای محلی در پروژههای خود بررسی کنید تا نرخ توهم را به صفر برسانید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو