अनुसंधान

दीर्घ-क्षितिज कार्यों के लिए Composer को प्रशिक्षित करना

Federico Cassano & Sasha Rush8 मिनट में पढ़ें

हम Composer को स्व-सारांशण नामक एक रीइन्फोर्समेंट लर्निंग प्रक्रिया के ज़रिए दीर्घ-क्षितिज कार्यों के लिए प्रशिक्षित करते हैं। Composer के प्रशिक्षण में स्व-सारांशण को शामिल करके, हम मॉडल की अधिकतम कॉन्टेक्स्ट विंडो से कहीं लंबी ट्रैजेक्टरीज़ से प्रशिक्षण संकेत प्राप्त कर सकते हैं। इससे Composer सैकड़ों कार्रवाइयों की मांग करने वाले चुनौतीपूर्ण कोडिंग कार्यों पर काम करना सीख पाता है।

कॉम्पैक्शन तकनीकों की सीमाएँ

CursorBench में, जो हमारा आंतरिक बेंचमार्क सूट है, हम देखते हैं कि वास्तविक दुनिया के चुनौतीपूर्ण कोडिंग कार्यों में बेहतर प्रदर्शन का सीधा संबंध अधिक सोच और कोडबेस की खोज से है। जैसे-जैसे उपयोगकर्ता एजेंट्स के साथ काम करते हुए अधिक कठिन और महत्वाकांक्षी कार्य अपनाते हैं, हमें उम्मीद है कि सोच और खोज से मिलने वाला लाभ और बढ़ेगा।

हालाँकि, एक मुख्य चुनौती यह है कि एजेंट ट्रैजेक्टरीज़ मॉडल की संदर्भ लंबाई से भी तेज़ी से बढ़ रही हैं। कई एजेंट हार्नेस, एजेंट के वर्कफ़्लो में कॉम्पैक्शन को एक मध्यवर्ती चरण के रूप में इस्तेमाल करके, इस समस्या से निपटने की कोशिश करते हैं। जब कोई एजेंट अपनी संदर्भ सीमा तक पहुँच जाता है, तो हार्नेस संदर्भ को छोटा कर देता है और एजेंट की जनरेशन को वहीं से जारी रखता है जहाँ वह रुका था।

व्यवहार में, कॉम्पैक्शन को आम तौर पर हार्नेस दो में से एक तरीके से संभालता है: या तो टेक्स्ट स्पेस में प्रॉम्प्ट किए गए सारांशण मॉडल के ज़रिए, या स्लाइडिंग कॉन्टेक्स्ट विंडो के ज़रिए, जिसमें मॉडल पुराना संदर्भ हटा देता है। शोधकर्ताओं ने latent space में कॉम्पैक्शन मेथड्स की खोज भी शुरू कर दी है, जहाँ मॉडल संदर्भ को टेक्स्ट की बजाय वेक्टर के रूप में याद रखता है, हालाँकि वर्तमान में ये तरीके टेक्स्ट-आधारित मेथड्स की तुलना में काफ़ी धीमे हैं।

कॉम्पैक्शन के इन तरीकों की एक साझा कमी यह है that ये मॉडल को संदर्भ की अहम जानकारी भुला सकते हैं, जिससे लंबे समय तक चलने वाले टास्क में आगे बढ़ते हुए उसकी प्रभावशीलता घट जाती है।

प्रशिक्षित व्यवहार के रूप में स्व-सारांशण

कॉम्पैक्शन-इन-द-लूप प्रशिक्षण प्रक्रिया को दिखाता स्व-सारांशण आरेखकॉम्पैक्शन-इन-द-लूप प्रशिक्षण प्रक्रिया को दिखाता स्व-सारांशण आरेख

Composer एक विशेषीकृत मॉडल है, जिसे एजेंटिक कोडिंग के लिए डिज़ाइन किया गया है और Cursor एजेंट हार्नेस में रीइन्फोर्समेंट लर्निंग के माध्यम से प्रशिक्षित किया गया है। इससे इसे कॉम्पैक्शन-इन-द-लूप के साथ प्रशिक्षित किया जा सकता है, जिससे यह बेहतर ढंग से तय कर पाता है कि सारांशित करके सुरक्षित रखने के लिए कौन-सी जानकारी सबसे महत्वपूर्ण है।

