将重复的系统 prompt、仓库地图、工具 schema 等块提取为命名版本化产物,解决缓存命中不稳定和团队协作混乱问题。
长上下文 AI Agent 不会因为模型支持百万级 Token 就变得可预测。
一个编码 Agent 可能在数百次运行中复用相同的 system prompt、仓库地图、风格指南、安全策略、工具 schema 束和任务评分标准。一个客服 Agent 可能会复用相同的产品手册、升级策略和客户安全回复格式。一个采购工作流可能会复用相同的合同条款和合规清单。
这些重复的区块很有价值,但也极易丢失。
如果每次请求都以略微不同的顺序组装 prefix、在稳定文本中插入时间戳、改变空白符、交换工具 schema 顺序,或者将路由元数据移入 prompt 中,网关就无法清晰地判断缓存命中的输入。工程侧期望复用。财务侧看到的是全新输入。客服没有任何证据说明发生了什么变化。
Prompt 前缀注册表解决了这个无聊的问题。它将可复用的 prompt 区块记录为命名的、带版本控制的产物。路由器因此可以为每个请求附加一个稳定的 prefix 指纹,将缓存假设从 prompt 正文中剥离出来,并对照实际使用情况来协调预期的缓存行为。
本文使用 AIWave 示例,因为 AIWave 在国内模型提供商之间暴露了 OpenAI 兼容的路由。该模式并非 AIWave 专属,它适用于任何在 DeepSeek、Qwen、GLM、Kimi、ERNIE、Moonshot、智谱、百川、StepFun、MiMo 或其他提供商家族之间路由长上下文工作负载的网关。
大多数团队从一个简单的 prompt 构建器开始:
prompt = system_prompt + "\n\n" + repo_summary + "\n\n" + user_task
这对原型来说没问题,但对生产环境远远不够。
一个请求的可复用部分需要自己的生命周期。一个稳定的 prefix 应该在请求到达模型之前回答以下问题:
没有这些字段,缓存未命中就只是一笔费用意外。有了它们,就变成了一个可调试的事件。
在撰写本文之前,我于 2026 年 8 月 29 日检查了 AIWave 的实时定价端点。它返回了 success=true、63 条模型记录、auto_groups=["default"] 以及 pricing_version=a42d372ccf0b5dd13ecf71203521f9d2。DeepSeek V4 行暴露了 deepseek-v4-flash 和 deepseek-v4-pro 的 OpenAI 兼容路由元数据,包括 model_ratio、completion_ratio、cache_ratio、create_cache_ratio 以及 default、vip 和 svip 的启用组。
这个实时端点是很有用的网关证据。但这不是凭空发明一张公开美元价格表的理由。公开价格声明需要有带日期的来源链接。
DeepSeek 官网定价页(2026 年 8 月 29 日检查)列出了 deepseek-v4-flash 和 deepseek-v4-pro,包含缓存命中输入、缓存未命中输入和输出行。可见美元价格表区分了高峰和非高峰价格。QwenCloud 的定价文档描述了按量计费、按上下文层级请求计费、Batch API 折扣、上下文缓存、思考 Token 计费、内置工具费用和账单查询视图。Z.AI 的定价页区分了输入、缓存输入、缓存输入存储、输出和工具相关行。Kimi 的公开 API 定价页描述了长上下文计费、上下文缓存、网页搜索、推理努力、JSON 模式以及 OpenAI 兼容 API 使用情况,但获取的页面正文并未暴露每一个 K3 价格行,因此在引用 K3 金额时请务必检查计费控制台或当前官方价格表。
重要的一点是结构性的:现代 AI 定价有多个计费桶。前缀注册表有助于保证缓存桶的准确性。
注册表不需要很复杂。从一个定义可复用区块的表或 JSON 文档开始即可。
{
"prefix_id": "coding-agent-base",
"version": "2026-08-29.1",
"owner": "agent-platform",
"purpose": "Shared instructions for repository analysis and patch generation",
"cache_eligible": true,
"content_sha256": "example_prefix_hash",
"token_estimate": 18400,
"allowed_routes": [
"deepseek-v4-flash",
"deepseek-v4-pro",
"qwen3.5-27b",
"glm-5.1"
],
"source_files": [
"system/coding-agent.md",
"policy/security-review.md",
"tools/repo-map-schema.json"
],
"created_at": "2026-08-29T13:05:00Z"
}
将注册表与 prompt 文本分开存放。Prompt 文本可以存在于源码控制、对象存储或应用数据库中。注册表是一份可审计的清单,说明了哪些稳定区块被预期复用。
对于小型网关,随路由一起提交的 JSON 文件可能就足够了。对于更大的平台,使用带有不可变版本和审查工作流的数据库表。
每个请求都应携带一份清单,将可复用 prefix 连接到任务特定的负载上。
{
"request_id": "req_20260829_001",
"tenant_id_hash": "tenant_hash_example",
"model": "deepseek-v4-pro",
"prefixes": [
{
"prefix_id": "coding-agent-base",
"version": "2026-08-29.1",
"content_sha256": "example_prefix_hash",
"cache_eligible": true,
"token_estimate": 18400
},
{
"prefix_id": "repo-map-aiwave-sdk",
"version": "2026-08-29.3",
"content_sha256": "example_repo_hash",
"cache_eligible": true,
"token_estimate": 61200
}
],
"task_tokens_estimate": 2200,
"max_output_tokens": 1200,
"pricing_version": "a42d372ccf0b5dd13ecf71203521f9d2",
"pricing_checked_at": "2026-08-29T13:20:00Z"
}
这份清单给了你一条审计跟踪,而无需记录 prompt、API 密钥或客户内容。你可以回答以下问题:预期的是哪个稳定上下文、哪个确切路由处理了调用、哪个定价快照批准了这次调度。
加载器应该产生确定性的文本。这意味着稳定的排序、稳定的分隔符,以及缓存计划区块内没有仅运行时的值。
import hashlib
import json
from dataclasses import dataclass
from pathlib import Path
@dataclass(frozen=True)
class PrefixBlock:
prefix_id: str
version: str
path: Path
cache_eligible: bool
def normalize_text(text: str) -> str:
lines = [line.rstrip() for line in text.splitlines()]
return "\n".join(lines).strip() + "\n"
def digest(text: str) -> str:
return hashlib.sha256(text.encode("utf-8")).hexdigest()
def load_prefixes(blocks: list[PrefixBlock]) -> tuple[str, list[dict]]:
parts: list[str] = []
manifest: list[dict] = []
for block in sorted(blocks, key=lambda item: (item.prefix_id, item.version)):
text = normalize_text(block.path.read_text(encoding="utf-8"))
parts.append(f"<prefix id=\"{block.prefix_id}\" version=\"{block.version}\">\n{text}</prefix>")
manifest.append({
"prefix_id": block.prefix_id,
"version": block.version,
"content_sha256": digest(text),
"cache_eligible": block.cache_eligible,
"bytes": len(text.encode("utf-8")),
})
return "\n\n".join(parts), manifest
prefix_text, prefix_manifest = load_prefixes([
PrefixBlock("coding-agent-base", "2026-08-29.1", Path("system/coding-agent.md"), True),
PrefixBlock("repo-map-aiwave-sdk", "2026-08-29.3", Path("context/repo-map.md"), True),
])
print(json.dumps(prefix_manifest, indent=2))
类似 XML 的包装器不是必需的。使用你的模型路由处理得最好的任何格式即可。关键是确定性。如果同一个 prefix 版本在明天产生了不同的哈希,注册表应该让构建失败。
有些值每次请求都会变化。它们不应该被放在稳定 prefix 内部:
这种分离看起来很严格,但它防止了意外的缓存抖动。稳定 prefix 内的时间戳会将每次请求变成一个不同的 prefix。Prompt 内的定价版本同样可能导致这个问题。除非任务明确涉及计费,否则模型不需要读取计费元数据。
路由器应该在看到 prefix 清单和任务大小之后选择模型。它不应该仅根据用户请求的模型来路由。
from dataclasses import dataclass
@dataclass(frozen=True)
class Route:
model: str
max_context_tokens: int
supports_cache_planning: bool
freshness_minutes: int
def choose_route(
routes: list[Route],
*,
requested_model: str,
prefix_tokens: int,
task_tokens: int,
output_cap: int,
) -> Route:
required = prefix_tokens + task_tokens + output_cap
candidates = [
route for route in routes
if route.model == requested_model and route.max_context_tokens >= required
]
if not candidates:
raise ValueError(f"no route can fit {required} tokens for {requested_model}")
return candidates[0]
route = choose_route(
[
Route("deepseek-v4-flash", 1_000_000, True, 30),
Route("deepseek-v4-pro", 1_000_000, True, 30),
Route("glm-5.1", 128_000, True, 30),
],
requested_model="deepseek-v4-pro",
prefix_tokens=79_600,
task_tokens=2_200,
output_cap=1_200,
)
这个示例有意做得很小。真实的路由器可能还会使用延迟级别、允许的提供商家族、地域策略、工具支持、重试策略和账户组等信息。前缀注册表给了该路由器一个缺失的输入:可复用上下文的大小和标识。
一旦路由选定,请求就可以使用普通的 OpenAI 兼容客户端。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://aiwave.live/v1",
api_key=os.environ["AIWAVE_API_KEY"],
)
def run_agent(prefix_text: str, task: str, model: str):
return client.chat.completions.create(
model=model,
temperature=0,
max_tokens=1200,
messages=[
{"role": "system", "content": prefix_text},
{"role": "user", "content": task},
],
)
该示例将凭证保存在环境变量中。它不会打印密钥,也不会记录 prompt。在生产环境中,请将请求清单附加到你的追踪和计费事件上,而不是附加到模型可见的 prompt 上——除非模型真正需要它。
注册表的价值在响应返回之后才真正体现。
def build_reconciliation_event(response, request_manifest: dict) -> dict:
usage = getattr(response, "usage", None)
prompt_tokens = getattr(usage, "prompt_tokens", None)
completion_tokens = getattr(usage, "completion_tokens", None)
expected_prefix_tokens = sum(
item["token_estimate"]
for item in request_manifest["prefixes"]
if item["cache_eligible"]
)
return {
"request_id": request_manifest["request_id"],
"model": request_manifest["model"],
"pricing_version": request_manifest["pricing_version"],
"prefix_fingerprints": [
f"{item['prefix_id']}@{item['version']}:{item['content_sha256'][:12]}"
for item in request_manifest["prefixes"]
],
"expected_cache_eligible_tokens": expected_prefix_tokens,
"actual_prompt_tokens": prompt_tokens,
"actual_completion_tokens": completion_tokens,
"cache_reconciliation_status": "needs_provider_usage_join"
}
如果你的提供商或网关直接返回缓存 Token 使用量,请在此处将其 join 进来。如果它不返回,仍然保留这个事件。状态使得证据缺口变得可见。这比将所有 prompt Token 静默地视为已缓存或未缓存要好得多。
日常检查应该小而具体。
这些检查运行成本很低,同时也创造了一级/二级采购方在采购过程中期望的证据:不是笼统的承诺,而是一个可复现的管控手段。
选择一个复用大上下文、并且使用量高的编码 Agent、客服分流 Agent 或文档分析 Agent。不要从所有路由开始。
第一步,将稳定区块置于注册表控制之下,并以影子模式计算指纹。保持调度行为不变。比较一周的 prefix 哈希值。如果哈希每天都在漂移,在讨论缓存优化之前先修复构建器。
第二步,将请求清单附加到追踪上。存储 prefix ID、版本、哈希、模型路由、定价版本和 Token 估算值。不要存储原始客户 prompt。
第三步,仅阻止明显的错误:缺失的 prefix 版本、过时的定价快照、prompt 日志中的原始密钥模式,或者无法容纳计划上下文的路由。这些检查保护了可靠性,而不需要完美的缓存核算。
第四步,协调使用情况。在可用的情况下 join 实际的 prompt、输出和缓存 Token 字段。按工作流、模型、账户组和 prefix 版本进行分段。如果一个新的 prefix 版本大幅增加了新鲜输入,将其视为生产变更来处理。
最后,在面向客户的客服中使用注册表。当买家问为什么一次长上下文运行花费了那么多时,你应该能够用路由、prefix 版本、Token 桶、定价来源和请求结果来回答。不要让客服从一个混合的使用数字中逆向推算。
将来源链接保存在元数据中,而不是放在可复用 prompt 正文中。
对于网关路由,保留对 AIWave 定价、AIWave 模型文档以及 https://aiwave.live/api/pricing 实时定价端点的带日期检查。
对于提供商校准,保留对 DeepSeek 定价、QwenCloud 定价、Z.AI 定价和 Kimi API 定价的带日期检查。在更改路由策略之前重新检查它们。
在生产环境中调用长上下文路由之前,网关应该知道:
长上下文窗口给了 Agent 工作空间。Prompt 前缀注册表给了网关一种方式来证明什么保持了稳定、什么发生了变化、以及哪个请求应该获得缓存处理。
这种证明是将一个巧妙的 prompt 构建器变成生产基础设施的关键。
你可能需要考虑屏蔽此人并/或报告滥用行为。