پرش به محتوای اصلی
OpenAI

۲۲ بهمن ۱۴۰۴

مهندسی

مهندسی Harness: بهره‌گیری از Codex در دنیایی که عامل اولویت است

توسط Ryan Lopopolo، عضو کادر فنی

در حال بارگذاری…

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

این محصول دارای کاربران روزانه داخلی و آزمایش‌کنندگان آلفای خارجی است. عرضه می‌شود، مستقر می‌شود، خراب می‌شود و تعمیر می‌شود. آنچه متفاوت است این است که هر خط کد—منطق برنامه، آزمون‌ها، پیکربندی CI، مستندات، پایش‌پذیری، و ابزارهای داخلی—توسط Codex نوشته شده است. ما برآورد می‌کنیم که این را در حدود 1/10th زمانی که برای نوشتن کد به‌صورت دستی لازم بود ساخته‌ایم.

انسان‌ها هدایت می‌کنند. عامل‌ها اجرا می‌کنند.

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

این نوشته درباره آن چیزی است که با ساخت یک محصول کاملاً جدید با یک تیم از عامل‌ها آموختیم—چه چیزهایی خراب شد، چه چیزهایی انباشته شد، و چگونه می‌توانیم بیشترین بهره را از تنها منبع واقعاً کمیاب خود ببریم: زمان و توجه انسانی.

ما با یک محل نگهداری git خالی شروع کردیم

اولین commit به یک محل نگهداری خالی در اواخر August 2025 انجام شد.

اسکفولد اولیه—ساختار محل نگهداری، پیکربندی CI، قوانین قالب‌بندی، راه‌اندازی package manager، و چارچوب برنامه—توسط Codex CLI با استفاده از GPT‑5 و با هدایت مجموعه کوچکی از الگوهای موجود تولید شد. حتی فایل اولیه AGENTS.md که به عامل‌ها نحوه کار در محل نگهداری را هدایت می‌کند، خودش توسط Codex نوشته شده بود.

هیچ کد از پیش نوشته‌شده توسط انسان برای تثبیت سیستم وجود نداشت. از همان ابتدا، محل نگهداری توسط عامل شکل داده شد.

پنج ماه بعد، محل نگهداری شامل حدود یک میلیون خط کد در بخش‌های منطق برنامه، زیرساخت، ابزارها، مستندات و ابزارهای داخلی توسعه‌دهندگان است. در طول آن دوره، تقریباً 1,500 pull request با یک تیم کوچک متشکل از تنها سه مهندس که Codex را هدایت می‌کردند باز و ادغام شده است. این به میانگین توان عملیاتی 3.5 PRs به ازای هر مهندس در روز ترجمه می‌شود، و به‌طور شگفت‌آوری توان عملیاتی با رشد تیم به هفت مهندس افزایش یافته است. مهم‌تر از همه، این خروجی صرفاً برای خود خروجی نبود: این محصول به‌صورت داخلی توسط صدها کاربر، از جمله کاربران حرفه‌ای داخلی روزانه، مورد استفاده قرار گرفته است.

در طول فرایند توسعه، انسان‌ها هرگز مستقیماً هیچ کدی را مشارکت ندادند. این به یک فلسفه اصلی برای تیم تبدیل شد: بدون کد نوشته‌شده به‌صورت دستی.

بازتعریف نقش مهندس

نبود کدنویسی مستقیم توسط انسان نوع متفاوتی از کار مهندسی را معرفی کرد که بر سیستم‌ها، اسکفلد، و اهرم تمرکز دارد.

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

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