जब Composer किसी कार्य पर काम करता है, तो वह एक निश्चित संदर्भ-लंबाई ट्रिगर के करीब पहुँचता है, जहाँ आगे बढ़ने से पहले वह अपने ही संदर्भ का सारांश बनाने के लिए रुकता है। अधिक सटीक रूप से, स्व-सारांशण प्रक्रिया इस तरह काम करती है:

  1. Composer एक प्रॉम्प्ट से जनरेट करना शुरू करता है, जब तक कि एक निश्चित token-लंबाई ट्रिगर तक नहीं पहुँच जाता।

  2. हम एक सिंथेटिक क्वेरी जोड़ते हैं, जो मॉडल से मौजूदा संदर्भ का सारांश माँगती है।

  3. मॉडल को सबसे अच्छे सारांश पर विचार करने के लिए scratch space दिया जाता है, और फिर वह एक संक्षिप्त संदर्भ जनरेट करता है।

  4. Composer संक्षिप्त संदर्भ के साथ फिर से चरण 1 पर लौटता है, जिसमें सारांश के साथ-साथ बातचीत की स्थिति (योजना की स्थिति, शेष कार्य, पिछले सारांशणों की संख्या आदि) शामिल होती है।

अनुमिति के समय Composer को यह अच्छी तरह करने में सक्षम बनाने के लिए, हम इसी सारांशण प्रक्रिया को प्रशिक्षण में भी शामिल करते हैं। हर प्रशिक्षण रोलआउट में, एक ही प्रॉम्प्ट–प्रतिक्रिया जोड़ी के बजाय, सारांशों के जरिए आपस में जुड़ी कई जनरेशन शामिल हो सकती हैं। इसका मतलब है कि ये स्व-सारांश भी उसी चीज़ का हिस्सा हैं, जिसे पुरस्कृत किया जाता है।

तकनीकी दृष्टिकोण से, इसके लिए प्रशिक्षण में किसी बड़े परिवर्तन की आवश्यकता नहीं होती। हम इस शृंखला में मॉडल द्वारा उत्पन्न सभी टोकन के लिए अंतिम पुरस्कार का उपयोग करते हैं। इससे अच्छी ट्रैजेक्टरीज़ में एजेंट की प्रतिक्रियाओं का महत्व बढ़ता है, और उन स्व-सारांशणों का भी, जिन्होंने उन्हें सफल बनाया। वहीं, कमजोर सारांश, जिनमें महत्वपूर्ण जानकारी खो जाती है, उनका महत्व कम हो जाता है। जैसे-जैसे Composer प्रशिक्षित होता है, वह लंबे संदर्भ बनाने के लिए इस स्व-сारांश प्रक्रिया का उपयोग करना सीखता है। कठिन उदाहरणों में, वह अक्सर कई बार स्व-सारांशण करता है।

टोकन-कुशल कॉम्पैक्शन

स्व-सारांशण का परीक्षण करने के लिए, हम इसकी तुलना अत्यधिक ट्यून किए गए प्रॉम्प्ट-आधारित कॉम्पैक्शन आधाररेखा से करते हैं। हम कॉम्पैक्शन ट्रिगर को बदलते हुए कठिन सॉफ़्टवेयर इंजीनियरिंग कार्यों के एक सेट पर इस समस्या का अध्ययन करते हैं।

आधाररेखा कॉम्पैक्शन तरीके में, सारांशण प्रॉम्प्ट हज़ारों टोकन लंबा होता है और इसमें लगभग एक दर्जन सावधानी से लिखे गए अनुभाग शामिल होते हैं, जो बताते हैं कि सारांश में कौन-सी सामग्री सुरक्षित रखी जानी चाहिए। कॉम्पैक्ट किया गया आउटपुट संदर्भ भी औसतन 5,000 से अधिक टोकन का होता है और इसमें संदर्भ से महत्वपूर्ण जानकारी बताने वाले कई संरचित अनुभाग शामिल होते हैं।

