صفحه ۵ از ۴۹، درس‌ها

درس 04. تقسیم دستورالعمل‌ها میان چند فایل

متنی ۱۰ دقیقه به‌روز شده در ۱۰ آبان ۱۴۰۵

در این صفحه
  1. چرخهٔ معیوب در ریشه
  2. مفاهیم اصلی
  3. معماری دستورالعمل‌ها
  4. چگونه تفکیک کنیم
  5. رویکرد OpenAI: فایل ورودی کوتاه و مستندات پیوندیافته
  6. نکات کلیدی
  7. منابع بیشتر
  8. تمرین‌ها

Code examples: code/ Practice project: Project 02. Agent-readable workspace

شما مهندسی هارنس (harness) را جدی گرفته‌اید — بسیار عالی است. یک فایل AGENTS.md ایجاد کردید و هر قاعده، محدودیت، و تجربهٔ آموخته‌شده‌ای را که به ذهنتان می‌رسید در آن قرار دادید. یک ماه بعد حجم فایل به 300 خط رسید، دو ماه بعد 450 خط، و سه ماه بعد 600 خط شد. سپس متوجه می‌شوید که عملکرد ایجنت (agent) در واقع رو به وخامت است: برای رفع یک باگ ساده، ایجنت مقادیر عظیمی از زمینه (context) را صرف پردازش دستورالعمل‌های نامربوط استقرار می‌کند؛ یک محدودیت امنیتی حیاتی که در خط 300 مدفون شده کاملاً نادیده گرفته می‌شود؛ و وجود سه قاعدهٔ متناقض در سبک کدنویسی باعث می‌شود ایجنت هر بار یکی از آن‌ها را به‌طور تصادفی برگزیند.

این همان دام «فایل دستورالعمل غول‌پیکر» است. همه‌چیز مفید به‌نظر می‌رسد، بنابراین همه را در آن می‌چپانید، و پیدا کردن یک قاعدهٔ مشخص به‌معنای زیرورو کردن کل فایل خواهد بود. شما 600 خط نوشته‌اید، اما تنها یک‌سوم آن با وظیفهٔ کنونی مرتبط است.

چرخهٔ معیوب در ریشه#

رایج‌ترین چرخهٔ معیوب این‌گونه رخ می‌دهد: ایجنت اشتباهی مرتکب می‌شود، شما می‌گویید «برای جلوگیری از این، یک قاعده اضافه کن»، آن را به AGENTS.md می‌افزایید، و موقتاً کار می‌کند. سپس ایجنت اشتباه متفاوتی انجام می‌دهد، بنابراین قاعدهٔ دیگری می‌افزایید. این روند آن‌قدر تکرار می‌شود تا فایل از کنترل خارج شده و باد کند.

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

بودجهٔ زمینه به‌سرعت بلعیده می‌شود. پنجرهٔ زمینهٔ ایجنت محدود است. فرض کنید ایجنت شما پنجره‌ای 200K توکنی دارد (استاندارد Claude). یک فایل دستورالعمل حجیم ممکن است 10 تا 20 هزار توکن را مصرف کند. شاید به‌نظر برسد هنوز فضای خالی زیادی باقی مانده است، اما یک وظیفهٔ پیچیده ممکن است نیاز به خواندن ده‌ها فایل منبع داشته باشد، خروجی اجرای ابزارها نیز زمینه را اشغال می‌کند، و تاریخچهٔ گفتگو پیوسته انباشته می‌شود. زمانی که ایجنت واقعاً نیاز به درک کد دارد، بودجه از قبل به پایان رسیده است.

گم‌شدن در میانه. مقالهٔ «Lost in the Middle» (لیو و همکاران، 2023) به‌روشنی نشان داد که مدل‌های زبانی بزرگ از اطلاعاتی که در میانهٔ متون طولانی قرار دارند، بسیار کمتر از اطلاعات ابتدا یا انتها استفاده می‌کنند. فایل AGENTS.md شما 600 خط است و در خط 300 آمده است: «تمام پرس‌وجوهای پایگاه داده باید از کوئری‌های پارامتری استفاده کنند» — این یک محدودیت امنیتی سفت‌وسخت است. اما در میانه دفن شده و ایجنت تقریباً به‌طور قطع آن را نادیده خواهد گرفت.

