Μετάβαση στο περιεχόμενο

Πλαίσιο εργαλείων και προσωρινή αποθήκευση προτροπών

Δύο πράγματα ισχύουν για κάθε αίτημα που κάνει ο ενσωματωμένος μηχανισμός: οι ορισμοί εργαλείων είναι το μεγαλύτερο σταθερό κόστος του και σχεδόν κανένας από αυτούς δεν θα χρησιμοποιηθεί. Αυτή η σελίδα εξηγεί τι κάνει το Control Center γι’ αυτό και γιατί η απάντηση δεν είναι απλώς «στείλε λιγότερα εργαλεία».

Το Control Center καταχωρίζει περίπου 126 εργαλεία. Όταν αποστέλλονται ολόκληρα, οι ορισμοί τους κοστίζουν περίπου 23.000 token σε κάθε αίτημα — κόστος που καμία συμπύκνωση δεν μπορεί να αγγίξει, γιατί οι ορισμοί εργαλείων ταξιδεύουν σε ξεχωριστό μέρος του αιτήματος από τη συνομιλία.

Ο λογαριασμός των token είναι το προφανές παράπονο και, μαζί με την προσωρινή αποθήκευση προτροπών, είναι και ο μικρότερος. Το πραγματικό κόστος είναι η ακρίβεια επιλογής. Δημοσιευμένες αξιολογήσεις της κλήσης εργαλείων συμφωνούν ότι τα μοντέλα επιλέγουν σωστά το εργαλείο αξιόπιστα μέχρι περίπου 30–50 εργαλεία στο πλαίσιο, και χειροτερεύουν προοδευτικά πέρα από αυτό. Η αναφερόμενη αιτία δεν είναι ο αριθμός των token αλλά η σημασιολογική επικάλυψη: όταν ένας κατάλογος περιέχει αρκετά εργαλεία των οποίων οι περιγραφές μοιάζουν, το μοντέλο επιλέγει ανάμεσα σε παρόμοια αντί να ανακαλεί μια δυνατότητα.

Με 126 εργαλεία, ένας πράκτορας είναι πολύ πέρα από αυτή τη ζώνη σε κάθε στροφή — ακόμη και στις πολλές στροφές όπου χρειαζόταν μόνο να διαβάσει ένα αρχείο.

Μια εκτέλεση βλέπει επομένως δύο πράγματα:

  • ένα μόνιμο σύνολο — περίπου δύο δωδεκάδες εργαλεία, που αποστέλλονται με πλήρη σχήματα σε κάθε αίτημα;
  • ένα ευρετήριο ονομάτων για όλα τα υπόλοιπα, ομαδοποιημένα κάτω από επικεφαλίδες όπως «Tickets and projects» ή «Memory and knowledge», με κόστος μερικών εκατοντάδων token για ολόκληρο τον κατάλογο.

Μετρημένο στον τρέχοντα κατάλογο, αυτό πάει το μπλοκ εργαλείων από ~23.1k token σε ~5.0k, περίπου 78% μικρότερο, και βάζει το πάντα ορατό σύνολο μέσα στη ζώνη όπου η επιλογή είναι αξιόπιστη.

Το μόνιμο σύνολο είναι τα εργαλεία που χρησιμοποιεί μια εκτέλεση στις περισσότερες εκτελέσεις: το λεξιλόγιο αρχείων και κελύφους (read, write, edit, search, bash, …), τα εργαλεία ανακάλυψης, η λίστα ελέγχου εργασιών, η αναζήτηση μνήμης και όποιο ρήμα πρέπει να καλέσει η τρέχουσα λειτουργία για να παραδώσει την έξοδό της. Το ρήμα εξόδου της ίδιας της λειτουργίας είναι πάντα μόνιμο — μια εκτέλεση δεν πρέπει ποτέ να χρειάζεται να ψάξει την κλήση που παράγει το παραδοτέο της.

