Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

215 lines
6.0 KiB
Go

package embedding
import (
"context"
"encoding/binary"
"encoding/json"
"math"
"os"
"path/filepath"
"testing"
)
func writeTestTokenizer(t *testing.T, dir string, vocab map[string]int) {
t.Helper()
tj := map[string]any{
"normalizer": map[string]any{
"type": "BertNormalizer", "clean_text": true,
"handle_chinese_chars": true, "strip_accents": nil, "lowercase": true,
},
"pre_tokenizer": map[string]any{"type": "BertPreTokenizer"},
"model": map[string]any{
"type": "WordPiece", "unk_token": "[UNK]",
"continuing_subword_prefix": "##", "max_input_chars_per_word": 100,
"vocab": vocab,
},
}
raw, err := json.Marshal(tj)
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, potionTokenizerFile), raw, 0o644); err != nil {
t.Fatal(err)
}
}
// f32ToF16 converts float32 → IEEE half for fixture building. Handles
// the normal range the fixtures use; no rounding subtleties needed.
func f32ToF16(f float32) uint16 {
bits := math.Float32bits(f)
sign := uint16(bits>>16) & 0x8000
exp := int32(bits>>23&0xff) - 127 + 15
man := bits >> 13 & 0x3ff
if exp <= 0 {
return sign
}
if exp >= 0x1f {
return sign | 0x7c00
}
return sign | uint16(exp)<<10 | uint16(man)
}
func writeTestWeights(t *testing.T, dir string, rows [][]float32) {
t.Helper()
dims := len(rows[0])
header := map[string]any{
"embeddings": map[string]any{
"dtype": "F16", "shape": []int{len(rows), dims},
"data_offsets": []int{0, len(rows) * dims * 2},
},
}
hj, err := json.Marshal(header)
if err != nil {
t.Fatal(err)
}
buf := make([]byte, 8, 8+len(hj)+len(rows)*dims*2)
binary.LittleEndian.PutUint64(buf, uint64(len(hj)))
buf = append(buf, hj...)
for _, row := range rows {
for _, v := range row {
var b [2]byte
binary.LittleEndian.PutUint16(b[:], f32ToF16(v))
buf = append(buf, b[:]...)
}
}
if err := os.WriteFile(filepath.Join(dir, potionWeightsFile), buf, 0o644); err != nil {
t.Fatal(err)
}
}
func TestWordPiece_BertSchemeHermetic(t *testing.T) {
dir := t.TempDir()
vocab := map[string]int{
"[PAD]": 0, "[UNK]": 1,
"bind": 2, "##body": 3, "body": 4, "(": 5, ")": 6, "*": 7,
"client": 8, "func": 9, ".": 10, "go": 11,
}
writeTestTokenizer(t, dir, vocab)
tok, err := loadWordPieceTokenizer(filepath.Join(dir, potionTokenizerFile))
if err != nil {
t.Fatal(err)
}
cases := []struct {
text string
want []int
}{
// camel-cased word lowercased then greedily split
{"BindBody", []int{2, 3}},
// punctuation isolated; unknown word → UNK
{"func (c *Client)", []int{9, 5, 1, 7, 8, 6}},
// dot split as punctuation
{"bind.go", []int{2, 10, 11}},
// whitespace collapse + empty
{" ", nil},
// no matching piece anywhere → whole-word UNK
{"zzzqqq", []int{1}},
}
for _, c := range cases {
got := tok.Encode(c.text)
if len(got) != len(c.want) {
t.Fatalf("Encode(%q) = %v, want %v", c.text, got, c.want)
}
for i := range got {
if got[i] != c.want[i] {
t.Fatalf("Encode(%q) = %v, want %v", c.text, got, c.want)
}
}
}
}
func TestPotionProvider_MeanPoolAndNormalize(t *testing.T) {
dir := t.TempDir()
vocab := map[string]int{"[PAD]": 0, "[UNK]": 1, "bind": 2, "##body": 3}
writeTestTokenizer(t, dir, vocab)
writeTestWeights(t, dir, [][]float32{
{0, 0, 0, 0}, // PAD
{1, 0, 0, 0}, // UNK
{0, 2, 0, 0}, // bind
{0, 0, 2, 0}, // ##body
})
p, err := NewPotionProviderFromDir(dir)
if err != nil {
t.Fatal(err)
}
if p.Dimensions() != 4 {
t.Fatalf("dims = %d, want 4", p.Dimensions())
}
vec, err := p.Embed(context.Background(), "BindBody")
if err != nil {
t.Fatal(err)
}
// mean of (0,2,0,0) and (0,0,2,0) = (0,1,1,0); L2-normalised.
want := []float32{0, float32(1 / math.Sqrt2), float32(1 / math.Sqrt2), 0}
for i := range want {
if math.Abs(float64(vec[i]-want[i])) > 1e-3 {
t.Fatalf("vec = %v, want %v", vec, want)
}
}
// Unknown-only text embeds the UNK row, not a zero vector.
vec2, _ := p.Embed(context.Background(), "zzzqqq")
if vec2[0] < 0.99 {
t.Fatalf("UNK-only embed = %v, want unit x-axis", vec2)
}
// Empty text → zero vector (signal reads it as no evidence).
vec3, _ := p.Embed(context.Background(), "")
for _, v := range vec3 {
if v != 0 {
t.Fatalf("empty embed should be zero vector, got %v", vec3)
}
}
}
// TestPotionProvider_GoldenAgainstReference verifies the pure-Go
// tokenizer + pooling against reference outputs captured from the
// upstream tokenizers + numpy implementation for the real model.
// Skipped when the model files are not installed on this machine.
func TestPotionProvider_GoldenAgainstReference(t *testing.T) {
dir := resolvePotionDir()
if dir == "" {
t.Skip("potion model files not installed; run with GORTEX_POTION_DIR pointing at the model")
}
p, err := NewPotionProviderFromDir(dir)
if err != nil {
t.Fatal(err)
}
golden := []struct {
text string
ids []int
head8 []float32
}{
{
"BindBody bsonBinding.BindBody binding/bson.go",
[]int{13190, 22687, 30716, 7431, 3670, 15, 13190, 22687, 7034, 16, 30716, 15, 1178},
[]float32{0.034474, 0.018522, -0.13514, 0.084147, 0.232714, -0.36536, 0.193378, 0.139676},
},
{
"decode bson request body",
[]int{29631, 30716, 4230, 1306},
[]float32{-0.07553, -0.022155, -0.119157, 0.177616, 0.124399, -0.224746, 0.050767, 0.065148},
},
{
"func (c *Client) Do(req *Request) (*Response, error)",
[]int{29527, 9, 42, 11, 6399, 10, 1082, 9, 29556, 11, 4230, 10, 9, 11, 2436, 13, 6564, 10},
[]float32{-0.087694, 0.013899, -0.003767, 0.109125, -0.006322, 0.076795, 0.031422, 0.040902},
},
}
for _, g := range golden {
ids := p.tok.Encode(g.text)
if len(ids) != len(g.ids) {
t.Fatalf("Encode(%q) ids = %v, want %v", g.text, ids, g.ids)
}
for i := range ids {
if ids[i] != g.ids[i] {
t.Fatalf("Encode(%q) ids = %v, want %v", g.text, ids, g.ids)
}
}
vec, _ := p.Embed(context.Background(), g.text)
for i, w := range g.head8 {
if math.Abs(float64(vec[i]-w)) > 2e-3 {
t.Fatalf("Embed(%q)[%d] = %.6f, want %.6f", g.text, i, vec[i], w)
}
}
}
}