انسان‌ها تقریباً به‌طور کامل از طریق اعلان‌ها با سیستم تعامل می‌کنند: یک مهندس یک وظیفه را توصیف می‌کند، عامل را اجرا می‌کند و به آن اجازه می‌دهد یک Pull Request باز کند. برای رساندن یک PR به تکمیل، ما به Codex دستور می‌دهیم تغییرات خود را به‌صورت محلی بازبینی کند، بازبینی‌های اضافی و مشخص از عامل‌ها را هم به‌صورت محلی و هم در فضای ابری درخواست کند، به هر بازخورد داده‌شده توسط انسان یا عامل پاسخ دهد، و در یک حلقه تکرار کند تا زمانی که همه بازبین‌های عامل راضی شوند (عملاً این یک Ralph Wiggum Loop(در یک پنجره جدید باز می‌شود) است). Codex مستقیماً از ابزارهای استاندارد توسعه ما (gh، اسکریپت‌های محلی، و مهارت‌های تعبیه‌شده در محل نگهداری) برای جمع‌آوری زمینه استفاده می‌کند بدون اینکه انسان‌ها چیزی را در CLI کپی و پیست کنند.

انسان‌ها ممکن است pull request ها را بازبینی کنند، اما الزامی نیست. با گذشت زمان، ما تقریباً تمام تلاش بازبینی را به سمت انجام شدن عامل‌به‌عامل سوق داده‌ایم.

افزایش خوانایی برنامه

با افزایش توان عملیاتی کد، گلوگاه ما به ظرفیت QA انسانی تبدیل شد. از آنجا که محدودیت ثابت، زمان و توجه انسانی بوده است، ما تلاش کرده‌ایم با خوانا کردن مستقیم مواردی مانند رابط کاربری برنامه، لاگ‌ها، و معیارهای برنامه برای Codex قابلیت‌های بیشتری به عامل اضافه کنیم.

برای مثال، ما برنامه را به‌ازای هر git worktree قابل راه‌اندازی کردیم، تا Codex بتواند به‌ازای هر تغییر یک نمونه را اجرا و هدایت کند. ما همچنین Chrome DevTools Protocol را به runtime عامل متصل کردیم و مهارت‌هایی برای کار با DOM snapshotها، screenshotها، و navigation ایجاد کردیم. این امر Codex را قادر ساخت باگ‌ها را بازتولید کند، اصلاح‌ها را اعتبارسنجی کند، و مستقیماً درباره رفتار UI استدلال کند.

نموداری با عنوان «Codex اپلیکیشن را با Chrome DevTools MCP هدایت می‌کند تا کار خود را اعتبارسنجی کند.» Codex یک هدف را انتخاب می‌کند، وضعیت را پیش و پس از فعال‌سازی یک مسیر UI عکس‌برداری می‌کند، رویدادهای زمان اجرا را از طریق Chrome DevTools مشاهده می‌کند، اصلاحات را اعمال می‌کند، مجدداً راه‌اندازی می‌کند، و در یک حلقه تکرار اعتبارسنجی اجرا می‌کند تا زمانی که برنامه بدون خطا شود.

ما همین کار را برای ابزارهای پایش‌پذیری نیز انجام دادیم. لاگ‌ها، معیارها، و traceها از طریق یک پشته پایش‌پذیری محلی که برای هر worktree موقتی است در اختیار Codex قرار می‌گیرند. Codex روی نسخه‌ای کاملاً ایزوله از آن برنامه کار می‌کند—از جمله لاگ‌ها و معیارهای آن، که پس از تکمیل آن وظیفه حذف می‌شوند. عامل‌ها می‌توانند لاگ‌ها را با LogQL و معیارها را با PromQL جستجو کنند. با در دسترس بودن این زمینه، اعلان‌هایی مانند «اطمینان حاصل کن که راه‌اندازی سرویس در کمتر از 800ms تکمیل می‌شود» یا «هیچ span در این چهار سفر کاربری حیاتی از دو ثانیه تجاوز نمی‌کند» قابل انجام می‌شوند.

