> ## Documentation Index
> Fetch the complete documentation index at: https://docs.poixe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 提示词缓存（缓存亲和性路由）

Poixe 实现了一套 **缓存亲和性路由（Cache Affinity Routing）** 机制，用于提高上游 API 的缓存命中率，从而降低实际计费成本。

## 背景

主流模型厂商（OpenAI、Anthropic 等）均提供了 **Prompt Caching** 能力：当连续请求的前缀内容相同或主动标记缓存时，上游会复用已缓存的计算结果，对缓存命中部分给予折扣计费。

但缓存有一个关键约束：**缓存绑定在具体的渠道（API Key / 账户）上，不能跨渠道共享。**

在聚合网关场景下，Poixe 后端接入了多个上游渠道，默认由权重负载均衡模块分配请求。这意味着同一个用户的连续请求可能被分发到不同渠道，导致上游缓存频繁失效。

缓存亲和性路由正是为了解决这个问题。

## 工作原理

<Steps>
  <Step title="首次请求">
    用户请求某个模型（如 `claude-opus-4-6`），系统按正常权重逻辑分配到某个上游渠道，请求成功后，系统记录下这个绑定关系：**用户 + 模型 → 渠道**。
  </Step>

  <Step title="后续请求">
    在绑定有效期内，该用户对同一模型的后续请求会 **优先路由到同一渠道**，使上游缓存得以复用。
  </Step>

  <Step title="绑定失效">
    当绑定关系失效后，系统回退到默认的权重负载均衡逻辑，重新分配渠道。
  </Step>
</Steps>

## 绑定失效条件

绑定关系是短暂且脆弱的，满足以下任一条件即自动解除：

| 条件         | 说明                                                 |
| ---------- | -------------------------------------------------- |
| **TTL 过期** | 绑定创建后 **5 分钟**强制失效，不续期                             |
| **请求次数上限** | 单个绑定最多承载 **100 次**请求，超过后自动解除                       |
| **渠道异常**   | 绑定渠道返回任何错误（无论是否为用户请求体问题），立即解除                      |
| **渠道速率不足** | 请求完成后，若渠道 TPM / RPM 过低，系统将拒绝建立亲和关系，优先保障请求健康度而非缓存收益 |

<Callout type="info" icon="info-circle">
  绑定失效不会导致请求失败。系统会立即回退到权重负载均衡，正常处理请求。
</Callout>

<Callout type="warning" icon="exclamation-triangle">
  **为什么速率不足时主动拒绝亲和？** 若对速率已告急的渠道继续建立亲和，下次请求极易触发速率限制，进入重试阶段，导致延迟显著增加甚至请求失败。系统以**请求健康度优先于缓存成本**为原则，在此场景下主动放弃亲和。
</Callout>

## 适用范围

缓存亲和性路由 **不是对所有模型生效**，仅对以下协议和厂商的特定模型启用：

| 协议                      | 厂商        | 启用模型                                        |
| ----------------------- | --------- | ------------------------------------------- |
| OpenAI Chat Completions | OpenAI    | `gpt-4o`、`gpt-4o-mini`、`...`                |
| OpenAI Responses        | OpenAI    | `gpt-4o`、`gpt-4o-mini`、`...`                |
| Anthropic Messages      | Anthropic | `claude-opus-4-6`、`claude-sonnet-4-6`、`...` |

<Callout type="warning" icon="exclamation-triangle">
  该列表会随上游厂商的缓存策略调整而更新。不在列表中的模型走默认负载均衡，不受影响。
</Callout>

## 实际节省效果

以下是一个 **Claude Code + claude-opus-4-6** 的真实请求示例，展示缓存命中对费用的影响：

