语义缓存
语义缓存与缓存检查点中间件的关系——精确匹配与语义相似度匹配两级、嵌入与相似度阈值配置、TTL 与失效、命中行为与短路、适用与不适用场景
语义缓存是灵渠平台在缓存检查点中间件之上提供的一项响应复用能力:对内容相近的查询请求,复用此前已生成过的响应,从而省去一次重复的上游推理调用,降低时延与成本。它不只看"两次请求字面是否完全一样",还能识别"措辞不同但意图相近"的请求——这一层判断由语义相似度匹配完成。
本节面向部署、运维与集成灵渠平台的内部管理员,讲清五件事:语义缓存与缓存检查点中间件的关系、精确匹配与语义相似度匹配两级如何协同、嵌入与相似度阈值如何配置、TTL 与失效如何管理,以及哪些场景适用、哪些不适用。
本节定位。 语义缓存挂载在缓存检查点中间件这一治理节点上,是其判定逻辑的一种实现形态。中间件的执行段位、短路语义与对称收尾遵循 中间件管道与扩展点 SDK 既定的编排模型,本节只补充"缓存如何判定命中"这一层,不改变管道骨架。
1. 与缓存检查点中间件的关系
中间件管道 把每次请求的治理拆成路由、缓存检查点、安全护栏三类中间件。缓存检查点中间件位于前置段,负责回答一个问题:这次请求是否还需要真的发给上游模型? 语义缓存就是这个判断的实现。
短路触发口径(重要)。 真正"跳过内建段、不再向上游发起推理调用"的短路,只由平台侧语义缓存命中触发(精确 / 语义两级中的任一级命中)。它与上游模型供应商自家的输入缓存是两回事:上游供应商缓存命中仍会真实调用上游,只是落到更低的输入单价档,并不跳过上游调用。两者的区分见本节末尾 口径注。
| 角色 | 由谁承担 | 说明 |
|---|---|---|
| 缓存检查点中间件 | 平台内建治理节点 | 在前置段判定本次请求能否复用历史响应;命中则短路内建段上游调用 |
| 语义缓存能力 | 挂在该节点上的判定逻辑 | 提供精确匹配 + 语义相似度匹配两级判定,给出"命中 / 未命中"结论 |
命中时,缓存检查点中间件按 短路语义 跳过内建段的上游推理,直接以缓存内容进入后置段返回。短路只跳过"还没发生的上游调用",不跳过已建立的前置处置的对称收尾——计量落账、命中标记写入等后置处置照常执行。
2. 精确匹配与语义相似度匹配两级
语义缓存采用两级判定,由快到慢、由严到宽依次尝试。默认两级串联:先试精确匹配,未命中再退到语义相似度匹配;两级都不命中才放行到上游。
| 级别 | 判定方式 | 命中条件 | 特点 |
|---|---|---|---|
| 精确匹配 | 对归一化后的请求输入、关键参数与流式标志取确定性指纹 | 指纹完全一致 | 无需调用嵌入,时延最低、结果稳定,对重试与流式天然友好 |
| 语义相似度匹配 | 对请求内容计算嵌入表示,与历史条目按嵌入相似度比对 | 相似度达到阈值 | 能识别措辞不同但意图相近的请求;需要一次嵌入计算 |
两级的命中结果都会在响应里标注命中类型(hit_type),便于事后区分这次复用走的是哪一级:
{
"cache": {
"semantic_hit": true,
"hit_type": "semantic",
"cache_entry_id": "<缓存条目标识>",
"threshold": 0.8,
"similarity": 0.95
}
}| 字段 | 含义 |
|---|---|
semantic_hit | 是否命中平台侧语义缓存(布尔)。与计量记录里的 usage.cache_hit(上游缓存命中)不是同一字段——前者由平台判定、命中即短路上游调用,后者以上游返回为准、只影响计量档位,详见 口径注 |
hit_type | 命中级别:exact(精确匹配)/ semantic(语义相似度匹配) |
cache_entry_id | 缓存条目标识,用于后续按条目失效 |
threshold | 本次比对所用的相似度阈值(仅语义命中时出现) |
similarity | 实际嵌入相似度得分(仅语义命中时出现) |
2.1 仅精确匹配模式(免嵌入)
若只需要"完全相同的请求去重",可只启用精确匹配级、不接入嵌入能力。此时每次请求按确定性指纹查缓存:指纹相同即命中,措辞不同一律视为未命中。
适合这几类诉求:只要精确去重、不需要相近意图的模糊匹配;不希望引入额外的嵌入计算开销;对时延极度敏感、希望零嵌入成本。仅精确匹配模式下,所有请求都走指纹判定,逐请求的命中级别覆盖标志不再生效。
3. 嵌入与相似度阈值配置
语义相似度匹配级需要两项关键配置:用哪套嵌入表示来度量"相近",以及相似度达到多少算"命中"。
{
"cache_checkpoint": {
"semantic": {
"enabled": true,
"embedding_model": "<嵌入模型中性名>",
"dimension": "<嵌入维度(须与模型产出一致)>",
"threshold": 0.8,
"ttl": "5m"
},
"exact": { "enabled": true }
}
}| 配置项 | 含义 | 建议 |
|---|---|---|
embedding_model | 计算嵌入表示所用的模型(统一中性名) | 接入时由平台校验维度一致性 |
dimension | 嵌入维度,须与所选嵌入模型实际产出的维度严格一致 | 维度不符会导致写入失败、读取静默落空 |
threshold | 相似度阈值(0~1),达到即判为语义命中 | 默认 0.8;调高更严格、误命中少但复用率低,调低更宽松、复用率高但误命中风险增 |
ttl | 缓存条目存活时长 | 见第 4 节 |
维度一致性须知。 一个缓存命名空间只能容纳同一维度的嵌入表示。一旦更换嵌入模型或调整维度,旧命名空间不会自动重建——后续写入会因维度不符而失败、读取静默落空。变更前应将缓存指向一个全新的命名空间,或先清空既有命名空间,再保存配置。
3.1 逐请求覆盖
默认 TTL 与相似度阈值可按单次请求覆盖,便于对特定业务线临时收紧或放宽:
curl https://<平台入口地址>/v1/chat/completions \
-H "Authorization: Bearer <API key>" \
-H "x-lq-cache-key: <缓存归组键>" \
-H "x-lq-cache-ttl: 30s" \
-H "x-lq-cache-threshold: 0.9" \
-H "Content-Type: application/json" \
-d '{ "model": "<上游模型中性名>", "messages": [ ... ] }'| 请求头 | 作用 |
|---|---|
x-lq-cache-key | 缓存归组键;未带此键的请求一律不参与缓存(既不读也不写) |
x-lq-cache-ttl | 覆盖本次请求的条目存活时长 |
x-lq-cache-threshold | 覆盖本次请求的相似度阈值 |
x-lq-cache-type | 强制本次只走某一级:exact(仅精确)/ semantic(仅语义);默认两级串联 |
x-lq-cache-no-store | 置真时只读缓存、不写入本次响应(用于一次性查询不污染缓存) |
缓存归组键是开关。 语义缓存只在请求携带
x-lq-cache-key时才启用——该键把同一会话 / 同一业务上下文的请求归到一组,缓存读写都在组内进行。不带键的请求完全绕过缓存,直接走常规路由与上游调用。
4. TTL 与失效
缓存条目不会无限存活。平台从三个层面控制条目生命周期,避免缓存膨胀与陈旧复用。
| 机制 | 触发 | 行为 |
|---|---|---|
| TTL 到期 | 条目存活超过 ttl | 自动失效,下次同类请求重新走上游并写入新条目 |
| 按条目失效 | 运维主动调用 | 用 cache_entry_id 精确清除单条 |
| 按归组键失效 | 运维主动调用 | 清除某个 x-lq-cache-key 名下的全部条目 |
主动失效通过控制平面接口完成,仅运营控制台可见:
# 按缓存条目标识清除单条
curl -X DELETE https://<平台入口地址>/api/v1/cache/entries/<缓存条目标识> \
-H "Cookie: <控制台会话凭证>"
# 清除某归组键名下全部条目
curl -X DELETE "https://<平台入口地址>/api/v1/cache/entries?cache_key=<缓存归组键>" \
-H "Cookie: <控制台会话凭证>"失效要趁早。 当上游模型版本切换、提示词模板更新或业务口径调整后,旧缓存可能产生陈旧复用,应及时按归组键失效相关条目;TTL 只是兜底,关键变更不应等 TTL 自然到期。
5. 命中行为与短路
语义缓存命中后,请求在管道里的后续行为遵循 缓存检查点的短路语义:
- 跳过上游调用。 命中即短路内建段,不再向上游模型发起推理,时延从"等上游一次完整生成"降到"一次缓存读取"。
- 护栏照常复核。 出站安全护栏在短路路径上同样执行——复用的内容仍要经过脱敏与应拒答复核,短路是节流手段,不绕过任何治理结论。
- 计量照常落账。 命中会落一条逐条调用记录,平台侧语义缓存命中标记(
semantic_hit)为真、命中类型随记录呈现,便于事后核对复用率。此处与计量记录里的usage.cache_hit(上游缓存命中)是两个并行字段:语义命中时根本不调用上游,上游的cache_hit自然不适用,二者区分见本节末尾 口径注。 - 流式同样支持。 命中条目若为流式响应,按原有分块顺序逐块回放,客户端体验与首次生成一致。
按会话历史长度的护栏:会话消息条数超过设定阈值时,缓存检查点会跳过缓存——长会话历史既难精确命中,又容易在语义层与无关会话产生误命中,跳过可避免低价值复用与误命中。该阈值可在缓存配置中调整。
6. 适用与不适用场景
语义缓存不是对所有请求都划算。判断是否启用、用哪一级,参照下表。
| 场景 | 适配级别 | 说明 |
|---|---|---|
| 高频重复的固定查询(如标准化问答、模板类指令) | 精确匹配优先 | 字面高度一致,精确级即可大量命中,零嵌入成本 |
| 措辞多变但意图集中(如同一问题的不同问法) | 语义相似度匹配 | 嵌入相似度能识别相近意图,复用率显著高于纯精确 |
| 检索 / 归纳 / 改写类的稳定任务 | 两级串联 | 输入相近、期望输出稳定,复用收益高 |
| 强时效、强个性化(如实时行情、含当前时间 / 用户态的查询) | 不适用 | 复用陈旧响应会出错,应绕过缓存 |
| 一次性、长尾、几乎不重复的查询 | 不适用或仅精确 | 语义级的嵌入开销换不回复用收益 |
| 超长会话上下文 | 谨慎 / 跳过 | 命中率低、误命中风险高,建议按会话历史阈值跳过 |
务实取舍。 语义缓存的价值高度依赖请求分布。建议先以默认阈值(0.8)和较短 TTL 在非时效业务线灰度,观察命中率与误命中反馈后,再逐步调阈值、放 TTL、扩大范围。
口径注:缓存命中标注的两层含义
平台计费侧的"缓存命中"与本节的语义缓存是两件并行、不混淆的事,请注意区分:
| 口径 | 含义 | 以谁为准 |
|---|---|---|
| 计费侧"缓存命中" | 上游模型供应商在其计价中标注的输入缓存命中(对应更低的输入单价档) | 以上游模型供应商返回为准 |
| 语义缓存命中 | 灵渠平台侧的响应复用能力——精确 / 语义两级命中,跳过上游调用 | 平台侧判定,落逐条记录 |
二者可以同时发生、也可以各自独立:一次语义缓存未命中的请求,仍可能在真正调用上游时落入上游的输入缓存命中档;一次语义缓存命中的请求则根本不调用上游,自然不涉及上游的缓存计费。计量与计费以上游返回的实际口径为底座,语义缓存是平台侧叠加的复用能力,两者并行记录、互不替代。
相关链接
- 中间件管道与扩展点 SDK:缓存检查点中间件的执行段位、短路语义、流式逐 chunk 处理与对称收尾。
- 扩展点 SDK 参考:以前置 / 后置对称 Hook 接入自定义缓存判定逻辑的接口契约。
- API 参考:缓存失效等控制平面接口的端点契约与通用约定。