update
This commit is contained in:
81
internal/repository/embedding_repository_test.go
Normal file
81
internal/repository/embedding_repository_test.go
Normal file
@ -0,0 +1,81 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFormatEmbeddingVector 向量串格式化是写入正确性的关键:
|
||||
// 维度必须精确、float32 精度不能丢(截断会让相似度漂移)。
|
||||
func TestFormatEmbeddingVector(t *testing.T) {
|
||||
v := make([]float32, 768)
|
||||
v[0] = 0.5
|
||||
v[767] = -0.25
|
||||
|
||||
s := FormatEmbeddingVector(v)
|
||||
if !strings.HasPrefix(s, "[") || !strings.HasSuffix(s, "]") {
|
||||
t.Fatalf("应输出 [..] 形式的向量串,得到 %q", truncForTest(s))
|
||||
}
|
||||
if got := strings.Count(s, ",") + 1; got != 768 {
|
||||
t.Fatalf("维度应为 768,得到 %d", got)
|
||||
}
|
||||
if !strings.Contains(s, "0.5") || !strings.Contains(s, "-0.25") {
|
||||
t.Fatalf("首尾元素未按 float32 精度输出: %s", truncForTest(s))
|
||||
}
|
||||
}
|
||||
|
||||
// TestFormatEmbeddingVectorEmpty 空向量必须能安全格式化,不能 panic。
|
||||
func TestFormatEmbeddingVectorEmpty(t *testing.T) {
|
||||
if got := FormatEmbeddingVector(nil); got != "[]" {
|
||||
t.Fatalf("nil 应格式化为 [],得到 %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseEmbeddingVectorRoundTrip 格式化与解析必须能精确往返,
|
||||
// 否则「写进去的向量」与「读出来算相似度的向量」不是同一个,阈值校准会失真。
|
||||
func TestParseEmbeddingVectorRoundTrip(t *testing.T) {
|
||||
v := make([]float32, 768)
|
||||
for i := range v {
|
||||
v[i] = float32(i%17-8) * 0.0173
|
||||
}
|
||||
got := ParseEmbeddingVector(FormatEmbeddingVector(v))
|
||||
if len(got) != len(v) {
|
||||
t.Fatalf("往返后长度应一致:%d != %d", len(got), len(v))
|
||||
}
|
||||
for i := range v {
|
||||
if got[i] != v[i] {
|
||||
t.Fatalf("第 %d 维往返后不一致:%v != %v", i, got[i], v[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseEmbeddingVectorInvalid 非法输入返回 nil(调用方据此跳过该行,不阻断渲染)。
|
||||
func TestParseEmbeddingVectorInvalid(t *testing.T) {
|
||||
for _, bad := range []string{"", "[]", "0.1,0.2", "[0.1,abc]", "[", "null"} {
|
||||
if got := ParseEmbeddingVector(bad); got != nil {
|
||||
t.Fatalf("非法输入 %q 应返回 nil,得到 %v", bad, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestFormatEmbeddingVectorNormalized 归一化向量点积等于余弦相似度:
|
||||
// 用同一向量的自点积验证模长≈1(服务端已归一化的前提)。
|
||||
func TestFormatEmbeddingVectorNormalized(t *testing.T) {
|
||||
v := []float32{0.6, 0.8} // 模长为 1
|
||||
got := ParseEmbeddingVector(FormatEmbeddingVector(v))
|
||||
var dot float64
|
||||
for _, f := range got {
|
||||
dot += float64(f) * float64(f)
|
||||
}
|
||||
if math.Abs(dot-1) > 1e-6 {
|
||||
t.Fatalf("模长应≈1,得到 %f", dot)
|
||||
}
|
||||
}
|
||||
|
||||
func truncForTest(s string) string {
|
||||
if len(s) > 80 {
|
||||
return s[:80] + "..."
|
||||
}
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user