<Tabs>
  <Tab title="请求概况">
    命令行终端打开 `claude`，多次对话输入 `hi`，触发对话请求。上游实际计费的 token 数如下：

    | 项目         | Token 数    |
    | ---------- | ---------- |
    | 输入 tokens  | 1          |
    | 输出 tokens  | 146        |
    | 缓存写入（5min） | 321        |
    | **缓存命中**   | **25,648** |

    这是一次典型的 Claude Code 对话请求——绝大部分 prompt 内容（系统提示、项目上下文、历史对话）在前次请求中已被缓存，本次直接命中。
  </Tab>

  <Tab title="费用对比">
    **claude-opus-4-6 官方定价（\$/MTok）**

    | 类型         | 单价         |
    | ---------- | ---------- |
    | 输入         | \$5        |
    | 输出         | \$25       |
    | 缓存写入（5min） | \$6.25     |
    | **缓存命中**   | **\$0.50** |

    **无缓存：25,648 tokens 全部按输入价计费**

    | 项目           | 计算                | 费用            |
    | ------------ | ----------------- | ------------- |
    | 输入（含 25,648） | 25,970 × \$5 / 1M | \$0.12985     |
    | 输出           | 146 × \$25 / 1M   | \$0.00365     |
    | **合计**       |                   | **\$0.13350** |

    **有缓存：25,648 tokens 命中缓存，按 \$0.50 计费**

    | 项目     | 计算                   | 费用            |
    | ------ | -------------------- | ------------- |
    | 输入     | 1 × \$5 / 1M         | \$0.000005    |
    | 缓存写入   | 321 × \$6.25 / 1M    | \$0.00201     |
    | 缓存命中   | 25,648 × \$0.50 / 1M | \$0.01282     |
    | 输出     | 146 × \$25 / 1M      | \$0.00365     |
    | **合计** |                      | **\$0.01849** |
  </Tab>
</Tabs>

<CardGroup cols={3}>
  <Card title="单次节省" icon="piggy-bank">
    <span style={{fontSize: "1.5rem", fontWeight: "bold"}}>86%</span>

    <br />

    \$0.1335 → \$0.0185
  </Card>

  <Card title="缓存命中价" icon="arrow-down">
    <span style={{fontSize: "1.5rem", fontWeight: "bold"}}>1/10</span>

    <br />

    {/* &#36;5.00 → &#36;0.50 / MTok */}

    \$5.00 → \$0.50 / MTok
  </Card>

  <Card title="Claude Code 场景" icon="repeat">
    <span style={{fontSize: "1.5rem", fontWeight: "bold"}}>\~90%+</span>

    <br />

    连续对话中 prompt 缓存命中率
  </Card>
</CardGroup>

<Callout type="info" icon="calculator">
  在 Claude Code 的典型工作流中，每轮对话都会携带完整的系统提示和项目上下文（通常 20K\~100K tokens），这些内容在连续请求间几乎不变。**缓存亲和性路由确保这些请求尽可能命中同一渠道的缓存**，将这部分 tokens 的单价从 \$5/MTok 降至 \$0.50/MTok。
</Callout>

## 设计取舍

缓存亲和性路由本质上是在 **缓存命中率** 和 **流量均衡** 之间做权衡：

* **短 TTL + 次数上限**：避免流量长期集中在单一渠道，防止负载倾斜
* **错误即解绑**：避免将后续请求持续路由到已异常的渠道
* **尽力而为**：亲和路由是优化手段而非硬性保证，任何环节失败都会静默回退到默认逻辑

## 对用户的影响

* **无需任何配置**，系统自动生效
* 在编程助手（Claude Code、Codex 等）场景下，连续对话的缓存命中率会显著提升
* 缓存命中时，上游按折扣价计费，Poixe 的扣费同步降低

## 对供应商的建议

建议为模型渠道部署**速率足够高的账号**。速率不足的账号存在以下连锁风险：

* 某次请求完成后，系统因渠道速率告急而拒绝建立亲和，导致接下来最多 **100 次**连续请求的缓存机会全部浪费
* 从数据面来看，低速率账号与高速率账号之间，**最坏情况下可产生接近 100 倍的有效缓存流量差异**

<Callout type="warning" icon="exclamation-triangle">
  **100 倍差异的来源**：单次亲和绑定最多可承载 100 次请求。若速率不足导致亲和未建立，则这 100 次请求均回退到默认负载均衡，无法持续命中同一渠道缓存；而速率充足的账号可完整利用这 100 次窗口，两者在缓存利用率上的最大差距即为 \~100 倍。
</Callout>

## 上游缓存机制参考

<CardGroup cols={2}>
  <Card title="OpenAI Prompt Caching" href="https://platform.openai.com/docs/guides/prompt-caching">
    OpenAI 官方 Prompt Caching 文档，包含缓存规则与计费说明
  </Card>

  <Card title="Anthropic Prompt Caching" href="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching">
    Anthropic 官方 Prompt Caching 文档，包含缓存规则与计费说明
  </Card>
</CardGroup>
