Ιστολόγιο

Οι σειρές του agent με πολλές εικόνες χωρούν στη μνήμη

Μια σειρά του agent σε παραγωγή εξαντλήθηκε από μνήμη στα 952 MB ενώ έκοβε προϊόντα από έξι σαρώσεις καταλόγου και τα έβλεπε ξανά. Δεν υπήρξε μία μόνο διαρροή — υπήρξαν τρεις. Κάθε κλήση στο μοντέλο ξανάστελνε τις εικόνες της σειράς σε πλήρες μέγεθος· η βιβλιοθήκη που χρησιμοποιούμε για να καλούμε το μοντέλο κρατούσε ζωντανό κάθε αίτημα μέχρι το τέλος της σειράς· και η ιχνηλάτηση του agent framework κρατούσε τις εισόδους κάθε κλήσης, συμπεριλαμβανομένων των εικόνων, για ολόκληρη τη σειρά. Τις διορθώσαμε και τις τρεις: οι εικόνες μικραίνουν πριν σταλούν, και οι εικόνες κάθε κλήσης αφήνονται ελεύθερες μόλις τελειώσει η κλήση.

Πώς βλέπει ο agent τις εικόνες

Όταν χτίζετε στο Mythex, ο agent δουλεύει μέσα στο cloud sandbox του project σας. Μπορεί να δει εικόνες — ένα στιγμιότυπο οθόνης που επισυνάπτετε, ένα mockup, ένα αρχείο στο project σας, ή μια εικόνα που μόλις έφτιαξε ο ίδιος — στέλνοντάς τες στο μοντέλο μαζί με τη συνομιλία.

Μια σειρά είναι όλα όσα κάνει ο agent ως απάντηση σε ένα μήνυμα σας. Μέσα σε μια σειρά, ο agent καλεί το μοντέλο πολλές φορές: σκέφτεται, τρέχει ένα εργαλείο, βλέπει το αποτέλεσμα, σκέφτεται ξανά. Κάθε κλήση στέλνει τη συνομιλία μέχρι εκείνη τη στιγμή, και αυτό περιλαμβάνει τις εικόνες της σειράς, κωδικοποιημένες ως κείμενο (base64, που τις κάνει περίπου κατά ένα τρίτο μεγαλύτερες).

Η σειρά που κατέρρευσε έκανε κάτι λογικό. Πήρε έξι σαρώσεις καταλόγου, περίπου 2,4 MB η καθεμία, έκοψε μεμονωμένα προϊόντα από αυτές, και ξαναδιάβαζε τα κομμάτια για να τα ελέγξει. Αυτό σημαίνει πολλές κλήσεις στο μοντέλο, καθεμία με αρκετές μεγάλες εικόνες.

Αιτία 1: κάθε κλήση ξαναέστελνε εικόνες πλήρους μεγέθους

Κάθε κλήση στο μοντέλο ξανάχτιζε το σώμα του αιτήματος με τις εικόνες της σειράς σε πλήρες μέγεθος — περίπου 20 MB base64 ανά κλήση. Το σώμα χτίζεται ως ένα μεγάλο string στη μνήμη του agent, οπότε κάθε κλήση δέσμευε άλλα ~20 MB.

Και η αποστολή πλήρους μεγέθους δεν πρόσφερε τίποτα. Το μοντέλο μικραίνει μόνο του τις εικόνες σε περίπου 1.300 pixels στην μεγαλύτερη πλευρά, οπότε τα επιπλέον pixels κόστιζαν μόνο μνήμη και χρόνο ανεβάσματος.

