embeddingModel操作milvus数据库集合

案例:

不是"创建集合的那一瞬间",而是"第一次使用时"

java 复制代码
// ========== 应用启动时(MilvusConfig执行) ==========

// 步骤1: 创建milvusClient
@Bean
public MilvusServiceClient milvusClient() {
    return new MilvusServiceClient(...);  // ✓ 只是连接数据库
}

// 步骤2: 创建embeddingModel
@Bean
public EmbeddingModel embeddingModel() {
    return new OpenAiEmbeddingModel(...);  // ✓ 只是创建工具对象
}

// 步骤3: 创建vectorStore
@Bean
public VectorStore zyVectorStore(
        MilvusServiceClient milvusClient,
        EmbeddingModel embeddingModel) {
    
    MilvusVectorStore vectorStore = MilvusVectorStore.builder(
            milvusClient,
            embeddingModel)
        .collectionName("zhi_yan")
        .initializeSchema(true)  // ← 注意!这里只是设置参数
        .build();
    
    // ⚠️ 到这里为止,集合还没有创建!
    // 只是创建了vectorStore对象,保存了配置
    
    return vectorStore;
}

// ========== 启动完成,集合仍然不存在 ==========

集合真正创建的时机

第一次调用vectorStore.add()

java 复制代码
// ========== 用户上传文件后 ==========

DocumentServiceImpl.importMarkdownContent() {
    
    // 1. 切片
    List<Document> chunks = textSplitter.apply(List.of(doc));
    
    // 2. 调用vectorStore.add() ← 这里才真正创建集合!
    vectorStore.add(chunks);
}

// ========== vectorStore.add()内部执行流程 ==========

class MilvusVectorStore {
    
    public void add(List<Document> documents) {
        
        // 步骤1: 检查集合是否存在
        boolean exists = checkCollectionExists("zhi_yan");
        
        if (!exists && initializeSchema) {
            // 步骤2: 集合不存在,需要创建
            createCollection();  // ← 这里才真正创建!
        }
        
        // 步骤3: 插入数据
        insertDocuments(documents);
    }
    
    private void createCollection() {
        // ========== 这里才使用embeddingModel! ==========
        
        // 1. 生成一个测试向量,获取维度
        log.info("正在获取向量维度...");
        List<Double> testVector = embeddingModel.embed("test");
        int dimension = testVector.size();  // ← 得到1024
        
        log.info("检测到向量维度: {}", dimension);
        
        // 2. 创建Schema
        List<FieldType> fields = new ArrayList<>();
        
        // 主键字段
        fields.add(FieldType.newBuilder()
            .withName("id")
            .withDataType(DataType.VarChar)
            .withMaxLength(36)
            .withPrimaryKey(true)
            .build());
        
        // 向量字段 ← 使用检测到的维度
        fields.add(FieldType.newBuilder()
            .withName("embedding")
            .withDataType(DataType.FloatVector)
            .withDimension(dimension)  // ← 1024
            .build());
        
        // 其他字段...
        
        // 3. 创建集合
        CollectionSchemaParam schema = CollectionSchemaParam.newBuilder()
            .withFieldTypes(fields)
            .build();
        
        CreateCollectionParam param = CreateCollectionParam.newBuilder()
            .withCollectionName("zhi_yan")
            .withSchema(schema)
            .build();
        
        milvusClient.createCollection(param);
        
        log.info("集合创建成功! embedding字段维度: {}", dimension);
    }
}

完整时间线

复制代码
时间点1: 应用启动
    ├─ 创建milvusClient ✓
    ├─ 创建embeddingModel ✓ (配置为1024维)
    ├─ 创建vectorStore ✓ (保存配置)
    └─ 集合状态: ❌ 不存在

时间点2: 应用启动完成
    └─ 集合状态: ❌ 仍然不存在

时间点3: 用户上传第一个文件
    ├─ DocumentController接收文件
    ├─ DocumentServiceImpl.importMarkdownContent()
    ├─ textSplitter.apply() 切片
    └─ vectorStore.add(chunks) ← 触发!
        ↓
        
时间点4: vectorStore.add()内部
    ├─ 检查集合是否存在 → 不存在
    ├─ 调用embeddingModel.embed("test") → 得到1024维向量
    ├─ 创建集合,embedding字段设为1024维 ✓
    └─ 集合状态: ✓ 创建成功,1024维

时间点5: 后续上传文件
    ├─ vectorStore.add(chunks)
    ├─ 检查集合是否存在 → 已存在
    ├─ 跳过创建步骤
    └─ 直接插入数据

验证:查看Spring AI源码逻辑

java 复制代码
// Spring AI的MilvusVectorStore实际实现(简化版)

public class MilvusVectorStore implements VectorStore {
    
    private final MilvusServiceClient milvusClient;
    private final EmbeddingModel embeddingModel;
    private final String collectionName;
    private final boolean initializeSchema;
    
    @Override
    public void add(List<Document> documents) {
        
        // 1. 确保集合存在
        if (initializeSchema) {
            createCollectionIfNotExists();  // ← 关键方法
        }
        
        // 2. 向量化并插入
        for (Document doc : documents) {
            List<Double> vector = embeddingModel.embed(doc.getContent());
            insert(doc.getId(), vector, doc.getContent(), doc.getMetadata());
        }
    }
    