تعارض در اولویت‌ها. فایل، محدودیت‌های سفت‌وسخت غیرقابل‌مذاکره («هرگز از eval() استفاده نکن»)، دستورالعمل‌های مهم طراحی («ترجیح سبک تابعی»)، و یک تجربهٔ تاریخی خاص («هفتهٔ پیش نشت حافظهٔ وب‌سوکت رفع شد، مراقب الگوهای مشابه باش») را با هم مخلوط می‌کند. این سه قاعده سطوح اهمیت کاملاً متفاوتی دارند، اما در فایل کاملاً یکسان به‌نظر می‌رسند. ایجنت هیچ نشانهٔ قابل‌اعتمادی برای تشخیص اینکه کدام خط قرمز و کدام صرفاً یک پیشنهاد است ندارد.

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

انباشت تناقضات. دستورالعمل‌هایی که در زمان‌های مختلف اضافه شده‌اند شروع به نقض یکدیگر می‌کنند — یکی می‌گوید «از حالت سخت‌گیرانهٔ تایپ‌اسکریپت استفاده کن»، دیگری می‌گوید «برخی فایل‌های قدیمی مجاز به استفاده از any هستند». ایجنت هر بار به‌صورت تصادفی یکی را برمی‌گزیند.

مفاهیم اصلی#

  • بادکردن دستورالعمل‌ها (Instruction Bloat): هنگامی که یک فایل دستورالعمل 10 تا 15 درصد از پنجرهٔ زمینه را اشغال می‌کند، شروع به حذف بودجهٔ مورد نیاز برای خواندن کد و استدلال دربارهٔ وظیفه می‌نماید. یک فایل 600 خطی AGENTS.md ممکن است 10,000 تا 20,000 توکن مصرف کند — یعنی 8 تا 15 درصد از یک پنجرهٔ 128 هزار توکنی.
  • گم‌شدن در میانه (Lost in the Middle): اطلاعات در میانهٔ متون طولانی به‌راحتی نادیده گرفته می‌شوند. پژوهش سال 2023 لیو و همکاران نشان داد که مدل‌های زبانی بزرگ از اطلاعات میانه به‌مراتب کمتر از ابتدا یا انتها بهره می‌برند. یک محدودیت حیاتی در خط 300 از یک فایل 600 خطی، احتمال بسیار بالایی برای نادیده گرفته شدن دارد.
  • نسبت سیگنال به نویز دستورالعمل (Instruction SNR): نسبتی از دستورالعمل‌های موجود در یک فایل که به وظیفهٔ کنونی مرتبط هستند. مجبور شدن به خواندن 50 خط دستورالعمل استقرار هنگام رفع یک باگ — این یعنی SNR پایین.
  • فایل ورودی (Entry File): یک فایل ورودی کوتاه که هدفش هدایت ایجنت به سمت مستندات با جزئیات بیشتر است، نه اینکه همه‌چیز را خودش در بر بگیرد. 50 تا 200 خط کفایت می‌کند.
  • آشکارسازی پیش‌رونده (Progressive Disclosure): ابتدا اطلاعات کلی را ارائه دهید و جزئیات را در زمان نیاز آشکار سازید. طراحی یک هارنس خوب مانند طراحی یک رابط کاربری خوب است — همهٔ گزینه‌ها را یک‌باره جلوی کاربر نریزید.
  • ناتوانی در تشخیص اولویت: وقتی همهٔ دستورالعمل‌ها در قالب و مکانی یکسان ظاهر می‌شوند، ایجنت نمی‌تواند خطوط قرمز غیرقابل‌مذاکره را از توصیه‌ها و راهنماهای نرم تشخیص دهد.

معماری دستورالعمل‌ها#

flowchart LR
    Mono["One giant AGENTS.md"] --> MonoLoad["Even a small bug fix<br/>means reading all deploy rules and old notes"]
    MonoLoad --> MonoRisk["Critical rules buried in the middle<br/>easily missed"]

    Router["Short AGENTS.md"] --> Topics["Read API / DB / testing docs<br/>only when this task needs them"]
    Topics --> RoutedResult["More context left for code reading<br/>and verification"]
flowchart TB
    File["600-line instruction file"] --> Top["Top section<br/>quick start + hard constraints"]
    File --> Mid["Middle section<br/>security rule at line 300"]
    File --> Bot["Bottom section<br/>explicit end-of-file checklist"]
    Top --> Seen["High probability of recall"]
    Bot --> Seen
    Mid --> Missed["High probability of being diluted or ignored"]

چگونه تفکیک کنیم#

اصل اساسی: اطلاعات پرکاربرد را دم دست نگه دارید، اطلاعات گه‌گاه مورد نیاز را کنار بگذارید، و آنچه را هرگز به کار نمی‌آید با خود حمل نکنید.

