Görsel Yoğun Agent Turlarını Bellek İçinde Tutmak
Üretimde bir agent turu, altı katalog taramasından ürünleri kırparken ve kırpmaları kontrol ederken 952 MB’da bellek yetersizliğine düştü. Tek bir sızıntı yoktu, üç tane vardı. Modele yapılan her çağrı, turdaki görselleri tam boyutta yeniden gönderiyordu; modeli çağırmak için kullandığımız kütüphane her isteği tur bitene kadar canlı tutuyordu; agent çatısının izlemesi (tracing) de her çağrının girdilerini, görseller dahil, tur boyunca saklıyordu. Üçünü de düzelttik: görseller gönderilmeden önce küçültülüyor ve her çağrının görselleri çağrı bitince hemen serbest bırakılıyor.
Agent görselleri nasıl görür
Mythex’te inşa ederken agent, projenizin bulut sandbox’ı içinde çalışır. Görselleri görebilir: eklediğiniz bir ekran görüntüsünü, bir maketi, projenizdeki bir dosyayı ya da kendi ürettiği bir görseli, bunları konuşmayla birlikte modele göndererek.
Tur, agentin sizin tek bir mesajınıza yanıt olarak yaptığı her şeydir. Bir tur içinde agent modeli birçok kez çağırır: düşünür, bir araç çalıştırır, sonucu görür, yeniden düşünür. Her çağrı o ana kadarki konuşmayı gönderir; buna turun görselleri de dahildir, metin olarak kodlanmış (base64, bu da yaklaşık üçte bir oranında büyütür).
Bellek yetersizliğine düşen tur, makul bir şey yapıyordu. Altı katalog taramasını, her biri yaklaşık 2,4 MB, aldı, tek tek ürünleri kırptı ve kırpmaları geri okuyarak kontrol etti. Bu, her biri birkaç büyük görsel taşıyan çok sayıda model çağrısı demekti.
1. neden: her çağrı tam boyutlu görselleri yeniden gönderiyordu
Her model çağrısı, turun görsellerini tam boyutta içeren istek gövdesini yeniden oluşturuyordu: çağrı başına yaklaşık 20 MB base64. Gövde, agentin belleğinde tek bir dize olarak oluşturulduğu için her çağrı yaklaşık 20 MB daha ayırıyordu.
Tam boyut göndermek bir fayda da sağlamıyordu. Model, görselleri kendisi uzun kenarda yaklaşık 1.300 piksele indirir; ekstra pikseller yalnızca bellek ve yükleme süresi harcatıyordu.
Çözüm: bir kez küçült, küçük gönder
- 400 KB’tan büyük görseller, gönderilmeden önce uzun kenarı en fazla 1.568 piksel olan bir JPEG’e dönüştürülür. Daha küçük görseller olduğu gibi gider.
- Dönüştürme, her Mythex sandbox’ında bulunan ImageMagick ile yapılır ve dosya başına bir kez çalışır. Aynı taramaları her çağrıda gösteren bir tur, küçültülmüş kopyayı yeniden kullanır. Bu önbellek dosyanın yolu, boyutu ve değiştirilme zamanıyla anahtarlanır; böylece düzenlenen bir dosya yeniden dönüştürülür. Ayrıca kendi boyut sınırı vardır, böylece belleği dolduran şey olamaz.
- Tek bir model çağrısındaki görseller için bütçe 16 MB’dan 6 MB’a düşürüldü.
Aynı altı tarama artık çağrı başına 19,7 MB yerine 4,4 MB tutuyor.
2. neden: model istemcisi bir isteği asla bırakmıyordu
Her isteğin boyutu sorunun sadece bir parçasıydı. Bellek de çağrıdan çağrıya büyüyordu. Staging ortamımızda aynı tür bir tur, tam bir çöp toplama sonrasında bile (erişilemeyen her şeyin serbest bırakıldığı nokta) 369 MB canlı bellek tutuyordu. Yığın örneklemesi tüm büyümenin, model istemci kütüphanesinin istek gövdelerini kodlayan kısmında olduğunu gösterdi.
Neden bir abort dinleyicisiydi. Durdur tuşuna bastığınızda turun abort sinyali tetiklenir ve buna bağlı her istek iptal olur. Biz bu tek, tur çapında sinyali her isteğe veriyorduk. İstemci kütüphanesi, verilen sinyale bir “abort” dinleyicisi ekler ve bunu asla kaldırmaz.
Yani bir turun her isteği, tur sürdüğü müddetçe turun sinyalinden erişilebilir kalıyordu: dinleyici, isteğin denetleyicisini tutuyor, denetleyici isteği, istek de görselleriyle birlikte tüm gövdeyi tutuyordu.
Çözüm: her istek için bir sinyal
Artık her isteğin kendi sinyali var. Bu sinyal, yalnızca istek çalışırken tur sinyaline bağlanır — akışlı bir yanıtta, son parça okunana kadar — ve hemen ardından bağlantısı kesilir. Durdur hâlâ çalışan isteğe ulaşır, ama tur sinyali aynı anda yalnızca tek bir dinleyici tutar.
Testler bu üç parçayı da kapsar:
- 12 çağrıdan sonra tur sinyalinde hiç dinleyici kalmaz. Düzeltmeden önce 12 tane vardı.
- Her biri 8 MB olan 15 istek boyunca bellek sabit kalır. Önceden 128 MB büyüyordu.
- Durdur’a basmak, bir isteği akışının ortasında hâlâ iptal eder.
3. neden: izleme her çağrının girdilerini tutuyordu
Bir yığın dökümü üçüncü bir tutucuyu gösterdi: model çağrısı başına yaklaşık 6 MB. Bu, agent çatısının olay akışından geliyordu. Olay akışı, bir turdaki her model çağrısını turun alt öğesi olarak, girdileriyle birlikte, tur bitene kadar kaydediyordu. Her çağrıya eklenen her görsel de onunla birlikte bellekte kalıyordu.
Çözüm: çağrı döndüğünde görselleri boşalt
Görseller yalnızca belirli bir model çağrısı için oluşturulan mesajlara eklenir. Konuşmanın kaydedilmiş durumunda hiçbir zaman saklanmazlar. Bu yüzden bir çağrı döndüğünde, o mesajlardaki görsel verisini boşaltmak güvenlidir. İzleme çağrının metin kaydını tutar; pikseller gider.
Bir ayrıntı önemliydi: görseller yerinde boşaltılmalıdır. İzleyici, aynı görsel verisine bir mesajda birden fazla referans üzerinden ulaşabiliyor; bu yüzden yeni, boş bir liste koymak, orijinali — pikselleriyle birlikte — erişilebilir bırakırdı. Kaydedilmiş konuşma durumu hiç değiştirilmez.
Bir test, agentin grafiğini aynı olay akışı altında çalıştırır; her çağrıda 4 MB’lık bir görsel vardır. Düzeltme olmadan bellek 16 çağrı boyunca 77 MB büyüdü. Düzeltmeyle birlikte bellek sabit kalır.
Bundan çıkardıklarımız
- Bellek sorunları katmanlar halinde gelebilir. Üç ayrı neden görselleri çok uzun tuttu ve tur bellek sınırları içinde kalmadan önce üçünün de çözülmesi gerekti.
- Bir kütüphaneye verdiğiniz her şey tutulabilir. Hem bir sinyal hem de bir iz, verildikleri çağrılardan uzun yaşadı. Bellek çağrı başına büyüyorsa, çağrının dokunduğu uzun ömürlü nesnelere bakın.
- Karşı tarafın atacağı şeyi göndermeyin. Modelin zaten atacağı pikseller, her çağrıda bize bellek maliyeti çıkardı.
- Belleği doğrudan test edin. Her düzeltme, yığın büyümesini ya da dinleyici sayılarını ölçen bir testle geldi; böylece bir gerileme bir çökme olarak değil, bir sayı olarak görünür.
Bu, kısa sürede agentten gelen ikinci bellek hikâyesi; birincisi bir ilerleme etiketinin 41.000 kez yeniden gönderilmesi. Agentin ne olduğunu ve nasıl çalıştığını öğrenmek için yapay zekâ agentleri rehberimize ve sohbet dokümanlarına bakabilirsiniz.