feat(rag): Milvus 集合维度自适应 — 切换 embedding 模型自动重建

ensure() 检测已存集合的向量维度,与当前 embedding 维度不一致则 Drop+重建
(DescribeCollection 读 TypeParams[dim])。支持从 mock(256)切到真实 embedding(如
百炼 text-embedding-v3=1024 维)无需手动清库。

验证: 接阿里云百炼 text-embedding-v3(OpenAI 兼容)真实 embedding——集合自动
256→1024 重建,入库5条;语义检索(查询措辞与文档不同):'存储搜索向量的组件'
→Milvus、'传消息的中间件'→NATS、'知识图谱存哪'→Neo4j,全部语义命中正确。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-06-10 17:12:24 +08:00
parent 84d1a1dd3a
commit e5bbe7318c
+30
View File
@@ -3,6 +3,8 @@ package rag
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strconv"
"sync" "sync"
"github.com/milvus-io/milvus-sdk-go/v2/client" "github.com/milvus-io/milvus-sdk-go/v2/client"
@@ -44,6 +46,18 @@ func (m *milvusStore) ensure(ctx context.Context, dim int) error {
if err != nil { if err != nil {
return err return err
} }
// 已存集合维度不一致(如切换 embedding 模型)→ 重建。
if has {
if coll, derr := m.cli.DescribeCollection(ctx, collection); derr == nil {
if existing := vectorDim(coll); existing != 0 && existing != dim {
log.Printf("[rag] 集合维度 %d≠%d,重建 %s", existing, dim, collection)
if err := m.cli.DropCollection(ctx, collection); err != nil {
return fmt.Errorf("drop collection: %w", err)
}
has = false
}
}
}
if !has { if !has {
schema := entity.NewSchema().WithName(collection).WithDescription("sundynix wiki vectors"). schema := entity.NewSchema().WithName(collection).WithDescription("sundynix wiki vectors").
WithField(entity.NewField().WithName("id").WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true).WithIsAutoID(true)). WithField(entity.NewField().WithName("id").WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true).WithIsAutoID(true)).
@@ -88,6 +102,22 @@ func (m *milvusStore) insert(ctx context.Context, kb string, texts []string, vec
return m.cli.Flush(ctx, collection, false) return m.cli.Flush(ctx, collection, false)
} }
// vectorDim 从集合 schema 读出向量字段维度(用于检测维度变化)。
func vectorDim(coll *entity.Collection) int {
if coll == nil || coll.Schema == nil {
return 0
}
for _, f := range coll.Schema.Fields {
if f.DataType == entity.FieldTypeFloatVector {
if d, ok := f.TypeParams["dim"]; ok {
n, _ := strconv.Atoi(d)
return n
}
}
}
return 0
}
// Hit 是一条检索结果。 // Hit 是一条检索结果。
type Hit struct { type Hit struct {
Text string Text string