فایل ورودی AGENTS.md در محدودهٔ 50 تا 200 خط باقی می‌ماند و تنها شامل ضروری‌ترین موارد است: مرور پروژه (یک یا دو جمله که مشخص کند پروژه چیست)، دستورات اجرای نخستین (make setup && make test)، محدودیت‌های سفت‌وسخت سراسری (حداکثر 15 قاعدهٔ غیرقابل‌مذاکره)، و پیوندهایی به اسناد موضوعی (یک خط توضیح به‌همراه شرط کاربرد).

# AGENTS.md

## Project Overview
Python 3.11 FastAPI backend, PostgreSQL 15 database.

## Quick Start
- Install: `make setup`
- Test: `make test`
- Full verification: `make check`

## Hard Constraints
- All APIs must use OAuth 2.0 authentication
- All database queries must use SQLAlchemy 2.0 syntax
- All PRs must pass pytest + mypy --strict + ruff check

## Topic Docs
- API Design Patterns (`docs/api-patterns.md`) — Required reading when adding endpoints
- Database Rules (`docs/database-rules.md`) — Required when modifying database operations
- Testing Standards (`docs/testing-standards.md`) — Reference when writing tests

هر سند موضوعی 50 تا 150 خط است، و بر اساس موضوع در دایرکتوری docs/ یا در کنار ماژول مربوطه سازماندهی می‌شود. ایجنت فقط در زمان نیاز آن‌ها را می‌خواند. این کار را مانند مکعب‌های بسته‌بندی چمدان در نظر بگیرید — لباس‌ها در یک بسته، لوازم بهداشتی در بسته‌ای دیگر، و شارژرها در سومی. پیدا کردن آنچه نیاز دارید مستلزم خالی کردن کل چمدان نیست.

برخی اطلاعات بهتر است مستقیماً در خود کد قرار گیرند — تعاریف تایپ‌ها، کامنت‌های اینترفیس‌ها، و توضیحات در فایل‌های پیکربندی. ایجنت هنگام خواندن کد به‌طور طبیعی آن‌ها را می‌بیند، بنابراین نیازی به تکرار آن‌ها در دستورالعمل‌ها نیست.

هر دستورالعمل باید منبع خود («چرا این قاعده افزوده شد؟»)، شرط کاربرد («چه زمانی به این قاعده نیاز است؟»)، و شرط انقضا («تحت چه شرایطی می‌توان این قاعده را حذف کرد؟») را مستند کند. به‌طور منظم بازبینی انجام دهید و ورودی‌های منسوخ، تکراری یا متناقض را حذف کنید. دستورالعمل‌ها را همان‌طور مدیریت کنید که وابستگی‌های کد را مدیریت می‌کنید — وابستگی‌های استفاده‌نشده باید حذف شوند، در غیر این صورت فقط سیستم را کند می‌کنند.

اگر قاعده‌ای حتماً باید در فایل ورودی باشد، آن را در ابتدا یا انتها بگذارید، هرگز در میانه قرار ندهید. اثر «گم‌شدن در میانه» به ما می‌گوید مدل‌های زبانی از اطلاعات دوسوی متن طولانی بسیار بهتر از مرکز آن بهره می‌برند. اما رویکرد بهتر این است که دستورالعمل‌ها را برای بارگذاری بر حسب تقاضا به اسناد موضوعی منتقل کنید.

هم OpenAI و هم Anthropic بر این شیوهٔ تفکیک صحه می‌گذارند. OpenAI می‌گوید فایل‌های ورودی باید «کوتاه و با ماهیت مسیریابی» باشند، در حالی که Anthropic می‌گوید اطلاعات کنترلی برای ایجنت‌های بلندمدت باید «موجز و با اولویت بالا» باشند. هر دو یک سخن می‌گویند: همه‌چیز را در یک فایل واحد نریزید.

رویکرد OpenAI: فایل ورودی کوتاه و مستندات پیوندیافته#

شرکت OpenAI گزارش می‌دهد که یک فایل واحد و بزرگ AGENTS.md زمینهٔ وظیفه را تحت‌الشعاع قرار می‌داد، اولویت‌ها را مبهم می‌ساخت، قواعد منسوخ را انباشته می‌کرد، و راستی‌آزمایی (verification) آن دشوار بود. تیم به‌جای آن از یک فایل ورودی حدوداً 100 خطی به‌عنوان نقشه‌ای به یک دایرکتوری ساختاریافته از اسناد استفاده کرد. لینترهای اختصاصی و بررسی‌های CI پایگاه دانش را نگهداری می‌کردند. این مقاله درصد موفقیت قبل و بعد وظایف یا انطباق امنیتی را برای این تغییر گزارش نمی‌کند. OpenAI: Harness engineering

