Prompt Caching、Reasoning Budget 与跨区域 Inference Profile 行为说明
受众:运维人员、接入方开发者
参见 AGENTS.md 中"缓存放置契约"和"两条推理渲染路径"段落。
目录
- Prompt Caching 行为
- 1.1 默认开启与注入顺序
- 1.2 支持缓存的判定规则
- 1.3 逐模型 cache_min_tokens 阈值
- 1.4 AWS 官方要点摘录
- 1.5 usage 字段计账
- 1.6 字节稳定前缀规则
- Reasoning / Extended Thinking Budget
- 跨区域 Inference Profile
- 3.1 带前缀模型 ID 的必要性
- 3.2 网关内部双 ID 策略
- 3.3 缓存与跨区域共用
- 3.4 /models 接口行为(当前部署 region 范围)
- 运维配置指南
- 可观测性与日志
- 相关源码位置
1. Prompt Caching 行为
1.1 默认开启与注入顺序
缓存点自动注入默认开启(环境变量 ENABLE_PROMPT_CACHING 默认 true;配置文件 config/app.toml 同样默认 true)。
注入顺序固定为:tools → system → messages
三个位置共享一个预算,总注入数不超过 max_cache_checkpoints(默认 4)。预算从 tools 区开始累计,用完后后续区域跳过注入。
tools cachePoint → system cachePoint → messages cachePoint
(slot 1) (slot 2) (slot 3)
↑── 共享 max_cache_checkpoints=4 ──────────────────可通过请求体里 extra_body 对象中的 prompt_caching 在单次请求内覆盖全局开关。OpenAI SDK 的 extra_body 参数会把内容合并到请求体顶层,所以用 SDK 时要再套一层 extra_body:
# 只缓存 system,跳过 messages
response = client.chat.completions.create(
model="anthropic.claude-3-5-sonnet-20241022-v2:0",
messages=[...],
extra_body={
"extra_body": {
"prompt_caching": {
"system": True,
"messages": False
}
}
}
)Responses API 只读取其中的 ttl。
全局关闭:设置 ENABLE_PROMPT_CACHING=false。
1.2 支持缓存的判定规则
模型是否支持缓存,完全由 config/models.toml 中是否声明 cache_min_tokens 参数决定。 代码(src/bedrock/cache.rs)不做任何模型名称判断,这是零硬编码契约的一部分。
判定函数(supports_caching):
// src/bedrock/cache.rs
pub fn supports_caching(model: &str, caps: &dyn ModelCapabilities) -> bool {
caps.cache_min_tokens(model).is_some() || caps.max_cache_tokens(model).is_some()
}Family 兜底机制: config/models.toml 末尾有一个 match = "anthropic.claude" 的兜底条目,未在前面单独列出的 Claude 模型 ID 会自动匹配到此条目,获得 cache_min_tokens = 4096 的保守默认值,不会因为新模型未录入而静默禁用缓存。
子串遮蔽陷阱(新增模型必读):
[model.params](cache_min_tokens、reasoning_path、available_regions等)取按声明顺序的首次子串命中。当新模型 ID 以已有条目的match值为前缀时(例如claude-fable-5-1含有claude-fable-5),新条目必须声明在旧条目之前,否则新模型会静默拿到旧条目的cache_min_tokens与reasoning_path,请求本身仍返回 200,没有任何报错。claude-fable-5-1的顺序由test_fable_5_1_declared_before_fable_5锁定。能力标志不走首次命中,而是并集:
ConfigModelCapabilities::has()用.filter(substring).any(has_capability),即所有match命中该 ID 的条目的能力取并集。因此claude-fable-5-1同时继承claude-fable-5与anthropic.claude兜底条目的标志,声明顺序对能力无影响,单个条目也无法收回上层条目给出的标志(当前没有 deny 机制)。所以兜底条目不声明任何能力标志:structured_output只写在 AWS 结构化输出文档列出的 Sonnet 4.5/4.6、Haiku 4.5、Opus 4.5/4.6 条目上。Opus 4.7+ 与 5 代模型收到 outputConfig 时上游返回output_config.format: Extra inputs are not permitted,网关现在直接对它们的response_format返回 400。
1.3 逐模型 cache_min_tokens 阈值
常见故障: 将
cache_min_tokens配置为错误值(例如把 1024 阈值模型配成 4096),会导致实际 prompt 未达阈值时静默不注入 cachePoint,缓存完全不命中,但请求本身正常返回 200——没有任何错误提示。
下表为网关当前配置(来源:config/models.toml)。1h TTL 列即 cache_ttl_1h 能力:未声明时 请求里的 ttl: "1h" 会被静默降级为 5 分钟。所有 Claude 条目的官方 max_cache_checkpoints 均为 4、可缓存字段均为 system / messages / tools,故不再单列这两列。
| 模型 | Model ID(foundation id) | cache_min_tokens | 1h TTL | config 条目 |
|---|---|---|---|---|
| Claude Sonnet 5.5 | anthropic.claude-sonnet-5-5 | 512 | 是 | claude-sonnet-5-5 |
| Claude Opus 5.5 | anthropic.claude-opus-5-5 | 512 | 是 | claude-opus-5-5 |
| Claude Fable 5.1 | anthropic.claude-fable-5-1 | 512 | 是 | claude-fable-5-1 |
| Claude Fable 5 | anthropic.claude-fable-5 | 512 | 是 | claude-fable-5 |
| Claude Mythos 5.1 | anthropic.claude-mythos-5-1(Gated) | 512 | 是 | claude-mythos-5-1 |
| Claude Mythos 5 | anthropic.claude-mythos-5(Gated) | 512 | 是 | claude-mythos-5 |
| Claude Opus 5 | anthropic.claude-opus-5 | 512 | 是 | claude-opus-5 |
| Claude Opus 4.8 | anthropic.claude-opus-4-8 | 1,024 | 是 | claude-opus-4-8 |
| Claude Sonnet 5 | anthropic.claude-sonnet-5 | 1,024 | 是 | claude-sonnet-5 |
| Claude Sonnet 4.6 | anthropic.claude-sonnet-4-6 | 1,024 | 是 | claude-sonnet-4-6 |
| Claude Sonnet 4.5 | anthropic.claude-sonnet-4-5-20250929-v1:0 | 1,024 | 是 | claude-sonnet-4-5 |
| Claude Opus 4.7 | anthropic.claude-opus-4-7 | 4,096 | 是 | claude-opus-4-7 |
| Claude Opus 4.6 | anthropic.claude-opus-4-6-v1 | 4,096 | 是 | claude-opus-4-6 |
| Claude Opus 4.5 | anthropic.claude-opus-4-5-20251101-v1:0 | 4,096 | 是 | claude-opus-4-5 |
| Claude Haiku 4.5 | anthropic.claude-haiku-4-5-20251001-v1:0 | 4,096 | 是 | claude-haiku-4-5 |
| Claude Mythos Preview | anthropic.claude-mythos-preview(Gated) | 4,096 | 是 | claude-mythos-preview |
| Claude 3.7 Sonnet | anthropic.claude-3-7-sonnet-20250219-v1:0 | 4,096(兜底) | 否 | anthropic.claude(兜底) |
| Claude 3.5 Sonnet v2 | anthropic.claude-3-5-sonnet-20241022-v2:0 | 4,096(兜底) | 否 | anthropic.claude(兜底) |
| Amazon Nova(所有) | amazon.nova-* | 1,024 | 否 | amazon.nova |
AWS 官方对应表(四列:Model / Model ID / 最小 token/checkpoint / 最大 checkpoints):
| Model | Model ID | Min tokens/checkpoint | Max checkpoints |
|---|---|---|---|
| Claude Sonnet 5.5 | anthropic.claude-sonnet-5-5 | 512 | 4 |
| Claude Opus 5.5 | anthropic.claude-opus-5-5 | 512 | 4 |
| Claude Fable 5.1 | anthropic.claude-fable-5-1 | 512 | 4 |
| Claude Fable 5 | anthropic.claude-fable-5 | 512 | 4 |
| Claude Opus 5 | anthropic.claude-opus-5 | 512 | 4 |
| Claude Opus 4.8 | anthropic.claude-opus-4-8 | 1,024 | 4 |
| Claude Sonnet 5 | anthropic.claude-sonnet-5 | 1,024 | 4 |
| Claude Opus 4.7 | anthropic.claude-opus-4-7 | 4,096 | 4 |
| Claude Opus 4.6 | anthropic.claude-opus-4-6-v1 | 4,096 | 4 |
| Claude Opus 4.5 | anthropic.claude-opus-4-5-20251101-v1:0 | 4,096 | 4 |
| Claude Sonnet 4.5 | anthropic.claude-sonnet-4-5-20250929-v1:0 | 1,024 | 4 |
| Claude Haiku 4.5 | anthropic.claude-haiku-4-5-20251001-v1:0 | 4,096 | 4 |
| Claude Mythos 5.1 | anthropic.claude-mythos-5-1(Gated) | 512 | 4 |
| Claude Mythos 5 | anthropic.claude-mythos-5(Gated) | 512 | 4 |
| Claude Mythos Preview | anthropic.claude-mythos-preview(Gated) | 4,096 | 4 |
| Claude Sonnet 4.6 | anthropic.claude-sonnet-4-6 | 1,024 | 4 |
| Claude 3.7 Sonnet | anthropic.claude-3-7-sonnet-20250219-v1:0 | 1,024 | 4 |
| Claude 3.5 Sonnet v2 | anthropic.claude-3-5-sonnet-20241022-v2:0 | 1,024 | 4 |
已对齐: 两张表的 Claude 行现已逐行一致。此前 Opus 5、Mythos 5 官方 512 被配成 4,096,Opus 4.8、Sonnet 5、Sonnet 4.5 官方 1,024 被配成 4,096,
claude-mythos-5-1没有条目而落到兜底 4,096——这些值当初是在还没有官方行时按 4,096 保守取的。同时补齐了 Opus 4.5/4.6/4.7/4.8、Sonnet 4.5/4.6/5、Haiku 4.5、Mythos 5/5.1/Preview 的cache_ttl_1h。降低阈值让缓存更早生效:cache write 增多、命中后更省,属计费相关变更。helm/bedrock-gateway/files/models.toml同步了同一批阈值与 TTL——该副本此前连 Sonnet 4.5 / Haiku 4.5 / Opus 4.5 / Sonnet 5 的cache_ttl_1h都没有,helm 部署会把ttl: "1h"静默降级为 5 分钟,与config/models.toml部署行为分叉。 阈值由cache_min_tokens_per_claude_version_floors逐条锁定,Mythos 的声明顺序由test_mythos_5_1_declared_before_mythos_5锁定。仍存的已知分叉(本次未改): Claude 3.7 Sonnet 与 3.5 Sonnet v2 官方为 1,024 且 只支持 5 分钟 TTL,网关没有专属条目、落到兜底的 4,096,即 1,024–4,095 tokens 的前缀 不注入 cachePoint。这两个是上一代模型,不在本次范围内。AWS 当前表也已不再列出 Claude Opus 4,因此本文档不再声称它的官方阈值。
helm/bedrock-gateway/files/models.toml现在与config/models.toml逐字一致(此前缺 Sonnet 4.5/4.6、Haiku 4.5、Opus 4.5/4.6 的structured_output与 GPT-5.4/5.5 的chat_backend),由helm_model_registry_matches_config_semantically锁定:改动主配置后需同步复制该副本。
1.4 AWS 官方要点摘录
以下摘录均来自 AWS Bedrock Prompt Caching 用户指南,均已核实为官方原文。
"Cache checkpoints have a minimum and maximum number of tokens, dependent on the specific model. You can only create a cache checkpoint if your total prompt prefix meets the minimum number of tokens. If you try to add a cache checkpoint before meeting the minimum, your inference will still succeed, but your prefix will not be cached."
这正是网关 cache_min_tokens floor gate 的设计依据:低于阈值时跳过 cachePoint 注入,避免发出无效 cachePoint(Bedrock 会静默忽略但浪费一个 checkpoint 配额)。
"Prompt caching is only supported for on-demand inference endpoints. It is not supported with the batch inference API."
网关仅调用 Converse/ConverseStream(on-demand),不走 batch,此限制不影响本网关。
"These prompt prefixes should be static between requests; alterations to the prompt prefix in subsequent requests will result in cache misses."
即字节稳定前缀规则,详见 1.6 节。
针对 Amazon Nova 模型,官方额外说明:
"Amazon Nova offers automatic prompt caching for all text prompts... we recommend opting in to Explicit Prompt Caching."
网关已为 Nova 配置 cache_min_tokens = 1024,走显式缓存(explicit prompt caching)路径,与官方推荐一致。
官方链接:
- Prompt caching 用户指南:https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html
- Bedrock 定价(缓存读/写费率):https://aws.amazon.com/bedrock/pricing/
1.5 usage 字段计账
网关使用统一的 compute_token_usage 函数(src/bedrock/tokens.rs)计算所有 usage 字段:
prompt_tokens = input + cacheRead + cacheWrite
total_tokens = prompt_tokens + output
cached_tokens = cacheRead(仅读取侧)关键说明:
cached_tokens只反映缓存读取(cacheRead)。第一次写入缓存时 Bedrock 返回cacheWriteInputTokens,但 OpenAI 协议中没有对应的写侧字段,因此它被折入prompt_tokens而不单独列出。- 响应字段位置:
- Chat Completions:
usage.prompt_tokens_details.cached_tokens - Responses API:
usage.input_tokens_details.cached_tokens
- Chat Completions:
1.6 字节稳定前缀规则
缓存命中依赖确定性序列化。修改任何 cachePoint 之前的内容都会导致该请求中后续所有缓存点失效。
实践要点:
- 将稳定内容(大型 system prompt、固定 tools 定义)放在对话靠前的位置。
- 多轮对话中,早期消息一旦确定,不要修改其内容,否则 messages 区 cachePoint 失效。
- 跨区路由时,注入的
cachePoint结构相同;切换区域本身不会破坏前缀稳定性,但官方提示高峰期跨区调用可能增加 cache write 次数(详见 3.3 节)。
2. Reasoning / Extended Thinking Budget
2.1 budget_tokens 计算路径
使用 reasoning_effort 参数触发推理:
# Chat Completions 接口(需显式带 reasoning_effort)
response = client.chat.completions.create(
model="anthropic.claude-3-5-sonnet-20241022-v2:0",
messages=[{"role": "user", "content": "请逐步推理:..."}],
extra_body={"reasoning_effort": "medium"}
)
# Responses 接口(默认携带 reasoning 字段)
response = client.post("/api/v1/responses", json={
"model": "anthropic.claude-3-5-sonnet-20241022-v2:0",
"input": [{"role": "user", "content": [{"type": "input_text", "text": "..."}]}],
"reasoning": {"effort": "medium"}
})支持的 effort 级别:none / minimal / low / medium / high / xhigh / max
BudgetTokens 路径的计算公式(来自 src/bedrock/reasoning.rs):
effective_max = max_completion_tokens ?? max_tokens
low -> budget = int(effective_max * 0.3)
medium -> budget = int(effective_max * 0.6)
high / xhigh / max -> budget = effective_max - 1比例来自 config/models.toml 的 budget_ratios(low=0.3, medium=0.6, high=-1.0 sentinel),可在 TOML 中逐模型覆盖,无需改代码。
五条推理路径(由 config/models.toml 的 reasoning_path 字段决定):
| reasoning_path | 适用模型示例 | Bedrock wire 字段 |
|---|---|---|
budget_tokens | claude-sonnet-4-x | reasoning_config = {type: "enabled", budget_tokens: N} |
adaptive_thinking | claude-opus-4-6/4-7/4-8/5/5-5、claude-sonnet-5/5-5、claude-fable-5/5-1 | thinking = {type: "adaptive", display: "summarized"} + output_config.effort |
deepseek_string | deepseek.v3 | reasoning_config = "low"/"medium"/"high" |
openai_effort | openai.gpt-6.1-sol / gpt-6-sol / gpt-6-luna / gpt-6-astra | reasoning = {effort: "<effort>"}(原样透传,模型不支持的值由上游 400) |
none | 无推理能力模型 | 无(reasoning_effort 被忽略) |
Fable 5.1 审视补充(两项均确认无需改代码):
- effort 等级不做逐模型门控。
effort_str(src/bedrock/reasoning.rs)把low|medium|high|xhigh|max原样写入output_config.effort。Fable 5.1 模型卡明确 列出 effort 可取 low..max(默认 high),因此透传对它是正确的;但 AWS adaptive thinking 文档的 effort 表把max限定为 Opus 4.6 / Sonnet 4.6 / Opus 5、xhigh限定为 Opus 4.6 / Opus 5,对其他 adaptive 模型发max/xhigh可能被上游拒。这是 既有面,不属于 Fable 5.1 的审视范围,本次未加门控。stop_reason: "refusal"走未知值小写透传。 Fable 5.1 模型卡有独立的 Content Restrictions 段:分类器拦截时返回 HTTP 200 加stop_reason: "refusal"与stop_details,且该模型的 refusal 率显著高于以往 Claude,官方要求客户端把 refusal 当作主响应路径处理。convert_finish_reason(src/bedrock/response.rs)只显式映射tool_use/end_turn/stop_sequence/complete/max_tokens/content_filtered,其余一律小写透传,因此客户端会收到finish_reason: "refusal"(非 OpenAI 枚举值):内容不丢失,但stop_details不透出。 Converse 是否真的发出该 stopReason 没有文档或探测证据,故不做推测性映射;一旦确认, 再决定是保留refusal还是映射为content_filter。
官方示例(Converse API with reasoning):https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-runtime_example_bedrock-runtime_Converse_AnthropicClaudeReasoning_section.html
官方示例中 budget 通过 additionalModelRequestFields 传入,网关已按此方式实现。
2.2 硬下限与 maxTokens 抬高
常见故障: 当
max_output_tokens(或max_tokens)过小时(例如 50),按比例算出的 thinking budget(如50 * 0.3 = 15)会低于 Anthropic 的硬性下限 1024,Bedrock 返回 HTTP 400:thinking.enabled.budget_tokens: Input should be greater than or equal to 1024
网关的修复方案(src/bedrock/reasoning.rs,commit c756e79):
Budget 上取整到下限:
budget = max(budget, min_budget_tokens)min_budget_tokens默认值 1024,来自config/models.toml的default条目- 可逐模型覆盖,仅改 TOML
maxTokens 抬高以容纳 budget: 同时将发往 Bedrock 的
maxTokens抬高到max(effective_max, budget + 256)+256是完成余量(COMPLETION_HEADROOM_TOKENS),确保 thinking 之外还有空间输出答案- Anthropic 要求
maxTokens > budget_tokens,此调整满足该约束 - 这只影响发往 Bedrock 的参数,不改变响应给客户端的任何字段
示例:max_output_tokens=50, effort=low
ratio budget = int(50 * 0.3) = 15
clamped budget = max(15, 1024) = 1024
maxTokens sent = max(50, 1024 + 256) = 1280请求成功,响应正常,客户端 usage.completion_tokens 基于实际生成量计算。
2.3 两条推理渲染路径(不可混淆)
推理输出在两个接口层上形式不同,不能合并:
| 接口 | 推理渲染方式 | 理由 |
|---|---|---|
/chat/completions | 内联 <think>...</think> 嵌入 content 字符串 | OpenAI Chat 协议无推理专用字段;reasoning_content 内部有值但标记 #[serde(skip_serializing)] 永不出现在响应 JSON 中 |
/responses | output 数组中的独立 reasoning 输出项(非 <think> 包裹) | Responses API 有专用的 reasoning output item 类型 |
这是架构规则,修改任意一条时必须确认另一条未受影响。详见 AGENTS.md 中"两条推理渲染路径"段。
3. 跨区域 Inference Profile
3.1 带前缀模型 ID 的必要性
AWS Bedrock 的跨区域推理通过 inference profile 实现。带地理前缀的模型 ID(如 us.anthropic.claude-sonnet-4-5-20250929-v1:0、eu.anthropic.claude-3-5-sonnet-20241022-v2:0)是 inference profile 标识符,必须原样发给 Bedrock。
如果将前缀去掉使用裸 foundation model ID(如 anthropic.claude-sonnet-4-5-20250929-v1:0),Bedrock 会拒绝:
HTTP 400 ValidationException:
Invocation of model ID anthropic.claude-sonnet-4-5-20250929-v1:0
with on-demand throughput isn't supported.
Retry with an inference profile.这正是本网关修复的第三个 bug:Responses 接口在处理跨区前缀模型时,曾误将
resolve_foundation()返回的裸 foundation ID 作为 model_id 发往 Bedrock,导致 100% 的 /responses 请求对跨区模型 400,而 /chat/completions 用原始模型 ID 所以正常。
支持的前缀(地理/跨区前缀全集):
| 前缀 | 覆盖区域(示例) |
|---|---|
us. | 美国区(us-east-1 / us-east-2 / us-west-2) |
eu. | 欧洲区(eu-west-_ / eu-central-_ 等) |
apac. | 亚太区(ap-northeast-_ / ap-southeast-_ / ap-south-* 等) |
jp. | 日本(ap-northeast-1) |
au. | 澳大利亚(ap-southeast-2) |
ca. | 加拿大(ca-central-1) |
global. | 全球多区(当前主要为 Claude 全系列) |
来源说明: 以上为 2026-06-20 扫描全部 34 个 AWS 商业区
aws bedrock list-inference-profiles --type-equals SYSTEM_DEFINED得到的完整前缀集(共 7 个,无其他);代码侧在src/bedrock/capabilities.rs的GEO_PREFIXES常量中枚举,AWS 新增地理前缀时需同步更新该常量。
官方链接: https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html
3.2 网关内部双 ID 策略
网关在以下两个场景中使用不同的模型 ID,两者绝对不可混用:
| 用途 | 使用的 ID | 示例 |
|---|---|---|
| 能力匹配(缓存阈值 / reasoning_path / 温度冲突检查) | resolve_foundation() 返回的 foundation ID(去前缀、小写) | anthropic.claude-sonnet-4-5-20250929-v1:0 |
| 发往 Bedrock 的实际调用(model_id) | 原始请求模型 ID(带前缀,原样) | us.anthropic.claude-sonnet-4-5-20250929-v1:0 |
能力匹配前先经 normalize_for_match()(src/bedrock/capabilities.rs)去掉地理前缀并小写,使 config/models.toml 的 match 字符串只需写一次,同时覆盖 GEO_PREFIXES 枚举的全部 7 个前缀变体(us./global./eu./apac./jp./au./ca.)。该归一化仅用于能力匹配,不改变 resolve_foundation() 的返回值,也不改变发往 Bedrock 的 model_id(始终原样带前缀发出)。
Chat 和 Responses 两个接口均已对齐此行为(src/bedrock/provider.rs 和 src/bedrock/responses_provider.rs)。
3.3 缓存与跨区域共用
缓存可以与跨区域推理同时使用,无需额外配置。需注意:
AWS 官方提示(来自 Prompt Caching 文档 中 "Prompt Caching with Cross-region Inference" 段): 跨区域流量在高峰时段会在多个区域路由,这可能导致同一前缀的 cache write 发生在不同区域,增加 cache write 次数。
实践建议:
- 跨区路由时,稳定的大型 system prompt 仍应放在对话开头,最大化 cache read 机会。
- 若观测到
cached_tokens偶发为 0(正常时应大于 0),可能是跨区切换导致落到了没有该缓存的区域,属正常现象,下次相同区域调用会恢复命中。 cached_tokens统计的是 cacheRead,不统计 cacheWrite,所以首次调用(写缓存)为 0 是预期行为。
3.4 /models 接口行为(当前部署 region 范围)
模型目录的范围由网关部署所在的 region决定,不做跨地理区聚合。
GET /api/v1/models列出当前部署 region 可用的模型。网关用 home region(AWS_REGION)调list-foundation-models+list-inference-profiles组装目录。因此部署在美国区(如 us-east-2)时,目录会包含us.前缀的跨区 profiles 与global.前缀模型,但不会聚合eu./apac./jp./au./ca.等其他地理区的 profiles。- INFERENCE_PROFILE-only 的模型(如 Claude 全系列,其裸 foundation
inferenceTypesSupported仅含INFERENCE_PROFILE、无ON_DEMAND):其裸 foundation ID 不出现在列表(不可直调,直接发裸 id 会被 Bedrock 拒绝),但其跨区 profile ID(us.anthropic.claude-*/global.anthropic.claude-*等)会出现在列表,且可直接用作model请求参数。 GET /api/v1/models/{id}支持用 profile ID 查询(如GET /api/v1/models/us.anthropic.claude-sonnet-4-5-20250929-v1:0→ 200)。
目录在启动时拉取一次,之后每隔
MODEL_CATALOG_REFRESH_SECS(默认 3600 秒,0= 只在启动时)在后台重新拉取,并同步刷新 profile → foundation 映射,所以启动后才上线的模型无需重启即可出现在列表中、通过图片能力检查。[[alias]]的目标若在目录中(例如gpt-6.1-sol→global.openai.gpt-6.1-sol),裸别名也会列出。这是现状设计:目录范围 = 部署 region 范围。如需访问其他地理区的模型,需在该地理区单独部署网关实例。目录组装逻辑见
src/bedrock/models.rs的assemble_catalog(裸 foundation 按ON_DEMAND过滤入目录;其 backing 的 inference profiles 独立纳入,使 INFERENCE_PROFILE-only 模型的跨区 profile 可被发现)。
4. 运维配置指南
4.1 修改缓存阈值或 reasoning 参数
只改 config/models.toml,不改代码,不需要重新编译。
# 示例:将某模型的缓存最小 token 改为 1024
[[model]]
match = "claude-sonnet-4-6"
capabilities = ["temperature_topp_conflict", "context_1m_beta"]
[model.params]
cache_min_tokens = 1024 # 修改此值
reasoning_path = "budget_tokens"
# 示例:调整 reasoning budget 比例
[[model]]
match = "default"
capabilities = []
[model.params]
min_budget_tokens = 1024 # Anthropic 硬下限,通常不需要改
[model.params.budget_ratios]
low = 0.3
medium = 0.6
high = -1.0 # sentinel: max_tokens - 1修改后需要:
- 单二进制部署:重启进程(config 在启动时读取)。
- 容器部署:
- 若使用嵌入 config(
include_str!):需重建镜像(cargo build --release+docker build)。 - 若通过
CONFIG_DIR环境变量挂载外部 config 目录:只需替换挂载目录下的 TOML 文件并重启容器,无需重建镜像。
- 若使用嵌入 config(
4.2 CONFIG_DIR 外部覆盖
设置 CONFIG_DIR 环境变量,可让网关优先从外部目录加载 config,覆盖编译时嵌入的默认值:
# 使用外部 config 目录
CONFIG_DIR=/etc/bedrock-gateway/config docker run ...
# 优先级:外部文件存在且解析成功 > 编译时嵌入默认
# 外部文件缺失或解析失败 → 自动回退到嵌入默认(不会降级为空配置)4.3 环境变量速查
| 变量 | 默认值 | 说明 |
|---|---|---|
ENABLE_PROMPT_CACHING | true | 全局缓存开关 |
CONFIG_DIR | config(相对 WORKDIR) | 外部 config 目录路径 |
LOG_LEVEL | info | 日志级别;设为 debug 可看 Bedrock 调用细节 |
DEFAULT_MODEL | anthropic.claude-3-5-sonnet-20241022-v2:0 | 默认模型 |
MODEL_CATALOG_REFRESH_SECS | 3600 | 后台重新拉取模型目录的间隔;0 = 只在启动时 |
5. 可观测性与日志
每次请求的业务日志字段(info 级别):
非流式 chat 完成:
chat completed | request_id=req-xxx model=us.anthropic.claude-sonnet-4-5-20250929-v1:0
| prompt_tokens=1234 completion_tokens=56 total_tokens=1290
| cached_tokens=1200 cache_hit=true duration_ms=890流式 chat 开始:
chat streaming started | request_id=req-xxx model=... ttfb_ms=320流式 chat 完成:
chat streaming completed | request_id=req-xxx prompt_tokens=1234 completion_tokens=56
| total_tokens=1290 cached_tokens=1200 cache_hit=true duration_ms=2100Responses 接口日志格式对称(responses completed / responses streaming started / responses streaming completed),字段含义相同,但 token 字段名为 input_tokens / output_tokens。
关键字段说明:
cached_tokens:缓存读取的 token 数;0表示首次写缓存或未命中。cache_hit:true表示本次有缓存读取;false表示全量 prompt 计算(包括首次建立缓存时)。ttfb_ms:流式场景下,从收到请求到第一个 token 的延迟(Time To First Byte)。request_id:网关自生成的 trace ID(格式req-{nanos:x}-{seq:x}),可关联同一请求的所有日志行。若客户端发送x-request-id头,则使用客户端提供的值。
隐私说明:任何日志级别下均不会打印 prompt/completion 文本内容、消息正文、API_KEY 或 bearer token。
6. 相关源码位置
| 功能 | 文件 | 关键函数/位置 |
|---|---|---|
| 缓存 floor gate(低于阈值不注入) | src/bedrock/cache.rs | decorate_system_blocks(约第 290 行 cache_min_tokens 判断) |
| Reasoning budget 计算与下限钳制 | src/bedrock/reasoning.rs | build_reasoning_config(ReasoningPath::BudgetTokens 分支,约第 198-204 行) |
| min_budget_tokens 配置读取 | src/config/capabilities.rs | ModelParams::min_budget_tokens 字段定义 |
| Responses 接口 outbound model_id | src/bedrock/responses_provider.rs | send_converse / send_converse_stream(使用原始 req.request.model 而非 resolved) |
| tools 区 cachePoint 转 SDK 类型 | src/bedrock/provider.rs | build_sdk_tool_config(cachePoint 分支,避免 "tool missing toolSpec" 错误) |
| 能力匹配前缀归一化(去地理前缀) | src/bedrock/capabilities.rs | normalize_for_match + GEO_PREFIXES(枚举 7 个实测前缀) |
| profile→foundation 解析(不改 model_id) | src/bedrock/capabilities.rs | ConfigModelCapabilities::resolve_foundation |
| token usage 计算 | src/bedrock/tokens.rs | compute_token_usage |
如发现本文档与代码行为不符,请以代码为准并更新本文档。相关架构决策见 AGENTS.md 中"缓存放置契约"、"零硬编码契约"段落。