# 降低成本与优化缓存

来源: https://platform.lyrouter.com/ai_gateway/docs/cost-practice
更新日期: 2026-10-14

Agent、编程助手这类应用每一轮都会重新发送系统提示词、工具定义和全部历史，输入 Token 往往占费用的大头，所以提示词缓存命中率基本决定了 Token 费用。降低成本的主要做法是让请求前缀保持稳定、让同一会话留在同一个通道上，再减少不必要的输出和上下文。每项调整后，用日志和用量分析中的缓存命中率与费用验证效果。

## 先找到钱花在哪

在 **用量分析** 中把「统计视角」切到「费用」，按模型、API Key 查看费用占比；「总览」的「缓存命中率」和「按模型」表格的「缓存命中率」列显示命中情况。费用集中、命中率又低的模型，是最值得优化的对象。具体请求的四项 Token 在[请求日志](https://platform.lyrouter.com/ai_gateway/docs/logs)详情中查看，费用计算方法见[调用费用与缓存计费](https://platform.lyrouter.com/ai_gateway/docs/estimate)。

（截图：在用量分析中切换统计视角，对比各模型的用量、费用和缓存命中率。）

设缓存命中率为 `h`，模型的缓存读取单价与输入单价之比为 `r`，输入费用约为全部未命中时的 `(1 − h) + h × r` 倍。`r` 越小，提高命中率省得越多。

## 让请求前缀保持稳定

上游按字节前缀匹配缓存，从第一个不同的字节开始，之后的内容全部按未命中计费。把越稳定的内容放得越靠前，从前到后依次是：

1. **固定的角色与规则**：最稳定，放在最前。
2. **工具定义**：会话内不变，顺序固定。
3. **示例与项目级上下文**：同一项目内不变。
4. **环境信息、日期等**：容易变化，尽量靠后。
5. **对话历史**：只追加，不改写。
6. **本轮新消息**。

- **前缀里不放变化的值**：请求 ID、trace ID、精确到秒的时间戳、随机数不要写进系统提示词开头；必须带时放到最后一条消息里，日期精确到天即可。
- **会话中途不改工具**：增删或调整工具会改变工具定义之后的全部内容。需要临时限制工具时，在提示词或调用逻辑中约束；按需加入的工具放在工具列表最后。
- **历史只追加、原样回放**：不要每轮重新拼装或格式化历史消息；工具调用参数按模型上一轮返回的原样回传。
- **不必担心 JSON 键顺序**：网关发往上游前会把请求体中 JSON 对象的键按固定顺序排列，包括工具调用参数里的 JSON（参数中含 15 位以上连续数字时保持原样，以免改写数字）。消息、工具和内容块的先后顺序不会调整，需要由客户端保持稳定。

## 让同一会话留在同一个通道

缓存保存在具体的服务商通道上，换通道就要重新建立。工作空间的「多渠道选路策略」为「最低价」（新建工作空间的默认值）或「负载均衡」时，网关会把同一个 API Key 对同一模型的调用保持在同一个通道上：

- 保持期为 30 分钟，每次调用续期；通道返回 429、408、5xx 或连接失败时改绑到其他通道，因请求本身格式错误而换通道时不改绑。
- 「最低价」只为新会话或保持过期后的调用选择当前预估最便宜的通道，价格排序变化不会把进行中的会话挪走。
- 「最低延迟」「最高吞吐」不做会话保持；虚拟模型的「Channel 排序策略」为按价格优先或负载均衡时同样会保持。
- `lyrouter/auto` 按每次请求的内容选择模型，同一会话可能换到不同模型，长会话请固定一个模型 ID。

调用方只需让同一个会话或 Agent 始终使用同一个 API Key 和同一个模型，不需要额外参数。如果客户端会发送 `X-Session-Id` 请求头，网关会原样转发；请为每个会话固定一个值，不要每个请求更换。设置方法见[通道选择与路由策略](https://platform.lyrouter.com/ai_gateway/docs/routing)。

## 使用显式缓存（cache_control）

隐式缓存由上游自动完成，不需要任何参数。显式缓存在请求中用 `cache_control` 标出断点，只在实际服务这次调用的上游使用 Anthropic 协议时生效：

| 调用接口 | 实际服务的上游协议 | `cache_control` 的处理 |
| --- | --- | --- |
| `/v1/messages` | Anthropic | 保留 `system`、消息文本块和工具定义上的标记 |
| `/v1/chat/completions` | Anthropic | 保留消息文本部分和工具定义上的标记 |
| 任意接口 | OpenAI 兼容 | 全部删除，只有隐式缓存 |

- 通过 `/v1/messages` 调用时，打在图片块或 `tool_result` 块本身上的标记不会转发，请把断点打在文本块上。
- `system` 有多个文本块时会合并成一个，只保留最后一个标记。
- 标记中写 `"ttl": "1h"` 时，网关会把 `anthropic-beta` 请求头设为 1 小时缓存所需的值；客户端自带的 `anthropic-beta` 会被覆盖。
- Anthropic 每个请求最多 4 个断点，前缀短于模型的最小可缓存长度时不会缓存。

下例把一段固定的长系统提示词标记为缓存断点（`MODEL_ID` 换成由 Anthropic 协议上游服务的模型，例如 Claude 系列；环境变量的设置见[完成第一次模型调用](https://platform.lyrouter.com/ai_gateway/docs/quickstart)）：

```bash
curl "$LYROUTER_BASE_URL/v1/messages" \
  -H "x-api-key: $LYROUTER_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "max_tokens": 1024,
    "system": [{"type": "text", "text": "你是合同审阅助手。以下是审阅规则……（每次相同的长文本）", "cache_control": {"type": "ephemeral"}}],
    "messages": [{"role": "user", "content": "请检查第 3 条的违约责任是否对等。"}]
  }'
```

第一次调用在日志中出现「显式缓存创建」，说明标记已被上游接受；之后几分钟内发送相同前缀的请求，这部分记为「输入（缓存命中）」。

## 客户端注意事项

- **Claude Code**：命中率精确为 0 时先升级 Claude Code。部分版本会在系统提示词开头写入一行每个请求都变化的 `cch=` 标记，使前缀从第一个字节起就不同。会话中途调整可用工具也会让工具定义之后的内容全部未命中。接入方法见[Claude Code](https://platform.lyrouter.com/ai_gateway/docs/claude-code)。
- **自研应用**：确认 SDK 或框架没有在每次请求中自动插入时间戳、请求 ID，也没有每轮重新排序工具或消息。

## 减少不必要的用量

- **控制输出**：用 `max_tokens` 限制输出长度；不需要深度思考的任务降低思考强度或关闭思考，思考过程计入「输出」。
- **控制上下文**：清理与任务无关的历史；超长会话可能落入更贵的长上下文档，定期总结后开启新会话。
- **选择模型与来源**：在相同任务和时间范围内比较不同模型与来源的费用和效果，见[如何选择模型](https://platform.lyrouter.com/ai_gateway/docs/choose)与[平台模型与 BYOK 如何选择](https://platform.lyrouter.com/ai_gateway/docs/byok-choice)。按 Credits 设置预算与配额见[预算、配额与限流](https://platform.lyrouter.com/ai_gateway/docs/quota)。

## 验证效果

调整后，在日志详情的「Token 消耗」中观察连续调用的「输入（缓存命中）」是否逐轮增加，再在 **用量分析** 中按相同时间长度比较调整前后的缓存命中率和费用。自己计算命中率时按 Token 加权：Σ 输入（缓存命中）÷ Σ（输入（缓存未命中）+ 输入（缓存命中）），不要对每次调用的命中率取平均。命中率仍然偏低时，按[费用异常与缓存未命中](https://platform.lyrouter.com/ai_gateway/docs/cache-errors)逐项排查。

（截图：在日志详情中观察缓存命中输入随调用轮次的变化，验证优化效果。）
