This commit is contained in:
toom1996
2026-10-18 17:42:10 +08:00
parent 1b06bd5bda
commit 1de1ec46a6
58 changed files with 5281 additions and 19191 deletions

View 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
}