从一次缓存命中率对不上的排查说起
上周在 Codex 里跑一个长系统提示的对照实验,同一段工具说明分别喂给 Sol、Terra、Luna,结果三次返回的 cached tokens 完全对不上:Sol 稳定命中,Terra 偶尔命中,Luna 干脆一次都没命中。一开始怀疑是模型差异,后来发现是请求体里 cache breakpoints 的位置写错了——三款模型对显式断点的解析行为并不完全一致。这篇就把这套验证流程完整走一遍:从 TaoToken 官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 拿 Key,到 Codex 或兼容 OpenAI 的客户端里配通 Base URL,再到逐款切换模型名跑 prompt caching 对照。TaoToken 在这里只负责提供 Key 和统一 Base URL,不替模型做缓存,缓存行为完全由 GPT-5.6 服务端决定。
GPT-5.6 这次把模型拆成 Sol(太阳)、Terra(大地)、Luna(月亮)三档,开发者侧新增了更可预测的 prompt caching、显式 cache breakpoints,以及至少 30 分钟的缓存生命周期。对长提示复用场景来说,这三档模型在缓存命中上的差异,比 benchmark 分数更值得先摸清楚。目前新模型只对 trusted partners 开放有限预览,所以本文的前提是:你已经拿到了对应 API 或 Codex 权限,接下来要做的只是把调用链路配通、把缓存行为验证清楚。
TaoToken 前置:Key 与 Base URL 的获取
在开始写配置之前,先把两样东西准备好。
第一是 API Key。打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end ,注册后在控制台创建 Key。这个 Key 会用在所有后续请求的 Authorization 头里,格式是Bearer YOUR_API_KEY。如果你已经有 Key,直接跳到下一步。
第二是 Base URL。TaoToken 的统一入口是:
https://taotoken.net/api注意两点:不要在后面加/v1,也不要带任何 UTM 参数。很多客户端默认会拼接/v1/chat/completions,如果你填的 Base URL 已经带了/v1,最终路径会变成/v1/v1/chat/completions,直接 404。这一点在 Codex 的 config.toml 和兼容 OpenAI 的客户端里都容易踩。
TaoToken 的定位是通道层:它提供 Key 和统一 Base URL,把请求转发到对应的模型服务。缓存命中与否、缓存生命周期多长,取决于 GPT-5.6 服务端对 cache breakpoints 的处理,TaoToken 不介入也不改写这部分逻辑。所以验证缓存时,你看到的 cached tokens 字段是模型侧的真实返回,可以直接用来做三款模型的对照。
如果你需要管理多个 Key 或查看用量,可以走 API Keys 页面;接入细节和字段说明在接入文档里;模型对话入口可以用来做单次快速验证。这几个入口在后面的 CTA 部分会再给一次。
可复制配置:Codex 与兼容 OpenAI 客户端
Codex 的 config.toml
Codex 使用config.toml管理模型和 provider。一个最小可用的配置如下:
model = "gpt-5.6-sol" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"然后在环境变量里设置:
export TAOTOKEN_API_KEY="YOUR_API_KEY"切换模型时,只改model字段即可,比如改成gpt-5.6-terra或gpt-5.6-luna。base_url保持https://taotoken.net/api不变,不要加/v1。
兼容 OpenAI 的客户端
如果你用的是 Python 的 openai SDK 或其他兼容客户端,配置方式类似:
from openai import OpenAI client = OpenAI( api_key="YOUR_API_KEY", base_url="https://taotoken.net/api" ) resp = client.chat.completions.create( model="gpt-5.6-sol", messages=[ {"role": "system", "content": LONG_SYSTEM_PROMPT}, {"role": "user", "content": "ping"} ] )同样,base_url只写到/api,不要带/v1。SDK 会自动补全后续路径。
关于 cache breakpoints 的写法
GPT-5.6 支持显式 cache breakpoints,意思是你可以明确告诉服务端:从哪一段内容开始缓存、到哪一段结束。在兼容 OpenAI 的请求体里,通常通过在 message 的 content 部分加标记来实现。一个常见的做法是把长系统提示拆成两段:前一段是需要缓存的部分,后一段是每次变化的用户输入。缓存断点放在两段之间。
具体字段名和写法以接入文档为准,不同客户端对 breakpoints 的暴露方式不一样。核心思路是:固定不变的长内容放在断点之前,变化的内容放在断点之后。这样 Sol、Terra、Luna 在收到同一段前缀时,才有机会命中缓存。
验证请求:三款模型各发两次
配置好之后,验证流程分三步。
第一步,固定一段长系统提示。建议用你实际项目里的工具说明或系统规则,长度在 2000 token 以上,这样缓存效果才明显。把这段内容存成一个变量,三款模型共用同一段。
第二步,对每款模型发两次请求。第一次请求会建立缓存,第二次请求应该命中缓存。两次请求之间不要超过 30 分钟,否则缓存可能过期。请求体里除了模型名不同,其他部分完全一致。
import time LONG_SYSTEM_PROMPT = "..." # 你的长系统提示,2000+ token for model in ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"]: for i in range(2): resp = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": LONG_SYSTEM_PROMPT}, {"role": "user", "content": "ping"} ] ) usage = resp.usage print(model, i, usage.prompt_tokens, usage.get("prompt_tokens_details", {})) time.sleep(1)第三步,看返回的 usage 字段。重点关注prompt_tokens_details里的cached_tokens。第一次请求cached_tokens通常为 0 或很小,第二次请求应该明显上升。如果第二次仍然是 0,说明缓存没命中,需要检查 breakpoints 的位置或请求体是否完全一致。
成功结果长什么样
一个正常的对照结果大致是这样:
- Sol:第一次
cached_tokens=0,第二次cached_tokens接近系统提示的 token 数,命中稳定。 - Terra:第一次
cached_tokens=0,第二次有命中,但可能比 Sol 略低,取决于断点解析。 - Luna:第一次
cached_tokens=0,第二次命中情况视版本而定,部分预览版本对显式断点的支持还在收敛。
如果三款模型第二次请求的cached_tokens都明显大于 0,说明缓存链路是通的。如果只有 Sol 命中,Terra 和 Luna 不命中,先别急着下结论说模型不支持,大概率是请求体或断点写法的问题,往下看排查部分。
本篇常见错排查
Base URL 带了 /v1
这是最高频的错误。https://taotoken.net/api/v1会导致路径重复,返回 404 或 401。正确写法是https://taotoken.net/api,不带/v1,也不带 UTM 参数。
请求体不一致导致缓存不命中
缓存命中的前提是前缀完全一致。如果你在两次请求之间改了系统提示里的任何一个字符,包括空格和换行,缓存都会失效。验证时把系统提示存成变量,确保两次请求用的是同一个字符串。
cache breakpoints 位置放错
断点应该放在固定内容和变化内容之间。如果你把断点放在系统提示开头,或者放在用户输入之后,缓存范围就不对。检查你的客户端是怎么暴露 breakpoints 的,确认断点落在长提示的末尾。
两次请求间隔超过 30 分钟
GPT-5.6 的缓存生命周期至少 30 分钟,但超过之后会失效。验证时尽量在几分钟内完成两次请求,不要隔夜再跑。
模型名写错
Sol、Terra、Luna 对应的模型 ID 以接入文档为准。如果你把gpt-5.6-sol写成gpt-5.6-sun或sol,请求会直接报模型不存在,而不是缓存不命中。先确认模型名能正常返回,再验证缓存。
把 TaoToken 当成缓存层
TaoToken 不替模型做缓存,也不改写 cache breakpoints。如果你发现缓存行为异常,排查方向应该在请求体和模型侧,而不是通道层。通道层只负责转发,返回的 usage 字段是模型侧的真实数据。
语义一致 CTA
验证完三款模型的缓存行为后,如果你要继续做接入或排障,可以走这两个入口:API Keys 页面管理你的 Key,接入文档查看字段和 breakpoints 的详细说明。如果你要长期跑编码或 Agent 任务,Coding Plan 更适合持续调用场景。如果只是想快速验证某个模型名能不能通,模型对话入口可以直接发请求看返回。
整套流程的核心就一句话:从官网拿 Key,Base URL 填https://taotoken.net/api,固定同一段长提示,对 Sol、Terra、Luna 各发两次请求,看cached_tokens是否稳定上升。缓存行为由模型侧决定,TaoToken 只保证通道通。把这一步跑通之后,再逐款切换模型名做更细的对照,就不会被发布新闻里的参数带偏了。