まず思ったのは、「こういう事故、ほんとうに見つけにくい」ということだった。
キャッシュが効いているかどうかって、普通はレスポンスの速さだけ見ていると分からない。速くても、実は毎回“書き込み”料金を払っているだけかもしれない。この記事はその嫌な盲点を、かなり生々しく見せていた。
いちばん刺さったのは、原因が派手なバグではなく、datetime.now() みたいな“ちょっと便利な実装”だった点だ。
人間の感覚だと、会話の進行を助けるために現在時刻を入れるのは自然に見える。でも prompt caching みたいに「先頭部分が完全一致しないと外れる」仕組みでは、マイクロ秒つきの timestamp ひとつで毎回別物になる。ここは本当に容赦がない。キャッシュって、賢そうに見えて実際はかなり機械的なんだなと思った。
もうひとつ面白かったのは、set の順序問題で 4 worker 分の prefix がズレるくだりだ。
ローカルでは通るのに本番でだけ hit rate が伸びない、というのはかなりいやらしい。しかも Python の hash randomization が絡むと、見た目には同じデータでもプロセスごとに並びが変わる。sorted() 一発で直る話なのに、現象としては「なんとなく効いていない」にしか見えないのが怖い。こういうのは、LLM そのものの問題というより、周辺の“普通のコード”が足を引っ張る典型だと思う。
読んでいて少し気持ちよかったのは、著者がちゃんと usage を見ていたことだ。
cache_read_input_tokens と cache_creation_input_tokens を追っていなければ、たぶん「なんか高い」で終わっていたはずで、しかも 0% や 78% みたいな数字の違いは請求書だけでは見えにくい。LLM はブラックボックスっぽく扱われがちだけど、こういう地味なメトリクスを追えば、意外と人間側のミスが浮く。そこはかなり実務的で、読んでいて納得した。
この記事を読んで一番残ったのは、LLM の最適化は「モデルをどう使うか」より「入力をどう固定するか」の勝負になりやすい、という感覚だ。
派手なプロンプト技法より、volatile な値を末尾に逃がす、順序を固定する、テストでプロセス差を潰す。地味だけど、こういう基本がそのままコストに跳ね返る。AI 周りの話なのに、最後はかなりソフトウェア工学そのものだなと思った。
参考: Claude Prompt Caching Hit Rate Was 0%. One Timestamp Did It