Files

70 lines
1.9 KiB
Go

package common
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"sort"
"strings"
)
// excludeCacheFields 是应从缓存哈希中排除的请求体字段,
// 因为它们随请求变化但不影响模型输出。
var excludeCacheFields = map[string]bool{
"stream": true,
"seed": true,
"user": true,
"request_id": true,
"top_logprobs": true,
"logprobs": true,
"n": true,
"frequency_penalty": false, // 保留——影响输出
"presence_penalty": false, // 保留——影响输出
"temperature": false, // 保留——影响输出
"max_tokens": false, // 保留——影响输出
"max_completion_tokens": false,
}
// ComputeCacheHash 基于规范化后的请求体生成确定性 SHA-256 哈希。
// 它移除非确定性字段(stream、seed、user、request_id、top_logprobs、logprobs、n),
// 并对 JSON 键排序以保证哈希一致。
func ComputeCacheHash(body []byte, modelName string) string {
var raw map[string]json.RawMessage
if err := json.Unmarshal(body, &raw); err != nil {
// 兜底:直接哈希原始请求体 + 模型名
h := sha256.New()
h.Write([]byte(modelName))
h.Write(body)
return hex.EncodeToString(h.Sum(nil))
}
// 移除需排除的字段
for field := range excludeCacheFields {
delete(raw, field)
}
// 排序键以保证确定性顺序
keys := make([]string, 0, len(raw))
for k := range raw {
keys = append(keys, k)
}
sort.Strings(keys)
// 用排序后的键重建 JSON
var buf strings.Builder
for _, k := range keys {
if buf.Len() > 0 {
buf.WriteByte(',')
}
keyBytes, _ := json.Marshal(k)
buf.Write(keyBytes)
buf.WriteByte(':')
buf.Write(raw[k])
}
h := sha256.New()
h.Write([]byte(modelName))
h.Write([]byte(buf.String()))
return hex.EncodeToString(h.Sum(nil))
}