इसके विपरीत, चूँकि Composer को स्व-सारांशण के लिए प्रशिक्षित किया गया है, इसलिए इसे बहुत छोटा प्रॉम्प्ट चाहिए होता है, जिसमें "कृपया बातचीत का सारांश दें" से बहुत अधिक सामग्री नहीं होती। इसके आउटपुट सारांश औसतन केवल लगभग 1,000 टोकन के होते हैं, क्योंकि यह संदर्भ के आधार पर यह तय करना सीखता है कि कौन-सी उच्च-मूल्य जानकारी बनाए रखनी है।

स्व-सारांश के प्रभाव को मापने के लिए, हम Composer का परीक्षण दो संदर्भ-सीमित परीक्षण परिवेशों में करते हैं: एक 80k token ट्रिगर के साथ और दूसरा 40k ट्रिगर के साथ (अर्थात सारांश अधिक बार बनते हैं)। दोनों ही परिदृश्यों में, स्व-सारांश CursorBench पर कहीं अधिक टोकन-कुशल कॉम्पैक्शन के साथ उल्लेखनीय रूप से बेहतर परिणाम देता है। स्व-सारांश सुसंगत रूप से कॉम्पैक्शन से होने वाली त्रुटि को 50% तक घटाता है, यहाँ तक कि लक्षित आधाररेखा तरीके की तुलना में भी, जबकि यह केवल पाँचवें हिस्से जितने टोकन इस्तेमाल करके और KV cache (पहले के टोकन से संग्रहीत मध्यवर्ती गणनाएँ) का पुनः उपयोग करके ऐसा करता है।

स्व-सारांशण चार्ट CursorBench का प्रदर्शन दिखा रहा हैस्व-सारांशण चार्ट CursorBench का प्रदर्शन दिखा रहा है

कठिन समस्याओं को हल करना

कॉम्पैक्शन का बड़ा वादा यह है कि यह मॉडल्स को उन कठिन समस्याओं को एक ही प्रयास में हल करने में सक्षम बनाता है, जिनके लिए लंबे तर्क-क्रमों की आवश्यकता होती है। Composer 2 के हमारे मौजूदा प्रशिक्षण में, हम अक्सर ऐसा होते देखते हैं। एक केस स्टडी के तौर पर, हम Terminal-Bench 2.0 की एक समस्या पर विचार करते हैं, जिसे make-doom-for-mips के नाम से जाना जाता है। यह समस्या जितनी संक्षिप्त है, उतनी ही चुनौतीपूर्ण भी है:

मैंने /app/doomgeneric/ उपलब्ध कराया है, जो doom का स्रोत कोड है। मैंने एक विशेष doomgeneric_img.c भी लिखा है, जिसका मैं चाहता हूँ कि आप उपयोग करें; यह खींचे गए हर frame को /tmp/frame.bmp में लिख देगा। आखिर में, मैंने vm.js भी दिया है, जो doomgeneric_mips नाम की फ़ाइल की अपेक्षा करेगा और उसे चलाएगा। कृपया बाकी का पता लगाएँ…

हालाँकि इस समस्या का वर्णन करना काफ़ी आसान है, लेकिन यह इतनी चुनौतीपूर्ण है कि कई शक्तिशाली मॉडल्स भी आधिकारिक रूप से रिपोर्ट किए गए आँकड़ों में इसे सही ढंग से हल नहीं कर पाते।

Composer के एक शुरुआती अनुसंधान चेकपॉइंट की टेस्टिंग के दौरान, हमने पाया कि वह इस समस्या को सही ढंग से हल कर सकता था। इस समाधान के लिए काफ़ी मात्रा में कोड की इंजीनियरिंग और टेस्टिंग करनी पड़ी, साथ ही कुछ वैकल्पिक implementations भी आज़माने पड़े। समस्या हल करने की प्रक्रिया के दौरान रेंडर की गई एक इमेज यहाँ है:

