Menjaga Giliran Agen yang Panjang Tetap dalam Context Window
Sebuah model hanya bisa membaca sejumlah tertentu dalam satu waktu, yaitu context window-nya. Agen Mythex mengerjakan pekerjaan yang panjang: membaca banyak file, menjalankan perintah, dan menyerahkan tugas terbatas kepada sub-agen. Kami menemukan tiga cara pekerjaan panjang itu rusak: sub-agen terus membesar sampai model menolak setiap permintaan, sebuah sub-agen berhenti lebih awal karena mengira ruangnya habis, dan hitungan token kami sangat keliru untuk teks bahasa Rusia, Mandarin, dan Jepang. Inilah yang kami ubah.
Beberapa istilah dulu
- Token adalah potongan-potongan yang dibaca model. Batas dan biaya dihitung dalam token, bukan dalam karakter atau kata.
- Context window adalah jumlah maksimum yang bisa dibaca model dalam satu permintaan. Kami juga menetapkan anggaran sendiri yang lebih rendah untuk setiap permintaan, supaya biaya dan kecepatan tetap wajar.
- Hasil tool adalah yang diterima agen dari tool-nya: isi file yang dibaca, output perintah yang dijalankan. Dalam pekerjaan panjang, hasil tool itulah sebagian besar yang dikirim.
- Sub-agen adalah pembantu yang dimulai agen utama untuk tugas yang berdiri sendiri, misalnya “periksa bab-bab ini terhadap catatan”. Ia menerima satu instruksi, lalu mengerjakan banyak panggilan tool sendiri.
Masalah 1: sub-agen membesar sampai model menolaknya
Setiap langkah, agen mengirim percakapan sejauh ini ke model. Saat percakapan itu terlalu besar, kode kami memangkasnya, tetapi hanya di awal pesan pengguna, sehingga pasangan panggilan tool dan hasilnya tidak pernah terpisah. Pesan pertama dipertahankan, ditambah catatan bahwa percakapan sebelumnya dipangkas, dan giliran-giliran terbaru yang utuh dan muat tetap dipertahankan.
Sub-agen hanya punya satu pesan pengguna: instruksinya. Tidak ada tempat untuk memotong. Jadi ia mengirim seluruh riwayatnya di setiap langkah, dan terus membesar, sampai permintaannya lebih besar daripada yang bisa diterima model sama sekali, sekitar satu juta token. Dalam sebuah tes dengan 8 sub-agen seperti itu, kedelapannya ditolak.
Perbaikan: hapus dulu hasil tool yang lama
Permintaan sekarang dipaskan ke anggaran dalam tiga langkah, dan setiap langkah hanya dicoba jika langkah sebelumnya belum cukup:
- Hapus hasil tool yang paling tua. Isinya diganti dengan catatan singkat: hasil ini dihapus agar percakapan tetap berada dalam context model, dan agen bisa menjalankan tool itu lagi jika membutuhkannya. File yang dibaca satu jam lalu biasanya adalah hal terbesar dan paling tidak berguna dalam permintaan, dan file itu masih bisa dibaca lagi. Hasil terbaru tetap utuh.
- Pertahankan giliran pengguna yang utuh. Seperti sebelumnya: pesan pertama, sebuah catatan, dan giliran terbaru yang lengkap dan muat.
- Pertahankan putaran tool yang utuh. Di dalam satu giliran panjang, yaitu satu-satunya jenis yang dimiliki sub-agen, pertahankan pesan pertama, sebuah catatan, dan putaran terbaru “panggil tool, dapatkan hasilnya” yang lengkap.
Ini hanya membentuk apa yang dikirim. Riwayat tersimpan agen tetap menyimpan semuanya. Dalam tes yang sama, 0 dari 8 ditolak dan kedelapannya selesai.
Penghapusan dalam batch, supaya cache tetap bekerja
Provider model bisa memakai ulang pekerjaan di awal sebuah permintaan jika permintaan itu identik dengan yang terakhir, yaitu prefix cache. Jika kami menghapus satu hasil tambahan di setiap panggilan, awal permintaan akan berubah di setiap panggilan dan cache tidak pernah membantu.
Karena itu, hasil tertua dihapus empat sekaligus, bukan satu-satu. Bagian yang dihapus lalu tetap sama selama beberapa panggilan. Hasil yang tidak jauh lebih besar dari catatannya dibiarkan: menghapusnya hampir tidak menghemat apa-apa dan tetap mengubah awal permintaan. Berapa banyak yang tetap utuh ditentukan oleh ukuran, bukan jumlah: hasil terbaru yang muat dalam seperempat anggaran tetap dipertahankan, dan selalu minimal satu. Versi sebelumnya mempertahankan enam hasil utuh secara tetap. Itu cocok untuk output perintah yang pendek, tetapi dengan pembacaan file yang panjang, sebagian besar anggaran dihabiskan oleh hasil lama.
Penolakan sekarang diberi tahu
Permintaan yang ditolak model sebagai tidak valid tidak lagi dicoba ulang; mengirim ulang permintaan yang sama hanya akan mendapat jawaban yang sama. Jika percakapan terlalu panjang untuk model, orang yang memakai akan melihat: “Percakapan ini menjadi terlalu panjang untuk dibaca model sekaligus. Mulai chat baru untuk langkah berikutnya. Semua yang sudah dibangun tetap ada.” Itu adalah sesuatu yang harus ditangani pengguna, bukan gangguan layanan, jadi tidak membangunkan tim kami.
Masalah 2: agen berhenti untuk “menghemat ruang”
Sebuah sub-agen yang diminta membaca 40 bab panjang berhenti setelah 2 bab, dengan alasan ingin menghemat ruang. Ia sudah memakai sekitar 100.000 token dari anggaran 400.000 token.
Ia tidak punya cara untuk tahu bahwa hasil lama sekarang akan dihapus untuknya. Jadi kami memberi tahu dia. Instruksi agen sekarang menyatakan bahwa ketika percakapan tumbuh melewati apa yang bisa diterima model, hasil tool yang paling tua dihapus dan yang terbaru tetap utuh. Jadi jangan menghentikan tugas panjang untuk menghemat ruang; teruslah bekerja, dan baca ulang sebuah file jika Anda membutuhkan yang sudah dihapus.
Perbaikan yang tidak bisa dilihat model bukanlah perbaikan dari sudut pandang model. Mekanismenya hanya membantu jika agen memercayainya.
Masalah 3: menghitung token seolah semuanya bahasa Inggris
Kami memperkirakan token tanpa menjalankan tokenizer, yaitu karakter dibagi empat. Itu aturan praktis yang masuk akal untuk bahasa Inggris. Untuk aksara lain, tidak: bahasa Rusia sekitar 2,2 karakter per token, dan Mandarin atau Jepang sekitar satu karakter per token.
Jadi sub-agen yang membaca bab-bab berbahasa Rusia mengirim permintaan sekitar 640.000 token, sementara perkiraan kami mengatakan jumlahnya masih di bawah anggaran 400.000. Perkiraan itu bisa dengan mudah membuat permintaan melewati batas keras model.
Perkiraan sekarang menghitung berdasarkan aksara: ASCII biasa empat karakter per token, Mandarin, Jepang, dan Korea satu karakter per token, dan semua yang lain (Sirilik, Yunani, Arab, huruf beraksen, emoji) dua karakter per token. Perkiraan ini memang dirancang agar cenderung tinggi. Untuk satu bab berbahasa Rusia, sekarang diperkirakan 43.423 token, sementara pengukuran sekitar 44.600; sebelumnya hanya 25.023. Karena sebuah pesan tidak pernah berubah setelah ditulis, perkiraannya dihitung sekali dan disimpan, bukan dihitung ulang di setiap langkah.
Apa yang kami pelajari
- Pangkas di tempat ukurannya sebenarnya berada. Dalam pekerjaan agen, itu adalah hasil tool, bukan pesan pengguna.
- Beri tahu agen tentang jaring pengamannya sendiri. Jika tidak, ia merencanakan dengan mengikuti batas yang sudah tidak berlaku.
- “Karakter ÷ 4” adalah asumsi bahasa Inggris. Apa pun yang menghitung token untuk pengguna multibahasa harus menghitung berdasarkan aksara, atau memakai tokenizer sungguhan.
- Perhatikan cache. Permintaan yang bagian depannya berubah di setiap panggilan lebih mahal dan berjalan lebih lambat.
Jika Anda membangun fitur AI ke aplikasi Anda sendiri, panduan kami tentang apa itu LLM dan cara memakai API LLM membahas context window dan token dari awal. Lebih banyak tentang cara sub-agen bekerja di Mythex ada di dokumentasi sub-agen.