نموداری با عنوان «دادن یک پشته کامل مشاهده‌پذیری به Codex در توسعه محلی». یک اپلیکیشن گزارش‌ها، معیارها و ردگیری‌ها را به Vector ارسال می‌کند و Vector داده‌ها را به یک پشتهٔ مشاهده‌پذیری که شامل Victoria Logs، Metrics و Traces است توزیع می‌کند که هرکدام از طریق APIهای LogQL، PromQL یا TraceQL پرس‌وجو می‌شوند. Codex از این سیگنال‌ها برای پرس‌وجو، همبستگی و استدلال استفاده می‌کند، سپس اصلاحات را در پایگاه کد پیاده‌سازی می‌کند، برنامه را مجدداً راه‌اندازی می‌کند، سناریوهای اجرایی را دوباره اجرا می‌کند، مسیرهای رابط کاربری را آزمایش می‌کند و در یک حلقه بازخورد تکرار می‌کند.

ما به‌طور منظم مشاهده می‌کنیم که یک اجرای تکی Codex روی یک وظیفه واحد برای بیش از شش ساعت کار می‌کند (اغلب در حالی که انسان‌ها در خواب هستند).

ما دانش محل نگهداری را به سیستم مرجع تبدیل کردیم

مدیریت زمینه یکی از بزرگ‌ترین چالش‌ها در مؤثر ساختن عامل‌ها برای انجام وظایف بزرگ و پیچیده است. یکی از نخستین درس‌هایی که آموختیم ساده بود: به Codex یک نقشه بدهید، نه یک دفترچه راهنمای 1000 صفحه‌ای.

ما رویکرد «یک AGENTS.md(در یک پنجره جدید باز می‌شود) بزرگ» را امتحان کردیم. این رویکرد به شیوه‌های قابل پیش‌بینی شکست خورد:

  • زمینه یک منبع کمیاب است. یک فایل دستورالعمل غول‌پیکر، وظیفه، کد و مستندات مرتبط را تحت‌الشعاع قرار می‌دهد—بنابراین عامل یا محدودیت‌های کلیدی را از دست می‌دهد یا شروع به بهینه‌سازی برای محدودیت‌های نادرست می‌کند.
  • راهنمایی بیش از حد به بی‌راهنمایی تبدیل می‌شود. وقتی همه چیز «مهم» است، هیچ چیز مهم نیست. عامل‌ها در نهایت به‌جای پیمایش هدفمند، به‌صورت محلی تطبیق الگو انجام می‌دهند.
  • فوراً فرسوده می‌شود. یک راهنمای یکپارچه به گورستانی از قوانین منسوخ تبدیل می‌شود. عامل‌ها نمی‌توانند تشخیص دهند چه چیزی هنوز معتبر است، انسان‌ها نگهداری آن را متوقف می‌کنند، و فایل به‌طور بی‌سروصدا به یک دردسر جذاب تبدیل می‌شود.
  • تأیید آن دشوار است. یک توده واحد برای بررسی‌های مکانیکی (coverage, freshness, ownership, cross-links) مناسب نیست، بنابراین واگرایی اجتناب‌ناپذیر است.

بنابراین به‌جای اینکه AGENTS.md را به‌عنوان دانشنامه در نظر بگیریم، آن را فهرست مطالب در نظر می‌گیریم.

پایگاه دانش محل نگهداری در یک فهرست ساختاریافته docs/ قرار دارد که به‌عنوان سیستم مرجع در نظر گرفته می‌شود. یک AGENTS.md کوتاه (در حدود 100 خط) به زمینه تزریق می‌شود و با ارجاع‌هایی به منابع عمیق‌تر حقیقت در بخش‌های دیگر عمدتاً به‌عنوان یک نقشه عمل می‌کند.

متن ساده

