mirror of
https://github.com/hanzoai/agent.git
synced 2026-09-11 21:08:51 +00:00
hanzoai/agents carried the reconciled Go, TypeScript and Python SDKs: memory in Base with one record schema across all three, scope ids resolved the way the control plane resolves them, /v1 paths, one address per vector operation, agents that start under Express 5, and suites that run (Go green, 92 TypeScript, 527 Python). They come home here. The Go module is github.com/hanzoai/agent/sdk/go, because the path has to name the repository it is fetched from. The TypeScript manifest names its versions directly and keeps npm's lockfile; this repo is not a pnpm workspace. Versions are 0.2.10. Co-authored-by: Hanzo Dev <[email protected]>
73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package agent
|
|
|
|
import (
|
|
"math"
|
|
"sort"
|
|
)
|
|
|
|
// The vector math every memory backend shares.
|
|
|
|
// cosine is the similarity of two vectors of equal width: 1 for the same
|
|
// direction, 0 for perpendicular, -1 for opposite. A zero vector has no
|
|
// direction, so it scores 0 rather than dividing by zero.
|
|
func cosine(a, b []float64) float64 {
|
|
var dot, na, nb float64
|
|
for i := range a {
|
|
dot += a[i] * b[i]
|
|
na += a[i] * a[i]
|
|
nb += b[i] * b[i]
|
|
}
|
|
if na == 0 || nb == 0 {
|
|
return 0
|
|
}
|
|
return dot / (math.Sqrt(na) * math.Sqrt(nb))
|
|
}
|
|
|
|
// matches reports whether metadata satisfies every filter. A missing key fails
|
|
// its filter; numbers compare as float64, as JSON decodes them.
|
|
func matches(metadata map[string]any, filters map[string]any) bool {
|
|
for key, want := range filters {
|
|
got, ok := metadata[key]
|
|
if !ok || !same(got, want) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func same(a, b any) bool {
|
|
if x, ok := number(a); ok {
|
|
if y, ok := number(b); ok {
|
|
return x == y
|
|
}
|
|
return false
|
|
}
|
|
return a == b
|
|
}
|
|
|
|
func number(v any) (float64, bool) {
|
|
switch n := v.(type) {
|
|
case float64:
|
|
return n, true
|
|
case float32:
|
|
return float64(n), true
|
|
case int:
|
|
return float64(n), true
|
|
case int64:
|
|
return float64(n), true
|
|
case int32:
|
|
return float64(n), true
|
|
default:
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
// rank orders results by score, strongest first, and cuts to the limit.
|
|
func rank(found []VectorSearchResult, limit int) []VectorSearchResult {
|
|
sort.SliceStable(found, func(i, j int) bool { return found[i].Score > found[j].Score })
|
|
if limit > 0 && len(found) > limit {
|
|
found = found[:limit]
|
|
}
|
|
return found
|
|
}
|