Ranap Memori yang Tersembunyi dalam Label Kemajuan
Pada satu petang di akhir September, ejen AI dalam ruang kerja seorang pengguna ranap dengan ralat kehabisan memori di tengah-tengah satu giliran. Sangkaan yang jelas, iaitu terlalu ramai sub-ejen berjalan serentak atau konteks yang membesar terlalu besar, kedua-duanya salah. Puncanya sebenar ialah satu label status: semasa model menstrim satu arahan shell yang besar beberapa aksara pada satu masa, kami menghantar semula keseluruhan arahan setakat ini sebagai label kemajuan pada setiap kepingan. Satu arahan 124 KB menjadi kira-kira 41,000 peristiwa dan kira-kira 690 MB rentetan dalam baris gilir.
Cara ejen menstrim kerjanya
Apabila anda membina di Mythex, ejen berjalan di dalam sandbox awan peribadi projek anda. Semasa model menulis, outputnya distrim kembali ke pelayar anda: teks muncul perkataan demi perkataan, dan apabila ia menjalankan alat, katakan arahan shell yang menulis fail, anda melihat label untuknya dikemas kini secara langsung, supaya anda tahu apa yang sedang dilakukannya.
Model menstrim dalam kepingan kecil. Dengan model yang kami gunakan, kepingan itu selalunya hanya tiga aksara panjangnya.
Hipotesis awal salah
Kerosakan itu kelihatan seperti masalah penskalaan, jadi kami bermula di situ.
- Sub-ejen selari? Giliran itu hanya menggunakan dua, setiap satu memegang kira-kira 1.5 MB keadaan. Tidak mencukupi.
- Jejak yang dikekalkan? Pengesanan kami menyimpan pokok larian dalam memori, tetapi ia jauh lebih kecil daripada timbunan memori ketika ranap.
Kedua-dua cerita itu munasabah, dan kedua-duanya mudah dipercayai. Tiada satu pun yang menghasilkan semula ranap itu. Pengajaran yang kami terus belajar semula: sesuatu hipotesis bukan punca sehingga ia boleh menghasilkan semula kegagalan itu.
Menghasilkan semula dengan sebenar
Kami membina sandbox sementara dengan had memori yang sama seperti pengeluaran, dan model palsu yang menstrim fail besar dalam kepingan tiga aksara yang realistik. Kami juga membuat pembaca di hujung soket lain bergerak perlahan, seperti rangkaian sebenar.
Itu berjaya. Timbunan memori meningkat dan proses itu mati dengan ralat yang sama.
Mekanismenya mudah setelah kami dapat memerhatikannya. Semasa model menulis arahan besar, dalam kes ini dokumen here yang menulis fail 124 KB, kod penstriman kami mengemas kini label alat pada setiap kepingan. Label itu bukan tiga aksara baharu; ia ialah keseluruhan arahan setakat ini. Maka peristiwa semakin bertambah: 3 aksara, kemudian 6, kemudian 9, ... sehingga 124 KB, kira-kira 41,000 kali. Soket tidak dapat menghantarnya secepat ia dihasilkan, jadi ia menumpuk dalam penimbal tulis sebagai rentetan, kira-kira 690 MB daripadanya.
Pembetulan
- Hadkan label. Label status hanya perlu menyatakan apa yang sedang berlaku. Kini ia dihadkan kepada 200 aksara, dan kami mengawal kekerapan kami mengimbas semula arahan separa.
- Hentikan penggabungan kuadratik. Menyambung kepingan yang distrim dengan penggabungan rentetan berulang ialah O(n²) untuk output besar. Kami beralih kepada pendekatan berasaskan ketulan yang menambah dalam masa linear.
Kemudian kami mencari apa-apa lagi yang boleh membesar tanpa had apabila aliran output yang banjir, dan mengehadkannya:
- Output arahan langsung yang ditunjukkan dalam sembang dikumpulkan dan dikekalkan kepada 8,000 aksara terakhir.
- Setiap baris peristiwa dihadkan kepada 4 MB.
- Penimbal main semula yang digunakan pelayar untuk mengejar selepas bersambung semula dihadkan kepada 8 MB bagi setiap projek.
- Pos semak lama dipangkas semasa giliran berjalan, dengan mengekalkan keadaan terbaru dan titik sauh yang diperlukan oleh giliran terdahulu.
Menguji banjir dengan jujur
Dua perkara menjadikan ujian ini lebih sukar daripada yang sepatutnya:
- Model sebenar tidak bekerjasama. Minta model mencetak fail yang sangat besar dan ia biasanya akan menolak, meringkaskan, atau menulisnya dengan lebih munasabah. Untuk menguji banjir, anda memerlukan model berskrip yang melakukan tepat apa yang anda suruh, berjalan melalui kod ejen yang sebenar.
- Skrip mesti berkelakuan seperti model. Model berskrip pertama kami menggunakan semula ID respons yang sama pada setiap balasan, jadi rangka kerja ejen menganggap setiap balasan sebagai penggantian yang sebelumnya dan menamatkan giliran lebih awal. Ia kelihatan seperti pepijat penyegaran UI. Ia bukan; ia ialah harness ujian yang menipu kami. Kami juga terpaksa menguatkuasakan had konteks sebenar model dalam skrip, jika tidak nombor memori tidak realistik.
Apa yang kami pelajari daripadanya
- UI penstriman memperbesar kesilapan kecil. Apa-apa yang dihantar "setiap ketulan" dihantar puluhan ribu kali. Hantar perbezaan (delta), atau hadkan muatan.
- Hadkan setiap penimbal yang melintasi sempadan perlahan. Soket, log main semula dan pos semak semuanya memerlukan had atas.
- Hasilkan semula sebelum membetulkan. Dua penjelasan pertama kami kedengaran betul dan salah.
Jika anda pernah melihat fail yang sangat panjang muncul dalam sembang Mythex baru-baru ini tanpa ejen terhenti, inilah sebahagian sebabnya.