package org.example.service; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import java.util.List; import static org.junit.jupiter.api.Assertions.*; /** * 全链路验证:DeepSeek → BGE-M3 → Milvus */ @SpringBootTest @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @DisplayName("DeepSeek → BGE-M3 → Milvus 全链路") class FullPipelineSmokeTest { @Autowired private ChatModel chatModel; @Autowired private EmbeddingModel embeddingModel; @Autowired private VectorEmbeddingService vectorEmbeddingService; @Autowired private VectorSearchService vectorSearchService; @TestConfiguration static class MockToolConfig { @Bean public ToolCallbackProvider toolCallbackProvider() { return () -> new ToolCallback[0]; } } // ===== ① Chat: DeepSeek ===== @Test @Order(1) @DisplayName("Chat: DeepSeek 聊天验证") void chatDeepSeekWorks() { System.out.println("\n===== ① Chat: DeepSeek ====="); System.out.println("ChatModel: " + chatModel.getClass().getSimpleName()); System.out.println("ChatOptions: " + chatModel.toString()); // 直接调用 chat var response = chatModel.call(new Prompt("请用一句话介绍你自己")); String text = response.getResult().getOutput().getText(); assertNotNull(text); assertFalse(text.isEmpty()); System.out.println("Response: " + text.substring(0, Math.min(200, text.length())) + "..."); System.out.println("Chat ✓"); } // ===== ② Embedding: BGE-M3 via SiliconFlow ===== @Test @Order(2) @DisplayName("Embedding: BGE-M3 向量生成验证") void embeddingBgeM3Works() { System.out.println("\n===== ② Embedding: BGE-M3 (SiliconFlow) ====="); System.out.println("EmbeddingModel: " + embeddingModel.getClass().getSimpleName()); String text = "你好,这是一条测试文本"; List vector = vectorEmbeddingService.generateEmbedding(text); assertNotNull(vector); assertFalse(vector.isEmpty()); assertEquals(1024, vector.size(), "BGE-M3 应返回 1024 维向量"); // 非零校验 boolean hasNonZero = vector.stream().anyMatch(v -> Math.abs(v) > 1e-6); assertTrue(hasNonZero, "向量不能全为零"); System.out.println("维度: " + vector.size()); System.out.println("前5维: " + vector.subList(0, Math.min(5, vector.size()))); System.out.println("Embedding ✓"); } @Test @Order(3) @DisplayName("Embedding: BGE-M3 批量向量生成验证") void embeddingBatchWorks() { System.out.println("\n===== ③ Embedding 批量 ====="); List texts = List.of("文本一", "文本二", "文本三"); List> results = vectorEmbeddingService.generateEmbeddings(texts); assertEquals(3, results.size()); for (List r : results) { assertEquals(1024, r.size()); } System.out.println("批量生成: " + results.size() + " 个 向量,各 " + results.get(0).size() + " 维 ✓"); } // ===== ③ Milvus: 向量搜索 ===== @Test @Order(4) @DisplayName("Milvus: 连接 + 搜索验证") void milvusSearchWorks() { System.out.println("\n===== ④ Milvus: 向量搜索 ====="); // 用 BGE-M3 生成查询向量 String query = "内部文档"; List queryVector = vectorEmbeddingService.generateQueryVector(query); assertNotNull(queryVector); assertEquals(1024, queryVector.size()); // 搜索 List results = vectorSearchService.searchSimilarDocuments(query, 3); assertNotNull(results); System.out.println("查询: " + query); System.out.println("返回: " + results.size() + " 条"); if (!results.isEmpty()) { // 至少有结果,验证结构 for (int i = 0; i < results.size(); i++) { var r = results.get(i); assertNotNull(r.getId()); assertNotNull(r.getContent()); System.out.println(" [" + (i + 1) + "] id=" + r.getId() + ", score=" + String.format("%.4f", r.getScore()) + ", content=" + r.getContent().substring(0, Math.min(50, r.getContent().length())) + "..."); } } else { System.out.println("(Milvus 中暂无数据,但连接正常)"); } System.out.println("Milvus ✓"); } // ===== 汇总 ===== @Test @Order(5) @DisplayName("总结") void summary() { System.out.println("\n=========================================="); System.out.println("全链路验证完成:"); System.out.println(" ① Chat → DeepSeek ✓"); System.out.println(" ② Embedding → BGE-M3 ✓ (SiliconFlow, 1024维)"); System.out.println(" ③ 向量存储 → Milvus ✓ (Zilliz Cloud)"); System.out.println("=========================================="); } }