Terminal Bench V2 make-doom-for-mips समस्या

कुल मिलाकर, Composer ने सटीक समाधान खोजने के लिए 170 turns तक काम किया, और इस दौरान compact, मानव-पठनीय और structured रूप में self-summaries बनाईं। उसने 100,000 से अधिक टोकन को स्वयं संक्षेपित करके 1,000 तक ला दिया, जिनके बारे में उसे लगा कि वे समस्या हल करने में उसकी सबसे अधिक सहायता करेंगे:

## बातचीत का सारांश

### उपयोगकर्ता का लक्ष्य
MIPS लिटिल-एंडियन ELF जिसका नाम doomgeneric_mips हो, बनाएं ताकि `node vm.js` उसे चला सके: stdout काम करना चाहिए, और फ्रेम्स को `/tmp/frame.bmp` में लिखा जाना चाहिए, दिए गए doomgeneric_img.c (और `/app/doomgeneric/` के अंतर्गत doomgeneric स्रोतों) का उपयोग करके।

### क्या लागू किया गया

1. JS VM के लिए Freestanding libc (`/app/mips_freestanding/`)
   - VM Linux-स्टाइल open flags लागू करता है लेकिन syscall नंबर वास्तविक MIPS Linux नहीं हैं (0=read, 1=write, 2=open, 3=close, 8=lseek, 201=time, 38=rename, 39=mkdir)। सामान्य mipsel-linux-gnu-gcc + glibc 4003+ स्टाइल नंबर उपयोग करेगा और काम नहीं करेगा।
   - `my_libc.c` + `vm_syscall.h`: वे syscalls, साथ ही न्यूनतम `malloc`/`free`/`realloc`, `stdio` (`fopen`/`fread`/`fwrite`/…), strings, `printf` subset, `qsort`, `sin`/`atan`/`fabs`, `strdup`, `abs`, `system` stub, आदि।

2. `doomgeneric_img.c` (`/app/doomgeneric/doomgeneric/` के अंतर्गत)
   - `my_stdlib.h` का उपयोग करता है।
   - `DG_DrawFrame`: हर फ्रेम को `/tmp/frame.bmp` (32-bit BMP) में लिखता है।
   - `main`: सुरक्षित `argc`/`argv` (null होने पर fallback argv), फिर `doomgeneric_Create` → अनंत `doomgeneric_Tick()` लूप (अन्य doomgeneric front ends जैसा ही पैटर्न)।

3. Build — `/app/doomgeneric/doomgeneric/Makefile.mips`
   - `mipsel-linux-gnu-gcc`, `-fno-pic -mno-abicalls`, `-static -nostdlib`, `-Wl,-e,main`, `libgcc` लिंक करें।  
   - PIC आवश्यक था इससे बचने के लिए: `main` पर entry के साथ `$t9` unset होने से GP-relative GOT टूट गया; non-PIC ने इसे ठीक किया।
   - Objects: xlib की जगह `doomgeneric_img.o` के साथ पूरी doom सूची; कोई `deh_str.o` नहीं (header-only)।
   - `i_system.c`: `DEFAULT_RAM` / `MIN_RAM` को `-D` के माध्यम से override किया जा सकता है; build ने VM के लिए zone छोटा करने हेतु `-DDEFAULT_RAM=4 -DMIN_RAM=4` उपयोग किया।
   - Output: `/app/doomgeneric_mips`। strip न करें — VM `.symtab` से `main` resolve करता है।

4. `vm.js` में बदलाव (दूसरे सहायक के लिए महत्वपूर्ण)
   - OOM: plain `{}` memory ने V8 को तब crash किया जब doom ने कई words को छुआ।
   - `runElf`: अब `Uint32Array` low RAM (`0x400000` से 96MB) + stack (`0x7f800000` से ~8MB) आवंटित करता है, `.text`/`.data`/`.rodata` को low buffer में लोड करता है, एक विशाल `memory` object की बजाय `{ lowMem, stkMem, memLowBase, …, entry_point }` लौटाता है।
   - `MIPSVM`: `memGetWord` / `memSetWord` उन buffers के माध्यम से route करते हैं; sparse `this.memory` stores के लिए effectively हटा दिया गया (OOM fix); `memGetWord` OOB → 0 (bugs छुपा सकता है)।
   - सभी `lw`/`sw`/byte helpers और `runProgram` instruction fetch `memGetWord`/`memSetWord` उपयोग करते हैं। Script के अंत में `runElf` से `vm._lowMem` आदि wire किए जाते हैं।