    private void createCollectionIfNotExists() {
        // 检查集合是否存在
        R<Boolean> response = milvusClient.hasCollection(
            HasCollectionParam.newBuilder()
                .withCollectionName(collectionName)
                .build()
        );
        
        if (!response.getData()) {
            // 集合不存在,创建它
            log.info("集合 {} 不存在,正在创建...", collectionName);
            
            // ========== 这里使用embeddingModel获取维度 ==========
            List<Double> dimensionVector = embeddingModel.embed("dimension test");
            int dimension = dimensionVector.size();
            
            log.info("从EmbeddingModel检测到向量维度: {}", dimension);
            
            // 创建Schema并创建集合
            createCollectionWithDimension(dimension);
        } else {
            log.info("集合 {} 已存在,跳过创建", collectionName);
        }
    }
}

为什么这样设计?

1. 延迟初始化(Lazy Initialization)

复制代码
好处:
✓ 启动更快 - 不需要在启动时创建集合
✓ 灵活性 - 可以先启动应用,后配置Milvus
✓ 自动适配 - 自动从embeddingModel获取维度,不需要手动配置

2. 自动维度检测

java 复制代码
// 你不需要这样写:
MilvusVectorStore.builder(...)
    .dimension(1024)  // ❌ 不需要手动指定
    .build();

// 而是自动检测:
MilvusVectorStore.builder(...)
    .initializeSchema(true)  // ✓ 自动从embeddingModel获取
    .build();

// 内部会:
int dimension = embeddingModel.embed("test").size();  // 自动得到1024

实际操作演示

场景1: 首次启动,集合不存在

bash 复制代码
# 1. 启动应用
mvn spring-boot:run

# 控制台输出:
# [INFO] 正在连接Milvus服务器: 10.0.0.15:19530
# [INFO] Milvus客户端连接成功
# [INFO] 正在创建OpenAI EmbeddingModel...
# [INFO] OpenAI EmbeddingModel创建成功
# [INFO] 正在创建Milvus VectorStore,集合名称: zhi_yan
# [INFO] Milvus VectorStore创建成功
# [INFO] 应用启动完成!

# ⚠️ 注意:这里没有"创建集合"的日志!

# 2. 上传第一个文件
curl -X POST http://localhost:8084/api/documents/import \
  -F "file=@test.md"

# 控制台输出:
# [INFO] 正在导入Markdown文件: test.md
# [INFO] 开始导入Markdown内容,文件名: test.md
# [INFO] 文档已分割成 3 个块
# [INFO] 集合 zhi_yan 不存在,正在创建...  ← 这里才创建!
# [INFO] 正在获取向量维度...
# [INFO] 从EmbeddingModel检测到向量维度: 1024
# [INFO] 创建集合Schema: embedding字段维度=1024
# [INFO] 集合创建成功!
# [INFO] 成功导入 3 个文档块到Milvus

场景2: 集合已存在

bash 复制代码
# 上传第二个文件
curl -X POST http://localhost:8084/api/documents/import \
  -F "file=@test2.md"

# 控制台输出:
# [INFO] 正在导入Markdown文件: test2.md
# [INFO] 开始导入Markdown内容,文件名: test2.md
# [INFO] 文档已分割成 4 个块
# [INFO] 集合 zhi_yan 已存在,跳过创建  ← 跳过创建步骤
# [INFO] 成功导入 4 个文档块到Milvus

总结

集合什么时候创建?

不是启动时,而是第一次调用vectorStore.add()时!

embeddingModel什么时候参与?

复制代码
启动时: 只是创建embeddingModel对象,不调用
    ↓
第一次add()时: 
    ├─ 调用embeddingModel.embed("test")
    ├─ 获取向量维度(1024)
    └─ 创建集合,设置embedding字段为1024维

为什么是1024?

复制代码
因为你配置了:
.dimensions(1024)
    ↓
embeddingModel.embed("test") 返回1024维向量
    ↓
vectorStore检测到1024维
    ↓
创建集合时设置embedding字段为1024维

关键代码

java 复制代码
// initializeSchema(true) 的作用:
// 在第一次add()时,自动创建集合,并从embeddingModel获取维度
MilvusVectorStore.builder(...)
    .initializeSchema(true)  // ← 这个参数很关键!
    .build();

集合是在第一次使用时才创建的,不是启动时! 🎯

相关推荐
Chan166 小时前
微服务 - Higress网关
java·spring boot·微服务·云原生·面试·架构·intellij-idea
幽络源小助理6 小时前
Springboot机场乘客服务系统源码 – SpringBoot+Vue项目免费下载 | 幽络源
vue.js·spring boot·后端
长路 ㅤ   7 小时前
Milvus向量库Java对接使用指南
milvus·向量数据库·索引优化·混合搜索·ann搜索
AC赳赳老秦8 小时前
Unity游戏开发实战指南:核心逻辑与场景构建详解
开发语言·spring boot·爬虫·搜索引擎·全文检索·lucene·deepseek
Java 码农8 小时前
Spring Boot集成RabbitMQ的各种队列使用案例
spring boot·rabbitmq·java-rabbitmq
qq_12498707538 小时前
基于springboot归家租房小程序的设计与实现(源码+论文+部署+安装)
java·大数据·spring boot·后端·小程序·毕业设计·计算机毕业设计
内存不泄露8 小时前
基于Spring Boot和Vue的宠物医院管理系统设计与实现
vue.js·spring boot·信息可视化
廋到被风吹走8 小时前
【Spring】Spring Boot Actuator 深度解析:健康检查、指标暴露与端点安全
spring boot·安全·spring
怦怦蓝8 小时前
详解 IntelliJ IDEA 中编写邮件发送功能(从环境搭建到实战落地)
java·spring boot·intellij-idea