从零开始搭建知识库 · EP07 · 范式篇(二)隐式缓存 vs 显式缓存

0 阅读1分钟

问题定义:这份编译产物到底该怎么放才最省

EP06 把两种范式对跑完,编译侧的成本结论是:命中前缀缓存后每问省一半以上,约 6 问回本。但这笔账完全押在缓存命中上,第一问没命中时编译侧比检索侧还贵 44%。两个悬案当时没解:隐式缓存到底活多久,全凭服务端;百炼还有一条显式缓存路,创建价 15 元、命中价 1 元(每百万),数字看着比隐式命中的 1.5 元还便宜,规则却完全不同。

本期实验目标:同一份资产,把两种缓存对着跑一遍,拆出三件事——隐式的失效边界、显式的命中判定、各自的回本条件。资产沿用 EP06:编译产物 wiki-A1a-neutral.md(7,929 token 的 prompt 前缀)、qwen3.8-max、system「你是暖屋家居的客服助手。」、四道问法(q1 报销发票 / q2 包邮运费 / q3 报销到账 / q4 新疆沙发)。11 次付费调用,合计约 0.93 元。

核心结论先行:显式缓存的命中判定是「完整请求一致」,不是「公共前缀」。「一份知识库前缀 + 千变万化的问题」这个最标准的知识库问答形态下,显式每一问都付 125% 的创建价,单问稳态比隐式贵 5.96 倍。

两种缓存机制对比:隐式缓存自动匹配消息的公共前缀,无需配置,命中按每百万 1.5 元计费;显式缓存需要在知识库块上手动挂 cache_control 标记,创建按每百万 15 元计费,命中按 1 元计费

单价四档,TTL 写在计费类型名里

bl model list --model qwen3.8-max 不需要鉴权,现场拉价:

档位

单价

相对输入价

输入

12 元 / M

100%

输出

36 元 / M

隐式命中

1.5 元 / M

12.5%

显式创建

15 元 / M

125%

显式命中

1 元 / M

8.33%

工程上值得记的一处:显式创建的计费类型名是 input_token_cache_creation_5m。TTL 5 分钟不在文档正文里,写在字段名里。后面 B3 实测这个 5 分钟是真的。

A 组:隐式缓存的失效边界

EP06 的 B 组拼法原样重跑:编译产物当 user 消息,追加问题,四道题换着问,控制调用间隔。

调用

时间

距上次命中

命中量

成本

A1

13:25:39

隔了两天

0

0.1075 元

A2

13:25:59

20 秒

7,168

0.0345 元

A3

13:35:31

9 分 32 秒

7,168

0.0285 元

A4

13:49:30

13 分 59 秒

7,168

0.0419 元

读表三条:

  1. 隔两天缓存全没了,A1 的 7,929 个输入 token 全价结算。低频负载的冷启动税有了实测数字
  2. A2 的命中量 7,168 与 EP06 五次调用逐位一致,前缀指纹没变,两期数据可互相印证
  3. A3、A4 是意外项:距首次命中 23 分半后隐式缓存仍活着。**隐式存活至少 14 分钟起步,两天必然失效,中间边界不透明。**这比直觉长得多

CLI 没有缓存命令,但 --messages-file 能透传

试显式的第一步是找入口。bailian-cli 的 reference 文档全文 grep「cache」「缓存」,零命中。CLI 没有专门的缓存命令。

但官方 API 的显式缓存靠 messages 数组里的结构标记,bl text chat --messages-file 传什么结构就发什么结构。通路现成,透传。

隐式组,user 一条字符串:

[
 {"role": "system", "content": "你是暖屋家居的客服助手。"},
 {"role": "user", "content": "(整份编译产物)\n\n---\n以上是公司知识库。用户问题:报销发票怎么提交"}
]

显式组,user 拆成数组,知识库块挂 cache_control

