प्रोग्रेस लेबलमध्ये लपलेला Out-of-Memory क्रॅश
सप्टेंबरच्या शेवटी एका संध्याकाळी, एका वापरकर्त्याच्या workspace मधील AI agent turn च्या मध्यात out-of-memory error ने क्रॅश झाला. उघड संशयित — एकाच वेळी खूप sub-agents चालणे, किंवा खूप मोठा झालेला context — दोन्ही चुकीचे होते. खरे कारण एक status लेबल होते: मॉडेल एक मोठी shell command काही अक्षरांच्या तुकड्यांत stream करत असताना, आम्ही प्रत्येक तुकड्यावर आतापर्यंतची संपूर्ण command progress लेबल म्हणून पुन्हा पाठवत होतो. एक 124 KB command सुमारे 41,000 events बनली आणि सुमारे 690 MB queued strings.
Agent आपले काम कसे stream करतो
Mythex वर बांधताना agent तुमच्या प्रोजेक्टच्या खासगी cloud sandbox मध्ये चालतो. मॉडेल लिहिताना, त्याचे आउटपुट तुमच्या browser ला stream होते: मजकूर शब्दाशब्दाने दिसतो, आणि तो tool चालवतो — उदाहरणार्थ फाइल लिहिणारी shell command — तेव्हा त्याचे लेबल लाइव्ह अपडेट होते, त्यामुळे तो काय करतोय ते तुम्हाला कळते.
मॉडेल लहान तुकड्यांत stream करते. आम्ही वापरत असलेल्या मॉडेलसह ते तुकडे अनेकदा फक्त तीन अक्षरे लांब असायचे.
पहिले अंदाज चुकीचे होते
क्रॅश स्केलिंगची समस्या दिसत होता, म्हणून आम्ही तिथून सुरुवात केली.
- समांतर sub-agents? Turn मध्ये फक्त दोन वापरले होते, प्रत्येकाकडे सुमारे 1.5 MB state. पुरेसे नव्हते.
- Retained traces? आमच्या tracing मध्ये run tree मेमरीत ठेवला जात होता, पण तो क्रॅशच्या वेळच्या heap च्या जवळपासही नव्हता.
दोन्ही कथा विश्वासार्ह वाटत होत्या, आणि दोन्ही विश्वास ठेवायला स्वस्त होत्या. दोन्हींनी अपयश पुन्हा घडवले नाही. आम्ही सतत पुन्हा शिकतो तो धडा: अपयश पुन्हा घडत नाही तोपर्यंत गृहीतक हे कारण नसते.
खऱ्या अर्थाने पुन्हा घडवणे
आम्ही उत्पादनाप्रमाणेच memory मर्यादा असलेली एक तात्पुरती sandbox बनवली आणि एक बनावट मॉडेल जे मोठी फाइल वास्तववादी तीन-अक्षरी तुकड्यांत stream करत होते. पलीकडच्या बाजूचा reader एखाद्या खऱ्या network सारखा मंद केला.
तेच घडले. Heap वाढत गेला आणि process त्याच error सह मरण पावला.
एकदा आम्ही ते पाहू शकल्यावर यंत्रणा साधी होती. मॉडेल एक मोठी command लिहित असताना — या प्रकरणात 124 KB फाइल लिहिणारा heredoc — आमचा streaming कोड प्रत्येक तुकड्यावर tool चे लेबल अपडेट करत होता. लेबल नवीन तीन अक्षरे नव्हते; ते आतापर्यंतची संपूर्ण command होते. त्यामुळे events वाढत गेले: 3 अक्षरे, मग 6, मग 9, … 124 KB पर्यंत, सुमारे 41,000 वेळा. Socket ते तितक्या वेगाने पाठवू शकत नव्हता जितक्या वेगाने ते तयार होत होते, म्हणून ते त्याच्या write buffer मध्ये strings म्हणून साचत गेले — सुमारे 690 MB.
उपाय
- लेबल मर्यादित करा. Status लेबलला फक्त काय चालले आहे ते सांगणे पुरेसे असते. ते आता 200 अक्षरांपर्यंत मर्यादित आहे, आणि आंशिक command पुन्हा स्कॅन करण्याची वारंवारता आम्ही throttle केली आहे.
- Quadratic concatenation थांबवा. Streamed तुकडे पुनरावृत्त string concatenation ने जोडणे मोठ्या आउटपुटसाठी O(n²) आहे. आम्ही chunk-आधारित पद्धतीकडे वळलो जी linear वेळेत जोडते.
त्यानंतर आम्ही बाउंड न होता वाढू शकणारे इतर काहीही शोधले आणि ते मर्यादित केले:
- Chat मध्ये दाखवलेले live command output batch केले जाते आणि शेवटच्या 8,000 अक्षरांपर्यंत ठेवले जाते.
- वैयक्तिक event ओळी 4 MB पर्यंत मर्यादित.
- ब्राउझर पुन्हा connect झाल्यावर पकडण्यासाठी वापरला जाणारा replay buffer प्रति प्रोजेक्ट 8 MB पर्यंत मर्यादित.
- जुने checkpoints turn सोबत छाटले जातात, नवीनतम state आणि आधीच्या turns ना लागणारे anchors ठेवून.
Floods ची प्रामाणिक चाचणी
दोन गोष्टींमुळे हे अपेक्षेपेक्षा अवघड झाले:
- खरे मॉडेल सहकार्य करत नाहीत. प्रचंड फाइल छापायला सांगितले तर मॉडेल सहसा नकार देते, सारांश देते, किंवा अधिक विवेकाने लिहिते. Floods चाचणी करण्यासाठी तुम्हाला एक scripted मॉडेल लागते जे तुम्ही सांगाल तेच करते, खऱ्या agent कोडमधून चालत.
- Scripts ना मॉडेलसारखे वागावे लागते. आमच्या पहिल्या scripted मॉडेलने प्रत्येक उत्तरावर एकच response ID वापरला, त्यामुळे agent framework ने प्रत्येक उत्तराला मागील उत्तराची जागा घेणारे मानले आणि turns लवकर संपवले. ते UI refresh bug सारखे दिसत होते. तसे नव्हते — ती चाचणी harness खोटे बोलत होती. Script मध्ये मॉडेलची खरी context मर्यादा लागू करावी लागली, नाहीतर memory आकडे अवास्तव होते.
आम्ही काय शिकलो
- Streaming UIs छोट्या चुका गुणित करतात. "प्रति chunk" पाठवलेले काहीही हजारो वेळा पाठवले जाते. Deltas पाठवा, किंवा payload मर्यादित करा.
- हळू सीमा ओलांडणारा प्रत्येक buffer बाउंड करा. Sockets, replay logs आणि checkpoints ना सर्वांना वरची मर्यादा हवी.
- दुरुस्तीपूर्वी पुन्हा घडवा. आमची पहिली दोन स्पष्टीकरणे बरोबर वाटत होती आणि चुकीची होती.
अलीकडे Mythex चॅटमध्ये एखादी खूप मोठी फाइल agent न अडखळता दिसली असेल, तर त्यामागचे हे एक कारण आहे.