70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
package common
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// excludeCacheFields are request body fields that should be excluded from cache hash
|
|
// because they vary between requests but don't affect the model's output.
|
|
var excludeCacheFields = map[string]bool{
|
|
"stream": true,
|
|
"seed": true,
|
|
"user": true,
|
|
"request_id": true,
|
|
"top_logprobs": true,
|
|
"logprobs": true,
|
|
"n": true,
|
|
"frequency_penalty": false, // include - affects output
|
|
"presence_penalty": false, // include - affects output
|
|
"temperature": false, // include - affects output
|
|
"max_tokens": false, // include - affects output
|
|
"max_completion_tokens": false,
|
|
}
|
|
|
|
// ComputeCacheHash produces a deterministic SHA-256 hash from a normalized request body.
|
|
// It removes non-deterministic fields (stream, seed, user, request_id, top_logprobs, logprobs, n)
|
|
// and sorts JSON keys for consistent hashing.
|
|
func ComputeCacheHash(body []byte, modelName string) string {
|
|
var raw map[string]json.RawMessage
|
|
if err := json.Unmarshal(body, &raw); err != nil {
|
|
// Fallback: hash raw body + model name
|
|
h := sha256.New()
|
|
h.Write([]byte(modelName))
|
|
h.Write(body)
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
}
|
|
|
|
// Remove excluded fields
|
|
for field := range excludeCacheFields {
|
|
delete(raw, field)
|
|
}
|
|
|
|
// Sort keys for deterministic ordering
|
|
keys := make([]string, 0, len(raw))
|
|
for k := range raw {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
|
|
// Rebuild JSON with sorted keys
|
|
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))
|
|
}
|