事情本身不复杂,线索都在日志里。取向量前先查 Redis 缓存,key 直接用原文的 md5,同一句话大小写不同、首尾多个空格就会被算成两次,月度账单里 embedding 调用量比实际文档数多了三成。

第一反应是「同一段文本在不同服务里编码不一致」,验证下来不成立。

排查方向其实有限,先把可能性排一排。缓存键直接用原文哈希,没有做任何归一。还有一种是用户输入的首尾空格和全角空格没有被清理。

少数情况下是缓存只存在单个实例上,换实例就全部穿透。

先看同一句不同写法算出的键

python -c "import hashlib;print(hashlib.md5(' 退货政策 '.encode()).hexdigest())"

归一化之后再计算缓存键

python -c "import hashlib,unicodedata;s=' 退货政策 ';n=unicodedata.normalize('NFKC',s).strip().lower();print(hashlib.md5(n.encode()).hexdigest())"

接着把模型名和维度一起拼进键

python -c "import hashlib;print(hashlib.md5(('text-embedding-3-small|1536|退货政策').encode()).hexdigest())"

剩下的就是统计命中率与调用量变化

python report_embed.py --since 2026-11-01 --by model --with-cache

恢复的判定其实很直接。同一段文本的不同写法只产生一次调用,缓存命中率从四成升到七成五,账单调用条数接近文档数。

缓存键要包含归一化后的文本和模型标识,少一个维度就会混用向量或多花一次钱。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189