1
AGENTS.md
2
ARCHITECTURE.md
3
docs/
4
├── design-docs/
5
│ ├── index.md
6
│ ├── core-beliefs.md
7
│ └── ...
8
├── exec-plans/
9
│ ├── active/
10
│ ├── completed/
11
│ └── tech-debt-tracker.md
12
├── generated/
13
│ └── db-schema.md
14
├── product-specs/
15
│ ├── index.md
16
│ ├── new-user-onboarding.md
17
│ └── ...
18
├── references/
19
│ ├── design-system-reference-llms.txt
20
│ ├── nixpacks-llms.txt
21
│ ├── uv-llms.txt
22
│ └── ...
23
├── DESIGN.md
24
├── FRONTEND.md
25
├── PLANS.md
26
├── PRODUCT_SENSE.md
27
├── QUALITY_SCORE.md
28
├── RELIABILITY.md
29
└── SECURITY.md

چیدمان محل نگهداری و ذخیره دانش درونی.

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

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

این امر افشای تدریجی را امکان‌پذیر می‌کند: عامل‌ها با یک نقطه ورود کوچک و پایدار شروع می‌کنند و به آن‌ها آموزش داده می‌شود که بعداً کجا را بررسی کنند، به‌جای اینکه از همان ابتدا دچار سردرگمی شوند.

ما این را به‌صورت مکانیکی اعمال می‌کنیم. لینترهای اختصاصی و وظایف CI تأیید می‌کنند که پایگاه دانش به‌روز، دارای پیوندهای متقابل و به‌درستی ساختاربندی شده است. یک عامل دوره‌ای «doc-gardening» برای مستندات منسوخ یا قدیمی که رفتار واقعی کد را منعکس نمی‌کنند اسکن می‌کند و pull request های اصلاحی را باز می‌کند.

هدف، خوانایی عامل است

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

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

از دیدگاه عامل، هر چیزی که در حین اجرا نتواند در همان زمینه به آن دسترسی پیدا کند، عملاً وجود ندارد. دانشی که در Google Docs، رشته‌های گفتگو یا در ذهن افراد وجود دارد، برای سیستم قابل دسترسی نیست. مصنوعات نسخه‌بندی‌شده و محلیِ محل نگهداری (e.g., code, markdown, schemas, executable plans) تمام چیزی است که می‌تواند ببیند.

نموداری با عنوان «محدودیت‌های دانش عامل: آنچه Codex نمی‌تواند ببیند وجود ندارد.» دانش Codex به‌صورت یک حباب محدود نمایش داده می‌شود. در پایین آن، نمونه‌هایی از دانش نادیدنی قرار دارند—Google Docs، پیام‌های Slack، و دانش ضمنی انسانی. فلش‌ها نشان می‌دهند که برای قابل مشاهده شدن این اطلاعات برای Codex، باید آن را به‌صورت markdown در پایگاه کد رمزگذاری کرد.

ما آموختیم که به مرور زمان باید زمینه بیشتری را به مخزن اضافه کنیم. آن گفت‌وگوی Slack که تیم را بر سر یک الگوی معماری هم‌راستا کرد؟ اگر برای عامل قابل کشف نباشد، به همان اندازه ناخوانا است که برای یک نیروی جدید که سه ماه بعد به تیم می‌پیوندد، ناشناخته خواهد بود.

دادن زمینه‌ی بیشتر به Codex به معنای سازمان‌دهی و ارائه اطلاعات صحیح است تا عامل بتواند بر اساس آن استدلال کند، به‌جای اینکه آن را با دستورالعمل‌های موردی و بداهه غرق کنیم. به همان شیوه‌ای که یک هم‌تیمی جدید را با اصول محصول، هنجارهای مهندسی، و فرهنگ تیم (شامل ترجیحات ایموجی) آشنا می‌کنید، دادن این اطلاعات به عامل به خروجی هم‌راستاتر منجر می‌شود.