«Αναβαλλόμενο» δεν σημαίνει «μη διαθέσιμο»

Ενότητα με τίτλο ««Αναβαλλόμενο» δεν σημαίνει «μη διαθέσιμο»»

Αυτό είναι το μέρος που κάνει τον σχεδιασμό ασφαλή και όχι απλώς φθηνό. Ένα αναβαλλόμενο εργαλείο καλείται από την πρώτη στροφή. Μόνο το σχήμα του κρατείται.

Ο πράκτορας βλέπει το όνομα στην προτροπή του. Αν καλέσει απευθείας αυτό το όνομα, ο μηχανισμός φορτώνει το σχήμα και εκτελεί το εργαλείο στο ίδιο βήμα — χωρίς σφάλμα, χωρίς επιπλέον διαδρομή. Το μοντέλο δεν χρειάζεται να ξέρει ότι το εργαλείο ήταν ποτέ «εκφορτωμένο».

Όταν ο πράκτορας ξέρει την εργασία αλλά όχι το όνομα, το search_tools δέχεται μια περιγραφή σε φυσική γλώσσα («ανάθεσε ένα εισιτήριο σε κάποιον»), κατατάσσει ολόκληρη την επιφάνεια της εκτέλεσης και επιστρέφει τα αποτελέσματα με τα σχήματά τους ήδη φορτωμένα, ώστε η αμέσως επόμενη στροφή να καλέσει κάποιο. Αν μια αναζήτηση δεν βρει τίποτα, το δηλώνει ρητά και προτείνει διαφορετική διατύπωση ή ευρύτερη αναζήτηση — σκόπιμα, γιατί ένας πράκτορας που διαβάζει μια κενή αναζήτηση ως «αυτή η δυνατότητα δεν υπάρχει» θα επινοήσει υποκατάστατο αντί να ψάξει ξανά.

Το search_tools υπάρχει μόνο στον ενσωματωμένο μηχανισμό. Οι εξωτερικοί πελάτες MCP έχουν αντ’ αυτού το search_tool_bm25, το οποίο κατατάσσει το ίδιο ευρετήριο αλλά μόνο περιγράφει τα αποτελέσματα — αυτοί οι πελάτες έχουν ήδη λάβει κάθε σχήμα από το tools/list, οπότε δεν υπάρχει τίποτα να φορτωθεί.

Η αναβολή εφαρμόζεται μετά το φίλτρο εργαλείων της λειτουργίας, ποτέ αντί γι’ αυτό. Κρύβει ένα σχήμα· δεν μπορεί να αποκαλύψει ένα εργαλείο που η λειτουργία απέρριψε. Ένα εργαλείο που ενεργοποιείται περνά ακόμη από την προτροπή έγκρισης και τους περιορισμούς ενεργειών ακριβώς όπως θα περνούσε ένα μόνιμο, και ένα εργαλείο δεν μπορεί να φορτώσει ένα όνομα που δεν ήταν εξαρχής στην επιφάνεια της εκτέλεσης.

Η επιφάνεια MCP που βλέπουν οι εξωτερικοί πελάτες δεν επηρεάζεται. Το tools/list εξακολουθεί να επιστρέφει τον πλήρη κατάλογο. Μια παλαιότερη απόπειρα να περιοριστεί το έσπασε εντελώς: οι πελάτες MCP επικυρώνουν τα ονόματα εργαλείων με βάση τη δική τους λίστα στην cache και απορρίπτουν καθετί που δεν περιλαμβάνεται χωρίς να ρωτήσουν ποτέ τον διακομιστή, οπότε ένα εργαλείο «κρυφό αλλά καλούμενο» ήταν απλώς απρόσιτο. Η αναβολή ζει στον μηχανισμό, όπου η φόρτωση ενός εργαλείου στη μέση της εκτέλεσης είναι κάτι που ο μηχανισμός μπορεί πραγματικά να κάνει.

