Ιστολόγιο

Η κρυφή κατάρρευση μνήμης σε μια ετικέτα προόδου

Ένα βράδυ στα τέλη Σεπτεμβρίου, ο πράκτορας τεχνητής νοημοσύνης σε έναν χώρο εργασίας χρήστη κατέρρευσε με σφάλμα έλλειψης μνήμης στη μέση μιας σειράς. Οι προφανείς ένοχοι — πάρα πολλοί υποπράκτορες να τρέχουν ταυτόχρονα, ή ένα πλαίσιο που είχε μεγαλώσει υπερβολικά — ήταν και οι δύο λάθος. Η πραγματική αιτία ήταν μια ετικέτα κατάστασης: καθώς το μοντέλο έστελνε μια μεγάλη εντολή shell λίγους χαρακτήρες τη φορά, στέλναμε ξανά ολόκληρη την εντολή μέχρι εκείνο το σημείο ως ετικέτα προόδου, σε κάθε κομμάτι. Μια εντολή 124 KB έγινε περίπου 41.000 συμβάντα και περίπου 690 MB συμβολοσειρών στην ουρά.

Πώς ο πράκτορας στέλνει τη δουλειά του

Όταν χτίζετε στο Mythex, ο πράκτορας τρέχει μέσα στο ιδιωτικό sandbox του έργου σας στο cloud. Καθώς γράφει το μοντέλο, η έξοδός του φτάνει ροή προς τον περιηγητή σας: το κείμενο εμφανίζεται λέξη προς λέξη, και όταν τρέχει ένα εργαλείο — ας πούμε μια εντολή shell που γράφει αρχείο — βλέπετε μια ετικέτα γι' αυτό να ενημερώνεται ζωντανά, ώστε να ξέρετε τι κάνει.

Το μοντέλο στέλνει σε μικρά κομμάτια. Με το μοντέλο που χρησιμοποιούσαμε, τα κομμάτια ήταν συχνά μόλις τρεις χαρακτήρες.

Οι πρώτες υποθέσεις ήταν λάθος

Η κατάρρευση έμοιαζε με πρόβλημα κλιμάκωσης, οπότε ξεκινήσαμε από εκεί.

  • Παράλληλοι υποπράκτορες; Η σειρά είχε χρησιμοποιήσει μόνο δύο, ο καθένας κρατούσε περίπου 1,5 MB κατάστασης. Ανεπαρκές.
  • Διατηρημένα ίχνη; Η παρακολούθησή μας κρατούσε ένα δέντρο εκτελέσεων στη μνήμη, αλλά ήταν μακριά από το μέγεθος της σωρού τη στιγμή της κατάρρευσης.

Και οι δύο ιστορίες ήταν πειστικές, και οι δύο ήταν εύκολο να τις πιστέψει κανείς. Καμία δεν αναπαρήγαγε την κατάρρευση. Το μάθημα που ξαναμαθαίνουμε: μια υπόθεση δεν είναι αιτία μέχρι να αναπαράγει την αποτυχία.

Αναπαράγοντάς το για πραγματικά

Φτιάξαμε ένα προσωρινό sandbox με τα ίδια όρια μνήμης με την παραγωγή, και ένα ψεύτικο μοντέλο που έστελνε ένα μεγάλο αρχείο σε ρεαλιστικά κομμάτια τριών χαρακτήρων. Κάναμε επίσης τον αναγνώστη στην άλλη άκρη της υποδοχής αργό, όπως ένα πραγματικό δίκτυο.

Αυτό το έκανε. Η σωρός ανέβηκε και η διεργασία πέθανε με το ίδιο σφάλμα.

Ο μηχανισμός ήταν απλός όταν μπορούσαμε να τον παρακολουθήσουμε. Όσο το μοντέλο έγραφε μια μεγάλη εντολή — σε αυτή την περίπτωση ένα heredoc που έγραφε αρχείο 124 KB — ο κώδικας ροής ενημέρωνε την ετικέτα του εργαλείου σε κάθε κομμάτι. Η ετικέτα δεν ήταν τα νέα τρεις χαρακτήρες· ήταν ολόκληρη η εντολή μέχρι εκείνο το σημείο. Άρα τα συμβάντα μεγάλωναν: 3 χαρακτήρες, μετά 6, μετά 9, … μέχρι 124 KB, περίπου 41.000 φορές. Η υποδοχή δεν μπορούσε να στείλει τόσο γρήγορα όσο παράγονταν, οπότε συσσωρεύονταν στον buffer εγγραφής της ως συμβολοσειρές — περίπου 690 MB.

