# 提升 Prompt Cache 命中率

本文档介绍如何通过稳定的请求结构、会话标识和模型协议配置，提高 UModelverse 平台的 Prompt Cache 命中率，从而降低首 Token 延迟（TTFT）和推理成本。

## 使用 X-Session-ID 保持会话亲和

`X-Session-ID` 是通过 HTTP Header 传递的会话标识。平台会尽量将同一会话的连续请求路由到同一个推理实例，从而提高该 `session` 对话的缓存命中率。

### 使用方式

在请求 Header 中添加 `X-Session-ID`：

```bash
X-Session-ID: session-abc123
```

完整请求示例：

```bash
curl -X POST 'https://api.modelverse.cn/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer your-api-key' \
  -H 'X-Session-ID: session-abc123' \
  -d '{
    "model": "your-model",
    "messages": [
      { "role": "system", "content": "你是一个助手。" },
      { "role": "user", "content": "请帮我总结这段内容。" }
    ]
  }'
```

### 使用建议

- 同一用户的多轮对话应保持 `X-Session-ID` 不变。
- 不同用户、不同会话或互不相关的上下文应使用不同的 Session ID。
- Session ID 应使用业务侧生成的稳定标识，避免每次请求都重新生成。
- 避免多个高并发用户复用同一个 Session ID，否则会降低调度亲和效果，也可能造成上下文串扰风险。

### 亲和性的边界

`X-Session-ID` 提供的是调度亲和能力，不是对推理实例的永久绑定。平台会尽量复用同一个推理实例，但在以下场景中可能重新选择实例：

- 同一 Session ID 下的并发请求较高，单个推理实例无法承载全部请求。
- 原推理实例负载较高、排队较长或暂时不可用。
- 会话亲和关系超过平台配置的 TTL，后续请求会重新选择合适的推理实例。

因此，`X-Session-ID` 可以提高同一会话命中本地缓存的概率，但不保证每一次请求都命中同一个推理实例。

## Claude Anthropic Messages 的 cache_control

当使用 Claude 模型并通过 Anthropic Messages 协议（`/v1/messages`）调用时，需要在请求中增加 `cache_control` 字段来开启 Claude 的 Prompt caching。其他模型或 OpenAI 兼容接口通常不需要手动开启缓存，保持请求前缀稳定即可。

Anthropic 官方文档说明，Claude Prompt caching 可以通过两种方式启用：顶层 `cache_control` 和内容块上的显式缓存断点。UModelverse 平台当前不支持请求顶层的 `cache_control`，请在具体内容块上增加 `cache_control` 来指定缓存断点。

下面示例将 `cache_control` 放在稳定的 `system` 内容块上：

```bash
curl https://api.modelverse.cn/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: $MODELVERSE_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-4-5-20250929",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "你是一个助手，请用简洁、准确的方式回答问题。",
        "cache_control": { "type": "ephemeral" }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "请帮我总结这段内容。"
      }
    ]
  }'
```

如果需要缓存长上下文、工具定义或历史消息，可以将 `cache_control` 放在对应的稳定内容块上。不要把 `cache_control` 放在请求根对象上，否则 UModelverse 平台无法识别该字段。具体字段、TTL 和计费规则请参考 [Anthropic Prompt caching 官方文档](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)。

Claude Prompt cache 的默认 TTL 为 5 分钟，官方也提供 1 小时缓存选项。这里的缓存 TTL 与 `X-Session-ID` 的平台调度亲和 TTL 不是同一个概念。

## 保持 System Prompt 稳定

不要在 System Prompt 中写入当天日期、当前时间、随机数、请求 ID 等动态内容。

时间或随机内容变化会导致 System Prompt 内容变化，前缀无法匹配，缓存会失效。例如日期在 0 点变化后，包含日期的 System Prompt 会整体变化，可能导致缓存命中率下降、TTFT 上升。

推荐将动态内容放在用户消息中，而不是放在 System Prompt 中。

```json
{
  "messages": [
    {
      "role": "system",
      "content": "你是一个助手，请用简洁、准确的方式回答问题。"
    },
    {
      "role": "user",
      "content": "今天是 2026 年 5 月 9 日，请帮我生成一份日报。"
    }
  ]
}
```

不推荐：

```json
{
  "messages": [
    {
      "role": "system",
      "content": "今天是 2026 年 5 月 9 日，你是一个助手。"
    },
    {
      "role": "user",
      "content": "请帮我生成一份日报。"
    }
  ]
}
```

## 设计稳定的 Request 结构

合理的请求结构是提升缓存命中率的基础。请求前缀越稳定，越容易复用已有缓存。

### 保持 messages 结构稳定

- **role 保持稳定**：`messages` 中各消息的 `role` 不要频繁变化。
- **消息数量尽量稳定**：不要无规律地插入、删除或合并历史消息。
- **消息顺序保持稳定**：不要调整已有消息的排列顺序。

### 只在 messages 末尾追加新内容

新的对话轮次应追加到 `messages` 数组末尾，避免在中间插入或修改已有消息。

第 1 轮请求：

```json
{
  "messages": [
    {
      "role": "system",
      "content": "你是一个助手。"
    },
    {
      "role": "user",
      "content": "问题 1"
    }
  ]
}
```

第 2 轮请求：

```json
{
  "messages": [
    {
      "role": "system",
      "content": "你是一个助手。"
    },
    {
      "role": "user",
      "content": "问题 1"
    },
    {
      "role": "assistant",
      "content": "回答 1"
    },
    {
      "role": "user",
      "content": "问题 2"
    }
  ]
}
```

在这个结构中，第 2 轮请求保留了第 1 轮请求的完整前缀，因此更容易复用已有 KV Cache。

## 优化方式总结

| 优化方式 | 作用 | 建议做法 |
| --- | --- | --- |
| 使用 `X-Session-ID` | 提高同一会话路由到同一推理实例的概率 | 在 HTTP Header 中传递稳定的会话 ID |
| 理解亲和性边界 | 避免把 Session ID 误认为实例强绑定 | 注意高并发、实例压力和亲和 TTL 都可能导致重新调度 |
| Claude 使用 `cache_control` | 开启 Anthropic Messages 协议下的 Claude Prompt caching | Claude `/v1/messages` 请求在稳定内容块上增加 `cache_control`，不要放在请求顶层 |
| 保持 System Prompt 稳定 | 避免前缀变化导致缓存失效 | 不在 System Prompt 中写入时间、随机数等动态内容 |
| 末尾追加消息 | 保持请求前缀一致 | 新对话轮次只追加到 `messages` 末尾 |
