例行检查 / Checklist
目标版本线 / Target Release Line
2.x
功能描述 / Feature Description
希望为 OpenAI Responses API 增加 prompt_cache_key 的安全软亲和支持。
当客户端在 Responses create 请求中提供有效的顶层 prompt_cache_key 时,GPT-Load 可以将其作为受限的软亲和信号,优先复用此前成功使用的凭据,从而提高同一 prompt cache 分组的凭据复用概率。
该能力不应把 prompt_cache_key 解释为严格的 session ID、认证凭据、机器绑定标识或跨实例会话状态。
同时,希望在请求日志和监控界面中区分:
- 软亲和目标实际命中;
previous_response_id 或 WebSocket binding 的硬续接命中;
- 软亲和未命中、目标不可用或缓存不可用等有限状态。
应用场景 / Use Case
当多个请求属于同一个 prompt cache 分组时,客户端会重复使用相同的 prompt_cache_key。如果每次请求都完全随机选择凭据,可能降低上游 prompt cache 的复用效率。
目标场景包括:
- 同一 AccessKey、协议、客户端模型和操作下,重复使用相同的
prompt_cache_key;
- 在没有显式 key 时,继续使用现有的 prompt-prefix 亲和逻辑;
- 使用
previous_response_id 时,仍严格复用原 response 绑定的凭据;
- 当软亲和目标不可用、分组禁用或本地缓存不可用时,安全回退到现有调度流程;
- 让运维人员能够在请求日志中区分软亲和和硬续接,而不是将两者都解释为
affinity_hit。
期望方案 / Desired Behavior
1. 请求信号
仅在 Responses create 请求的 JSON 顶层读取 prompt_cache_key。
有效值必须满足:
- 非空字符串;
- 有效 UTF-8;
- 首尾无空白;
- 不包含控制字符;
- 不超过 256 字节。
无效值应被静默忽略,不阻断原请求,也不改变原有请求转发行为。
有效的显式 prompt_cache_key 应优先于 prompt-prefix 派生信号。prompt-prefix 仅在没有有效显式 key 时作为 fallback 使用,来源包括:
instructions;
system;
developer;
- 首个
user 或 input_text。
显式 key 与 prompt-prefix 应使用独立 namespace,避免同值信号意外共享。
2. 软亲和路由
软亲和应遵循以下边界:
- 不扩大现有候选凭据集合;
- 不绕过 AccessKey、分组、凭据身份或响应绑定安全检查;
- 不改变现有重试策略;
- 在现有候选范围内提供凭据优先级提示;
- 软亲和目标不可用时继续走现有降级路径;
- 仅在成功终态后学习软亲和目标;
- 失败、取消、不完整流和硬续接请求不应学习软亲和。
当前方案还会将同一受限信号用于已有的 provider-private replay scope。该 scope 不对外暴露,也不等同于严格 session 身份、机器绑定或认证凭据。希望在本 Issue 中确认是否保留这一行为,或是否应将软亲和限制为候选优先级提示。
3. 硬续接优先
previous_response_id 和 WebSocket binding 继续作为硬绑定信号,优先于软亲和:
continuity_hit:表示已找到并采用硬续接绑定;
affinity_hit:仅表示首轮实际选择了已有软亲和目标;
- 两者不应混用;
- 硬续接失败时保持现有拒绝或失败语义,不扩大允许使用的凭据集合。
4. 请求日志和监控
请求日志、控制面 API 和监控界面可以提供以下有界观测:
affinity_source
affinity_state
continuity_hit
建议的 affinity_source:
none
prompt_cache_key
prompt_prefix
建议的 affinity_state:
no_signal
cache_miss
hit
group_disabled
target_unavailable
cache_unavailable
这些字段只表示 GPT-Load 本地的亲和决策:
affinity_state=hit 不表示上游 prompt cache 一定命中;
continuity_hit 不表示上游一定成功恢复响应状态。
原始 prompt_cache_key、派生 key 和 HMAC 输入不应写入:
- 请求日志;
- API 响应;
- 错误信息;
- 监控 UI;
- 调试输出;
- 持久化数据。
5. 缓存和派生 key
亲和缓存可以继续使用进程内缓存:
- 不要求重启后共享;
- 不承诺多实例之间共享;
- 不新增数据库缓存;
- 使用现有稳定 Hash 能力生成 opaque key;
- 派生 key 应按 AccessKey、协议、客户端模型、操作和信号类型隔离;
- 显式 key 与 prefix-derived key 不应共用 namespace。
兼容性、数据与安全影响 / Compatibility, Data, and Security Impact
API 兼容性
这是对 Responses create 顶层可选字段的非阻断式支持。
现有客户端请求格式保持兼容:
- 有效
prompt_cache_key 被内部用作软亲和提示;
- 无效或未知格式的值被忽略;
- 无效值不会导致请求失败;
- 请求原始 body 不因本地亲和处理而被改写。
路由兼容性
软亲和不会:
- 扩大客户端已有的凭据访问权限;
- 扩大候选凭据集合;
- 覆盖
previous_response_id 硬续接;
- 改变现有重试策略;
- 将
prompt_cache_key 变成严格的 session 或机器绑定标识。
数据库影响
请求日志需要增加以下字段:
continuity_hit
affinity_source
affinity_state
数据库变更应使用下一个连续的 additive migration,不应固定依赖某个未来迁移编号。历史记录使用安全默认值,例如:
continuity_hit=false
affinity_source=none
affinity_state=no_signal
历史数据不应回填任何原始 prompt cache key、派生 key 或 HMAC 输入。
SQLite 应覆盖本地迁移回归;MySQL/PostgreSQL 的升级、默认值读取和中断恢复应由 CI 或维护者数据库矩阵补充验证。
安全和隐私
不新增依赖、密钥配置或 X-Session-ID。
原始 key、派生 key 和 HMAC 输入不得进入:
- durable storage;
- 请求日志;
- API 响应;
- 错误文本;
- 调试捕获;
- 监控 UI。
调查结果 / Investigation
已对上游仓库现有 Issues 和 Responses 相关实现进行检索。
精确重复检索
搜索:
prompt_cache_key
prompt cache affinity
Responses prompt_cache_key
previous_response_id
结果:
- 未发现针对
prompt_cache_key 软亲和的相同 Issue;
- 未发现已经讨论该字段校验、软亲和 namespace 或 affinity/continuity 观测拆分的 Issue。
搜索链接:
相关 Issue:#365
#365 添加密钥轮询间隔配置以优化 KV 缓存利用率
该 Issue 讨论:
- 当前轮询会导致同一用户/会话跨 API key;
- 跨 key 可能降低上游 KV/prompt cache 利用率;
- 是否增加密钥轮询间隔;
- 是否使用会话粘性或一致性哈希。
该 Issue 与本提案有相同的用户价值背景:减少多凭据轮换导致的上游缓存浪费。
但两者不是同一个方案:
相关 Responses 实现:PR #609
PR #609 feat(responses): 实现响应状态续接路由
该 PR 已实现 previous_response_id 的硬续接路由,明确了以下边界:
- response ID 归属应按 AccessKey 隔离;
- 续接只使用当前路由仍允许的原凭据;
- ID 路由与提示词软亲和互斥;
- 硬续接不应被普通软亲和逻辑覆盖。
本提案沿用并扩展这一边界,不试图替代或放宽 previous_response_id 的硬绑定。
备选方案 / Alternatives Considered
1. 新增 X-Session-ID
不采用。它会引入新的客户端协议契约,并容易被误解为严格 session 绑定。
2. 将 prompt_cache_key 作为严格 session 或机器绑定
不采用。该字段只能作为软亲和提示,不能改变现有凭据权限、候选集合或 response binding 规则。
3. 固定密钥轮询间隔
相关方案见 #365。
不作为本提案的主要方案,因为固定轮询间隔无法识别不同的 prompt cache 分组,也无法表达客户端明确提供的缓存分组信号。
4. 持久化原始 prompt cache key 或亲和缓存
不采用。原始 key 和派生 key 不应进入 durable storage;进程内缓存足以支持当前目标。
5. 将显式 key 与 prompt-prefix 合并到同一个 namespace
不采用。两类信号语义不同,合并可能造成意外共享或碰撞。
6. 将软亲和限制为纯候选排序
这是需要维护者确认的设计选择。
当前原型除了候选优先级,还将受限派生信号用于已有的 provider-private replay scope。该 scope 不对外暴露,但会影响执行层行为。需要确认:
- 是否保留该 scope 影响;
- 是否仅允许它作用于已有需要 replay scope 的 Responses 渠道;
- 或者是否将实现收窄为只影响候选优先级。
当前状态 / Current Status
该方案已在独立 worktree 和分支中完成原型实现与验证,尚未提交正式 PR:
当前原型已覆盖:
- Responses 顶层
prompt_cache_key 解析;
- 显式 key 校验和 prefix fallback;
- 显式 key 与 prefix namespace 隔离;
- HTTP 和 Responses WebSocket 软亲和;
affinity_hit 与 continuity_hit 分离;
- 请求日志、API、数据库迁移和监控 UI 投影;
- 三份 README;
- Go、race、vet、build、前端 lint/type-check/format/build 验证。
已通过的主要验证包括:
make PNPM=pnpm check
go test -race -count=1 ./internal/affinity ./internal/gateway ./internal/requestlog
例行检查 / Checklist
目标版本线 / Target Release Line
2.x
功能描述 / Feature Description
希望为 OpenAI Responses API 增加
prompt_cache_key的安全软亲和支持。当客户端在 Responses
create请求中提供有效的顶层prompt_cache_key时,GPT-Load 可以将其作为受限的软亲和信号,优先复用此前成功使用的凭据,从而提高同一 prompt cache 分组的凭据复用概率。该能力不应把
prompt_cache_key解释为严格的 session ID、认证凭据、机器绑定标识或跨实例会话状态。同时,希望在请求日志和监控界面中区分:
previous_response_id或 WebSocket binding 的硬续接命中;应用场景 / Use Case
当多个请求属于同一个 prompt cache 分组时,客户端会重复使用相同的
prompt_cache_key。如果每次请求都完全随机选择凭据,可能降低上游 prompt cache 的复用效率。目标场景包括:
prompt_cache_key;previous_response_id时,仍严格复用原 response 绑定的凭据;affinity_hit。期望方案 / Desired Behavior
1. 请求信号
仅在 Responses
create请求的 JSON 顶层读取prompt_cache_key。有效值必须满足:
无效值应被静默忽略,不阻断原请求,也不改变原有请求转发行为。
有效的显式
prompt_cache_key应优先于 prompt-prefix 派生信号。prompt-prefix 仅在没有有效显式 key 时作为 fallback 使用,来源包括:instructions;system;developer;user或input_text。显式 key 与 prompt-prefix 应使用独立 namespace,避免同值信号意外共享。
2. 软亲和路由
软亲和应遵循以下边界:
当前方案还会将同一受限信号用于已有的 provider-private replay scope。该 scope 不对外暴露,也不等同于严格 session 身份、机器绑定或认证凭据。希望在本 Issue 中确认是否保留这一行为,或是否应将软亲和限制为候选优先级提示。
3. 硬续接优先
previous_response_id和 WebSocket binding 继续作为硬绑定信号,优先于软亲和:continuity_hit:表示已找到并采用硬续接绑定;affinity_hit:仅表示首轮实际选择了已有软亲和目标;4. 请求日志和监控
请求日志、控制面 API 和监控界面可以提供以下有界观测:
affinity_sourceaffinity_statecontinuity_hit建议的
affinity_source:noneprompt_cache_keyprompt_prefix建议的
affinity_state:no_signalcache_misshitgroup_disabledtarget_unavailablecache_unavailable这些字段只表示 GPT-Load 本地的亲和决策:
affinity_state=hit不表示上游 prompt cache 一定命中;continuity_hit不表示上游一定成功恢复响应状态。原始
prompt_cache_key、派生 key 和 HMAC 输入不应写入:5. 缓存和派生 key
亲和缓存可以继续使用进程内缓存:
兼容性、数据与安全影响 / Compatibility, Data, and Security Impact
API 兼容性
这是对 Responses
create顶层可选字段的非阻断式支持。现有客户端请求格式保持兼容:
prompt_cache_key被内部用作软亲和提示;路由兼容性
软亲和不会:
previous_response_id硬续接;prompt_cache_key变成严格的 session 或机器绑定标识。数据库影响
请求日志需要增加以下字段:
continuity_hitaffinity_sourceaffinity_state数据库变更应使用下一个连续的 additive migration,不应固定依赖某个未来迁移编号。历史记录使用安全默认值,例如:
continuity_hit=falseaffinity_source=noneaffinity_state=no_signal历史数据不应回填任何原始 prompt cache key、派生 key 或 HMAC 输入。
SQLite 应覆盖本地迁移回归;MySQL/PostgreSQL 的升级、默认值读取和中断恢复应由 CI 或维护者数据库矩阵补充验证。
安全和隐私
不新增依赖、密钥配置或
X-Session-ID。原始 key、派生 key 和 HMAC 输入不得进入:
调查结果 / Investigation
已对上游仓库现有 Issues 和 Responses 相关实现进行检索。
精确重复检索
搜索:
prompt_cache_keyprompt cache affinityResponses prompt_cache_keyprevious_response_id结果:
prompt_cache_key软亲和的相同 Issue;搜索链接:
prompt_cache_keyIssues 搜索prompt cacheIssues 搜索previous_response_idIssues 搜索相关 Issue:#365
#365 添加密钥轮询间隔配置以优化 KV 缓存利用率
该 Issue 讨论:
该 Issue 与本提案有相同的用户价值背景:减少多凭据轮换导致的上游缓存浪费。
但两者不是同一个方案:
prompt_cache_key作为软亲和提示;previous_response_id硬续接和软亲和;closed / not planned。相关 Responses 实现:PR #609
PR #609 feat(responses): 实现响应状态续接路由
该 PR 已实现
previous_response_id的硬续接路由,明确了以下边界:本提案沿用并扩展这一边界,不试图替代或放宽
previous_response_id的硬绑定。备选方案 / Alternatives Considered
1. 新增
X-Session-ID不采用。它会引入新的客户端协议契约,并容易被误解为严格 session 绑定。
2. 将
prompt_cache_key作为严格 session 或机器绑定不采用。该字段只能作为软亲和提示,不能改变现有凭据权限、候选集合或 response binding 规则。
3. 固定密钥轮询间隔
相关方案见 #365。
不作为本提案的主要方案,因为固定轮询间隔无法识别不同的 prompt cache 分组,也无法表达客户端明确提供的缓存分组信号。
4. 持久化原始 prompt cache key 或亲和缓存
不采用。原始 key 和派生 key 不应进入 durable storage;进程内缓存足以支持当前目标。
5. 将显式 key 与 prompt-prefix 合并到同一个 namespace
不采用。两类信号语义不同,合并可能造成意外共享或碰撞。
6. 将软亲和限制为纯候选排序
这是需要维护者确认的设计选择。
当前原型除了候选优先级,还将受限派生信号用于已有的 provider-private replay scope。该 scope 不对外暴露,但会影响执行层行为。需要确认:
当前状态 / Current Status
该方案已在独立 worktree 和分支中完成原型实现与验证,尚未提交正式 PR:
当前原型已覆盖:
prompt_cache_key解析;affinity_hit与continuity_hit分离;已通过的主要验证包括: