Ini artikel jawabannya. Kalau kamu belum mengerjakan lab 6 dan masih mau mencoba sendiri, tutup dulu halaman ini. Sisanya di bawah adalah jawabannya, lengkap dengan angka pengukurannya.
Bagian menariknya bukan perbaikannya. Yang menarik: tiga dari lima suntingan tidak mengubah angka apa pun selama dua tahap, dan yang mengubah segalanya cuma satu baris yang tidak akan ditandai siapa pun saat review.
Poin Penting
- Array tool adalah satu-satunya baris yang mahal. Timestamp registry di dalam deskripsi tool menahan hit rate di 0,0%; membuat definisinya konstan menaikkannya ke 78,4%.
- Memindahkan jam dan breakpoint saja tidak mengubah apa pun. Keduanya perlu, tidak satu pun cukup, dan keluaran
make checkmengatakannya di setiap tahap. - Penulisan ulang transkrip membeli 10.029 token dan menagih empat kali lipat. Loop yang diperbaiki mengirim 6% token lebih banyak dan membayar 34% dari jalan tanpa cache.
- Penulisan satu jam adalah yang bertahan melewati jeda sepuluh menit. Setelah jeda, giliran berikutnya membaca 6.135 token dari cache alih-alih menulisnya ulang.
Delapan keadaan, satu loop
Diukur dengan scripts/check.py, di mesin yang sama, tanpa mengubah data/, scripts/check.py, atau agent/provider.py:
| tahap | perubahan | hit rate | tagihan | hijau |
|---|---|---|---|---|
| 0 | apa adanya | 0,0% | $0,4841 | 0/7 |
| 1 | jam keluar dari system prompt | 0,0% | $0,4840 | 0/7 |
| 2 | + breakpoint di ujung buku panduan | 0,0% | $0,4840 | 0/7 |
| 3 | + array tool yang stabil | 78,4% | $0,1865 | 2/7 |
| 4 | + transkrip append-only | 80,4% | $0,1857 | 4/7 |
| 5 | + tanggal pindah ke giliran user | 80,4% | $0,1860 | 5/7 |
| 6 | + TTL satu jam untuk buku panduan | 90,9% | $0,1437 | 6/7 |
| 7 | + loop melaporkan angkanya sendiri | 90,9% | $0,1437 | 7/7 |
Permintaan yang sama dengan caching dimatikan menagih $0,4017 di tahap 0 dan $0,4218 di tahap 7. Angka kedua lebih besar karena loop yang diperbaiki membawa transkripnya alih-alih meringkasnya.
Array tool, tempat uangnya berada
def tools_for_request() -> list[dict]:
return TOOLS
Tahap 3 cuma satu baris, dan dia menaikkan hit rate dari nol ke sebagian besar. Provider mem-hash definisi tool sebelum menghash system prompt, jadi field notes yang berisi waktu snapshot registry membatalkan semua yang di bawahnya, di setiap permintaan, selamanya. Model tidak pernah membaca field itu. Dia ada untuk manusia.
Urutannya juga penting. Menghapus timestamp dari system prompt di tahap 1 benar dan tidak membeli apa pun, karena tools-nya masih menyerahkan prefix berbeda ke cache tiap giliran. Sebuah prefix hanya sekuat bagiannya yang paling tidak stabil, dan tools duduk di paling atas.
Breakpoint, dan tanggal yang harus pindah
Breakpoint mengerjakan dua hal: menulis entri di batas itu, dan menjadi posisi yang dicari mundur oleh permintaan berikutnya. Memarkirnya di pesan terakhir berarti entrinya ditulis di batas yang diperpanjang giliran berikutnya, jadi permintaan berikutnya tidak menemukan apa pun kecuali jendela pencariannya mencapai tulisan yang lebih lama.
blocks = [Block(role="system", text=system_prompt(), cache=True, ttl=LONG_TTL)]
Dua breakpoint akhirnya menjadi bentuk yang benar: satu di ujung buku panduan, disimpan sejam, dan satu di ujung transkrip yang tumbuh, disimpan lima menit bawaan. Yang pertama adalah yang dibagi semua tiket; yang kedua adalah yang menyelamatkan giliran sebelumnya.
Tanggalnya lalu harus pindah, bukan hilang. Pemeriksaan C gagal kalau prefix statis berubah antara dua hari, dan gagal lagi kalau tanggalnya tidak pernah sampai ke model, jadi satu-satunya perbaikan yang lolos keduanya adalah mencap gilirannya:
history.append({"role": "user", "text": f"{text}\n\n[session date {today(provider.clock)}]"})
Tahap 5 adalah tempat pemeriksaan C jadi hijau sementara tagihannya tidak bergerak sama sekali, dan itulah intinya. Kebenaran dan biaya adalah dua gerbang terpisah di sini.
Penulisan ulang yang tidak dihitung siapa pun
Setiap giliran ketiga loop mengganti transkrip dengan ringkasan satu baris. Itu menghemat 10.029 token selama satu jalan dan membuat setiap prefix setelah yang kedua tidak berguna. Versi yang diperbaiki mengirim 174.883 token dibanding 164.854 milik versi awal, dan membayar $0,1437 dibanding $0,4841.
Kalau kamu perlu ringkasan, tambahkan sebagai pesan baru di ujung. Blok sebelumnya tetap utuh, prefix-nya masih cocok, dan ringkasannya menjadi bagian dari riwayat yang di-cache alih-alih lubang di dalamnya.
Masa hidup itu pengali tagihan, bukan detail
Dengan bawaan lima menit, diamnya pelanggan selama sepuluh menit menagih satu penulisan ulang penuh 6.135 token per tiket. Dengan penulisan satu jam di 1,25x hanya untuk blok itu, jedanya gratis: giliran sesudahnya membaca 6.135 token dari cache. Premi tulisnya dibayar sekali per jam per buku panduan, dan buku panduannya tidak berubah.
Perhatikan bentuk keputusannya. Blok statis mendapat penulisan mahal yang berumur panjang; transkrip mendapat yang murah dan berumur pendek. Satu TTL untuk seluruh prompt akan salah di dua arah sekaligus.
Penghitungnya bagian dari perbaikannya
Pemeriksaan G ada di urutan terakhir karena suatu alasan. Dia menjalankan loop sebagai program dan membandingkan baris yang dicetaknya dengan ledger:
$ python3 agent/loop.py
summary turns=24 hit_rate=0.909 cost_usd=0.143682
Tanpa baris itu, tahap 0 dan tahap 7 tidak bisa dibedakan dari luar: dua-duanya menjawab semua tiket, dua-duanya keluar dengan kode 0, dua-duanya kelihatan baik-baik saja. Angka yang dilaporkan loop tentang dirinya sendiri dan diturunkan ulang oleh pemeriksa adalah bedanya perbaikan dengan keyakinan.