Η διόρθωση: μικραίνουμε μία φορά, στέλνουμε μικρά

  • Οι εικόνες πάνω από 400 KB μετατρέπονται πλέον σε JPEG με το πολύ 1.568 pixels στη μεγαλύτερη πλευρά πριν σταλούν. Οι μικρότερες εικόνες στέλνονται όπως είναι.
  • Η μετατροπή γίνεται με το ImageMagick, που υπάρχει σε κάθε sandbox του Mythex, και τρέχει μία φορά ανά αρχείο. Μια σειρά που δείχνει τις ίδιες σαρώσεις σε κάθε κλήση επαναχρησιμοποιεί το μικρύνσμένο αντίγραφο. Η προσωρινή αποθήκευση κλειδώνεται με τη διαδρομή, το μέγεθος και την ημερομηνία τροποποίησης του αρχείου, οπότε ένα επεξεργασμένο αρχείο μετατρέπεται ξανά, και έχει δικό της όριο μεγέθους ώστε να μην γίνει η ίδια η αιτία που γεμίζει τη μνήμη.
  • Ο προϋπολογισμός για εικόνες σε μία κλήση μειώνεται από 16 MB σε 6 MB.

Οι ίδιες έξι σαρώσεις κοστίζουν τώρα 4,4 MB ανά κλήση αντί για 19,7 MB.

Αιτία 2: το client του μοντέλου δεν άφηνε ποτέ ένα αίτημα

Το μέγεθος κάθε αιτήματος ήταν μόνο ένα μέρος του προβλήματος. Η μνήμη μεγάλωνε και από κλήση σε κλήση. Στο staging μας, η ίδια σειρά κρατούσε 369 MB ζωντανής μνήμης ακόμα και μετά από πλήρη συλλογή απορριμμάτων — το σημείο όπου έχει ελευθερωθεί ό,τι δεν είναι προσβάσιμο. Η δειγματοληψία σωρού έδειξε ότι όλη η ανάπτυξη βρισκόταν στο τμήμα της βιβλιοθήκης του client του μοντέλου που κωδικοποιεί τα σώματα των αιτημάτων.

Η αιτία ήταν ένας listener abort. Όταν πατάτε Stop, το abort signal της σειράς ενεργοποιείται, και κάθε αίτημα που το ακούει ακυρώνεται. Περνούσαμε αυτό το ένα σήμα σε όλη τη σειρά σε κάθε αίτημα. Ο client προσθέτει έναν listener «abort» σε όποιο σήμα του δοθεί — και ποτέ δεν τον αφαιρεί.

Έτσι, κάθε αίτημα της σειράς παρέμενε προσβάσιμο από το σήμα της σειράς για όλη τη διάρκειά της: ο listener κρατούσε τον controller του αιτήματος, ο controller κρατούσε το αίτημα, και το αίτημα κρατούσε ολόκληρο το σώμα του με τις εικόνες του.

Η διόρθωση: ένα σήμα ανά αίτημα

Κάθε αίτημα παίρνει πλέον το δικό του σήμα. Συνδέεται με το σήμα της σειράς μόνο όσο τρέχει εκείνο το αίτημα — για μια ροή, μέχρι να διαβαστεί το τελευταίο κομμάτι — και αποσυνδέεται αμέσως μετά. Το Stop εξακολουθεί να φτάνει σε ό,τι αίτημα είναι σε εξέλιξη, αλλά το σήμα της σειράς κρατά ποτέ περισσότερο από έναν listener τη φορά.

Οι δοκιμές καλύπτουν και τα τρία μέρη:

  • Μετά από 12 κλήσεις, δεν μένει κανένας listener στο σήμα της σειράς. Πριν από τη διόρθωση, υπήρχαν 12.
  • Σε 15 αιτήματα των 8 MB το καθένα, η μνήμη μένει σταθερή. Πριν, αύξανε κατά 128 MB.
  • Το Stop εξακολουθεί να διακόπτει ένα αίτημα στη μέση της ροής του.

Αιτία 3: η ιχνηλάτηση κρατούσε τις εισόδους κάθε κλήσης

