Blog

Menjaga Giliran Agen yang Berat Gambar Tetap dalam Memori

Sebuah giliran agen di produksi kehabisan memori pada 952 MB saat memotong produk dari enam pindaian katalog dan memeriksa potongannya. Penyebabnya bukan satu kebocoran, melainkan tiga. Setiap panggilan ke model mengirim ulang gambar giliran itu dalam ukuran penuh; library yang kami pakai untuk memanggil model menyimpan setiap permintaan hidup sampai giliran selesai; dan tracing dari framework agen menyimpan input setiap panggilan, termasuk gambarnya, sepanjang giliran. Ketiganya sudah kami perbaiki: gambar diperkecil sebelum dikirim, dan gambar setiap panggilan dilepas segera setelah panggilan itu selesai.

Cara agen melihat gambar

Saat Anda membangun di Mythex, agen bekerja di sandbox cloud proyek Anda. Ia bisa melihat gambar, seperti screenshot yang Anda lampirkan, mockup, file di proyek Anda, atau gambar yang baru ia hasilkan sendiri, dengan mengirimkannya ke model bersama percakapan.

Giliran adalah semua yang dilakukan agen sebagai respons terhadap satu pesan dari Anda. Dalam satu giliran, agen memanggil model berkali-kali: berpikir, menjalankan tool, melihat hasilnya, berpikir lagi. Setiap panggilan itu mengirim percakapan sejauh ini, dan itu termasuk gambar-gambar giliran tersebut, yang dikodekan sebagai teks (base64, yang membuatnya sekitar sepertiga lebih besar).

Giliran yang crash itu sebenarnya melakukan sesuatu yang wajar. Ia mengambil enam pindaian katalog, masing-masing sekitar 2,4 MB, memotong produk satu per satu dari pindaian itu, dan terus membaca kembali potongannya untuk memeriksa. Itu banyak panggilan model, dan setiap panggilan membawa beberapa gambar besar.

Penyebab 1: setiap panggilan mengirim ulang gambar ukuran penuh

Setiap panggilan model menyusun ulang badan permintaannya dengan gambar giliran dalam ukuran penuh, sekitar 20 MB base64 per panggilan. Badan itu dibangun sebagai satu string di memori agen, sehingga setiap panggilan mengalokasikan lagi sekitar 20 MB.

Mengirim ukuran penuh bahkan tidak memberi manfaat apa pun. Model sendiri memperkecil gambar hingga sekitar 1.300 piksel pada sisi terpanjang, jadi piksel ekstra hanya memakan memori dan waktu unggah.

Perbaikan: perkecil sekali, kirim yang kecil

  • Gambar di atas 400 KB sekarang diubah menjadi JPEG dengan sisi terpanjang paling besar 1.568 piksel sebelum dikirim. Gambar yang lebih kecil dikirim apa adanya.
  • Konversi memakai ImageMagick, yang sudah ada di setiap sandbox Mythex, dan dijalankan sekali per file. Giliran yang menampilkan pindaian yang sama di setiap panggilan memakai ulang salinan yang sudah diperkecil. Cache itu dikunci berdasarkan path, ukuran, dan waktu modifikasi file, sehingga file yang diedit akan dikonversi ulang, dan cache itu punya batas ukurannya sendiri agar tidak menjadi penyebab memori penuh.
  • Anggaran untuk gambar dalam satu panggilan model turun dari 16 MB menjadi 6 MB.

Enam pindaian yang sama sekarang memakan 4,4 MB per panggilan, bukan 19,7 MB.

Penyebab 2: klien model tidak pernah melepas permintaan

Ukuran setiap permintaan hanya sebagian masalahnya. Memori juga terus bertambah dari panggilan ke panggilan. Di lingkungan staging kami, giliran jenis yang sama menahan 369 MB memori hidup bahkan setelah garbage collection penuh, yaitu titik ketika apa pun yang tidak bisa dijangkau sudah dibebaskan. Sampling heap menempatkan semua pertumbuhan itu di bagian library klien model yang meng-encode badan permintaan.

Penyebabnya adalah abort listener. Saat Anda menekan Stop, abort signal giliran itu menyala, dan setiap permintaan yang mendengarkannya dibatalkan. Kami memberikan satu signal untuk seluruh giliran ke setiap permintaan. Library klien menambahkan listener “abort” ke signal apa pun yang diberikan kepadanya, dan tidak pernah menghapusnya.

