refactor(clip): CLIP 收敛为稠密 MultimodalEmbedder,不污染稀疏 Vectorizer/TF-IDF 语义

文本相似度检索是层次化系统:TF-IDF 高频削弱加权(idf<0.1 丢弃)+
倒排剪枝(只召回共享特征者)+ cosine。CLIP 512 维稠密向量若以
map[string]float64 稀疏形式实现 vector.Vectorizer 并塞进 vector.Store,
会让 512 维全部成为倒排 key → 候选集≈全库、剪枝失效,且绕过 TF-IDF
高频削弱,与既有文本检索语义错配。

收敛:
- vector.MultimodalEmbedder 改为独立稠密接口(VectorizeDense/
  EmbedImageDense/Fingerprint/Dim/Loaded/Close),不再继承稀疏 Vectorizer
- clip.Embedder 删除稀疏垫片 Vectorize/EmbedImage/denseToVector,
  只产出稠密向量;文档/知识/上下文层继续用 TF-IDF/fastText 稀疏路径
- 分层明确:文本→文本走 TF-IDF/fastText;文本↔图像、图像↔图像走
  CLIP 稠密 QueryMedia(媒体层独立稠密余弦,原样保留)
This commit is contained in:
JianFeeeee
2026-09-09 10:26:10 +08:00
parent f8a35d1647
commit b860c8cea5
4 changed files with 29 additions and 58 deletions

View File

@ -58,12 +58,12 @@ func TestSmokeLoadAndEncode(t *testing.T) {
t.Errorf("cat-dog sim (%.4f) should be > cat-physics sim (%.4f)", sim12, sim13)
}
// 通过 Vectorizer 接口(稀疏 map)
sparseVec := emb.Vectorize("hello world")
if len(sparseVec) == 0 {
t.Error("sparse Vectorize should return non-empty")
// 稠密 VectorizeDense 再次调用验证可重复
vAgain, _ := emb.VectorizeDense("hello world")
if len(vAgain) != 512 {
t.Errorf("dense VectorizeDense len = %d, want 512", len(vAgain))
}
fmt.Printf("sparse len = %d\n", len(sparseVec))
fmt.Printf("dense len = %d\n", len(vAgain))
}
// TestCrossModalAlignment 验证图文在同一向量空间可比: