feat(embedding): 嵌入(n-gram 哈希向量 + 关键词 FTS + OpenAI 兼容 API 钩子 + Manager 选择)
This commit is contained in:
1 parent
70fd915242
commit
51b2bdfba2
9 files changed
+1125
No files matched your search
@@ -0,0 +1,155 @@
|
||||
package embedding
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNGramEmbedder_Dim(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(128)
|
||||
if got := e.Dim(); got != 128 {
|
||||
t.Fatalf("Dim() = %d, want 128", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGramEmbedder_DefaultDim(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(0)
|
||||
if got := e.Dim(); got != defaultNGramDim {
|
||||
t.Fatalf("Dim() = %d, want defaultNGramDim (%d)", got, defaultNGramDim)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGramEmbedder_VectorLengthMatchesDim(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(64)
|
||||
vectors, err := e.Embed(context.Background(), []string{"alpha", "beta gamma"})
|
||||
if err != nil {
|
||||
t.Fatalf("Embed() error: %v", err)
|
||||
}
|
||||
if len(vectors) != 2 {
|
||||
t.Fatalf("got %d vectors, want 2", len(vectors))
|
||||
}
|
||||
for i, v := range vectors {
|
||||
if got := len(v); got != e.Dim() {
|
||||
t.Errorf("vector %d length = %d, want %d", i, got, e.Dim())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGramEmbedder_Deterministic(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(128)
|
||||
ctx := context.Background()
|
||||
texts := []string{"hello world", "the quick brown fox jumps", "Golang embedding"}
|
||||
|
||||
first, err := e.Embed(ctx, texts)
|
||||
if err != nil {
|
||||
t.Fatalf("Embed() error: %v", err)
|
||||
}
|
||||
second, err := e.Embed(ctx, texts)
|
||||
if err != nil {
|
||||
t.Fatalf("Embed() error: %v", err)
|
||||
}
|
||||
if len(first) != len(second) {
|
||||
t.Fatalf("got %d vectors on first call, %d on second", len(first), len(second))
|
||||
}
|
||||
for i := range first {
|
||||
if !equalVector(first[i], second[i]) {
|
||||
t.Fatalf("vector %d differs between calls", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGramEmbedder_Normalized(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(128)
|
||||
vectors, err := e.Embed(context.Background(), []string{
|
||||
"a",
|
||||
"the quick brown fox jumps over the lazy dog",
|
||||
"golang fts embedding test",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Embed() error: %v", err)
|
||||
}
|
||||
for i, v := range vectors {
|
||||
norm := l2Norm(v)
|
||||
if math.Abs(norm-1) > 1e-6 {
|
||||
t.Errorf("vector %d L2 norm = %f, want 1", i, norm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGramEmbedder_DifferentTextsDiffer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(128)
|
||||
vectors, err := e.Embed(context.Background(), []string{"dog", "cat", "astronaut"})
|
||||
if err != nil {
|
||||
t.Fatalf("Embed() error: %v", err)
|
||||
}
|
||||
if len(vectors) != 3 {
|
||||
t.Fatalf("got %d vectors, want 3", len(vectors))
|
||||
}
|
||||
for i := 0; i < len(vectors); i++ {
|
||||
if l2Norm(vectors[i]) == 0 {
|
||||
t.Errorf("vector %d is a zero vector", i)
|
||||
}
|
||||
for j := i + 1; j < len(vectors); j++ {
|
||||
if equalVector(vectors[i], vectors[j]) {
|
||||
t.Errorf("vectors %d and %d are identical", i, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGramEmbedder_EmptyInput(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(128)
|
||||
vectors, err := e.Embed(context.Background(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Embed(nil) error: %v", err)
|
||||
}
|
||||
if len(vectors) != 0 {
|
||||
t.Errorf("got %d vectors, want 0", len(vectors))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGramEmbedder_CanceledContext(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := NewNGram(128)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
if _, err := e.Embed(ctx, []string{"hello"}); err == nil {
|
||||
t.Fatal("expected error on canceled context, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func equalVector(a, b Vector) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func l2Norm(v Vector) float64 {
|
||||
var sum float64
|
||||
for _, x := range v {
|
||||
sum += float64(x) * float64(x)
|
||||
}
|
||||
return math.Sqrt(sum)
|
||||
}
|
||||
Reference in new issue
Block a user