Akibatnya, setiap permintaan dalam satu giliran tetap bisa dijangkau dari signal giliran itu selama giliran berlangsung: listener itu memegang controller, controller itu memegang permintaan, dan permintaan itu memegang seluruh badan permintaan beserta gambarnya.

Perbaikan: satu signal per permintaan

Setiap permintaan sekarang mendapat signal sendiri. Signal itu dihubungkan ke signal giliran hanya selama permintaan tersebut berjalan, untuk respons streaming berarti sampai potongan terakhir selesai dibaca, lalu diputus segera setelahnya. Stop tetap sampai ke permintaan yang sedang berjalan, tetapi signal giliran hanya pernah memegang satu listener dalam satu waktu.

Tes-tesnya mencakup ketiga bagian itu:

  • Setelah 12 panggilan, tidak ada listener yang tersisa di signal giliran. Sebelum perbaikan, ada 12.
  • Selama 15 permintaan masing-masing 8 MB, memori tetap datar. Sebelumnya, memori bertambah 128 MB.
  • Menekan Stop tetap membatalkan permintaan yang berada di tengah streaming-nya.

Penyebab 3: tracing menyimpan input setiap panggilan

Snapshot heap menunjukkan pemegang ketiga: sekitar 6 MB yang tertahan per panggilan model. Ini berasal dari streaming event di framework agen. Framework itu mencatat setiap panggilan model dalam satu giliran sebagai anak dari giliran tersebut, termasuk inputnya, sampai giliran berakhir. Setiap gambar yang dilampirkan ke setiap panggilan ikut tersimpan di memori.

Perbaikan: kosongkan gambar begitu panggilan kembali

Gambar hanya pernah dilampirkan ke pesan yang dibangun untuk panggilan model tertentu. Gambar tidak pernah disimpan di state percakapan yang tersimpan. Jadi, begitu panggilan kembali, aman untuk mengosongkan data gambar di pesan-pesan itu. Trace tetap menyimpan catatan teks tentang panggilan itu; pikselnya dihapus.

Satu detail penting: gambar harus dikosongkan di tempat. Tracer bisa mencapai data gambar yang sama lewat lebih dari satu referensi pada sebuah pesan, sehingga mengganti dengan daftar kosong yang baru akan membiarkan yang asli, beserta pikselnya, tetap bisa dijangkau. State percakapan yang tersimpan tidak pernah diubah.

Sebuah tes menjalankan graph agen di bawah streaming event yang sama dengan gambar 4 MB di setiap panggilan. Tanpa perbaikan, memori bertambah 77 MB selama 16 panggilan. Dengan perbaikan, memori tetap datar.

Apa yang kami pelajari

  • Masalah memori bisa datang berlapis. Tiga penyebab terpisah masing-masing menahan gambar terlalu lama, dan ketiganya harus dihilangkan sebelum giliran tetap berada dalam batas memori.
  • Apa pun yang Anda serahkan ke sebuah library bisa tetap disimpan. Sebuah signal dan sebuah trace sama-sama bertahan lebih lama daripada panggilan yang diberikan kepada mereka. Jika memori bertambah per panggilan, lihatlah objek berumur panjang apa saja yang disentuh panggilan itu.
  • Jangan kirim apa yang tidak akan dibuang oleh pihak lain. Piksel yang akan dibuang model tetap memakan memori kami di setiap panggilan.
  • Uji memori secara langsung. Setiap perbaikan disertai tes yang mengukur pertumbuhan heap atau jumlah listener, sehingga regresi muncul sebagai angka, bukan crash.

Ini adalah cerita memori kedua dari agen dalam waktu singkat; yang pertama adalah label progres yang mengantre 41.000 kali. Jika Anda ingin tahu lebih banyak tentang apa itu agen dan cara kerjanya, lihat panduan kami tentang agen AI dan dokumentasi chat.

Mythex · Pricing · Bangun apa pun dengan AI · Template website dan aplikasi · Mythex dibandingkan · Glosarium membuat aplikasi dengan AI · Alat gratis untuk membuat aplikasi dengan AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)