Ένα στιγμιότυπο σωρού έδειξε έναν τρίτο κάτοχο: περίπου 6 MB ανά κλήση στο μοντέλο. Αυτό προερχόταν από τη ροή γεγονότων του agent framework. Καταγράφει κάθε κλήση μοντέλου μέσα σε μια σειρά ως παιδί της σειράς, μαζί με τις εισόδους της, μέχρι να τελειώσει η σειρά. Κάθε εικόνα που επισυνάπτεται σε κάθε κλήση έμενε στη μνήμη μαζί της.

Η διόρθωση: αδειάζουμε τις εικόνες μόλις επιστρέψει η κλήση

Οι εικόνες επισυνάπτονται μόνο στα μηνύματα που φτιάχνονται για μια συγκεκριμένη κλήση στο μοντέλο. Δεν αποθηκεύονται ποτέ στην αποθηκευμένη κατάσταση της συνομιλίας. Οπότε, μόλις επιστρέψει μια κλήση, είναι ασφαλές να αδειάσουμε τα δεδομένα εικόνας σε αυτά τα μηνύματα. Η ιχνηλάτηση κρατά μια κειμενική εγγραφή της κλήσης· τα pixels φεύγουν.

Ένα λεπτό είχε σημασία: οι εικόνες πρέπει να αδειάζονται επί τόπου. Ο ιχνηλάτης μπορεί να φτάσει τα ίδια δεδομένα εικόνας μέσω περισσότερων από μίας αναφορών σε ένα μήνυμα, οπότε αν αντικαθιστούσαμε τη λίστα με μια νέα, κενή, το αρχικό — με τα pixels του — θα παρέμενε προσβάσιμο. Η αποθηκευμένη κατάσταση της συνομιλίας δεν τροποποιείται ποτέ.

Μία δοκιμή τρέχει το γράφημα του agent με την ίδια ροή γεγονότων και μια εικόνα 4 MB σε κάθε κλήση. Χωρίς τη διόρθωση, η μνήμη αυξήθηκε κατά 77 MB σε 16 κλήσεις. Με τη διόρθωση, μένει σταθερή.

Τι κρατήσαμε από αυτό

  • Τα προβλήματα μνήμης μπορεί να έχουν επίπεδα. Τρεις ξεχωριστές αιτίες κρατούσαν τις εικόνες πολύ καιρό, και ήταν ανάγκη να φύγουν και οι τρεις για να μείνει η σειρά εντός μνήμης.
  • Ό,τι δίνετε σε μια βιβλιοθήκη μπορεί να διατηρηθεί. Ένα σήμα και μια ιχνηλάτηση επέζησαν των κλήσεων στις οποίες δόθηκαν. Όταν η μνήμη μεγαλώνει ανά κλήση, κοιτάξτε ποια μακράς διάρκειας αντικείμενα αγγίζει η κλήση.
  • Μην στέλνετε ό,τι η άλλη πλευρά θα πετάξει. Τα pixels που το μοντέλο θα απέρριπτε ούτως ή άλλως μας κόστιζαν μνήμη σε κάθε κλήση.
  • Δοκιμάστε τη μνήμη απευθείας. Κάθε διόρθωση συνοδεύτηκε από δοκιμή που μετρά την ανάπτυξη σωρού ή τον αριθμό listeners, οπότε μια παλινδρόμηση φαίνεται ως αριθμός και όχι ως κατάρρευση.

Αυτή είναι η δεύτερη ιστορία μνήμης από τον agent μέσα σε λίγο χρόνο. Η πρώτη ήταν μια ετικέτα προόδου που έστελνε ξανά 41.000 φορές. Αν θέλετε να μάθετε περισσότερα για το τι είναι ο agent και πώς λειτουργεί, δείτε τον οδηγό μας για τους AI agents και τα docs της συνομιλίας.

Mythex · Pricing · Χτίστε οτιδήποτε με AI · Πρότυπα ιστοσελίδων και εφαρμογών · Το Mythex σε σύγκριση · Γλωσσάρι δημιουργίας εφαρμογών με AI · Δωρεάν εργαλεία δημιουργίας εφαρμογών με AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Í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 简体中文 繁體中文(香港) 繁體中文(台灣)