Τα --tool-deferral=off (ή CC_SERVER_TOOL_DEFERRAL=off) κάνουν κάθε εργαλείο που έχει γίνει δεκτό και πάλι μόνιμο, παράγοντας ακριβώς τα αιτήματα που έκανε ο διακομιστής πριν υπάρξει η αναβολή. Δείτε την αναφορά CLI του cc_server.

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

Η cache λειτουργεί με ακριβή αντιστοίχιση προθέματος, πράγμα που αποδίδει έναν κανόνα που τα διέπει όλα.

Μην ξαναγράφεις ποτέ ό,τι έχει ήδη σταλεί

Ενότητα με τίτλο «Μην ξαναγράφεις ποτέ ό,τι έχει ήδη σταλεί»

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

Ο βρόχος επίσης κόβει τις παλιές εξόδους εργαλείων από προηγούμενες στροφές για να ανακτήσει συμφραζόμενα. Περιμένει μέχρι να υπάρχει αρκετό υλικό προς ανάκτηση ώστε να αξίζει η επανεγγραφή, οπότε το κόψιμο είναι μια σπάνια βαθιά επανεγγραφή αντί για συνεχή αστοχία στην cache.

Ένας πάροχος επιτρέπει περιορισμένο αριθμό δεικτών cache και το Control Center τους ξοδεύει σκόπιμα:

Δείκτης Καλύπτει Διάρκεια ζωής
Τελευταίο μόνιμο εργαλείο Το μπλοκ εργαλείων 1 ώρα
Τελευταίο μπλοκ συστήματος Εργαλεία + προτροπή συστήματος 1 ώρα
Ουρά της προηγούμενης στροφής Ιστορικό μέχρι το τελευταίο αίτημα 5 λεπτά
Ουρά της τρέχουσας στροφής Το πλήρες ιστορικό 5 λεπτά

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

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

Οι υποπράκτορες μοιράζονται ένα πρόθεμα

Ενότητα με τίτλο «Οι υποπράκτορες μοιράζονται ένα πρόθεμα»

Οι υποπράκτορες του ίδιου τύπου παράγουν πανομοιότυπα κατά byte προθέματα προτροπών, οπότε θα πρέπει να διαβάζουν μία καταχώριση cache αντί να γράφει ο καθένας τη δική του. Όμως μια καταχώριση γίνεται αναγνώσιμη μόνο όταν το αίτημα που την έγραψε αρχίσει να απαντά, οπότε μια διασπορά που ξεκινά όλη μαζί κάνει κάθε παιδί να πληρώνει το επιπλέον κόστος για ένα πρόθεμα που όλα το μοιράζονται.

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

Και τα δύο μισά είναι παρατηρήσιμα αντί να υποτίθενται:

  • Ο εξερευνητής συμφραζομένων σε μια συνομιλία αναφέρει τα μόνιμα εργαλεία, το αναβαλλόμενο ευρετήριο και πόσο θα κόστιζε κάθε σχήμα που κρατείται, χτισμένος από την ίδια διαδρομή κώδικα που χρησιμοποιεί μια πραγματική εκτέλεση.
  • Κάθε εκτέλεση καταγράφει ποια αναβαλλόμενα εργαλεία φόρτωσε και τι την προκάλεσε, ώστε μια αναζήτηση που δεν βρίσκει τίποτα να φαίνεται ως αστοχία ανάκτησης αντί να χάνεται μέσα σε έναν πράκτορα που κάνει ήσυχα κάτι συναφές.
  • Η παρατηρησιμότητα αναφέρει το Ποσοστό cache ως τις αναγνώσεις από την cache προς όλα τα token προτροπών που υποβλήθηκαν σε επεξεργασία, μαζί με τις εγγραφές στην cache — μια εκτέλεση που ξαναχτίζει συνεχώς το πρόθεμά της βαθμολογείται χαμηλά, αντί να βαθμολογείται σαν μια που δεν χρειάστηκε ποτέ cache.