Διατήρηση μεγάλων σειρών εργασίας του agent μέσα στο παράθυρο συμφραζομένων
Ένα μοντέλο μπορεί να διαβάσει μόνο ορισμένο όγκο κειμένου κάθε φορά — το παράθυρο συμφραζομένων του. Ο agent του Mythex κάνει μακρές εργασίες: διαβάζει πολλά αρχεία, τρέχει εντολές, αναθέτει οριοθετημένες δουλειές σε υπο-agent. Βρήκαμε τρεις τρόπους με τους οποίους η μακρά εργασία χαλούσε: οι υπο-agent μεγάλωναν μέχρι το μοντέλο να απορρίπτει κάθε αίτημα, ένας υπο-agent σταματούσε νωρίς επειδή νόμιζε ότι δεν είχε χώρο, και η καταμέτρηση tokens μας ήταν πολύ λάθος για ρωσικό, κινεζικό και ιαπωνικό κείμενο. Εδώ είναι τι αλλάξαμε.
Μερικοί όροι πρώτα
- Tokens είναι τα κομμάτια που διαβάζει ένα μοντέλο. Τα όρια και το κόστος μετρώνται σε αυτά, όχι σε χαρακτήρες ή λέξεις.
- Παράθυρο συμφραζομένων είναι το μέγιστο που μπορεί να διαβάσει ένα μοντέλο σε ένα αίτημα. Εμείς ορίζουμε επίσης ένα πιο χαμηλό δικό μας budget για κάθε αίτημα, ώστε το κόστος και η ταχύτητα να μένουν λογικά.
- Αποτελέσματα εργαλείων είναι όσα παίρνει πίσω ο agent από τα εργαλεία του: το περιεχόμενο ενός αρχείου που διάβασε, η έξοδος μιας εντολής που έτρεξε. Στη μακρά εργασία είναι το μεγαλύτερο μέρος όσων στέλνονται.
- Ένας υπο-agent είναι ένας βοηθός που ξεκινά ο κύριος agent για μια αυτοτελή εργασία, όπως «έλεγξε αυτά τα κεφάλαια με τις σημειώσεις». Παίρνει μία οδηγία και στη συνέχεια δουλεύει μέσα από πολλές κλήσεις εργαλείων μόνος του.
Πρόβλημα 1: οι υπο-agent μεγάλωναν μέχρι το μοντέλο να τους απορρίπτει
Σε κάθε βήμα, ο agent στέλνει στο μοντέλο τη συνομιλία μέχρι εκείνη τη στιγμή. Όταν αυτή γινόταν πολύ μεγάλη, ο κώδικάς μας την έκοβε — αλλά μόνο στην αρχή ενός μηνύματος χρήστη, ώστε ένα κάλεσμα εργαλείου και το αποτέλεσμά του να μην χωρίζονται ποτέ. Κρατούσε το πρώτο μήνυμα, πρόσθετε μια σημείωση ότι η προηγούμενη συνομιλία περικόπηκε, και κρατούσε τις πιο πρόσφατες ολόκληρες σειρές που χωρούσαν.
Ένας υπο-agent έχει ακριβώς ένα μήνυμα χρήστη: την οδηγία του. Δεν υπήρχε πουθενά να κοπεί. Έτσι, έστελνε ολόκληρο το ιστορικό του σε κάθε βήμα, και αυτό μεγάλωνε κάθε φορά, μέχρι το αίτημα να είναι μεγαλύτερο από αυτό που δέχεται καθόλου το μοντέλο — περίπου ένα εκατομμύριο tokens. Σε μια δοκιμή με 8 τέτοιους υπο-agent, και οι 8 απορρίφθηκαν.
Η διόρθωση: πρώτα καθαρίζουμε παλιά αποτελέσματα εργαλείων
Τα αιτήματα τώρα χωρούν στο budget σε τρία βήματα, και κάθε βήμα δοκιμάζεται μόνο αν το προηγούμενο δεν αρκούσε:
- Καθαρισμός των παλαιότερων αποτελεσμάτων εργαλείων. Το περιεχόμενό τους αντικαθίσταται με μια σύντομη σημείωση: το αποτέλεσμα καθαρίστηκε για να μείνει η συνομιλία εντός των συμφραζομένων του μοντέλου, και ο agent μπορεί να ξανατρέξει το εργαλείο αν το χρειαστεί. Ένα αρχείο που διαβάστηκε πριν από μία ώρα είναι συνήθως το μεγαλύτερο και το λιγότερο χρήσιμο πράγμα στο αίτημα, και το αρχείο υπάρχει ακόμα για να ξαναδιαβαστεί. Τα νεότερα αποτελέσματα μένουν ολόκληρα.
- Διατήρηση ολόκληρων σειρών χρήστη. Όπως και πριν: το πρώτο μήνυμα, μια σημείωση, και οι πιο πρόσφατες πλήρεις σειρές που χωρούν.
- Διατήρηση ολόκληρων γύρων εργαλείων. Μέσα σε μία μακρά σειρά — το μόνο είδος που έχει ένας υπο-agent — κρατάμε το πρώτο μήνυμα, μια σημείωση, και τους πιο πρόσφατους πλήρεις γύρους «κάλεσε ένα εργαλείο, πάρε το αποτέλεσμά του».
Αυτό αλλάζει μόνο το τι στέλνεται. Το αποθηκευμένο ιστορικό του agent κρατά τα πάντα. Στην ίδια δοκιμή, 0 από τα 8 απορρίφθηκαν και τα 8 ολοκλήρωσαν.
Καθαρισμός σε παρτίδες, ώστε η προσωρινή αποθήκευση να συνεχίσει να δουλεύει
Οι πάροχοι μοντέλων μπορούν να επαναχρησιμοποιήσουν εργασία στην αρχή ενός αιτήματος, αν είναι πανομοιότυπη με το προηγούμενο — μια προσωρινή αποθήκευση προθέματος (prefix cache). Αν καθαρίζαμε ένα αποτέλεσμα ακόμα σε κάθε κλήση, η αρχή του αιτήματος θα άλλαζε κάθε φορά και η προσωρινή αποθήκευση δεν θα βοηθούσε ποτέ.
Γι' αυτό τα παλαιότερα αποτελέσματα καθαρίζονται τέσσερα τη φορά, όχι ένα. Το καθαρισμένο τμήμα μένει το ίδιο για αρκετές κλήσεις. Ένα αποτέλεσμα που δεν είναι πολύ μεγαλύτερο από τη σημείωση μένει ανέγγιχτο: ο καθαρισμός του θα εξοικονομούσε σχεδόν τίποτα και θα άλλαζε πάλι την αρχή του αιτήματος. Το πόσα μένουν ολόκληρα καθορίζεται από το μέγεθος, όχι από το πλήθος: τα νεότερα αποτελέσματα που χωρούν σε το ένα τέταρτο του budget μένουν, και πάντα τουλάχιστον ένα. Μια προηγούμενη έκδοση κρατούσε σταθερά έξι ολόκληρα, κάτι σωστό για σύντομες εξόδους εντολών, αλλά με μεγάλα αρχεία άφηνε το μεγαλύτερο μέρος του budget σε παλιά αποτελέσματα.
Οι απορρίψεις τώρα το λένε
Ένα αίτημα που το μοντέλο απορρίπτει ως άκυρο δεν ξαναδοκιμάζεται· η αποστολή του ίδιου αιτήματος ξανά παίρνει την ίδια απάντηση. Αν η συνομιλία είναι πολύ μεγάλη για το μοντέλο, ο χρήστης βλέπει: «Η συνομιλία έγινε πολύ μεγάλη για να τη διαβάσει το μοντέλο σε μία φορά. Ξεκινήστε νέα συνομιλία για το επόμενο βήμα — όσα έχουν χτιστεί μέχρι τώρα παραμένουν.» Αυτό είναι κάτι που αφορά τον χρήστη και μπορεί να το χειριστεί, όχι διακοπή λειτουργίας, οπότε δεν ειδοποιεί εμάς.
Πρόβλημα 2: ο agent σταματούσε για να «εξοικονομήσει χώρο»
Ένας υπο-agent που είχε ζητηθεί να διαβάσει 40 μεγάλα κεφάλαια σταμάτησε μετά από 2, λέγοντας ότι ήθελε να εξοικονομήσει χώρο. Είχε χρησιμοποιήσει περίπου 100.000 tokens από budget 400.000.
Δεν είχε τρόπο να ξέρει ότι τα παλιά αποτελέσματα θα καθαρίζονταν για χάρη του. Γι' αυτό του το είπαμε. Οι οδηγίες του agent λένε πλέον ότι, όταν η συνομιλία μεγαλώνει πέρα από ό,τι μπορεί να δεχτεί το μοντέλο, τα παλαιότερα αποτελέσματα εργαλείων καθαρίζονται και τα νεότερα μένουν ολόκληρα — οπότε μην σταματάτε μια μακρά εργασία για να εξοικονομήσετε χώρο· συνεχίστε, και ξαναδιαβάστε ένα αρχείο αν χρειαστείτε ό,τι καθαρίστηκε.
Μια διόρθωση που το μοντέλο δεν βλέπει δεν είναι διόρθωση από τη σκοπιά του μοντέλου. Ο μηχανισμός βοηθά μόνο αν ο agent τον εμπιστεύεται.
Πρόβλημα 3: μέτρηση tokens σαν όλα τα κείμενα να ήταν αγγλικά
Υπολογίζαμε τα tokens χωρίς να τρέχουμε tokenizer, ως χαρακτήρες διά τέσσερα. Αυτός είναι ένας λογικός εμπειρικός κανόνας για τα αγγλικά. Δεν ισχύει για άλλα αλφάβητα: τα ρωσικά έχουν περίπου 2,2 χαρακτήρες ανά token, και τα κινεζικά ή ιαπωνικά περίπου έναν.
Έτσι, ένας υπο-agent που διάβαζε ρωσικά κεφάλαια έστελνε ένα αίτημα περίπου 640.000 tokens, ενώ η εκτίμησή μας έλεγε ότι ήταν κάτω από το budget των 400.000. Η εκτίμηση θα μπορούσε εξίσου εύκολα να βάλει ένα αίτημα πάνω από το σκληρό όριο του μοντέλου.
Η εκτίμηση μετρά πλέον ανά αλφάβητο: απλό ASCII με τέσσερα χαρακτήρες ανά token, κινεζικά, ιαπωνικά και κορεατικά με έναν, και όλα τα υπόλοιπα — κυριλλικά, ελληνικά, αραβικά, τονούμενα γράμματα, emoji — με δύο. Σκοπός είναι να σφάλλει προς τα πάνω. Σε ένα ρωσικό κεφάλαιο εκτιμά τώρα 43.423 tokens, έναντι περίπου 44.600 μετρημένων· πριν, έλεγε 25.023. Επειδή ένα μήνυμα δεν αλλάζει αφού γραφτεί, η εκτίμησή του υπολογίζεται μία φορά και αποθηκεύεται, αντί να γίνεται σε κάθε βήμα.
Τι μάθαμε από αυτό
- Κόβετε εκεί όπου είναι πραγματικά το μέγεθος. Στη δουλειά agent, αυτό είναι τα αποτελέσματα εργαλείων, όχι τα μηνύματα των χρηστών.
- Πείτε στον agent για τις δικές του δικλίδες ασφαλείας. Αλλιώς σχεδιάζει γύρω από όρια που δεν ισχύουν πια.
- Το «χαρακτήρες ÷ 4» είναι αγγλική υπόθεση. Ό,τι μετρά tokens για πολυγλωσσικούς χρήστες πρέπει να μετράει ανά αλφάβητο, ή να χρησιμοποιεί έναν πραγματικό tokenizer.
- Προσέξτε την προσωρινή αποθήκευση. Ένα αίτημα που αλλάζει στην αρχή του σε κάθε κλήση κοστίζει περισσότερο και τρέχει πιο αργά.
Αν χτίζετε λειτουργίες AI στη δική σας εφαρμογή, οι οδηγοί μας για το τι είναι ένα LLM και πώς να χρησιμοποιήσετε APIs LLM καλύπτουν τα παράθυρα συμφραζομένων και τα tokens από την αρχή. Περισσότερα για το πώς λειτουργούν οι υπο-agent στο Mythex υπάρχουν στα docs των υπο-agent.