این چارچوب بسیاری از موازنه‌ها را روشن کرد. ما وابستگی‌ها و انتزاع‌هایی را ترجیح دادیم که بتوان آن‌ها را به‌طور کامل درون‌مخزنی درونی‌سازی کرد و درباره‌شان استدلال کرد. فناوری‌هایی که اغلب «خسته‌کننده» توصیف می‌شوند، به دلیل ترکیب‌پذیری، پایداری api، و حضور در مجموعه آموزش، معمولاً برای عامل‌ها مدل‌سازی آسان‌تری دارند. در برخی موارد، ارزان‌تر بود که عامل زیرمجموعه‌هایی از قابلیت را دوباره پیاده‌سازی کند تا اینکه با رفتار بالادستی غیرشفاف از کتابخانه‌های عمومی کنار بیاید. برای مثال، به‌جای وارد کردن یک بسته به سبک p-limit عمومی، ابزار کمکی خودمان برای map-with-concurrency را پیاده‌سازی کردیم: این ابزار به‌طور تنگاتنگ با ابزارسازی ما در OpenTelemetry یکپارچه است، 100% پوشش آزمون دارد، و دقیقاً به همان شکلی رفتار می‌کند که runtime ما انتظار دارد.

کشیدن بخش‌های بیشتری از سیستم به شکلی که عامل بتواند مستقیماً آن را بررسی، اعتبارسنجی، و ویرایش کند اهرم بیشتری ایجاد می‌کند—نه فقط برای Codex، بلکه برای دیگر عامل‌ها (به‌عنوان مثال Aardvark) که روی همین پایگاه کد نیز کار می‌کنند.

اعمال معماری و سلیقه

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

عامل‌ها در محیط‌هایی با مرزهای سخت‌گیرانه و ساختار قابل پیش‌بینی(در یک پنجره جدید باز می‌شود) بیشترین اثربخشی را دارند، بنابراین ما برنامه را بر اساس یک مدل معماری سخت‌گیرانه ساختیم. هر دامنهٔ کسب‌وکار به مجموعه‌ای ثابت از لایه‌ها تقسیم می‌شود، با جهت‌های وابستگی که به‌طور سخت‌گیرانه اعتبارسنجی شده‌اند و مجموعه‌ای محدود از شاخه‌های مجاز. این محدودیت‌ها به‌صورت مکانیکی از طریق lintهای سفارشی (البته تولیدشده توسط Codex!) و آزمایش‌های ساختاری اعمال می‌شوند.

نمودار زیر این قاعده را نشان می‌دهد: درون هر دامنه کسب‌وکار (مثلاً تنظیمات اپلیکیشن)، کد فقط می‌تواند به‌صورت «رو به جلو» از طریق یک مجموعه ثابت از لایه‌ها وابسته باشد (Types → Config → Repo → Service → Runtime → UI). ملاحظات میانی(احراز هویت، کانکتورها، تله‌متری، پرچم‌های ویژگی) از طریق یک رابط صریح و واحد وارد می‌شوند: ارائه‌دهنده‌ها. هر چیز دیگری ممنوع است و به‌صورت مکانیکی اجرا می‌شود.

نموداری با عنوان «معماری دامنه لایه‌ای با مرزهای عرضی صریح.» در داخل دامنه منطق کسب‌وکار، ماژول‌ها عبارت‌اند از: Types → Config → Repo، و Providers → Service → Runtime → UI، با App Wiring + UI در پایین. یک ماژول Utils خارج از مرز قرار دارد و به Providers داده می‌دهد.

این همان نوع معماری است که معمولاً تا زمانی که صدها مهندس داشته باشید آن را به تعویق می‌اندازید. با عامل‌های کدنویسی، این یک پیش‌نیاز اولیه است: محدودیت‌ها همان چیزی هستند که امکان سرعت بدون فرسایش یا انحراف معماری را فراهم میک‌نند.

در عمل، ما این قواعد را با lintهای سفارشی و آزمون‌های ساختاری، به‌علاوه مجموعه کوچکی از «ثابت‌های سلیقه‌ای» اجرا می‌کنیم. برای مثال، ما به‌صورت ایستا لاگ‌گیری ساختاریافته، قراردادهای نام‌گذاری برای الگوها و نوع‌ها، محدودیت‌های اندازهٔ فایل، و الزامات قابلیت اطمینانِ خاص پلتفرم را با lint‌های سفارشی اعمال می‌کنیم. از آن‌جا که lintها سفارشی هستند، پیام‌های خطا را می‌نویسیم تا دستورالعمل‌های رفع مشکل را به زمینهٔ عامل تزریق کنیم.

در یک گردش کار انسان‌محور، این قواعد ممکن است وسواسی یا محدودکننده به نظر برسند. با عامل‌ها، آن‌ها به ضریب تبدیل می‌شوند: پس از کدگذاری، در همه‌جا به‌طور هم‌زمان اعمال می‌شوند.

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

کدی که در نتیجه تولید می‌شود همیشه با ترجیحات سبکیِ انسانی مطابقت ندارد، و این اشکالی ندارد. تا زمانی که خروجی صحیح، قابل نگه‌داری، و برای اجرای‌های بعدی عامل‌ها خوانا باشد، معیار لازم را برآورده می‌کند.

سلیقه انسانی به‌طور مداوم به سیستم بازخورد داده می‌شود. نظرات بازبینی، pull requestها برای بازآرایی، و باگ‌های کاربرمحور به‌عنوان به‌روزرسانی‌های مستندات ثبت می‌شوند یا مستقیماً در ابزارها کُدگذاری می‌شوند. هنگامی که مستندات کافی نیست، قاعده را به کد ارتقا می‌دهیم

توان عملیاتی فلسفه ادغام را تغییر می‌دهد

وقتی توان عملیاتی Codex افزایش یافت، بسیاری از هنجارهای مهندسی معمولی بی‌اثر یا حتی مضر شدند.

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

این در یک محیط با توان عملیاتی پایین غیرمسئولانه خواهد بود. اینجا، اغلب موازنه درستی است.

«تولیدشده توسط عامل» در واقع به چه معناست

هنگامی که می‌گوییم پایگاه کد توسط عامل‌های Codex تولید شده است، منظورمان همه‌چیز در پایگاه کد است.

عوامل موارد زیر را تولید می‌کنند:

  • کد محصول و آزمایش‌ها
  • پیکربندی CI و ابزارهای انتشار
  • ابزارهای داخلی توسعه‌دهندگان
  • مستندات و تاریخچهٔ طراحی
  • چارچوب‌های ارزیابی
  • نظرات بازبینی و پاسخ‌ها
  • اسکریپت‌هایی که خودِ محل نگهداری را مدیریت می‌کنند
  • فایل‌های تعریف داشبوردِ تولید

انسان‌ها همواره در چرخه باقی می‌مانند، اما در سطحی متفاوت از انتزاع نسبت به گذشته کار می‌کنند. ما کارها را اولویت‌بندی می‌کنیم، بازخورد کاربران را به معیارهای پذیرش تبدیل می‌کنیم، و نتایج را اعتبارسنجی می‌کنیم. وقتی عامل دچار مشکل می‌شود، آن را به‌عنوان یک سیگنال در نظر می‌گیریم: مشخص می‌کنیم چه چیزی کم است—ابزارها، نرده‌های حفاظتی، مستندات—و آن را به محل نگهداری بازمی‌گردانیم، همواره با این رویکرد که خودِ Codex اصلاح را بنویسد.

عامل‌ها مستقیماً از ابزارهای توسعه استاندارد ما استفاده می‌کنند. آن‌ها بازخورد بازبینی را دریافت می‌کنند، به‌صورت درون‌خطی پاسخ می‌دهند، به‌روزرسانی‌ها را ارسال می‌کنند و اغلب pull requestهای خود را squash و merge می‌کنند.

سطوح در حال افزایش خودمختاری

با کدگذاری مستقیم بخش‌های بیشتری از حلقه توسعه در سیستم—آزمایش، اعتبارسنجی، بازبینی، رسیدگی به بازخورد، و بازیابی—محل نگهداری اخیراً از یک آستانه معنادار عبور کرد که در آن Codex می‌تواند یک ویژگی جدید را به‌طور کامل هدایت کند.

