这类问题我又碰上了一次。把客服提示词迁到 Langfuse 3.2 管理,代码里用 get_prompt 并按 label=production 拉取,上线后 Anthropic 的 cache_read_input_tokens 从每轮 1800 掉到 0,成本翻了近一倍。
第一反应是「prompt 拼在变量之后,可变内容跑到了缓存前缀前面」,验证下来不成立。
真正麻烦的地方在于,几个原因的现象几乎一样。prompt 文本里带了版本号注释,前缀每版都不同;每次拉取都用最新 label,灰度期间前缀在两版间跳;SDK 默认把 prompt 包成对象,序列化顺序每次不同。
动手时先把实际发送的 system 文本导出来比对前后两次
python -c "import hashlib;t=open('sys.txt',encoding='utf-8').read();print(len(t),hashlib.md5(t.encode()).hexdigest())"
再往下确认前缀是否被版本号污染
python -c "print(open('sys.txt',encoding='utf-8').read()[:120])"
锁定 prompt 版本号而不是跟随 label
python -c "from langfuse import Langfuse;print(Langfuse().get_prompt('cs-reply',version=12).compile()[:80])"
等前面都确认过,再把固定前缀放前面变量放后面再测命中
python cache_probe.py --prefix-len 1700 --repeat 3
恢复的判定其实很直接。连续三次请求的 cache_read_input_tokens 稳定在 1700 以上,账单里缓存读的单价明显低于输入单价。
提醒一点。缓存命中看的是逐字节前缀,任何版本号、时间戳或变量顺序变动都会让前缀失效,prompt 管理工具再方便也不能把可变内容放前面。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
