Download internal/upstream/cache_key.go from a3216/gcli2api: direct link, hf CLI and curl.
- Browser
- Download file 3.46 kB
-
https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/upstream/cache_key.go
- Command line
-
hf download hf://spaces/a3216/gcli2api/internal/upstream/cache_key.go
-
curl -L -o cache_key.go https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/upstream/cache_key.go
3.46 kB
| // cache_key.go 注入上游 prompt_cache_key 字段(P0 费用优化)。 | |
| // | |
| // 逆向实测(buddy-adapter.ts:706-714):上游服务端支持 prompt_cache_key, | |
| // 同一段 8k token 前缀: | |
| // - 不带 → prompt_cache_hit_tokens=0, credit≈0.34 | |
| // - 带 → prompt_cache_hit_tokens=7808, credit≈0.02(费用降 ~17×) | |
| // | |
| // 网关在此为每个出站 chat 请求注入一个稳定、按账号隔离的 cache key, | |
| // 让同一客户端对同一账号的连续请求复用上游前缀缓存。 | |
| package upstream | |
| import ( | |
| "crypto/sha256" | |
| "encoding/hex" | |
| "encoding/json" | |
| "strings" | |
| ) | |
| // InjectPromptCacheKey 在已改写的出站 body 上注入 prompt_cache_key 字段。 | |
| // | |
| // 优先级: | |
| // 1. body 已带 prompt_cache_key → 原值保留(客户端自知复用哪个键) | |
| // 2. body 已带 conversation_id / conversationId → 用它做会话哈希源 | |
| // 3. 都没有 → 用入站 conversationID 参数(来自 X-Conversation-ID 头解析) | |
| // | |
| // 安全约束——按账号隔离: | |
| // - 生成键格式 `wb2a-<uid8>-<convHex>` | |
| // - uid8 是账号 UID 前 8 字符,跨账号绝不相同 → 跨账号缓存键绝不碰撞 | |
| // - 跨账号复用同一 cache key 会让上游命中错账号的前缀缓存、泄露对方对话,故 uid 是硬隔离因子 | |
| // | |
| // 入参 uid 为账号 UID(空则用 "-",但仍会注入键;调用方应保证传真实 UID)。 | |
| // 入参 conversationID 为网关解析出的会话标识(body 里没有 conversation_id 时用它做哈希源)。 | |
| // 两源都空时 convHex 为定值(每次新会话不复用前缀,但仍保留账号隔离段)。 | |
| // body 不可解析时原样返回(与 prepareBody 语义一致:坏 body 不二次错误化)。 | |
| func InjectPromptCacheKey(body []byte, uid, conversationID string) []byte { | |
| if len(body) == 0 { | |
| return body | |
| } | |
| var obj map[string]any | |
| if err := json.Unmarshal(body, &obj); err != nil { | |
| return body | |
| } | |
| // 优先级 1:客户端已显式带 key → 绝不覆盖。 | |
| if existing, ok := obj["prompt_cache_key"].(string); ok && existing != "" { | |
| return body | |
| } | |
| // 优先级 2:body 里的 conversation_id / conversationId 做会话哈希源。 | |
| conv := conversationID | |
| if v := strField(obj, "conversation_id"); v != "" { | |
| conv = v | |
| } else if v := strField(obj, "conversationId"); v != "" { | |
| conv = v | |
| } | |
| key := buildCacheKey(uid, conv) | |
| obj["prompt_cache_key"] = key | |
| out, err := json.Marshal(obj) | |
| if err != nil { | |
| return body | |
| } | |
| return out | |
| } | |
| // buildCacheKey 生成 `wb2a-<uid8>-<convHex>` 格式的稳定 cache key。 | |
| // | |
| // uid8 提供账号隔离段;convHex = sha256(uid + conversationID)[:16] 的 hex 提供会话段 | |
| // (同账号同会话稳定、不同会话不同)。会话源为空时 convHex 仍由 uid 单独哈希, | |
| // 保证跨账号绝不碰撞但同一空会话不复用(空会话 = 新会话语义)。 | |
| func buildCacheKey(uid, conversation string) string { | |
| uid8 := uid | |
| if len(uid8) > 8 { | |
| uid8 = uid8[:8] | |
| } | |
| if uid8 == "" { | |
| uid8 = "-" | |
| } | |
| sum := sha256.Sum256([]byte(uid + "|" + conversation)) | |
| convHex := hex.EncodeToString(sum[:16]) | |
| return "wb2a-" + uid8 + "-" + convHex | |
| } | |
| // strField 从 map 取 string 字段,非 string 或空串返回 ""。 | |
| func strField(obj map[string]any, key string) string { | |
| v, ok := obj[key].(string) | |
| if !ok { | |
| return "" | |
| } | |
| return strings.TrimSpace(v) | |
| } | |