向量数据库 (Vector Database)
Embedding 搞定后,我们需要把这些向量存起来,并支持快速的最近邻搜索 (ANN)。这就需要用到向量数据库。
常用向量数据库选型
| 数据库 | 类型 | 语言 | 优势 | 适用场景 |
|---|---|---|---|---|
| Milvus | 专用向量库 | Go/C++ | 高性能、云原生、功能全 | 海量数据 (亿级),企业级生产环境 |
| Qdrant | 专用向量库 | Rust | 易用、支持混合检索 | 中大规模,追求开发体验 |
| Weaviate | 专用向量库 | Go | 模块化、自带 Embedding | 需要一体化解决方案 |
| Pgvector | PG 插件 | C | 运维简单,复用 PG | 数据量不大 (<千万级),已有 PG 设施 |
在 Golang 生态中,Milvus 和 Weaviate 是原生 Go 开发的,SDK 支持非常完善。
Milvus 实战 (Golang SDK)
Milvus 是目前最流行的开源向量数据库之一。
1. 安装 SDK
bash
go get -u github.com/milvus-io/milvus-sdk-go/v22. 连接与创建 Collection
go
package main
import (
"context"
"fmt"
"log"
"github.com/milvus-io/milvus-sdk-go/v2/client"
"github.com/milvus-io/milvus-sdk-go/v2/entity"
)
func main() {
ctx := context.Background()
// 1. 连接 Milvus
c, err := client.NewClient(ctx, client.Config{
Address: "localhost:19530",
})
if err != nil {
log.Fatal("failed to connect to milvus:", err)
}
defer c.Close()
// 2. 定义 Schema
collectionName := "rag_knowledge_base"
schema := &entity.Schema{
CollectionName: collectionName,
Description: "RAG 知识库",
Fields: []*entity.Field{
{
Name: "id",
DataType: entity.FieldTypeInt64,
PrimaryKey: true,
AutoID: true,
},
{
Name: "embedding",
DataType: entity.FieldTypeFloatVector,
TypeParams: map[string]string{
"dim": "1536", // 对应 OpenAI embedding 维度
},
},
{
Name: "content",
DataType: entity.FieldTypeVarChar,
TypeParams: map[string]string{
"max_length": "65535",
},
},
},
}
// 3. 创建 Collection
err = c.CreateCollection(ctx, schema, entity.DefaultShardNumber)
if err != nil {
log.Println("collection 可能已存在:", err)
}
// 4. 创建索引 (IVF_FLAT)
idx, _ := entity.NewIndexIvfFlat(entity.L2, 1024)
c.CreateIndex(ctx, collectionName, "embedding", idx, false)
// 5. 加载到内存
c.LoadCollection(ctx, collectionName, false)
fmt.Println("Milvus 初始化完成")
}3. 插入数据
go
func InsertData(c client.Client, vectors [][]float32, contents []string) {
// 列式存储构造数据
idCol := entity.NewColumnInt64("id", nil) // AutoID 不需要填
embeddingCol := entity.NewColumnFloatVector("embedding", 1536, vectors)
contentCol := entity.NewColumnVarChar("content", contents)
_, err := c.Insert(context.Background(), "rag_knowledge_base", "", idCol, embeddingCol, contentCol)
if err != nil {
log.Fatal(err)
}
}4. 向量检索 (Search)
go
func Search(c client.Client, queryVec []float32) {
sp, _ := entity.NewIndexIvfFlatSearchParam(10) // nprobe
searchResult, err := c.Search(
context.Background(),
"rag_knowledge_base",
[]string{}, // partitions
"", // expr (标量过滤条件)
[]string{"content"}, // output fields
[]entity.Vector{entity.FloatVector(queryVec)},
"embedding", // vector field
entity.L2, // metric type
3, // topK
sp,
)
if err != nil {
log.Fatal(err)
}
for _, result := range searchResult {
for i := 0; i < result.ResultCount; i++ {
content, _ := result.Fields.GetColumn("content").GetAsString(i)
score := result.Scores[i]
fmt.Printf("Top%d Score: %f Content: %s\n", i, score, content)
}
}
}总结
向量数据库是 RAG 的长期记忆体。
- 对于 Demo,用
langchaingo/vectorstores/memory即可。 - 对于生产环境,Milvus 是 Golang 开发者的首选,性能强劲且 SDK 友好。