فایده به محتوا و وظیفه بستگی دارد. مطالعه‌ای در دانشگاه ETH زوریخ نشان داد که فایل‌های زمینه در سطح مخزن به‌طور کلی موفقیت وظایف را در تنظیمات ارزیابی‌شده بهبود نبخشیدند و هزینهٔ استنتاج را بیش از 20% افزایش دادند. توصیهٔ آن پژوهش این است که نیازمندی‌های نوشته‌شده توسط انسان در حداقل ممکن نگه داشته شوند. یک فایل کوتاه‌تر تضمینی برای بهبود نیست؛ دستورالعمل‌ها را روی وظایفی که قرار است پشتیبانی کنند آزمایش کنید. ETH Zurich: Evaluating AGENTS.md

یک مطالعهٔ جفتی از gpt-5.2-codex روی 124 وظیفهٔ برگرفته از PR در 10 مخزن استفاده کرد و همان وظیفه و وضعیت مخزن را با و بدون AGENTS.md مقایسه نمود. جدول 1 گزارش می‌دهد که میانهٔ زمان اجرا از 98.57 ثانیه به 70.34 ثانیه کاهش یافته است (28.64% کمتر)، و میانهٔ توکن‌های خروجی از 2,925 به 2,440 کاهش یافته است (16.58% کمتر). وظایف حداکثر 100 خط را در حداکثر پنج فایل تغییر می‌دادند. این سنجه نشان‌دهندهٔ کارایی است، نه اثر تفکیک یک فایل بزرگ؛ درستی عملکردی کامل خارج از دامنهٔ (scope) آن پژوهش بوده است. Lulla et al., Table 1

نکات کلیدی#

  • «اضافه کردن یک قاعده» داروی تسکین کوتاه‌مدت و سمی بلندمدت است. پیش از افزودن هر قاعده، بیندیشید آیا جای آن در یک سند موضوعی است یا خیر.
  • فایل ورودی یک مسیریاب (router) است، نه یک دانشنامه. 50 تا 200 خط — فقط نمای کلی، خطوط قرمز، و پیوندها.
  • از اثر «گم‌شدن در میانه» بهره ببرید: اطلاعات مهم را در بالا یا پایین بگذارید، و موارد کم‌اهمیت‌تر را به اسناد موضوعی انتقال دهید.
  • بادکردن دستورالعمل‌ها را مانند بدهی فنی مدیریت کنید. بازبینی‌های منظم، و اختصاص منبع، شرط کاربرد، و شرط انقضا برای هر دستورالعمل.
  • پس از تفکیک، نسبت سیگنال به نویز بهبود می‌یابد و ایجنت بخش بیشتری از بودجهٔ زمینهٔ خود را به‌جای پردازش دستورالعمل‌های نامربوط، صرف وظیفهٔ اصلی می‌کند.

منابع بیشتر#

تمرین‌ها#

  1. بازبینی SNR: فایل دستورالعمل ورودی کنونی خود را بردارید و تمام مدخل‌های آن را فهرست کنید. 5 نوع وظیفهٔ رایج و متفاوت را انتخاب کرده و علامت بزنید آیا هر دستورالعمل با آن وظیفه مرتبط است یا خیر. مقدار SNR را برای هر وظیفه محاسبه نمایید. دستورالعمل‌هایی که برای اکثر وظایف نویز هستند باید به اسناد موضوعی منتقل شوند.

  2. بازآرایی بر اساس آشکارسازی پیش‌رونده: اگر فایل دستورالعملی با بیش از 300 خط دارید، آن را تفکیک کنید به: (الف) یک فایل ورودی زیر 100 خط، (ب) 3 تا 5 سند موضوعی. همان مجموعه وظایف (دست‌کم 5 مورد) را قبل و بعد از بازآرایی اجرا کرده و نرخ‌های موفقیت را مقایسه کنید.

  3. راستی‌آزمایی گم‌شدن در میانه: در یک فایل دستورالعمل طولانی، یک محدودیت حیاتی را به‌ترتیب در بالا، وسط و پایین قرار دهید و هر بار همان مجموعه وظایف را اجرا کنید (دست‌کم 5 اجرا برای هر موقعیت). ببینید آیا تفاوتی در نرخ پیروی وجود دارد یا خیر. شاید از قدرت اثر موقعیت شگفت‌زده شوید.