为什么要缓存向量
同一段文本被反复向量化是最常见的浪费:重建索引、增量更新或调整下游参数时,往往又要跑一遍全量 embedding。按内容哈希做缓存键,把文本到向量的映射存下来,重跑时直接命中缓存,可以同时省掉时间和调用费用。注意缓存键必须包含模型标识与版本,否则换模型后仍会命中旧向量。
基本信息
| 缓存键 | 内容哈希加模型标识与版本 |
|---|---|
| 键的归一化 | 生成键前先归一化空白与换行,避免同一文本算出不同键 |
| 失效策略 | 模型版本变化即整体失效 |
| 存储位置 | 进程内、本地文件或集中式缓存,按场景选择 |
典型使用场景
- 重复重建索引:调切分参数后重跑,未变更的切片直接命中缓存
- 增量更新:新文档入库时只计算新增与变更部分的向量
- 失败重跑:批次中断后重跑,已成功的部分不重复计费
- 成本统计:命中率可以直接换算成节省的调用次数
- 多机并行:集中式缓存让多台机器共享计算结果
内容哈希做缓存键
内容哈希做缓存键
import hashlib
def content_key(text: str, model_tag: str) -> str:
normalized = " ".join(text.split()) # 先归一化再算哈希
h = hashlib.sha256(normalized.encode("utf-8")).hexdigest()[:32]
return f"{model_tag}:{h}" # 键里必须带模型标识与版本
# 命中缓存则复用向量;未命中再调用 embed 并回写
缓存层次
| 层次 | 做法 | 命中场景 |
|---|---|---|
| 进程内 | 字典或 LRU 缓存 | 单次任务内的重复文本 |
| 本地文件 | 键值文件或轻量数据库 | 跨次任务重跑 |
| 集中式 | 共享缓存服务 | 多机并行索引 |
| 索引侧复用 | 未变更切片不重算 | 增量更新与版本升级 |
缓存键要包含模型名与版本,否则升级模型后会命中旧向量,检索结果与预期不符且没有报错提示。
缓存条目要设容量上限与淘汰策略:内容哈希分布很散,长期不清理会让缓存体积持续增长,最终占满磁盘,进而影响索引任务本身。
命中率要纳入监控:命中率突然下降通常意味着归一化规则或切分逻辑变了,这类变化同样会影响检索结果,值得一并排查。