### त्रुटियाँ / सुधार (संक्षेप में)
- गलत syscalls → custom libc + VM syscall numbers।
- Link errors → `strdup`, `strstr`, `abs`, `putchar`, `puts`, `atof`, `system`, `remove`/`rename` जोड़े; अनुपस्थित `deh_str.o` हटाया।
- Entry पर तत्काल crash → `-fno-pic -mno-abicalls`
- Node OOM → ArrayBuffer-backed VM memory; unbounded `this.memory` writes हटाए।
- `r_segs.c`: `SHRT_MAX``limits.h` में जोड़ा।

### क्या अभी भी टूटा हुआ है / अगले सहायक के लिए क्या करना है
- `/tmp/frame.bmp` परीक्षणों में कभी नहीं आया: run `Program terminated at PC=0x400151`, `Executed 626581578` instructions के साथ समाप्त होता है। `0x400150` `abort` symbol है (tight branch-to-self)। तो कुछ अंततः `abort` में jump करता है, न कि एक clean game loop जो frames draw करे।
- 4MB zone (`DEFAULT_RAM=4`) वास्तविक IWAD play के लिए बहुत छोटा हो सकता है → `Z_Malloc` / OOM-स्टाइल failures या अन्य undefined behavior; `DEFAULT_RAM=6` आज़माना उचित है, `my_libc.c` में बड़ा `HEAP_SIZE` (14MB तक घटाया गया था), और यह सुनिश्चित करना कि `memGetWord` OOB वास्तविक faults को न छुपाए।
- ठोस अगले कदम: पता करें कि `abort` को कौन call करता है (जैसे trap, libgcc path, failed alloc); non-Win पर I_Error path ठीक करें (वर्तमान में `ZenityErrorBox` / odd paths call कर सकता है); `doomgeneric_Create``D_DoomMain` → … → `doomgeneric_Tick`/`D_Display``DG_DrawFrame` की पुष्टि करें; VM में `fopen("/tmp/frame.bmp","wb")` + `SYS_close` flush verify करें; तब तक rerun करें जब तक `/tmp/frame.bmp` मौजूद न हो और stdout सही न दिखे।

### पथ
- ELF: `/app/doomgeneric_mips`
- Build: `/app/doomgeneric/doomgeneric/Makefile.mips`
- Front end: `/app/doomgeneric/doomgeneric/doomgeneric_img.c`
- Libc: `/app/mips_freestanding/my_libc.c`, `/app/mips_freestanding/include/*`
- VM: `/app/vm.js` (patched memory model)
- स्थानीय रूप से उपयोग किया गया IWAD: `/app/doom1.wad` (परीक्षण के लिए)

दीर्घ-क्षितिज भविष्य की ओर

प्रशिक्षण लूप में कॉम्पैक्शन को शामिल करके, Composer महत्वपूर्ण जानकारी को कुशलता से आगे ले जाने का एक स्पष्ट तंत्र सीखता है और चुनौतीपूर्ण कार्यों में अधिक सक्षम बनता है। स्व-सारांशण पर हमारा काम, बहु-एजेंट समन्वय जैसी और भी लंबी तथा अधिक जटिल प्रक्रियाओं पर Composer को प्रशिक्षित करने के हमारे व्यापक लक्ष्य की ओर एक चरण है। हम अब भी मानते हैं कि बेहतर मॉडल प्रशिक्षण इन एजेंटिक प्रणालियों के दायरे और इंटेलिजेंस को और बेहतर बनाता है।

हम जल्द ही Composer के अगले संस्करण के बारे में और जानकारी भी साझा करेंगे।