Η διόρθωση

  • Περιορίστε την ετικέτα. Μια ετικέτα κατάστασης χρειάζεται μόνο να λέει τι συμβαίνει. Τώρα περιορίζεται σε 200 χαρακτήρες, και περιορίζουμε πόσο συχνά ξαναεξετάζουμε την μερική εντολή.
  • Σταματήστε τη συνένωση με κόστος τετραγωνικό. Το να ενώνουμε κομμάτια ροής με επαναλαμβανόμενη συνένωση συμβολοσειρών είναι O(n²) για μεγάλες εξόδους. Περάσαμε σε προσέγγιση βασισμένη σε κομμάτια που προσθέτει γραμμικά.

Μετά ψάξαμε για οτιδήποτε άλλο μπορούσε να μεγαλώνει χωρίς όριο σε ροή από έξοδο, και το περιορίσαμε:

  • Η ζωντανή έξοδος εντολών που εμφανίζεται στη συνομιλία ομαδοποιείται και κρατά μόνο τους τελευταίους 8.000 χαρακτήρες.
  • Κάθε γραμμή συμβάντος περιορίζεται σε 4 MB.
  • Ο buffer επανάληψης που χρησιμοποιεί ένας περιηγητής για να καλύψει την καθυστέρηση μετά από επανασύνδεση περιορίζεται σε 8 MB ανά έργο.
  • Τα παλιά checkpoints κλαδεύονται καθώς προχωρά η σειρά, κρατώντας την πιο πρόσφατη κατάσταση και τις αγκύρες που χρειάζονται οι προηγούμενες σειρές.

Ο ειλικρινής έλεγχος πλημμυρών

Δύο πράγματα έκαναν τη δοκιμή πιο δύσκολη απ' όσο έπρεπε:

  1. Τα πραγματικά μοντέλα δεν συνεργάζονται. Αν ζητήσετε από μοντέλο να τυπώσει τεράστιο αρχείο, συνήθως αρνείται, συνοψίζει ή το γράφει πιο λογικά. Για να δοκιμάσετε πλημμύρες χρειάζεστε ένα σκριπτ μοντέλο που κάνει ακριβώς ό,τι του λέτε, τρέχοντας μέσα από τον πραγματικό κώδικα του πράκτορα.
  2. Τα σενάρια πρέπει να συμπεριφέρονται σαν μοντέλα. Το πρώτο μας σκριπτ μοντέλο ξαναχρησιμοποιούσε το ίδιο αναγνωριστικό απάντησης σε κάθε απάντηση, οπότε το πλαίσιο του πράκτορα αντιμετώπιζε κάθε απάντηση ως αντικατάσταση της προηγούμενης και τερμάτιζε σειρές νωρίς. Έμοιαζε με σφάλμα ανανέωσης της διεπαφής. Δεν ήταν — ήταν το σύστημα δοκιμών που μας έλεγε ψέματα. Χρειάστηκε επίσης να επιβάλουμε το πραγματικό όριο πλαισίου του μοντέλου μέσα στο σκριπτ, αλλιώς οι αριθμοί μνήμης ήταν μη ρεαλιστικοί.

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

  • Οι ροές διεπαφής πολλαπλασιάζουν τα μικρά λάθη. Ό,τι στέλνετε «ανά κομμάτι» στέλνεται δεκάδες χιλιάδες φορές. Στείλτε μόνο τις αλλαγές, ή περιορίστε το φορτίο.
  • Περιορίστε κάθε buffer που περνά από αργό όριο. Υποδοχές, αρχεία επανάληψης και checkpoints χρειάζονται όλα ταβάνι.
  • Αναπαράγετε πριν διορθώσετε. Οι δύο πρώτες εξηγήσεις μας ακούγονταν σωστές και ήταν λάθος.

Αν πρόσφατα έχετε δει ένα πολύ μεγάλο αρχείο να εμφανίζεται στη συνομιλία του Mythex χωρίς ο πράκτορας να κολλά, αυτός είναι ένας από τους λόγους.

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 简体中文 繁體中文(香港) 繁體中文(台灣)