[
 {"role": "system", "content": "你是暖屋家居的客服助手。"},
 {"role": "user", "content": [
   {"type": "text", "text": "(整份编译产物)\n\n---\n以上是公司知识库。",
    "cache_control": {"type": "ephemeral"}},
   {"type": "text", "text": "用户问题:报销发票怎么提交"}
 ]}
]

两组展开后文本完全一致,模型同款,参数同款,唯一差异是标记。单变量。(messages 文件照例 UTF-8 存盘,别走命令行传中文,这是 EP06 踩过的坑。)

透传判定标准前置:显式组的 usage 必须出现 A 组从没见过的新字段,才算服务端真执行了缓存创建;光看 cached_tokens 变化不算数,那可能只是隐式命中。

B0 实测:

"prompt_tokens_details": {
  "cache_creation": {"ephemeral_5m_input_tokens": 7923},
  "cache_creation_input_tokens": 7923,
  "cache_type": "ephemeral",
  "cached_tokens": 0
}

三个新字段全到位,ephemeral_5m_input_tokens 与价目表的计费类型名对上。7,923 个 token 走了显式创建,答案 291 字,质量无异常。

反向信息一条:B0 距 A4 仅 31 秒,A4 刚隐式命中过,B0 的 cached_tokens 却是 0。挂了标记就退出隐式局。

B 组:换个问题,就重新创建

预期剧本:B0 创建,B1 换问题连问,命中知识库前缀,付 1 元命中价。

调用

问题

距上次

创建量

命中

成本

B0

q1 报销

7,923

0

0.1305 元

B1

q2 包邮

12 秒

7,929

0

0.1365 元

B2

q4 新疆沙发

15 秒

7,936

0

0.1418 元

B1 距 B0 只有 12 秒,共享 7,900 多个相同 token 的前缀,没命中,全额重新创建。B2 同样。显式缓存不按前缀匹配,这是第一层证据。

9 秒对照实验:命中判定拆解

三步,前后各隔 9 秒:

**B3:与 B0 逐字节相同,等 8 分钟再发。**B0 缓存创建于 13:50:01,TTL 5 分钟。13:58:14 发出 B3,过去 8 分 13 秒。结果:重新创建 7,923,没命中。TTL 5 分钟实测成立,过期即蒸发。

**B4:与 B3 逐字节相同,隔 9 秒再发。**命中,7,923,零创建,成本 0.0202 元,全期最便宜的一问,比隐式最好的那问还低 29%。

**B5:与 B4 只差问题文本,隔 9 秒发。**没命中,重新创建 7,926。

命中判定对比:隐式缓存只要知识库前缀匹配就命中,无论问题怎么换;显式缓存只在完整请求逐字节一致时才命中,换了问题不命中,原样重发才命中

五个数据点(B1/B2/B3/B4/B5)同向:

**百炼显式缓存的命中判定是「完整请求一致」,不是「公共前缀」。**整个 messages 数组逐字节相同才算命中。

这个语义与 Anthropic 的前缀缓存不同。Anthropic 是标记位之前的前缀命中即可,标准用法就是「固定知识库 + 变化问题」。把那套直觉搬过来,每一问都付 125% 创建价,比隐式稳态贵 6 倍。显式的适用面收窄到:完全相同请求的重复,多 Agent 并行同 prompt、批量重试、评测集重跑。

D1 交叉验证:两条通道两套独立账

实验矩阵埋了交叉项:显式缓存建好后,用不带标记的隐式拼法问一道,看通道通不通。

D1 跑在 B0、B1 之后 9 秒,隐式拼法,问 q3。命中量 7,168,隐式口径,不是显式刚创建的 7,923。

数字本身就是证据:若通道共享,D1 该吃到覆盖更全的 7,923;实际吃到的是隐式按 1,024 对齐的 7,168。官方公告「隐式缓存与显式缓存对于同一次模型调用不共享」,这里拿到数值版,连计费口径都不一样。

两条平行账本被一堵标有互不共享的砖墙隔开:左边蓝色隐式账本 7168 token,右边橙色显式账本 7923 token,不带标记的请求走左边,带标记的请求走右边