با ارائه یک اعلان واحد، عامل اکنون می‌تواند:

  • وضعیت کنونی پایگاه کد را اعتبارسنجی کند
  • یک باگ گزارش‌شده را بازتولید کند
  • ویدئویی ضبط کند که خرابی را نشان دهد
  • یک اصلاح را پیاده‌سازی کند
  • اصلاح را با اجرای برنامه بررسی کند
  • یک ویدئوی دیگری ضبط کند که وضوح را نشان دهد
  • یک pull Request باز کند
  • به بازخورد عاملی و انسانی پاسخ دهد
  • خطاهای ساخت را شناسایی و رفع کند
  • تنها زمانی به یک انسان ارجاع دهد که نیاز به قضاوت باشد
  • تغییر را ادغام کند

این رفتار به‌شدت به ساختار و ابزارهای خاص این محل نگهداری وابسته است و نباید فرض کرد که بدون سرمایه‌گذاری مشابه قابل تعمیم است—دست‌کم، فعلاً نه.

آنتروپی و جمع‌آوری زباله

خودمختاری کامل عامل همچنین مشکلات جدیدی را به وجود می‌آورد. Codex الگوهایی را که از قبل در محل نگهداری وجود دارند—حتی الگوهای ناهموار یا غیربهینه—تکرار می‌کند. با گذشت زمان، این امر به‌ناچار به انحراف منجر می‌شود.

در ابتدا، انسان‌ها این مسئله را به‌صورت دستی حل می‌کردند. تیم ما قبلاً هر جمعه (20٪ از هفته) را صرف پاک‌سازی «آشغال‌های AI» می‌کرد. جای تعجب نبود که این رویکرد مقیاس‌پذیر نبود.

در عوض، ما شروع کردیم آنچه را «اصول طلایی» می‌نامیم مستقیماً در محل نگهداری کُد گذاری کرده و یک فرآیند پاک‌سازی دوره‌ای ایجاد کردیم. این اصول، قواعد مکانیکی و مبتنی بر دیدگاه هستند که پایگاه کد را برای اجرای‌های آیندهٔ عامل‌ها خوانا و منسجم نگه می‌دارند. برای مثال: (۱) ما بسته‌های کاربردیِ مشترک را به کمک ابزارهای دست‌ساز ترجیح می‌دهیم تا ثوابت متمرکز باقی بمانند، و (۲) داده‌ها را به سبک «YOLO» کاوش نمی‌کنیم—مرزها را اعتبارسنجی می‌کنیم یا به SDKهای نوع‌دار تکیه می‌کنیم تا عامل نتواند به‌طور تصادفی بر اساس ساختارهای حدسی چیزی بسازد. به‌طور منظم، ما مجموعه‌ای از وظایف پس‌زمینه Codex داریم که انحرافات را بررسی کرده، نمرات کیفی را به‌روزرسانی و pull request های هدفمند برای بازسازی کد باز می‌کند. بیشترِ این‌ها را می‌توان در کمتر از یک دقیقه بازبینی و به‌صورت خودکار ادغام نمود.

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

آنچه هنوز در حال یادگیری هستیم

این استراتژی تاکنون تا مرحله‌ی راه‌اندازی داخلی و پذیرش در OpenAI به‌خوبی عمل کرده است. ساخت یک محصول واقعی برای کاربران واقعی به ما کمک کرد تا سرمایه‌گذاری‌هایمان را در واقعیت منسجم کنیم و ما را به سمت نگهداری بلندمدت هدایت کند.

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

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

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

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

نویسنده

Ryan Lopopolo

قدردانی‌ها

با تشکر ویژه از Victor Zhu و Zach Brock که در این پست مشارکت داشتند، و همچنین از کل تیمی که این محصول جدید را ساختند.