六个月前,你的提示词前缀是 4,000 tokens。它稳定、缓存预热,几乎可以摊销到不计成本——系统指令的每次调用附加费,相比每次响应的成本,只是一个舍入误差。今天那个前缀变成了 11,000 tokens,你的缓存命中率从 92% 滑到了 31%,你的推理账单上升了 4 倍。团队里没有人能指出是哪个 PR 干的。没有一条 commit message 写着"将提示词增加 7,000 tokens"。每一次修改都很小,每一次修改都有理有据,每一次修改都干干净净地合入了。
提示词前缀长出胳膊和腿,就像地下室积攒纸箱一样。一个团队需要注入用户的订阅等级,这样 agent 才能解释套餐限制。另一个团队需要用户时区的今天日期,这样"明天提醒我"才能工作。第三个团队把当前 A/B 变体名硬塞进去,这样 eval traces 才能切片。市场团队加进了当前促销 banner,这样 agent 才能适时提及它。合规团队加进了功能标志清单,这样模型才能拒绝那些不在灰度名单里的用户访问 beta 功能。每一条都是一行的添加。每一条单独看都站得住脚。但加起来摧毁了你的缓存。
这是新一代的依赖地狱。它无声地复合,躲过代码评审,只在你的 CFO 不看的那条预算线超过某个阈值时才浮出水面。你的团队为其他回归形式建立的防御——类型检查、CI、eval gates——都不会看这个层面。那个在系统提示里加了一行的 PR 没有改变一个测试。它没有翻动一个基准。它改变了之后每一次请求的可缓存性,而那次改动的成本被每个用户、永远地、每次一个 token 地支付,直到有人把那行代码再拽出来。
为什么前缀是一个没有主人的共享资源
系统提示在代码库里处在一个尴尬的位置。它技术上只是一个配置文件里的字符串,但功能上它是一个共享的 API 表面。每个发布 AI 功能的产品团队都有理由往里加东西。PM 想让 agent 知道当前的促销活动。增长团队想让 agent 推荐升级路径。客服想让 agent 永不提到已下线的功能。法务想要免责声明段落。提示词就是所有这些需求最后落地的地方,因为提示词是唯一所有人一致同意"模型会看到这条约束"的地方。
问题在于这个提示词没有维护者。仓库里其他每一个共享资源都有 owner。Dockerfile 有人负责让构建保持精简。CI 配置有人负责调成本。package.json 有一位 steward 顶住添加依赖的压力。系统提示没有对应的人。第一个写它的工程师已经换团队了。on-call 轮值不包括它。当一个新团队需要加一行时,他们找到这个文件,加上那行,合并。没有针对提示词前缀膨胀的评审,因为没有任何评审者被告知那是他们的工作。
这就在 token 空间里造就了一场公地悲剧。每一个出资团队都在理性地优化自己的功能;没人看得见自己添加内容的总成本。成本是真实的,但分散。收益是集中且可见的——功能跑起来了,demo 落地了,PR 合入了。工程经济学 101 已经预测了结果。公地崩塌,账单在一个季度后到来,应对的是一场恐慌式的优化冲刺,而不是本可以预防它的常态化所有权。
究竟是什么杀死了缓存命中率
各大供应商的提示词缓存共享一个结构性假设:它们以前缀的字节、按顺序、直到第一个分歧的 token 为 key。Anthropic 要求显式的 cache_control 标记,并把缓存当作严格前缀匹配。OpenAI 在 1,024-token 阈值之上自动应用缓存,但底层用同样的精确前缀机制。Google 的实现细节有别,但精神不变。这三家的缓存被杀死,不是被提示词深处的内容变化,而是被任何发生在可缓存边界之前的改动。
这就是动态注入模式如此致命的原因。当一个团队在系统提示的第 47 行写下 "今天是 {date}" 时,他们并没有添加 11 tokens 的膨胀。他们添加了 11 tokens 的膨胀,并使其后前缀中的每一个字节失效。缓存从位置 0 开始往前读,在第一个不匹配的字节处停下。在位置 47 注入一个每请求变化的值,那么位置 48 到 11,000 现在都是缓存冷态,无论它们单独看多么稳定。
工程师们靠惨痛的代价学到这一点。第一个迹象通常是一个跟功能发布对不上号的成本峰值。延迟和成本同步上升,因为模型正在处理它过去从缓存内存里读的 tokens。eval 分数没动,因为提示词内容仍然正确;只是缓存 key 不再匹配。等团队搞清楚发生了什么,账单已经累积了一个计费周期,加日期注入那行的工程师已经在另一个 sprint 里捍卫另一个优先级了。
按字节的所有权台账
能守住底线的模式是把提示词前缀当作一个共享依赖清单。前缀里的每一个字节都有 owner、引入日期和依赖关系。当一个团队请求添加内容时,这个请求要面对跟 package.json 里一个依赖一样的问题。它带来什么能力?如果删掉,谁会坏掉?它和周围的字节如何交互?它什么时候过期?
机制是行政性的,不是技术性的。提示词文件头部一个小小的注释块列出每个贡献者的小节,带一行描述和一个 owner 的 handle。新添加追加一行;删除由原始请求者评审。文件变得自带文档,任何评审者都能回答"为什么这条在这里",而不必从六个月的 git history 里做考古。代价是每次改动多花几分钟。收益是没有人会加他们不需要的东西,因为他们必须写下为什么需要。
听起来很官僚,直到你拿它跟替代方案比——也就是大多数团队目前的状态,提示词是一个没人能详细辩护的单个字符串。你在 package 依赖、数据库迁移、API 表面、环境变量上接受的官僚——那些官僚正是阻止这些资源腐化的东西。提示词前缀一直是一个免费资源,因为没人给它定过价。当成本变得可见,官僚就变得划算了。
把缓存命中率作为合并前的 gate
所有权的补充是可观测性。重要的指标是按请求级别测量的缓存命中率,按产生那个请求的前缀版本切分。如果一次部署发布了一个提示词改动,把缓存命中率从 92% 拉到 60%,团队应该在他们看 p50 延迟和错误率的同一个 dashboard 上看到它。Anthropic 在 usage metadata 里暴露 cache_read_input_tokens 和 cache_creation_input_tokens;OpenAI 暴露 prompt_tokens_details.cached_tokens。两者都可以作为派生指标使用:缓存命中率是 (缓存的 input tokens) / (总 input tokens),在感兴趣的时间窗口里取平均。
在它们变成账单之前抓住回归的纪律,是把这个指标作为合并前的 gate。修改提示词的 PR 在 staging 上跑一个小的合成负载,把预测的缓存命中率连同提示词的 diff 一起报告出来。如果预测低于某个阈值——根据你目前的状态挑一个,然后随时间往下卡——这个 PR 就需要二级评审,询问新加的动态内容能否移出前缀。这是后端部署里 bundle-size gates 在提示词上的对应物,它有效的理由也是一样的:没有显式仪表化,成本表面在 PR 时是不可见的,而添加那一行的工程师不是支付账单的工程师。
这个想法的弱化版本是把缓存命中率作为先行指标做每周评审。拥有账单的团队盯着趋势线。当它掉下来时,他们在下一个计费周期前调查。这比 gate 更便宜实现,但损失几天的复合成本;gate 在合并前抓住回归,评审在部署后抓住。两者中任何一个都比默认状态好,默认状态是在季度 P&L 评审中才发现。
让缓存挣回来的重构
一旦团队有了 dashboard 和所有权台账,自然的下一步是结构性的:把前缀分成稳定系统块和按请求动态块。稳定块是可缓存的契约——角色定义、工具描述、响应格式、安全规则、锚定行为的长示例。这一块很少改变,占据大部分 token 数。动态块在它之后,包含所有每请求变化的——用户的等级、当前日期、活跃变体、功能标志清单、促销 banner。
这就是每一个提示词缓存文档页都推荐的结构,也是大多数生产提示词违背的结构。违背的原因是动态内容是一次加一行,在那个时刻对工程师有意义的任何位置加进去,结构完整性通过累积衰减。重构在技术上不难。对一个理解提示词的工程师来说,这是一个一天的项目。它没有发生的原因是没有人拥有它,而不做它的成本由一条没人盯着的预算线支付。
重构还会暴露一个有用的问题:当一位工程师被要求把一行从稳定块挪到动态块时,有一半的时候答案是这一行根本就不需要在提示词里。用户等级可以在相关时作为工具参数传入,而不是每次调用都注入。用户时区里的今天日期可以在"提醒我"意图触发时计算,而不是先声明出来以备所需。促销 banner 可以在用户提到价格时用工具调用取回,而不是在每个回合都告知模型。许多摧毁缓存的动态注入是防御性的——"以防万一"模型需要它们而加进去的——而重构把它们暴露为可删除的。
当它正常运转时是什么样子
一个支付过这笔债并且不再继续支付的团队,会有三件东西到位。第一,提示词前缀有一个命名的 owner,对添加有否决权,有一个季度性的前缀字节预算。第二,缓存命中率和团队每天早上检查的同一个 dashboard 上的成本和延迟一起画出来。第三,稳定块和动态块之间的结构性分离能存活下来,因为它编码在文件的形状里——一个章节标题、一个注释、一个在边界之上检测到动态内容就失败的构建步骤。
架构上的领悟和这个领域一代人以前为 SQL 查询、为数据库索引、为 Dockerfile 层、为 npm 依赖搞清楚的那个一样。资源在小的时候便宜,在大的时候昂贵,需要一位守护者。成本在边际上不可见,在总量上压垮一切。提示词前缀的字节现在属于这一类。把它们当作免费的团队就是那个,晚一个计费周期才发现,它们从来都不是免费——只是没被测量。把它们当作预算的团队就是那个,留住了 90% 的成本折扣——那个缓存本该给他们的折扣——而不是每个季度都付一遍,运气好的话拿回一半。
缓存正在做它当初宣称的事。失去折扣的团队失去它,是因为他们让契约一次一行地侵蚀。守住前缀那条线,数学就成立。停止守住它,账单就复合,而所有人都在事后同意,是的,那一行大概不该加进去。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部