Files
llama-sidecar/internal/pool/hash.go
indifferentketchup fe7f36ae98 llama-sidecar v0.1.0: daemon + benchmarks + eval suite
Go daemon (cmd/llama-sidecar): per-agent llama-server process pool with
LRU eviction, OpenAI-compatible proxy, flag validation (Unsloth port),
deterministic hash-keyed sidecar reuse. Windows service support via
schtasks/NSSM with DETACHED_PROCESS, stdout pipe drain, and request-ctx
decoupled child lifetime.

Bug fixes (3b.1–3b5): -c flag drop from StripShadowingFlags, UTF-8 BOM
in JSON config, -fa → --flash-attn on default, child process exit after
one request (stdin devnull, stdout pipe, CREATE_NO_WINDOW → DETACHED,
context.Background for child lifetime, background reaper goroutine).

bench/: MTP on/off throughput sweep across 8 GGUFs via SSH+schtasks
automation to sam-desktop. Per-GGUF production flags from llama-swap
config with --ctx-size 32768 override.

eval/: accuracy benchmarks (MMLU 100q, GSM8K 50q, HumanEval 164) +
A/B model comparison (14 agent-typed prompts × 8 models). All scripts
resumable at individual question level.

94 Go tests, race detector clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 01:55:13 +00:00

54 lines
1.1 KiB
Go

package pool
import (
"crypto/sha256"
"fmt"
"sort"
"strings"
"github.com/indifferentketchup/llama-sidecar/internal/validator"
)
// Hash computes a deterministic hash for a (modelID, flags) pair.
// Flag order does not affect the result.
func Hash(modelID string, flags []string) string {
type pair struct {
key, val string
}
var pairs []pair
i := 0
for i < len(flags) {
tok := flags[i]
key := validator.FlagName(tok)
if key == "" {
i++
continue
}
if idx := strings.IndexByte(tok, '='); idx >= 0 {
pairs = append(pairs, pair{key: tok[:idx], val: tok[idx+1:]})
i++
} else if i+1 < len(flags) && validator.FlagName(flags[i+1]) == "" {
pairs = append(pairs, pair{key: key, val: flags[i+1]})
i += 2
} else {
pairs = append(pairs, pair{key: key, val: ""})
i++
}
}
sort.Slice(pairs, func(a, b int) bool {
return pairs[a].key < pairs[b].key
})
var parts []string
for _, p := range pairs {
parts = append(parts, p.key+"\x1f"+p.val)
}
serialized := strings.Join(parts, "\x1e")
input := modelID + "\x1d" + serialized
sum := sha256.Sum256([]byte(input))
return fmt.Sprintf("%x", sum[:8])
}