四个方向测齐:显式不吃隐式(B0),隐式不吃显式(D1),显式创建不破坏隐式链(D1 照常命中),两通道各记各账。实操推论:显式实验跑完,隐式缓存毫发无伤,两套负载可并存。

隐式的 1,024 对齐:命中量的地板

A2/A3/A4/D1 四次命中量恒为 7,168,而这些调用的 prompt 总长在 7,929 到 7,942 之间浮动(问题长短不同)。

7,168 = 7 × 1,024。**隐式缓存按 1,024 token 块对齐存储,公共前缀里不满一块的尾部不入缓存。**每次约 767 个 token 按全价结算,永远吃不到折扣。

摊薄后隐式等效输入单价 2.515 元每百万,标准价的 21%。名义 12.5% 只对入了缓存的 token 成立。对照组显式无此截断:创建量与命中量都是 7,923,覆盖 99.9%。单价低(1 元对 1.5 元)加覆盖全,显式命中的真实优势,可惜被「换问题即 miss」锁死。

成本账:回本边界在哪

四种稳态,输入侧等效单价:

稳态

等效输入单价

相对标准价

出处

全价冷启动

12.00 元 / M

100%

A1

隐式稳态

2.515 元 / M

21.0%

A2

显式创建

15.00 元 / M

125%

B0-B5 五次

显式命中

1.008 元 / M

8.4%

B4

场景一,知识库问答真实形态(一份前缀连问 5 个不同问题):

  • 隐式:首问全价 0.0951 元,后四问各 0.0200 元,合计 0.1750 元
  • 显式:每问创建价 0.1189 元,合计 0.5946 元

3.4 倍。单问稳态 0.1189 ÷ 0.0200 = 5.96 倍。这个场景显式是纯负优化:8.33% 命中价一次用不到,12.5% 隐式命中也放弃了(挂标记即出隐式局),每问付 125%。

场景二,显式的甜区(同一份 messages 原样重复,间隔 5 分钟内):

重复次数

隐式合计

显式合计

3 次

0.1349 元

0.1349 元

打平

5 次

0.1747 元

0.1509 元

显式省 13.6%

10 次

0.2741 元

0.1909 元

显式省 30.4%

**同题 5 分钟内问 3 次以上显式开始赢,极限省 60%。**换一个问题立刻回到 6 倍的贵。TTL 不给第二次机会:5 分钟内没有下一次命中,125% 创建溢价全蒸发。

四档输入侧成本柱状图:显式创建 15 元是最高的红色柱,全价 12 元是灰色柱,隐式稳态 2.5 元是较矮的蓝色柱,显式命中 1 元是最矮的绿色柱

选型结论

负载形态

怎么放

依据

客服问答:前缀固定,问题千变万化

隐式,什么都不用配

显式换问题即创建(B1/B2/B5),每问贵 6 倍

同题复现:评测集重跑、批量重试、多 Agent 并行同 prompt

显式标记

第 3 次调用回本,之后最多省 60%(B4)

低频零散:一天问不了几次

哪种都救不了,考虑回检索范式

隔两天全失效(A1);TTL 5 分钟蒸发(B3)

用隐式时想多命中

控制节奏:14 分钟内跟问有效,问题文本不影响前缀命中

A3/A4 实测

本系列那份编译产物落在第一行:什么都不配,靠隐式。要做的只有把提问节奏控制在失效边界内,让 7,168 那段前缀一直热着。批量评测或多 Agent 并行出现的那天,再回来挂显式标记。

下期进入权限边界:同一份库切两个权限视图,编译产物、检索 metadata 过滤、Agent 提示词三种放法各能守住什么。

API Key 在控制台的密钥管理页签发,新用户有免费额度。

本文全部数据来自 bl CLI 实测。11 次调用的完整 usage、思考链与产物留痕于项目仓库。命令格式可能随版本更新调整,以官方文档为准。