Sfoglia il codice sorgente

embedding 接入aliyun模型

wangyunpeng 1 settimana fa
parent
commit
3d1af7f0f1
19 ha cambiato i file con 1030 aggiunte e 627 eliminazioni
  1. 162 0
      core/src/main/java/com/tzld/videoVector/api/DashScopeEmbeddingApiService.java
  2. 14 14
      core/src/main/java/com/tzld/videoVector/dao/mapper/videoVector/deconstruct/DeconstructContentVectorMapper.java
  3. 23 11
      core/src/main/java/com/tzld/videoVector/dao/mapper/videoVector/deconstruct/DeconstructVectorConfigMapper.java
  4. 43 33
      core/src/main/java/com/tzld/videoVector/job/VideoVectorJob.java
  5. 3 0
      core/src/main/java/com/tzld/videoVector/model/param/MatchTopNVideoParam.java
  6. 113 77
      core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructContentVector.java
  7. 87 87
      core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructContentVectorExample.java
  8. 85 49
      core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructVectorConfig.java
  9. 77 17
      core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructVectorConfigExample.java
  10. 4 7
      core/src/main/java/com/tzld/videoVector/service/EmbeddingService.java
  11. 9 0
      core/src/main/java/com/tzld/videoVector/service/VectorizeService.java
  12. 25 188
      core/src/main/java/com/tzld/videoVector/service/impl/EmbeddingServiceImpl.java
  13. 75 28
      core/src/main/java/com/tzld/videoVector/service/impl/VectorizeServiceImpl.java
  14. 170 38
      core/src/main/java/com/tzld/videoVector/service/impl/VideoSearchServiceImpl.java
  15. 2 2
      core/src/main/resources/generator/mybatis-vector-generator-config.xml
  16. 62 45
      core/src/main/resources/mapper/videoVector/deconstruct/DeconstructContentVectorMapper.xml
  17. 53 23
      core/src/main/resources/mapper/videoVector/deconstruct/DeconstructVectorConfigMapper.xml
  18. 0 8
      server/src/main/resources/application.yml
  19. 23 0
      server/src/test/java/EmbeddingTest.java

+ 162 - 0
core/src/main/java/com/tzld/videoVector/api/DashScopeEmbeddingApiService.java

@@ -0,0 +1,162 @@
+package com.tzld.videoVector.api;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 阿里云 DashScope 多模态 Embedding API 服务
+ * 对接 qwen3-vl-embedding(默认 2560 维)
+ * API 文档:https://help.aliyun.com/zh/model-studio/multimodal-embedding-api-reference
+ */
+@Slf4j
+@Service
+public class DashScopeEmbeddingApiService {
+
+    private static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
+
+    @Value("${dashscope.embedding.dashscope.api-url:https://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding}")
+    private String apiUrl;
+
+    @Value("${dashscope.embedding.dashscope.api-key:sk-590b6529891f48c08970c66e9b76f8d6}")
+    private String apiKey;
+
+    @Value("${dashscope.embedding.dashscope.timeout:60}")
+    private int timeout;
+
+    private OkHttpClient client;
+
+    @PostConstruct
+    public void init() {
+        client = new OkHttpClient.Builder()
+                .connectTimeout(timeout, TimeUnit.SECONDS)
+                .readTimeout(timeout, TimeUnit.SECONDS)
+                .writeTimeout(timeout, TimeUnit.SECONDS)
+                .build();
+        log.info("DashScope Embedding 服务初始化完成");
+    }
+
+    /**
+     * 单条文本向量化
+     *
+     * @param text 输入文本
+     * @return 向量列表,失败返回空列表
+     */
+    public List<Float> embed(String text, String model, Integer dimension) {
+        if (text == null || text.trim().isEmpty()) {
+            log.warn("输入文本为空,返回空向量");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 构造请求体:contents 数组中放 text 对象
+            JSONObject contentItem = new JSONObject();
+            contentItem.put("text", text);
+
+            JSONArray contents = new JSONArray();
+            contents.add(contentItem);
+
+            JSONObject input = new JSONObject();
+            input.put("contents", contents);
+
+            JSONObject requestBody = new JSONObject();
+            requestBody.put("model", model);
+            requestBody.put("input", input);
+
+            // 设置向量维度
+            JSONObject parameters = new JSONObject();
+            parameters.put("dimension", dimension);
+            requestBody.put("parameters", parameters);
+
+            RequestBody body = RequestBody.create(JSON_MEDIA_TYPE, requestBody.toJSONString());
+            Request request = new Request.Builder()
+                    .url(apiUrl)
+                    .post(body)
+                    .addHeader("Content-Type", "application/json")
+                    .addHeader("Authorization", "Bearer " + apiKey)
+                    .build();
+
+            try (Response response = client.newCall(request).execute()) {
+                if (!response.isSuccessful()) {
+                    String errorBody = response.body() != null ? response.body().string() : "无";
+                    log.error("DashScope Embedding 请求失败,HTTP状态码: {}, 错误信息: {}", response.code(), errorBody);
+                    return Collections.emptyList();
+                }
+                String responseBody = response.body().string();
+                return parseEmbedding(responseBody);
+            }
+        } catch (IOException e) {
+            log.error("调用 DashScope Embedding API 失败: {}", e.getMessage(), e);
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * 批量文本向量化(逐条调用)
+     *
+     * @param texts 输入文本列表
+     * @return 向量列表,失败对应空列表
+     */
+    public List<List<Float>> batchEmbed(List<String> texts, String model, Integer dimension) {
+        if (texts == null || texts.isEmpty()) {
+            return Collections.emptyList();
+        }
+        List<List<Float>> results = new ArrayList<>(texts.size());
+        for (String text : texts) {
+            results.add(embed(text, model, dimension));
+        }
+        return results;
+    }
+
+    /**
+     * 解析 DashScope 响应,提取 embedding 向量
+     * 响应结构:output.embeddings[0].embedding
+     *
+     * @param responseBody API 响应体
+     * @return 向量列表
+     */
+    private List<Float> parseEmbedding(String responseBody) {
+        try {
+            JSONObject json = JSONObject.parseObject(responseBody);
+            JSONObject output = json.getJSONObject("output");
+            if (output == null) {
+                log.error("DashScope 响应中未找到 output 字段,响应: {}", responseBody);
+                return Collections.emptyList();
+            }
+
+            JSONArray embeddings = output.getJSONArray("embeddings");
+            if (embeddings == null || embeddings.isEmpty()) {
+                log.error("DashScope 响应中 output.embeddings 为空,响应: {}", responseBody);
+                return Collections.emptyList();
+            }
+
+            JSONObject firstEmbedding = embeddings.getJSONObject(0);
+            JSONArray embeddingArray = firstEmbedding.getJSONArray("embedding");
+            if (embeddingArray == null || embeddingArray.isEmpty()) {
+                log.error("DashScope 响应中 embedding 数组为空,响应: {}", responseBody);
+                return Collections.emptyList();
+            }
+
+            List<Float> vector = new ArrayList<>(embeddingArray.size());
+            for (int i = 0; i < embeddingArray.size(); i++) {
+                vector.add(embeddingArray.getFloat(i));
+            }
+
+            log.debug("DashScope Embedding 解析成功,维度: {}", vector.size());
+            return vector;
+        } catch (Exception e) {
+            log.error("解析 DashScope Embedding 响应失败: {}, 响应: {}", e.getMessage(), responseBody);
+            return Collections.emptyList();
+        }
+    }
+}

+ 14 - 14
core/src/main/java/com/tzld/videoVector/dao/mapper/videoVector/deconstruct/DeconstructContentVectorMapper.java

@@ -10,7 +10,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     long countByExample(DeconstructContentVectorExample example);
 
@@ -18,7 +18,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int deleteByExample(DeconstructContentVectorExample example);
 
@@ -26,7 +26,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int deleteByPrimaryKey(Long id);
 
@@ -34,7 +34,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int insert(DeconstructContentVector record);
 
@@ -42,7 +42,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int insertSelective(DeconstructContentVector record);
 
@@ -50,7 +50,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     List<DeconstructContentVector> selectByExampleWithBLOBs(DeconstructContentVectorExample example);
 
@@ -58,7 +58,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     List<DeconstructContentVector> selectByExample(DeconstructContentVectorExample example);
 
@@ -66,7 +66,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     DeconstructContentVector selectByPrimaryKey(Long id);
 
@@ -74,7 +74,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int updateByExampleSelective(@Param("record") DeconstructContentVector record, @Param("example") DeconstructContentVectorExample example);
 
@@ -82,7 +82,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int updateByExampleWithBLOBs(@Param("record") DeconstructContentVector record, @Param("example") DeconstructContentVectorExample example);
 
@@ -90,7 +90,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int updateByExample(@Param("record") DeconstructContentVector record, @Param("example") DeconstructContentVectorExample example);
 
@@ -98,7 +98,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int updateByPrimaryKeySelective(DeconstructContentVector record);
 
@@ -106,7 +106,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int updateByPrimaryKeyWithBLOBs(DeconstructContentVector record);
 
@@ -114,7 +114,7 @@ public interface DeconstructContentVectorMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     int updateByPrimaryKey(DeconstructContentVector record);
 }

+ 23 - 11
core/src/main/java/com/tzld/videoVector/dao/mapper/videoVector/deconstruct/DeconstructVectorConfigMapper.java

@@ -10,7 +10,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     long countByExample(DeconstructVectorConfigExample example);
 
@@ -18,7 +18,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int deleteByExample(DeconstructVectorConfigExample example);
 
@@ -26,7 +26,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int deleteByPrimaryKey(Long id);
 
@@ -34,7 +34,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int insert(DeconstructVectorConfig record);
 
@@ -42,7 +42,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int insertSelective(DeconstructVectorConfig record);
 
@@ -50,7 +50,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     List<DeconstructVectorConfig> selectByExample(DeconstructVectorConfigExample example);
 
@@ -58,7 +58,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     DeconstructVectorConfig selectByPrimaryKey(Long id);
 
@@ -66,7 +66,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int updateByExampleSelective(@Param("record") DeconstructVectorConfig record, @Param("example") DeconstructVectorConfigExample example);
 
@@ -74,7 +74,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int updateByExample(@Param("record") DeconstructVectorConfig record, @Param("example") DeconstructVectorConfigExample example);
 
@@ -82,7 +82,7 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int updateByPrimaryKeySelective(DeconstructVectorConfig record);
 
@@ -90,7 +90,19 @@ public interface DeconstructVectorConfigMapper {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     int updateByPrimaryKey(DeconstructVectorConfig record);
+
+    /**
+     * 按业务类型和内容类型查询启用的向量配置,支持 null 表示通配所有类型
+     * 参数为 null 时不过滤该字段;非 null 时匹配该字段为 null(通用)或等于指定小数值的配置
+     *
+     * @param bizType     业务类型,为 null 时不过滤
+     * @param contentType 内容类型,为 null 时不过滤
+     * @return 匹配的向量配置列表
+     */
+    List<DeconstructVectorConfig> selectMatchingConfigs(
+            @Param("bizType") Byte bizType,
+            @Param("contentType") Byte contentType);
 }

+ 43 - 33
core/src/main/java/com/tzld/videoVector/job/VideoVectorJob.java

@@ -68,7 +68,9 @@ public class VideoVectorJob {
 
     /**
      * 内容类型:长文
+     * @deprecated 已不再按内容类型过滤,加载所有启用的配置
      */
+    @Deprecated
     private static final byte CONTENT_TYPE_LONG_ARTICLE = 1;
 
     /**
@@ -83,14 +85,20 @@ public class VideoVectorJob {
         log.info("开始执行视频向量化任务, param: {}", param);
 
         try {
-            // 1. 获取所有启用的向量化配置
-            List<DeconstructVectorConfig> configs = getEnabledConfigs(CONTENT_TYPE_LONG_ARTICLE);
+            // 1. 获取所有启用的向量化配置(不限制内容类型)
+            List<DeconstructVectorConfig> configs = getEnabledConfigs();
             if (CollectionUtils.isEmpty(configs)) {
                 log.warn("未找到启用的向量化配置");
                 return ReturnT.SUCCESS;
             }
             log.info("加载 {} 个向量化配置", configs.size());
 
+            // 2. 分页处理前,每次 Job 执行只做一次审核清理
+            for (DeconstructVectorConfig config : configs) {
+                checkAndRemoveNotAuditPassedVideos(config.getConfigCode());
+            }
+            log.info("审核清理完成,开始分页向量化处理");
+
             int totalSuccessCount = 0;
             int totalFailCount = 0;
             int pageNum = 0;
@@ -108,9 +116,7 @@ public class VideoVectorJob {
                 for (DeconstructVectorConfig config : configs) {
                     String configCode = config.getConfigCode();
 
-                    // 3.0 检查已有向量的审核状态,移除审核不通过的视频
-                    checkAndRemoveNotAuditPassedVideos(configCode);
-
+                    // 3.0 审核清理已移至分页外,此处仅进行向量存在性检查
                     // 3.1 查询哪些 videoId 在该配置下已有向量
                     Set<Long> existingIds = vectorStoreService.existsByIds(configCode, videoIds);
                     // 3.2 过滤出需要处理的 videoId(排除已有向量的)
@@ -181,13 +187,11 @@ public class VideoVectorJob {
     }
 
     /**
-     * 获取启用的向量化配置
+     * 获取启用的向量化配置(不限制内容类型)
      */
-    private List<DeconstructVectorConfig> getEnabledConfigs(byte contentType) {
+    private List<DeconstructVectorConfig> getEnabledConfigs() {
         DeconstructVectorConfigExample example = new DeconstructVectorConfigExample();
-        example.createCriteria()
-                .andEnabledEqualTo((byte) 1)
-                .andContentTypeEqualTo(contentType);
+        example.createCriteria().andEnabledEqualTo((byte) 1);
         example.setOrderByClause("priority ASC");
         return vectorConfigMapper.selectByExample(example);
     }
@@ -355,35 +359,41 @@ public class VideoVectorJob {
 
     /**
      * 向量化并存储
+     * 取第一段有效文本进行向量化,以 configCode 为命名空间存储
+     * 避免多分段时拼接 configCode:i 导致存储键与查询键不一致
      */
     private boolean vectorizeAndStore(DeconstructVectorConfig config, Long videoId, List<String> texts) {
         String configCode = config.getConfigCode();
         Integer maxLength = config.getMaxLength();
-        
-        for (int i = 0; i < texts.size(); i++) {
-            String text = texts.get(i);
-            if (!StringUtils.hasText(text)) {
-                continue;
-            }
-            
-            // 文本截断
-            if (maxLength != null && maxLength > 0 && text.length() > maxLength) {
-                text = text.substring(0, maxLength);
-            }
-            
-            // 向量化
-            List<Float> vector = embeddingService.embed(text);
-            if (vector == null || vector.isEmpty()) {
-                log.warn("videoId={} 配置 {} 文本向量化失败", videoId, configCode);
-                continue;
+
+        // 取第一段有效文本(VIDEO_TOPIC 等配置通常只有一段)
+        String text = null;
+        for (String t : texts) {
+            if (StringUtils.hasText(t)) {
+                text = t;
+                break;
             }
-            
-            // 存储(如果有多个分段,使用 configCode:segmentIndex 作为key的一部分)
-            String storeConfigCode = texts.size() > 1 ? configCode + ":" + i : configCode;
-            vectorStoreService.save(storeConfigCode, videoId, vector);
-            log.debug("videoId={} 配置 {} 向量化存储成功", videoId, storeConfigCode);
         }
-        
+        if (text == null) {
+            log.debug("videoId={} 配置 {} 无有效文本,跳过", videoId, configCode);
+            return false;
+        }
+
+        // 文本截断
+        if (maxLength != null && maxLength > 0 && text.length() > maxLength) {
+            text = text.substring(0, maxLength);
+        }
+
+        // 向量化
+        List<Float> vector = embeddingService.embed(text, config);
+        if (vector == null || vector.isEmpty()) {
+            log.warn("videoId={} 配置 {} 文本向量化失败", videoId, configCode);
+            return false;
+        }
+
+        // 以 configCode 为命名空间存储
+        vectorStoreService.save(configCode, videoId, vector);
+        log.debug("videoId={} 配置 {} 向量化存储成功", videoId, configCode);
         return true;
     }
 

+ 3 - 0
core/src/main/java/com/tzld/videoVector/model/param/MatchTopNVideoParam.java

@@ -7,6 +7,9 @@ import java.util.List;
 @Data
 public class MatchTopNVideoParam {
 
+    /** 业务内容ID(帖子ID/视频ID) */
+    private String channelContentId;
+
     /** 配置编码,用于指定搜索哪个向量配置(如不指定则使用默认配置) */
     private String configCode;
 

+ 113 - 77
core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructContentVector.java

@@ -15,7 +15,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private Long id;
 
@@ -26,7 +26,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.content_id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private Long contentId;
 
@@ -37,10 +37,21 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.task_id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private String taskId;
 
+    /**
+     * Database Column Remarks:
+     *   配置编码
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column deconstruct_content_vector.config_code
+     *
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
+     */
+    private String configCode;
+
     /**
      * Database Column Remarks:
      *   向量化内容来源字段:title/summary/full_text/topics/points/theme等
@@ -48,7 +59,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.source_field
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private String sourceField;
 
@@ -59,7 +70,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.source_path
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private String sourcePath;
 
@@ -70,21 +81,10 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.vector_dimension
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private Integer vectorDimension;
 
-    /**
-     * Database Column Remarks:
-     *   向量数据(Float数组存储为JSON)
-     *
-     * This field was generated by MyBatis Generator.
-     * This field corresponds to the database column deconstruct_content_vector.vector_data
-     *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
-     */
-    private String vectorData;
-
     /**
      * Database Column Remarks:
      *   文本内容MD5哈希(用于去重)
@@ -92,18 +92,18 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.text_hash
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private String textHash;
 
     /**
      * Database Column Remarks:
-     *   使用的嵌入模型:Qwen3-Embedding-4B等
+     *   使用的嵌入模型:Qwen3-Embedding-0.6B等
      *
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.embedding_model
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private String embeddingModel;
 
@@ -114,7 +114,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.segment_index
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private Integer segmentIndex;
 
@@ -125,7 +125,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.segment_total
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private Integer segmentTotal;
 
@@ -136,7 +136,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.create_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private Date createTime;
 
@@ -147,10 +147,21 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.update_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private Date updateTime;
 
+    /**
+     * Database Column Remarks:
+     *   向量数据(Float数组存储为JSON)
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column deconstruct_content_vector.vector_data
+     *
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
+     */
+    private String vectorData;
+
     /**
      * Database Column Remarks:
      *   向量化前的原始文本内容
@@ -158,7 +169,7 @@ public class DeconstructContentVector {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_content_vector.source_text
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     private String sourceText;
 
@@ -168,7 +179,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Long getId() {
         return id;
@@ -180,7 +191,7 @@ public class DeconstructContentVector {
      *
      * @param id the value for deconstruct_content_vector.id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setId(Long id) {
         this.id = id;
@@ -192,7 +203,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.content_id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Long getContentId() {
         return contentId;
@@ -204,7 +215,7 @@ public class DeconstructContentVector {
      *
      * @param contentId the value for deconstruct_content_vector.content_id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setContentId(Long contentId) {
         this.contentId = contentId;
@@ -216,7 +227,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.task_id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public String getTaskId() {
         return taskId;
@@ -228,19 +239,43 @@ public class DeconstructContentVector {
      *
      * @param taskId the value for deconstruct_content_vector.task_id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setTaskId(String taskId) {
         this.taskId = taskId;
     }
 
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column deconstruct_content_vector.config_code
+     *
+     * @return the value of deconstruct_content_vector.config_code
+     *
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
+     */
+    public String getConfigCode() {
+        return configCode;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column deconstruct_content_vector.config_code
+     *
+     * @param configCode the value for deconstruct_content_vector.config_code
+     *
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
+     */
+    public void setConfigCode(String configCode) {
+        this.configCode = configCode;
+    }
+
     /**
      * This method was generated by MyBatis Generator.
      * This method returns the value of the database column deconstruct_content_vector.source_field
      *
      * @return the value of deconstruct_content_vector.source_field
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public String getSourceField() {
         return sourceField;
@@ -252,7 +287,7 @@ public class DeconstructContentVector {
      *
      * @param sourceField the value for deconstruct_content_vector.source_field
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setSourceField(String sourceField) {
         this.sourceField = sourceField;
@@ -264,7 +299,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.source_path
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public String getSourcePath() {
         return sourcePath;
@@ -276,7 +311,7 @@ public class DeconstructContentVector {
      *
      * @param sourcePath the value for deconstruct_content_vector.source_path
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setSourcePath(String sourcePath) {
         this.sourcePath = sourcePath;
@@ -288,7 +323,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.vector_dimension
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Integer getVectorDimension() {
         return vectorDimension;
@@ -300,43 +335,19 @@ public class DeconstructContentVector {
      *
      * @param vectorDimension the value for deconstruct_content_vector.vector_dimension
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setVectorDimension(Integer vectorDimension) {
         this.vectorDimension = vectorDimension;
     }
 
-    /**
-     * This method was generated by MyBatis Generator.
-     * This method returns the value of the database column deconstruct_content_vector.vector_data
-     *
-     * @return the value of deconstruct_content_vector.vector_data
-     *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
-     */
-    public String getVectorData() {
-        return vectorData;
-    }
-
-    /**
-     * This method was generated by MyBatis Generator.
-     * This method sets the value of the database column deconstruct_content_vector.vector_data
-     *
-     * @param vectorData the value for deconstruct_content_vector.vector_data
-     *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
-     */
-    public void setVectorData(String vectorData) {
-        this.vectorData = vectorData;
-    }
-
     /**
      * This method was generated by MyBatis Generator.
      * This method returns the value of the database column deconstruct_content_vector.text_hash
      *
      * @return the value of deconstruct_content_vector.text_hash
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public String getTextHash() {
         return textHash;
@@ -348,7 +359,7 @@ public class DeconstructContentVector {
      *
      * @param textHash the value for deconstruct_content_vector.text_hash
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setTextHash(String textHash) {
         this.textHash = textHash;
@@ -360,7 +371,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.embedding_model
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public String getEmbeddingModel() {
         return embeddingModel;
@@ -372,7 +383,7 @@ public class DeconstructContentVector {
      *
      * @param embeddingModel the value for deconstruct_content_vector.embedding_model
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setEmbeddingModel(String embeddingModel) {
         this.embeddingModel = embeddingModel;
@@ -384,7 +395,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.segment_index
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Integer getSegmentIndex() {
         return segmentIndex;
@@ -396,7 +407,7 @@ public class DeconstructContentVector {
      *
      * @param segmentIndex the value for deconstruct_content_vector.segment_index
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setSegmentIndex(Integer segmentIndex) {
         this.segmentIndex = segmentIndex;
@@ -408,7 +419,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.segment_total
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Integer getSegmentTotal() {
         return segmentTotal;
@@ -420,7 +431,7 @@ public class DeconstructContentVector {
      *
      * @param segmentTotal the value for deconstruct_content_vector.segment_total
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setSegmentTotal(Integer segmentTotal) {
         this.segmentTotal = segmentTotal;
@@ -432,7 +443,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.create_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Date getCreateTime() {
         return createTime;
@@ -444,7 +455,7 @@ public class DeconstructContentVector {
      *
      * @param createTime the value for deconstruct_content_vector.create_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setCreateTime(Date createTime) {
         this.createTime = createTime;
@@ -456,7 +467,7 @@ public class DeconstructContentVector {
      *
      * @return the value of deconstruct_content_vector.update_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Date getUpdateTime() {
         return updateTime;
@@ -468,19 +479,43 @@ public class DeconstructContentVector {
      *
      * @param updateTime the value for deconstruct_content_vector.update_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setUpdateTime(Date updateTime) {
         this.updateTime = updateTime;
     }
 
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column deconstruct_content_vector.vector_data
+     *
+     * @return the value of deconstruct_content_vector.vector_data
+     *
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
+     */
+    public String getVectorData() {
+        return vectorData;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column deconstruct_content_vector.vector_data
+     *
+     * @param vectorData the value for deconstruct_content_vector.vector_data
+     *
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
+     */
+    public void setVectorData(String vectorData) {
+        this.vectorData = vectorData;
+    }
+
     /**
      * This method was generated by MyBatis Generator.
      * This method returns the value of the database column deconstruct_content_vector.source_text
      *
      * @return the value of deconstruct_content_vector.source_text
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public String getSourceText() {
         return sourceText;
@@ -492,7 +527,7 @@ public class DeconstructContentVector {
      *
      * @param sourceText the value for deconstruct_content_vector.source_text
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setSourceText(String sourceText) {
         this.sourceText = sourceText;
@@ -502,7 +537,7 @@ public class DeconstructContentVector {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     @Override
     public String toString() {
@@ -513,16 +548,17 @@ public class DeconstructContentVector {
         sb.append(", id=").append(id);
         sb.append(", contentId=").append(contentId);
         sb.append(", taskId=").append(taskId);
+        sb.append(", configCode=").append(configCode);
         sb.append(", sourceField=").append(sourceField);
         sb.append(", sourcePath=").append(sourcePath);
         sb.append(", vectorDimension=").append(vectorDimension);
-        sb.append(", vectorData=").append(vectorData);
         sb.append(", textHash=").append(textHash);
         sb.append(", embeddingModel=").append(embeddingModel);
         sb.append(", segmentIndex=").append(segmentIndex);
         sb.append(", segmentTotal=").append(segmentTotal);
         sb.append(", createTime=").append(createTime);
         sb.append(", updateTime=").append(updateTime);
+        sb.append(", vectorData=").append(vectorData);
         sb.append(", sourceText=").append(sourceText);
         sb.append("]");
         return sb.toString();

+ 87 - 87
core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructContentVectorExample.java

@@ -9,7 +9,7 @@ public class DeconstructContentVectorExample {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     protected String orderByClause;
 
@@ -17,7 +17,7 @@ public class DeconstructContentVectorExample {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     protected boolean distinct;
 
@@ -25,7 +25,7 @@ public class DeconstructContentVectorExample {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     protected List<Criteria> oredCriteria;
 
@@ -33,7 +33,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public DeconstructContentVectorExample() {
         oredCriteria = new ArrayList<Criteria>();
@@ -43,7 +43,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setOrderByClause(String orderByClause) {
         this.orderByClause = orderByClause;
@@ -53,7 +53,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public String getOrderByClause() {
         return orderByClause;
@@ -63,7 +63,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void setDistinct(boolean distinct) {
         this.distinct = distinct;
@@ -73,7 +73,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public boolean isDistinct() {
         return distinct;
@@ -83,7 +83,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public List<Criteria> getOredCriteria() {
         return oredCriteria;
@@ -93,7 +93,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void or(Criteria criteria) {
         oredCriteria.add(criteria);
@@ -103,7 +103,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Criteria or() {
         Criteria criteria = createCriteriaInternal();
@@ -115,7 +115,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public Criteria createCriteria() {
         Criteria criteria = createCriteriaInternal();
@@ -129,7 +129,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     protected Criteria createCriteriaInternal() {
         Criteria criteria = new Criteria();
@@ -140,7 +140,7 @@ public class DeconstructContentVectorExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public void clear() {
         oredCriteria.clear();
@@ -152,7 +152,7 @@ public class DeconstructContentVectorExample {
      * This class was generated by MyBatis Generator.
      * This class corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     protected abstract static class GeneratedCriteria {
         protected List<Criterion> criteria;
@@ -385,6 +385,76 @@ public class DeconstructContentVectorExample {
             return (Criteria) this;
         }
 
+        public Criteria andConfigCodeIsNull() {
+            addCriterion("config_code is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeIsNotNull() {
+            addCriterion("config_code is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeEqualTo(String value) {
+            addCriterion("config_code =", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeNotEqualTo(String value) {
+            addCriterion("config_code <>", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeGreaterThan(String value) {
+            addCriterion("config_code >", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeGreaterThanOrEqualTo(String value) {
+            addCriterion("config_code >=", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeLessThan(String value) {
+            addCriterion("config_code <", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeLessThanOrEqualTo(String value) {
+            addCriterion("config_code <=", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeLike(String value) {
+            addCriterion("config_code like", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeNotLike(String value) {
+            addCriterion("config_code not like", value, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeIn(List<String> values) {
+            addCriterion("config_code in", values, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeNotIn(List<String> values) {
+            addCriterion("config_code not in", values, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeBetween(String value1, String value2) {
+            addCriterion("config_code between", value1, value2, "configCode");
+            return (Criteria) this;
+        }
+
+        public Criteria andConfigCodeNotBetween(String value1, String value2) {
+            addCriterion("config_code not between", value1, value2, "configCode");
+            return (Criteria) this;
+        }
+
         public Criteria andSourceFieldIsNull() {
             addCriterion("source_field is null");
             return (Criteria) this;
@@ -585,76 +655,6 @@ public class DeconstructContentVectorExample {
             return (Criteria) this;
         }
 
-        public Criteria andVectorDataIsNull() {
-            addCriterion("vector_data is null");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataIsNotNull() {
-            addCriterion("vector_data is not null");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataEqualTo(String value) {
-            addCriterion("vector_data =", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataNotEqualTo(String value) {
-            addCriterion("vector_data <>", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataGreaterThan(String value) {
-            addCriterion("vector_data >", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataGreaterThanOrEqualTo(String value) {
-            addCriterion("vector_data >=", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataLessThan(String value) {
-            addCriterion("vector_data <", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataLessThanOrEqualTo(String value) {
-            addCriterion("vector_data <=", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataLike(String value) {
-            addCriterion("vector_data like", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataNotLike(String value) {
-            addCriterion("vector_data not like", value, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataIn(List<String> values) {
-            addCriterion("vector_data in", values, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataNotIn(List<String> values) {
-            addCriterion("vector_data not in", values, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataBetween(String value1, String value2) {
-            addCriterion("vector_data between", value1, value2, "vectorData");
-            return (Criteria) this;
-        }
-
-        public Criteria andVectorDataNotBetween(String value1, String value2) {
-            addCriterion("vector_data not between", value1, value2, "vectorData");
-            return (Criteria) this;
-        }
-
         public Criteria andTextHashIsNull() {
             addCriterion("text_hash is null");
             return (Criteria) this;
@@ -1040,7 +1040,7 @@ public class DeconstructContentVectorExample {
      * This class was generated by MyBatis Generator.
      * This class corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated do_not_delete_during_merge Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated do_not_delete_during_merge Thu Apr 23 15:03:47 CST 2026
      */
     public static class Criteria extends GeneratedCriteria {
 
@@ -1053,7 +1053,7 @@ public class DeconstructContentVectorExample {
      * This class was generated by MyBatis Generator.
      * This class corresponds to the database table deconstruct_content_vector
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 15:03:47 CST 2026
      */
     public static class Criterion {
         private String condition;

+ 85 - 49
core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructVectorConfig.java

@@ -15,7 +15,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Long id;
 
@@ -26,7 +26,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.config_code
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private String configCode;
 
@@ -37,7 +37,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.config_name
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private String configName;
 
@@ -48,7 +48,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.biz_type
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Byte bizType;
 
@@ -59,7 +59,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.content_type
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Byte contentType;
 
@@ -70,7 +70,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.source_field
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private String sourceField;
 
@@ -81,7 +81,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.source_path
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private String sourcePath;
 
@@ -92,7 +92,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.extract_rule
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private String extractRule;
 
@@ -103,10 +103,21 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.embedding_model
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private String embeddingModel;
 
+    /**
+     * Database Column Remarks:
+     *   维度
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column deconstruct_vector_config.dimension
+     *
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
+     */
+    private Integer dimension;
+
     /**
      * Database Column Remarks:
      *   最大文本长度
@@ -114,7 +125,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.max_length
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Integer maxLength;
 
@@ -125,7 +136,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.enable_segment
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Byte enableSegment;
 
@@ -136,7 +147,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.segment_size
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Integer segmentSize;
 
@@ -147,7 +158,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.priority
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Integer priority;
 
@@ -158,7 +169,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.enabled
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Byte enabled;
 
@@ -169,7 +180,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.create_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Date createTime;
 
@@ -180,7 +191,7 @@ public class DeconstructVectorConfig {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database column deconstruct_vector_config.update_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     private Date updateTime;
 
@@ -190,7 +201,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Long getId() {
         return id;
@@ -202,7 +213,7 @@ public class DeconstructVectorConfig {
      *
      * @param id the value for deconstruct_vector_config.id
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setId(Long id) {
         this.id = id;
@@ -214,7 +225,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.config_code
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public String getConfigCode() {
         return configCode;
@@ -226,7 +237,7 @@ public class DeconstructVectorConfig {
      *
      * @param configCode the value for deconstruct_vector_config.config_code
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setConfigCode(String configCode) {
         this.configCode = configCode;
@@ -238,7 +249,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.config_name
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public String getConfigName() {
         return configName;
@@ -250,7 +261,7 @@ public class DeconstructVectorConfig {
      *
      * @param configName the value for deconstruct_vector_config.config_name
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setConfigName(String configName) {
         this.configName = configName;
@@ -262,7 +273,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.biz_type
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Byte getBizType() {
         return bizType;
@@ -274,7 +285,7 @@ public class DeconstructVectorConfig {
      *
      * @param bizType the value for deconstruct_vector_config.biz_type
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setBizType(Byte bizType) {
         this.bizType = bizType;
@@ -286,7 +297,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.content_type
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Byte getContentType() {
         return contentType;
@@ -298,7 +309,7 @@ public class DeconstructVectorConfig {
      *
      * @param contentType the value for deconstruct_vector_config.content_type
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setContentType(Byte contentType) {
         this.contentType = contentType;
@@ -310,7 +321,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.source_field
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public String getSourceField() {
         return sourceField;
@@ -322,7 +333,7 @@ public class DeconstructVectorConfig {
      *
      * @param sourceField the value for deconstruct_vector_config.source_field
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setSourceField(String sourceField) {
         this.sourceField = sourceField;
@@ -334,7 +345,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.source_path
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public String getSourcePath() {
         return sourcePath;
@@ -346,7 +357,7 @@ public class DeconstructVectorConfig {
      *
      * @param sourcePath the value for deconstruct_vector_config.source_path
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setSourcePath(String sourcePath) {
         this.sourcePath = sourcePath;
@@ -358,7 +369,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.extract_rule
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public String getExtractRule() {
         return extractRule;
@@ -370,7 +381,7 @@ public class DeconstructVectorConfig {
      *
      * @param extractRule the value for deconstruct_vector_config.extract_rule
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setExtractRule(String extractRule) {
         this.extractRule = extractRule;
@@ -382,7 +393,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.embedding_model
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public String getEmbeddingModel() {
         return embeddingModel;
@@ -394,19 +405,43 @@ public class DeconstructVectorConfig {
      *
      * @param embeddingModel the value for deconstruct_vector_config.embedding_model
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setEmbeddingModel(String embeddingModel) {
         this.embeddingModel = embeddingModel;
     }
 
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column deconstruct_vector_config.dimension
+     *
+     * @return the value of deconstruct_vector_config.dimension
+     *
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
+     */
+    public Integer getDimension() {
+        return dimension;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column deconstruct_vector_config.dimension
+     *
+     * @param dimension the value for deconstruct_vector_config.dimension
+     *
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
+     */
+    public void setDimension(Integer dimension) {
+        this.dimension = dimension;
+    }
+
     /**
      * This method was generated by MyBatis Generator.
      * This method returns the value of the database column deconstruct_vector_config.max_length
      *
      * @return the value of deconstruct_vector_config.max_length
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Integer getMaxLength() {
         return maxLength;
@@ -418,7 +453,7 @@ public class DeconstructVectorConfig {
      *
      * @param maxLength the value for deconstruct_vector_config.max_length
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setMaxLength(Integer maxLength) {
         this.maxLength = maxLength;
@@ -430,7 +465,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.enable_segment
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Byte getEnableSegment() {
         return enableSegment;
@@ -442,7 +477,7 @@ public class DeconstructVectorConfig {
      *
      * @param enableSegment the value for deconstruct_vector_config.enable_segment
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setEnableSegment(Byte enableSegment) {
         this.enableSegment = enableSegment;
@@ -454,7 +489,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.segment_size
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Integer getSegmentSize() {
         return segmentSize;
@@ -466,7 +501,7 @@ public class DeconstructVectorConfig {
      *
      * @param segmentSize the value for deconstruct_vector_config.segment_size
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setSegmentSize(Integer segmentSize) {
         this.segmentSize = segmentSize;
@@ -478,7 +513,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.priority
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Integer getPriority() {
         return priority;
@@ -490,7 +525,7 @@ public class DeconstructVectorConfig {
      *
      * @param priority the value for deconstruct_vector_config.priority
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setPriority(Integer priority) {
         this.priority = priority;
@@ -502,7 +537,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.enabled
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Byte getEnabled() {
         return enabled;
@@ -514,7 +549,7 @@ public class DeconstructVectorConfig {
      *
      * @param enabled the value for deconstruct_vector_config.enabled
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setEnabled(Byte enabled) {
         this.enabled = enabled;
@@ -526,7 +561,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.create_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Date getCreateTime() {
         return createTime;
@@ -538,7 +573,7 @@ public class DeconstructVectorConfig {
      *
      * @param createTime the value for deconstruct_vector_config.create_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setCreateTime(Date createTime) {
         this.createTime = createTime;
@@ -550,7 +585,7 @@ public class DeconstructVectorConfig {
      *
      * @return the value of deconstruct_vector_config.update_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Date getUpdateTime() {
         return updateTime;
@@ -562,7 +597,7 @@ public class DeconstructVectorConfig {
      *
      * @param updateTime the value for deconstruct_vector_config.update_time
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setUpdateTime(Date updateTime) {
         this.updateTime = updateTime;
@@ -572,7 +607,7 @@ public class DeconstructVectorConfig {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     @Override
     public String toString() {
@@ -589,6 +624,7 @@ public class DeconstructVectorConfig {
         sb.append(", sourcePath=").append(sourcePath);
         sb.append(", extractRule=").append(extractRule);
         sb.append(", embeddingModel=").append(embeddingModel);
+        sb.append(", dimension=").append(dimension);
         sb.append(", maxLength=").append(maxLength);
         sb.append(", enableSegment=").append(enableSegment);
         sb.append(", segmentSize=").append(segmentSize);

+ 77 - 17
core/src/main/java/com/tzld/videoVector/model/po/videoVector/deconstruct/DeconstructVectorConfigExample.java

@@ -9,7 +9,7 @@ public class DeconstructVectorConfigExample {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     protected String orderByClause;
 
@@ -17,7 +17,7 @@ public class DeconstructVectorConfigExample {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     protected boolean distinct;
 
@@ -25,7 +25,7 @@ public class DeconstructVectorConfigExample {
      * This field was generated by MyBatis Generator.
      * This field corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     protected List<Criteria> oredCriteria;
 
@@ -33,7 +33,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public DeconstructVectorConfigExample() {
         oredCriteria = new ArrayList<Criteria>();
@@ -43,7 +43,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setOrderByClause(String orderByClause) {
         this.orderByClause = orderByClause;
@@ -53,7 +53,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public String getOrderByClause() {
         return orderByClause;
@@ -63,7 +63,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void setDistinct(boolean distinct) {
         this.distinct = distinct;
@@ -73,7 +73,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public boolean isDistinct() {
         return distinct;
@@ -83,7 +83,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public List<Criteria> getOredCriteria() {
         return oredCriteria;
@@ -93,7 +93,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void or(Criteria criteria) {
         oredCriteria.add(criteria);
@@ -103,7 +103,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Criteria or() {
         Criteria criteria = createCriteriaInternal();
@@ -115,7 +115,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public Criteria createCriteria() {
         Criteria criteria = createCriteriaInternal();
@@ -129,7 +129,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     protected Criteria createCriteriaInternal() {
         Criteria criteria = new Criteria();
@@ -140,7 +140,7 @@ public class DeconstructVectorConfigExample {
      * This method was generated by MyBatis Generator.
      * This method corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public void clear() {
         oredCriteria.clear();
@@ -152,7 +152,7 @@ public class DeconstructVectorConfigExample {
      * This class was generated by MyBatis Generator.
      * This class corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     protected abstract static class GeneratedCriteria {
         protected List<Criterion> criteria;
@@ -795,6 +795,66 @@ public class DeconstructVectorConfigExample {
             return (Criteria) this;
         }
 
+        public Criteria andDimensionIsNull() {
+            addCriterion("dimension is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionIsNotNull() {
+            addCriterion("dimension is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionEqualTo(Integer value) {
+            addCriterion("dimension =", value, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionNotEqualTo(Integer value) {
+            addCriterion("dimension <>", value, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionGreaterThan(Integer value) {
+            addCriterion("dimension >", value, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionGreaterThanOrEqualTo(Integer value) {
+            addCriterion("dimension >=", value, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionLessThan(Integer value) {
+            addCriterion("dimension <", value, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionLessThanOrEqualTo(Integer value) {
+            addCriterion("dimension <=", value, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionIn(List<Integer> values) {
+            addCriterion("dimension in", values, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionNotIn(List<Integer> values) {
+            addCriterion("dimension not in", values, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionBetween(Integer value1, Integer value2) {
+            addCriterion("dimension between", value1, value2, "dimension");
+            return (Criteria) this;
+        }
+
+        public Criteria andDimensionNotBetween(Integer value1, Integer value2) {
+            addCriterion("dimension not between", value1, value2, "dimension");
+            return (Criteria) this;
+        }
+
         public Criteria andMaxLengthIsNull() {
             addCriterion("max_length is null");
             return (Criteria) this;
@@ -1220,7 +1280,7 @@ public class DeconstructVectorConfigExample {
      * This class was generated by MyBatis Generator.
      * This class corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated do_not_delete_during_merge Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated do_not_delete_during_merge Thu Apr 23 14:55:06 CST 2026
      */
     public static class Criteria extends GeneratedCriteria {
 
@@ -1233,7 +1293,7 @@ public class DeconstructVectorConfigExample {
      * This class was generated by MyBatis Generator.
      * This class corresponds to the database table deconstruct_vector_config
      *
-     * @mbg.generated Mon Mar 09 10:39:51 CST 2026
+     * @mbg.generated Thu Apr 23 14:55:06 CST 2026
      */
     public static class Criterion {
         private String condition;

+ 4 - 7
core/src/main/java/com/tzld/videoVector/service/EmbeddingService.java

@@ -1,5 +1,7 @@
 package com.tzld.videoVector.service;
 
+import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructVectorConfig;
+
 import java.util.List;
 
 /**
@@ -12,18 +14,13 @@ public interface EmbeddingService {
      * @param text 输入文本
      * @return 向量数据
      */
-    List<Float> embed(String text);
+    List<Float> embed(String text, DeconstructVectorConfig config);
 
     /**
      * 批量将文本转换为向量
      * @param texts 输入文本列表
      * @return 向量数据列表
      */
-    List<List<Float>> batchEmbed(List<String> texts);
+    List<List<Float>> batchEmbed(List<String> texts, DeconstructVectorConfig config);
 
-    /**
-     * 获取向量维度
-     * @return 向量维度
-     */
-    int getDimension();
 }

+ 9 - 0
core/src/main/java/com/tzld/videoVector/service/VectorizeService.java

@@ -54,6 +54,15 @@ public interface VectorizeService {
      */
     List<DeconstructContentVector> getVectorsByContentId(Long contentId);
 
+    /**
+     * 根据内容ID和配置编码查询向量列表
+     *
+     * @param contentId  内容ID
+     * @param configCode 配置编码,为空时不过滤
+     * @return 向量列表
+     */
+    List<DeconstructContentVector> getVectorsByContentId(Long contentId, String configCode);
+
     /**
      * 根据内容ID和字段标识查询向量
      *

+ 25 - 188
core/src/main/java/com/tzld/videoVector/service/impl/EmbeddingServiceImpl.java

@@ -1,5 +1,7 @@
 package com.tzld.videoVector.service.impl;
 
+import com.tzld.videoVector.api.DashScopeEmbeddingApiService;
+import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructVectorConfig;
 import com.tzld.videoVector.service.EmbeddingService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
@@ -7,237 +9,72 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 /**
- * 基于本地哈希向量化的文本向量化服务实现
- * 使用 MurmurHash + TF 特征提取,完全本地执行,无需下载模型
+ * 文本向量化服务实现
+ * 支持两种模式:api(内部OpenAI接口) / dashscope(阿里云DashScope qwen3-vl-embedding)
  */
 @Slf4j
 @Service
 public class EmbeddingServiceImpl implements EmbeddingService {
 
     /**
-     * 向量维度
+     * 向量化模式:api(内部OpenAI接口) / dashscope(阿里云DashScope)
      */
-    @Value("${embedding.dimension:2560}")
-    private int dimension;
-
-    /**
-     * N-gram 大小
-     */
-    @Value("${embedding.ngram:2}")
-    private int ngram;
-
-    /**
-     * 向量化模式:local(本地) 或 api(远程API)
-     */
-    @Value("${embedding.mode:local}")
+    @Value("${embedding.mode:dashscope}")
     private String embeddingMode;
 
     @Resource
     private com.tzld.videoVector.api.EmbeddingApiService embeddingApiService;
 
-    private int[] hashSeeds;
+    @Resource
+    private DashScopeEmbeddingApiService dashScopeEmbeddingApiService;
 
     @PostConstruct
     public void init() {
-        // 初始化哈希种子
-        hashSeeds = new int[]{31, 37, 41, 43, 47, 53, 59, 61};
-        log.info("向量化服务初始化完成,模式: {}, 向量维度: {}, N-gram: {}", embeddingMode, dimension, ngram);
+        log.info("向量化服务初始化完成,模式: {}", embeddingMode);
     }
 
     @Override
-    public List<Float> embed(String text) {
+    public List<Float> embed(String text, DeconstructVectorConfig config) {
         if (text == null || text.trim().isEmpty()) {
             log.warn("输入文本为空,返回空向量");
             return Collections.emptyList();
         }
 
         // 根据配置选择向量化方式
-        if ("api".equalsIgnoreCase(embeddingMode)) {
+        if ("dashscope".equalsIgnoreCase(embeddingMode)) {
+            String model = config != null ? config.getEmbeddingModel() : null;
+            Integer dim = config != null ? config.getDimension() : null;
+            return dashScopeEmbeddingApiService.embed(text, model, dim);
+        } else if ("api".equalsIgnoreCase(embeddingMode)) {
             return embeddingApiService.embed(text);
         } else {
-            return localEmbed(text);
+            log.error("不支持的 embedding 模式: {}", embeddingMode);
+            return Collections.emptyList();
         }
     }
 
     @Override
-    public List<List<Float>> batchEmbed(List<String> texts) {
+    public List<List<Float>> batchEmbed(List<String> texts, DeconstructVectorConfig config) {
         if (texts == null || texts.isEmpty()) {
             return Collections.emptyList();
         }
 
         // 根据配置选择向量化方式
-        if ("api".equalsIgnoreCase(embeddingMode)) {
+        if ("dashscope".equalsIgnoreCase(embeddingMode)) {
+            String model = config != null ? config.getEmbeddingModel() : null;
+            Integer dim = config != null ? config.getDimension() : null;
+            return dashScopeEmbeddingApiService.batchEmbed(texts, model, dim);
+        } else if ("api".equalsIgnoreCase(embeddingMode)) {
             return embeddingApiService.batchEmbed(texts);
         } else {
-            List<List<Float>> results = new ArrayList<>(texts.size());
-            for (String text : texts) {
-                results.add(localEmbed(text));
-            }
-            return results;
-        }
-    }
-
-    @Override
-    public int getDimension() {
-        // 如果使用 API 模式,尝试从 API 获取维度
-        if ("api".equalsIgnoreCase(embeddingMode)) {
-            List<Float> sample = embeddingApiService.embed("测试");
-            if (!sample.isEmpty()) {
-                return sample.size();
-            }
-        }
-        return dimension;
-    }
-
-    /**
-     * 本地向量化实现
-     */
-    private List<Float> localEmbed(String text) {
-        try {
-            // 1. 文本预处理
-            String processedText = preprocess(text);
-            
-            // 2. 提取 N-gram 特征
-            List<String> features = extractNgrams(processedText, ngram);
-            
-            // 3. 生成哈希向量
-            float[] vector = new float[dimension];
-            
-            for (String feature : features) {
-                // 使用多个哈希函数
-                for (int seed : hashSeeds) {
-                    int hash = murmurHash(feature, seed);
-                    int index = Math.abs(hash % dimension);
-                    // 使用符号位决定加减
-                    float value = (hash & 0x80000000) == 0 ? 1.0f : -1.0f;
-                    vector[index] += value;
-                }
-            }
-            
-            // 4. L2 归一化
-            normalize(vector);
-            
-            return toFloatList(vector);
-        } catch (Exception e) {
-            log.error("本地文本向量化失败: {}", e.getMessage(), e);
+            log.error("不支持的 embedding 模式: {}", embeddingMode);
             return Collections.emptyList();
         }
     }
 
-    /**
-     * 文本预处理:转小写、去除特殊字符
-     */
-    private String preprocess(String text) {
-        return text.toLowerCase()
-                .replaceAll("[^a-z0-9\\u4e00-\\u9fa5\\s]", " ")
-                .replaceAll("\\s+", " ")
-                .trim();
-    }
-
-    /**
-     * 提取 N-gram 特征
-     */
-    private List<String> extractNgrams(String text, int n) {
-        List<String> ngrams = new ArrayList<>();
-        
-        // 字符级 N-gram(适合中文)
-        for (int i = 0; i <= text.length() - n; i++) {
-            ngrams.add(text.substring(i, i + n));
-        }
-        
-        // 词级特征(适合英文和分词后的中文)
-        String[] words = text.split("\\s+");
-        for (String word : words) {
-            if (!word.isEmpty()) {
-                ngrams.add(word);
-            }
-        }
-        
-        // 词级 N-gram
-        for (int i = 0; i <= words.length - n; i++) {
-            StringBuilder sb = new StringBuilder();
-            for (int j = 0; j < n; j++) {
-                if (j > 0) sb.append(" ");
-                sb.append(words[i + j]);
-            }
-            ngrams.add(sb.toString());
-        }
-        
-        return ngrams;
-    }
-
-    /**
-     * MurmurHash 哈希函数
-     */
-    private int murmurHash(String text, int seed) {
-        byte[] data = text.getBytes(StandardCharsets.UTF_8);
-        int length = data.length;
-        int h = seed ^ length;
-        int k;
-        
-        for (int i = 0; i + 4 <= length; i += 4) {
-            k = (data[i] & 0xff) 
-                | ((data[i + 1] & 0xff) << 8)
-                | ((data[i + 2] & 0xff) << 16)
-                | ((data[i + 3] & 0xff) << 24);
-            
-            k *= 0x5bd1e995;
-            k ^= k >>> 24;
-            k *= 0x5bd1e995;
-            
-            h *= 0x5bd1e995;
-            h ^= k;
-        }
-        
-        // 处理剩余字节
-        int remaining = length % 4;
-        if (remaining > 0) {
-            int tail = 0;
-            for (int i = 0; i < remaining; i++) {
-                tail |= (data[length - remaining + i] & 0xff) << (i * 8);
-            }
-            h ^= tail;
-            h *= 0x5bd1e995;
-        }
-        
-        h ^= h >>> 13;
-        h *= 0x5bd1e995;
-        h ^= h >>> 15;
-        
-        return h;
-    }
-
-    /**
-     * L2 归一化
-     */
-    private void normalize(float[] vector) {
-        float norm = 0.0f;
-        for (float v : vector) {
-            norm += v * v;
-        }
-        norm = (float) Math.sqrt(norm);
-        
-        if (norm > 0) {
-            for (int i = 0; i < vector.length; i++) {
-                vector[i] /= norm;
-            }
-        }
-    }
-
-    /**
-     * 将 float[] 转换为 List<Float>
-     */
-    private List<Float> toFloatList(float[] array) {
-        List<Float> list = new ArrayList<>(array.length);
-        for (float f : array) {
-            list.add(f);
-        }
-        return list;
-    }
 }
+

+ 75 - 28
core/src/main/java/com/tzld/videoVector/service/impl/VectorizeServiceImpl.java

@@ -37,22 +37,11 @@ public class VectorizeServiceImpl implements VectorizeService {
 
     @Override
     public List<DeconstructVectorConfig> getVectorConfigs(Integer bizType, Integer contentType) {
-        DeconstructVectorConfigExample example = new DeconstructVectorConfigExample();
-        DeconstructVectorConfigExample.Criteria criteria = example.createCriteria();
-        criteria.andEnabledEqualTo((byte) 1);
-
-        // 业务类型匹配(null表示通用)
-        if (bizType != null) {
-            criteria.andBizTypeEqualTo(bizType.byteValue());
-        }
-
-        // 内容类型匹配(null表示通用)
-        if (contentType != null) {
-            criteria.andContentTypeEqualTo(contentType.byteValue());
-        }
-
-        example.setOrderByClause("priority ASC");
-        return vectorConfigMapper.selectByExample(example);
+        // 使用 null-aware 查询:字段为 null(通用配置)和字段等于指定値的配置均可匹配
+        return vectorConfigMapper.selectMatchingConfigs(
+                bizType != null ? bizType.byteValue() : null,
+                contentType != null ? contentType.byteValue() : null
+        );
     }
 
     @Override
@@ -79,6 +68,13 @@ public class VectorizeServiceImpl implements VectorizeService {
         // 按配置逐个向量化
         for (DeconstructVectorConfig config : configs) {
             try {
+                // 幂等检查:若该 configCode 已有向量则跳过,防止重复向量化
+                List<DeconstructContentVector> existing = getVectorsByContentId(content.getId(), config.getConfigCode());
+                if (!CollectionUtils.isEmpty(existing)) {
+                    log.debug("contentId={} 已有 configCode={} 的向量,跳过向量化",
+                            content.getId(), config.getConfigCode());
+                    continue;
+                }
                 List<DeconstructContentVector> vectors = vectorizeByConfig(content, config);
                 if (!CollectionUtils.isEmpty(vectors)) {
                     allVectors.addAll(vectors);
@@ -111,11 +107,6 @@ public class VectorizeServiceImpl implements VectorizeService {
             return vectors;
         }
 
-        String embeddingModel = config.getEmbeddingModel();
-        if (!StringUtils.hasText(embeddingModel)) {
-            embeddingModel = "Qwen3-Embedding-4B";
-        }
-
         int segmentIndex = 0;
         for (String text : texts) {
             if (!StringUtils.hasText(text)) {
@@ -124,24 +115,35 @@ public class VectorizeServiceImpl implements VectorizeService {
 
             // 文本截断
             String truncatedText = truncateText(text, config.getMaxLength());
-
-            // 调用向量化服务
-            List<Float> vectorData = embeddingService.embed(truncatedText);
-            if (CollectionUtils.isEmpty(vectorData)) {
-                log.warn("向量化失败,text={}", truncatedText.substring(0, Math.min(50, truncatedText.length())));
-                continue;
+            // 提前计算 textHash,用于复用查询
+            String textHash = Md5Util.encoderByMd5(truncatedText);
+
+            // 优先查询历史向量缓存:text_hash + config_code 已存在则直接复用向量数据
+            List<Float> vectorData = findCachedVectorData(textHash, config.getConfigCode());
+            String embeddingModel = config.getEmbeddingModel();
+            if (vectorData != null) {
+                log.debug("命中 text_hash 向量缓存,跳过 embedding API,hash={}, configCode={}",
+                        textHash, config.getConfigCode());
+            } else {
+                // 未命中缓存,调用 embedding API
+                vectorData = embeddingService.embed(truncatedText, config);
+                if (CollectionUtils.isEmpty(vectorData)) {
+                    log.warn("向量化失败,text={}", truncatedText.substring(0, Math.min(50, truncatedText.length())));
+                    continue;
+                }
             }
 
             // 构建向量实体
             DeconstructContentVector vector = new DeconstructContentVector();
             vector.setContentId(content.getId());
             vector.setTaskId(content.getTaskId());
+            vector.setConfigCode(config.getConfigCode());
             vector.setSourceField(config.getSourceField());
             vector.setSourcePath(config.getSourcePath());
             vector.setVectorDimension(vectorData.size());
             vector.setVectorData(JSON.toJSONString(vectorData));
             vector.setSourceText(truncatedText);
-            vector.setTextHash(Md5Util.encoderByMd5(truncatedText));
+            vector.setTextHash(textHash);
             vector.setEmbeddingModel(embeddingModel);
             vector.setSegmentIndex(segmentIndex++);
             vector.setSegmentTotal(texts.size());
@@ -323,6 +325,36 @@ public class VectorizeServiceImpl implements VectorizeService {
         return text.substring(0, maxLength);
     }
 
+    /**
+     * 查询已缓存的向量数据(text_hash + config_code 联合匹配)
+     * 命中则返回向量浮点数列表,否则返回 null
+     */
+    private List<Float> findCachedVectorData(String textHash, String configCode) {
+        if (!StringUtils.hasText(textHash) || !StringUtils.hasText(configCode)) {
+            return null;
+        }
+        try {
+            DeconstructContentVectorExample example = new DeconstructContentVectorExample();
+            example.createCriteria()
+                    .andTextHashEqualTo(textHash)
+                    .andConfigCodeEqualTo(configCode);
+            example.setOrderByClause("id DESC");
+            List<DeconstructContentVector> cached = contentVectorMapper.selectByExampleWithBLOBs(example);
+            if (CollectionUtils.isEmpty(cached)) {
+                return null;
+            }
+            String vectorDataJson = cached.get(0).getVectorData();
+            if (!StringUtils.hasText(vectorDataJson)) {
+                return null;
+            }
+            return JSON.parseArray(vectorDataJson, Float.class);
+        } catch (Exception e) {
+            log.error("查询 text_hash 向量缓存失败,hash={}, configCode={}, error={}",
+                    textHash, configCode, e.getMessage());
+            return null;
+        }
+    }
+
     @Override
     public int batchSaveVectors(List<DeconstructContentVector> vectors) {
         if (CollectionUtils.isEmpty(vectors)) {
@@ -343,6 +375,9 @@ public class VectorizeServiceImpl implements VectorizeService {
         return count;
     }
 
+    /**
+     * 根据 contentId 查询向量列表
+     */
     @Override
     public List<DeconstructContentVector> getVectorsByContentId(Long contentId) {
         DeconstructContentVectorExample example = new DeconstructContentVectorExample();
@@ -351,6 +386,18 @@ public class VectorizeServiceImpl implements VectorizeService {
         return contentVectorMapper.selectByExampleWithBLOBs(example);
     }
 
+    @Override
+    public List<DeconstructContentVector> getVectorsByContentId(Long contentId, String configCode) {
+        DeconstructContentVectorExample example = new DeconstructContentVectorExample();
+        DeconstructContentVectorExample.Criteria criteria = example.createCriteria()
+                .andContentIdEqualTo(contentId);
+        if (StringUtils.hasText(configCode)) {
+            criteria.andConfigCodeEqualTo(configCode);
+        }
+        example.setOrderByClause("source_field ASC, segment_index ASC");
+        return contentVectorMapper.selectByExampleWithBLOBs(example);
+    }
+
     @Override
     public List<DeconstructContentVector> getVectorsByField(Long contentId, String sourceField) {
         DeconstructContentVectorExample example = new DeconstructContentVectorExample();

+ 170 - 38
core/src/main/java/com/tzld/videoVector/service/impl/VideoSearchServiceImpl.java

@@ -1,9 +1,10 @@
 package com.tzld.videoVector.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
-import com.google.common.collect.Lists;
 import com.tzld.videoVector.api.VideoApiService;
 import com.tzld.videoVector.dao.mapper.videoVector.deconstruct.DeconstructContentMapper;
+import com.tzld.videoVector.dao.mapper.videoVector.deconstruct.DeconstructContentVectorMapper;
+import com.tzld.videoVector.dao.mapper.videoVector.deconstruct.DeconstructVectorConfigMapper;
 import com.tzld.videoVector.model.entity.DeconstructResult;
 import com.tzld.videoVector.model.entity.VideoDetail;
 import com.tzld.videoVector.model.entity.VideoMatch;
@@ -13,17 +14,18 @@ import com.tzld.videoVector.model.param.MatchTopNVideoParam;
 import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructContent;
 import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructContentExample;
 import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructContentVector;
-import com.tzld.videoVector.service.DeconstructService;
-import com.tzld.videoVector.service.EmbeddingService;
-import com.tzld.videoVector.service.VectorStoreService;
-import com.tzld.videoVector.service.VectorizeService;
-import com.tzld.videoVector.service.VideoSearchService;
+import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructContentVectorExample;
+import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructVectorConfig;
+import com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructVectorConfigExample;
+import com.tzld.videoVector.service.*;
+import com.tzld.videoVector.util.Md5Util;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
 import java.util.*;
+import java.util.concurrent.*;
 import java.util.stream.Collectors;
 
 import static com.tzld.videoVector.service.VectorStoreService.DEFAULT_CONFIG_CODE;
@@ -44,12 +46,31 @@ public class VideoSearchServiceImpl implements VideoSearchService {
     @Resource
     private DeconstructContentMapper deconstructContentMapper;
 
+    @Resource
+    private DeconstructContentVectorMapper deconstructContentVectorMapper;
+
     @Resource
     private VectorizeService vectorizeService;
 
     @Resource
     private VideoApiService videoApiService;
 
+    @Resource
+    private DeconstructVectorConfigMapper deconstructVectorConfigMapper;
+
+    // 异步向量化线程池,避免裸创建 Thread
+    private static final ExecutorService VECTORIZE_EXECUTOR = new ThreadPoolExecutor(
+            2, 10, 60L, TimeUnit.SECONDS,
+            new LinkedBlockingQueue<>(100),
+            r -> {
+                Thread t = new Thread(r);
+                t.setName("vectorize-async-" + t.getId());
+                t.setDaemon(true);
+                return t;
+            },
+            new ThreadPoolExecutor.CallerRunsPolicy()
+    );
+
     @Override
     public String deconstruct(DeconstructParam param) {
         if (param == null) {
@@ -177,15 +198,11 @@ public class VideoSearchServiceImpl implements VideoSearchService {
             content = updateContentFromResult(content, result, taskId, param);
         }
 
-        // 如果任务完成且成功,进行向量化
+        // 如果任务完成且成功,触发向量化处理
+        // vectorizeContent 内部已按 configCode 做幂等检查,新增配置也会被自动补充向量化
         if (content != null && content.getStatus() != null && content.getStatus() == 2) {
-            // 检查是否已向量化
-            List<DeconstructContentVector> existingVectors = vectorizeService.getVectorsByContentId(content.getId());
-            if (existingVectors == null || existingVectors.isEmpty()) {
-                // 异步进行向量化处理
-                vectorizeContentAsync(content);
-                log.info("触发向量化处理,contentId={}, taskId={}", content.getId(), taskId);
-            }
+            vectorizeContentAsync(content);
+            log.info("触发向量化处理,contentId={}, taskId={}", content.getId(), taskId);
         }
 
         // 构建返回结果
@@ -352,11 +369,10 @@ public class VideoSearchServiceImpl implements VideoSearchService {
     }
 
     /**
-     * 异步向量化内容
+     * 异步向量化内容,使用线程池执行,避免阻塞接口响应
      */
     private void vectorizeContentAsync(DeconstructContent content) {
-        // 使用异步线程执行向量化,避免阻塞接口响应
-        new Thread(() -> {
+        VECTORIZE_EXECUTOR.submit(() -> {
             try {
                 log.info("开始异步向量化处理,contentId={}", content.getId());
                 vectorizeService.vectorizeContent(content);
@@ -365,7 +381,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
                 log.error("异步向量化处理失败,contentId={}, error={}",
                         content.getId(), e.getMessage(), e);
             }
-        }).start();
+        });
     }
 
     @Override
@@ -381,32 +397,18 @@ public class VideoSearchServiceImpl implements VideoSearchService {
             configCode = DEFAULT_CONFIG_CODE;
         }
 
-        // 确定查询向量:直接传入 or 文本向量化
-        List<Float> queryVector = param.getQueryVector();
+        // 确定查询向量:直接传入 > channelContentId历史向量 > text_hash历史embedding > 文本向量化
+        List<Float> queryVector = resolveQueryVector(param);
         if (queryVector == null || queryVector.isEmpty()) {
-            if (param.getQueryText() == null || param.getQueryText().trim().isEmpty()) {
-                log.error("matchTopNVideo 缺少 queryVector 和 queryText");
-                return Collections.emptyList();
-            }
-            log.info("对文本进行向量化,文本: {}", param.getQueryText());
-            queryVector = embeddingService.embed(param.getQueryText());
-            if (queryVector == null || queryVector.isEmpty()) {
-                log.error("文本向量化失败");
-                return Collections.emptyList();
-            }
+            log.error("matchTopNVideo 无法获取查询向量,param={}", param);
+            return Collections.emptyList();
         }
 
         log.info("开始匹配 Top-{} 视频,configCode: {},向量维度: {}", topN, configCode, queryVector.size());
 
-        // 在 Redis 中搜索(支持按 configCode 搜索)
-        // 为了确保返回足够的结果,搜索更多的候选
+        // configCode 已在上方确保非空,直接使用它搜索
         int candidateSize = topN * 3;
-        List<VideoMatch> matches;
-        if (configCode != null && !configCode.isEmpty()) {
-            matches = vectorStoreService.searchTopN(configCode, queryVector, candidateSize);
-        } else {
-            matches = vectorStoreService.searchTopN(queryVector, candidateSize);
-        }
+        List<VideoMatch> matches = vectorStoreService.searchTopN(configCode, queryVector, candidateSize);
 
         // 过滤审核状态不通过的视频
         List<VideoMatch> filteredMatches = filterByAuditStatus(matches, topN);
@@ -424,6 +426,136 @@ public class VideoSearchServiceImpl implements VideoSearchService {
         return result;
     }
 
+    /**
+     * 解析查询向量,优先级:直接传入 > channelContentId历史向量 > text_hash历史embedding > 文本向量化
+     * 任意一级命中则直接返回,不再继续降级
+     */
+    private List<Float> resolveQueryVector(MatchTopNVideoParam param) {
+        // 1. 直接传入
+        if (param.getQueryVector() != null && !param.getQueryVector().isEmpty()) {
+            log.info("使用直接传入的 queryVector,向量维度={}", param.getQueryVector().size());
+            return param.getQueryVector();
+        }
+
+        // 2. channelContentId 历史向量
+        if (StringUtils.hasText(param.getChannelContentId())) {
+            List<Float> vector = getVectorByChannelContentId(param.getChannelContentId(), param.getConfigCode());
+            if (vector != null && !vector.isEmpty()) {
+                log.info("命中 channelContentId 历史向量缓存,channelContentId={}, 向量维度={}",
+                        param.getChannelContentId(), vector.size());
+                return vector;
+            }
+        }
+
+        // 3. queryText:先查 text_hash 历史 embedding,再调用 embedding API
+        if (StringUtils.hasText(param.getQueryText())) {
+            String textHash = Md5Util.encoderByMd5(param.getQueryText());
+            if (StringUtils.hasText(textHash)) {
+                List<Float> vector = getVectorByTextHash(textHash, param.getConfigCode());
+                if (vector != null && !vector.isEmpty()) {
+                    log.info("命中 text_hash 历史 embedding 缓存,hash={}, 向量维度={}", textHash, vector.size());
+                    return vector;
+                }
+            }
+            // 根据 configCode 获取向量配置
+            DeconstructVectorConfig vectorConfig = getVectorConfigByCode(param.getConfigCode());
+            log.info("调用 embedding API 向量化,文本: {},configCode: {},embeddingModel: {}",
+                    param.getQueryText(), param.getConfigCode(),
+                    vectorConfig != null ? vectorConfig.getEmbeddingModel() : null);
+            List<Float> vector = embeddingService.embed(param.getQueryText(), vectorConfig);
+            if (vector != null && !vector.isEmpty()) {
+                return vector;
+            }
+            log.error("embedding API 向量化失败,文本: {}", param.getQueryText());
+        }
+
+        return null;
+    }
+
+    /**
+     * 根据 configCode 查询向量配置,未找到时返回 null
+     */
+    private DeconstructVectorConfig getVectorConfigByCode(String configCode) {
+        if (!StringUtils.hasText(configCode)) {
+            return null;
+        }
+        try {
+            DeconstructVectorConfigExample example = new DeconstructVectorConfigExample();
+            example.createCriteria().andConfigCodeEqualTo(configCode);
+            List<DeconstructVectorConfig> configs = deconstructVectorConfigMapper.selectByExample(example);
+            if (configs != null && !configs.isEmpty()) {
+                return configs.get(0);
+            }
+            log.warn("未找到 configCode={} 对应的向量配置,将使用默认 embedding 参数", configCode);
+        } catch (Exception e) {
+            log.error("查询向量配置失败,configCode={}, error={}", configCode, e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 通过 text_hash 查询历史 embedding 结果,命中则跳过 embedding API 调用
+     */
+    private List<Float> getVectorByTextHash(String textHash, String configCode) {
+        try {
+            DeconstructContentVectorExample example = new DeconstructContentVectorExample();
+            DeconstructContentVectorExample.Criteria criteria = example.createCriteria()
+                    .andTextHashEqualTo(textHash);
+            if (StringUtils.hasText(configCode)) {
+                criteria.andConfigCodeEqualTo(configCode);
+            }
+            example.setOrderByClause("id DESC");
+            List<DeconstructContentVector> vectors = deconstructContentVectorMapper.selectByExampleWithBLOBs(example);
+            if (vectors == null || vectors.isEmpty()) {
+                return null;
+            }
+            String vectorDataJson = vectors.get(0).getVectorData();
+            if (!StringUtils.hasText(vectorDataJson)) {
+                return null;
+            }
+            return com.alibaba.fastjson.JSON.parseArray(vectorDataJson, Float.class);
+        } catch (Exception e) {
+            log.error("按 text_hash 查询向量失败,hash={}, configCode={}, error={}", textHash, configCode, e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 通过 channelContentId 查询历史向量化结果,有则直接复用,避免重复调用 embedding
+     */
+    private List<Float> getVectorByChannelContentId(String channelContentId, String configCode) {
+        try {
+            // 查询 deconstruct_content
+            DeconstructContent content = getDeconstructContentByChannelContentId(channelContentId);
+            if (content == null || content.getId() == null) {
+                log.info("未找到 channelContentId={} 对应的解构内容", channelContentId);
+                return null;
+            }
+            // 查询 deconstruct_content_vector(按 configCode 过滤)
+            List<DeconstructContentVector> vectors = vectorizeService.getVectorsByContentId(content.getId(), configCode);
+            if (vectors == null || vectors.isEmpty()) {
+                log.info("channelContentId={} 尚无历史向量化结果,contentId={}, configCode={}",
+                        channelContentId, content.getId(), configCode);
+                return null;
+            }
+            // 使用第一条向量数据
+            DeconstructContentVector vector = vectors.get(0);
+            String vectorDataJson = vector.getVectorData();
+            if (!StringUtils.hasText(vectorDataJson)) {
+                return null;
+            }
+            List<Float> vectorData = com.alibaba.fastjson.JSON.parseArray(vectorDataJson, Float.class);
+            log.info("复用历史向量化结果,channelContentId={}, contentId={}, configCode={}, sourceField={}, 向量维度={}",
+                    channelContentId, content.getId(), configCode, vector.getSourceField(),
+                    vectorData != null ? vectorData.size() : 0);
+            return vectorData;
+        } catch (Exception e) {
+            log.error("获取历史向量化结果失败,channelContentId={}, configCode={}, error={}",
+                    channelContentId, configCode, e.getMessage(), e);
+            return null;
+        }
+    }
+
     /**
      * 根据审核状态过滤视频
      * 每批次最多查询20个videoId

+ 2 - 2
core/src/main/resources/generator/mybatis-vector-generator-config.xml

@@ -46,9 +46,9 @@
             <property name="enableSubPackages" value="true"/>
         </javaClientGenerator>
 
-        <table tableName="deconstruct_content" domainObjectName="" alias=""/>
+<!--        <table tableName="deconstruct_content" domainObjectName="" alias=""/>-->
         <table tableName="deconstruct_content_vector" domainObjectName="" alias=""/>
-        <table tableName="deconstruct_vector_config" domainObjectName="" alias=""/>
+<!--        <table tableName="deconstruct_vector_config" domainObjectName="" alias=""/>-->
     </context>
 
 </generatorConfiguration>

+ 62 - 45
core/src/main/resources/mapper/videoVector/deconstruct/DeconstructContentVectorMapper.xml

@@ -5,15 +5,15 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     <id column="id" jdbcType="BIGINT" property="id" />
     <result column="content_id" jdbcType="BIGINT" property="contentId" />
     <result column="task_id" jdbcType="VARCHAR" property="taskId" />
+    <result column="config_code" jdbcType="VARCHAR" property="configCode" />
     <result column="source_field" jdbcType="VARCHAR" property="sourceField" />
     <result column="source_path" jdbcType="VARCHAR" property="sourcePath" />
     <result column="vector_dimension" jdbcType="INTEGER" property="vectorDimension" />
-    <result column="vector_data" jdbcType="CHAR" property="vectorData" />
     <result column="text_hash" jdbcType="VARCHAR" property="textHash" />
     <result column="embedding_model" jdbcType="VARCHAR" property="embeddingModel" />
     <result column="segment_index" jdbcType="INTEGER" property="segmentIndex" />
@@ -25,15 +25,16 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
+    <result column="vector_data" jdbcType="LONGVARCHAR" property="vectorData" />
     <result column="source_text" jdbcType="LONGVARCHAR" property="sourceText" />
   </resultMap>
   <sql id="Example_Where_Clause">
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     <where>
       <foreach collection="oredCriteria" item="criteria" separator="or">
@@ -67,7 +68,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     <where>
       <foreach collection="example.oredCriteria" item="criteria" separator="or">
@@ -101,24 +102,24 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
-    id, content_id, task_id, source_field, source_path, vector_dimension, vector_data, 
+    id, content_id, task_id, config_code, source_field, source_path, vector_dimension, 
     text_hash, embedding_model, segment_index, segment_total, create_time, update_time
   </sql>
   <sql id="Blob_Column_List">
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
-    source_text
+    vector_data, source_text
   </sql>
   <select id="selectByExampleWithBLOBs" parameterType="com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructContentVectorExample" resultMap="ResultMapWithBLOBs">
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     select
     <if test="distinct">
@@ -139,7 +140,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     select
     <if test="distinct">
@@ -158,7 +159,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     select 
     <include refid="Base_Column_List" />
@@ -171,7 +172,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     delete from deconstruct_content_vector
     where id = #{id,jdbcType=BIGINT}
@@ -180,7 +181,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     delete from deconstruct_content_vector
     <if test="_parameter != null">
@@ -191,24 +192,26 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     insert into deconstruct_content_vector (id, content_id, task_id, 
-      source_field, source_path, vector_dimension, 
-      vector_data, text_hash, embedding_model, 
+      config_code, source_field, source_path, 
+      vector_dimension, text_hash, embedding_model, 
       segment_index, segment_total, create_time, 
-      update_time, source_text)
+      update_time, vector_data, source_text
+      )
     values (#{id,jdbcType=BIGINT}, #{contentId,jdbcType=BIGINT}, #{taskId,jdbcType=VARCHAR}, 
-      #{sourceField,jdbcType=VARCHAR}, #{sourcePath,jdbcType=VARCHAR}, #{vectorDimension,jdbcType=INTEGER}, 
-      #{vectorData,jdbcType=CHAR}, #{textHash,jdbcType=VARCHAR}, #{embeddingModel,jdbcType=VARCHAR}, 
+      #{configCode,jdbcType=VARCHAR}, #{sourceField,jdbcType=VARCHAR}, #{sourcePath,jdbcType=VARCHAR}, 
+      #{vectorDimension,jdbcType=INTEGER}, #{textHash,jdbcType=VARCHAR}, #{embeddingModel,jdbcType=VARCHAR}, 
       #{segmentIndex,jdbcType=INTEGER}, #{segmentTotal,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, 
-      #{updateTime,jdbcType=TIMESTAMP}, #{sourceText,jdbcType=LONGVARCHAR})
+      #{updateTime,jdbcType=TIMESTAMP}, #{vectorData,jdbcType=LONGVARCHAR}, #{sourceText,jdbcType=LONGVARCHAR}
+      )
   </insert>
   <insert id="insertSelective" parameterType="com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructContentVector">
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     insert into deconstruct_content_vector
     <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -221,6 +224,9 @@
       <if test="taskId != null">
         task_id,
       </if>
+      <if test="configCode != null">
+        config_code,
+      </if>
       <if test="sourceField != null">
         source_field,
       </if>
@@ -230,9 +236,6 @@
       <if test="vectorDimension != null">
         vector_dimension,
       </if>
-      <if test="vectorData != null">
-        vector_data,
-      </if>
       <if test="textHash != null">
         text_hash,
       </if>
@@ -251,6 +254,9 @@
       <if test="updateTime != null">
         update_time,
       </if>
+      <if test="vectorData != null">
+        vector_data,
+      </if>
       <if test="sourceText != null">
         source_text,
       </if>
@@ -265,6 +271,9 @@
       <if test="taskId != null">
         #{taskId,jdbcType=VARCHAR},
       </if>
+      <if test="configCode != null">
+        #{configCode,jdbcType=VARCHAR},
+      </if>
       <if test="sourceField != null">
         #{sourceField,jdbcType=VARCHAR},
       </if>
@@ -274,9 +283,6 @@
       <if test="vectorDimension != null">
         #{vectorDimension,jdbcType=INTEGER},
       </if>
-      <if test="vectorData != null">
-        #{vectorData,jdbcType=CHAR},
-      </if>
       <if test="textHash != null">
         #{textHash,jdbcType=VARCHAR},
       </if>
@@ -295,6 +301,9 @@
       <if test="updateTime != null">
         #{updateTime,jdbcType=TIMESTAMP},
       </if>
+      <if test="vectorData != null">
+        #{vectorData,jdbcType=LONGVARCHAR},
+      </if>
       <if test="sourceText != null">
         #{sourceText,jdbcType=LONGVARCHAR},
       </if>
@@ -304,7 +313,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     select count(*) from deconstruct_content_vector
     <if test="_parameter != null">
@@ -315,7 +324,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     update deconstruct_content_vector
     <set>
@@ -328,6 +337,9 @@
       <if test="record.taskId != null">
         task_id = #{record.taskId,jdbcType=VARCHAR},
       </if>
+      <if test="record.configCode != null">
+        config_code = #{record.configCode,jdbcType=VARCHAR},
+      </if>
       <if test="record.sourceField != null">
         source_field = #{record.sourceField,jdbcType=VARCHAR},
       </if>
@@ -337,9 +349,6 @@
       <if test="record.vectorDimension != null">
         vector_dimension = #{record.vectorDimension,jdbcType=INTEGER},
       </if>
-      <if test="record.vectorData != null">
-        vector_data = #{record.vectorData,jdbcType=CHAR},
-      </if>
       <if test="record.textHash != null">
         text_hash = #{record.textHash,jdbcType=VARCHAR},
       </if>
@@ -358,6 +367,9 @@
       <if test="record.updateTime != null">
         update_time = #{record.updateTime,jdbcType=TIMESTAMP},
       </if>
+      <if test="record.vectorData != null">
+        vector_data = #{record.vectorData,jdbcType=LONGVARCHAR},
+      </if>
       <if test="record.sourceText != null">
         source_text = #{record.sourceText,jdbcType=LONGVARCHAR},
       </if>
@@ -370,22 +382,23 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     update deconstruct_content_vector
     set id = #{record.id,jdbcType=BIGINT},
       content_id = #{record.contentId,jdbcType=BIGINT},
       task_id = #{record.taskId,jdbcType=VARCHAR},
+      config_code = #{record.configCode,jdbcType=VARCHAR},
       source_field = #{record.sourceField,jdbcType=VARCHAR},
       source_path = #{record.sourcePath,jdbcType=VARCHAR},
       vector_dimension = #{record.vectorDimension,jdbcType=INTEGER},
-      vector_data = #{record.vectorData,jdbcType=CHAR},
       text_hash = #{record.textHash,jdbcType=VARCHAR},
       embedding_model = #{record.embeddingModel,jdbcType=VARCHAR},
       segment_index = #{record.segmentIndex,jdbcType=INTEGER},
       segment_total = #{record.segmentTotal,jdbcType=INTEGER},
       create_time = #{record.createTime,jdbcType=TIMESTAMP},
       update_time = #{record.updateTime,jdbcType=TIMESTAMP},
+      vector_data = #{record.vectorData,jdbcType=LONGVARCHAR},
       source_text = #{record.sourceText,jdbcType=LONGVARCHAR}
     <if test="_parameter != null">
       <include refid="Update_By_Example_Where_Clause" />
@@ -395,16 +408,16 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     update deconstruct_content_vector
     set id = #{record.id,jdbcType=BIGINT},
       content_id = #{record.contentId,jdbcType=BIGINT},
       task_id = #{record.taskId,jdbcType=VARCHAR},
+      config_code = #{record.configCode,jdbcType=VARCHAR},
       source_field = #{record.sourceField,jdbcType=VARCHAR},
       source_path = #{record.sourcePath,jdbcType=VARCHAR},
       vector_dimension = #{record.vectorDimension,jdbcType=INTEGER},
-      vector_data = #{record.vectorData,jdbcType=CHAR},
       text_hash = #{record.textHash,jdbcType=VARCHAR},
       embedding_model = #{record.embeddingModel,jdbcType=VARCHAR},
       segment_index = #{record.segmentIndex,jdbcType=INTEGER},
@@ -419,7 +432,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     update deconstruct_content_vector
     <set>
@@ -429,6 +442,9 @@
       <if test="taskId != null">
         task_id = #{taskId,jdbcType=VARCHAR},
       </if>
+      <if test="configCode != null">
+        config_code = #{configCode,jdbcType=VARCHAR},
+      </if>
       <if test="sourceField != null">
         source_field = #{sourceField,jdbcType=VARCHAR},
       </if>
@@ -438,9 +454,6 @@
       <if test="vectorDimension != null">
         vector_dimension = #{vectorDimension,jdbcType=INTEGER},
       </if>
-      <if test="vectorData != null">
-        vector_data = #{vectorData,jdbcType=CHAR},
-      </if>
       <if test="textHash != null">
         text_hash = #{textHash,jdbcType=VARCHAR},
       </if>
@@ -459,6 +472,9 @@
       <if test="updateTime != null">
         update_time = #{updateTime,jdbcType=TIMESTAMP},
       </if>
+      <if test="vectorData != null">
+        vector_data = #{vectorData,jdbcType=LONGVARCHAR},
+      </if>
       <if test="sourceText != null">
         source_text = #{sourceText,jdbcType=LONGVARCHAR},
       </if>
@@ -469,21 +485,22 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     update deconstruct_content_vector
     set content_id = #{contentId,jdbcType=BIGINT},
       task_id = #{taskId,jdbcType=VARCHAR},
+      config_code = #{configCode,jdbcType=VARCHAR},
       source_field = #{sourceField,jdbcType=VARCHAR},
       source_path = #{sourcePath,jdbcType=VARCHAR},
       vector_dimension = #{vectorDimension,jdbcType=INTEGER},
-      vector_data = #{vectorData,jdbcType=CHAR},
       text_hash = #{textHash,jdbcType=VARCHAR},
       embedding_model = #{embeddingModel,jdbcType=VARCHAR},
       segment_index = #{segmentIndex,jdbcType=INTEGER},
       segment_total = #{segmentTotal,jdbcType=INTEGER},
       create_time = #{createTime,jdbcType=TIMESTAMP},
       update_time = #{updateTime,jdbcType=TIMESTAMP},
+      vector_data = #{vectorData,jdbcType=LONGVARCHAR},
       source_text = #{sourceText,jdbcType=LONGVARCHAR}
     where id = #{id,jdbcType=BIGINT}
   </update>
@@ -491,15 +508,15 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 15:03:47 CST 2026.
     -->
     update deconstruct_content_vector
     set content_id = #{contentId,jdbcType=BIGINT},
       task_id = #{taskId,jdbcType=VARCHAR},
+      config_code = #{configCode,jdbcType=VARCHAR},
       source_field = #{sourceField,jdbcType=VARCHAR},
       source_path = #{sourcePath,jdbcType=VARCHAR},
       vector_dimension = #{vectorDimension,jdbcType=INTEGER},
-      vector_data = #{vectorData,jdbcType=CHAR},
       text_hash = #{textHash,jdbcType=VARCHAR},
       embedding_model = #{embeddingModel,jdbcType=VARCHAR},
       segment_index = #{segmentIndex,jdbcType=INTEGER},

+ 53 - 23
core/src/main/resources/mapper/videoVector/deconstruct/DeconstructVectorConfigMapper.xml

@@ -5,7 +5,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     <id column="id" jdbcType="BIGINT" property="id" />
     <result column="config_code" jdbcType="VARCHAR" property="configCode" />
@@ -16,6 +16,7 @@
     <result column="source_path" jdbcType="VARCHAR" property="sourcePath" />
     <result column="extract_rule" jdbcType="VARCHAR" property="extractRule" />
     <result column="embedding_model" jdbcType="VARCHAR" property="embeddingModel" />
+    <result column="dimension" jdbcType="INTEGER" property="dimension" />
     <result column="max_length" jdbcType="INTEGER" property="maxLength" />
     <result column="enable_segment" jdbcType="TINYINT" property="enableSegment" />
     <result column="segment_size" jdbcType="INTEGER" property="segmentSize" />
@@ -28,7 +29,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     <where>
       <foreach collection="oredCriteria" item="criteria" separator="or">
@@ -62,7 +63,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     <where>
       <foreach collection="example.oredCriteria" item="criteria" separator="or">
@@ -96,17 +97,17 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     id, config_code, config_name, biz_type, content_type, source_field, source_path, 
-    extract_rule, embedding_model, max_length, enable_segment, segment_size, priority, 
-    enabled, create_time, update_time
+    extract_rule, embedding_model, dimension, max_length, enable_segment, segment_size, 
+    priority, enabled, create_time, update_time
   </sql>
   <select id="selectByExample" parameterType="com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructVectorConfigExample" resultMap="BaseResultMap">
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     select
     <if test="distinct">
@@ -125,7 +126,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     select 
     <include refid="Base_Column_List" />
@@ -136,7 +137,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     delete from deconstruct_vector_config
     where id = #{id,jdbcType=BIGINT}
@@ -145,7 +146,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     delete from deconstruct_vector_config
     <if test="_parameter != null">
@@ -156,26 +157,26 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     insert into deconstruct_vector_config (id, config_code, config_name, 
       biz_type, content_type, source_field, 
       source_path, extract_rule, embedding_model, 
-      max_length, enable_segment, segment_size, 
-      priority, enabled, create_time, 
-      update_time)
+      dimension, max_length, enable_segment, 
+      segment_size, priority, enabled, 
+      create_time, update_time)
     values (#{id,jdbcType=BIGINT}, #{configCode,jdbcType=VARCHAR}, #{configName,jdbcType=VARCHAR}, 
       #{bizType,jdbcType=TINYINT}, #{contentType,jdbcType=TINYINT}, #{sourceField,jdbcType=VARCHAR}, 
       #{sourcePath,jdbcType=VARCHAR}, #{extractRule,jdbcType=VARCHAR}, #{embeddingModel,jdbcType=VARCHAR}, 
-      #{maxLength,jdbcType=INTEGER}, #{enableSegment,jdbcType=TINYINT}, #{segmentSize,jdbcType=INTEGER}, 
-      #{priority,jdbcType=INTEGER}, #{enabled,jdbcType=TINYINT}, #{createTime,jdbcType=TIMESTAMP}, 
-      #{updateTime,jdbcType=TIMESTAMP})
+      #{dimension,jdbcType=INTEGER}, #{maxLength,jdbcType=INTEGER}, #{enableSegment,jdbcType=TINYINT}, 
+      #{segmentSize,jdbcType=INTEGER}, #{priority,jdbcType=INTEGER}, #{enabled,jdbcType=TINYINT}, 
+      #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP})
   </insert>
   <insert id="insertSelective" parameterType="com.tzld.videoVector.model.po.videoVector.deconstruct.DeconstructVectorConfig">
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     insert into deconstruct_vector_config
     <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -206,6 +207,9 @@
       <if test="embeddingModel != null">
         embedding_model,
       </if>
+      <if test="dimension != null">
+        dimension,
+      </if>
       <if test="maxLength != null">
         max_length,
       </if>
@@ -256,6 +260,9 @@
       <if test="embeddingModel != null">
         #{embeddingModel,jdbcType=VARCHAR},
       </if>
+      <if test="dimension != null">
+        #{dimension,jdbcType=INTEGER},
+      </if>
       <if test="maxLength != null">
         #{maxLength,jdbcType=INTEGER},
       </if>
@@ -283,7 +290,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     select count(*) from deconstruct_vector_config
     <if test="_parameter != null">
@@ -294,7 +301,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     update deconstruct_vector_config
     <set>
@@ -325,6 +332,9 @@
       <if test="record.embeddingModel != null">
         embedding_model = #{record.embeddingModel,jdbcType=VARCHAR},
       </if>
+      <if test="record.dimension != null">
+        dimension = #{record.dimension,jdbcType=INTEGER},
+      </if>
       <if test="record.maxLength != null">
         max_length = #{record.maxLength,jdbcType=INTEGER},
       </if>
@@ -355,7 +365,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     update deconstruct_vector_config
     set id = #{record.id,jdbcType=BIGINT},
@@ -367,6 +377,7 @@
       source_path = #{record.sourcePath,jdbcType=VARCHAR},
       extract_rule = #{record.extractRule,jdbcType=VARCHAR},
       embedding_model = #{record.embeddingModel,jdbcType=VARCHAR},
+      dimension = #{record.dimension,jdbcType=INTEGER},
       max_length = #{record.maxLength,jdbcType=INTEGER},
       enable_segment = #{record.enableSegment,jdbcType=TINYINT},
       segment_size = #{record.segmentSize,jdbcType=INTEGER},
@@ -382,7 +393,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     update deconstruct_vector_config
     <set>
@@ -410,6 +421,9 @@
       <if test="embeddingModel != null">
         embedding_model = #{embeddingModel,jdbcType=VARCHAR},
       </if>
+      <if test="dimension != null">
+        dimension = #{dimension,jdbcType=INTEGER},
+      </if>
       <if test="maxLength != null">
         max_length = #{maxLength,jdbcType=INTEGER},
       </if>
@@ -438,7 +452,7 @@
     <!--
       WARNING - @mbg.generated
       This element is automatically generated by MyBatis Generator, do not modify.
-      This element was generated on Mon Mar 09 10:39:51 CST 2026.
+      This element was generated on Thu Apr 23 14:55:06 CST 2026.
     -->
     update deconstruct_vector_config
     set config_code = #{configCode,jdbcType=VARCHAR},
@@ -449,6 +463,7 @@
       source_path = #{sourcePath,jdbcType=VARCHAR},
       extract_rule = #{extractRule,jdbcType=VARCHAR},
       embedding_model = #{embeddingModel,jdbcType=VARCHAR},
+      dimension = #{dimension,jdbcType=INTEGER},
       max_length = #{maxLength,jdbcType=INTEGER},
       enable_segment = #{enableSegment,jdbcType=TINYINT},
       segment_size = #{segmentSize,jdbcType=INTEGER},
@@ -458,4 +473,19 @@
       update_time = #{updateTime,jdbcType=TIMESTAMP}
     where id = #{id,jdbcType=BIGINT}
   </update>
+
+  <!-- 按业务类型和内容类型匹配向量配置:参数为 null 时不过滤,非 null 时匹配字段为 null(通用)或等于指定値的配置 -->
+  <select id="selectMatchingConfigs" resultMap="BaseResultMap">
+    SELECT
+    <include refid="Base_Column_List" />
+    FROM deconstruct_vector_config
+    WHERE enabled = 1
+    <if test="bizType != null">
+      AND (biz_type IS NULL OR biz_type = #{bizType,jdbcType=TINYINT})
+    </if>
+    <if test="contentType != null">
+      AND (content_type IS NULL OR content_type = #{contentType,jdbcType=TINYINT})
+    </if>
+    ORDER BY priority ASC
+  </select>
 </mapper>

+ 0 - 8
server/src/main/resources/application.yml

@@ -99,11 +99,3 @@ cdn:
   upload:
     domain: https://weappupload.piaoquantv.com/
 
-embedding:
-  dimension: 2560    # 向量维度
-  ngram: 2          # N-gram 大小
-  mode: api         # 向量化模式:local(本地N-gram哈希) 或 api(远程API)
-  api:
-    url: http://192.168.100.31:8000/v1/embeddings  # 向量化API地址
-    model: /models/Qwen3-Embedding-4B            # 模型路径
-    timeout: 60                                    # 超时时间(秒)

+ 23 - 0
server/src/test/java/EmbeddingTest.java

@@ -0,0 +1,23 @@
+import com.tzld.videoVector.Application;
+import com.tzld.videoVector.api.DashScopeEmbeddingApiService;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.List;
+
+
+@SpringBootTest(classes = Application.class)
+@Slf4j
+public class EmbeddingTest {
+    @Autowired
+    private DashScopeEmbeddingApiService dashScopeEmbeddingApiService;
+
+    @Test
+    public void testDashScopeEmbedding() {
+        String text = "通过分享富婆频繁倒垃圾的异常行为社会奇闻,利用华丽制服形象与廉价堆积式垃圾的视觉反差,配合震惊体标题和高饱和度大字报,构建警察进门后的叙事悬疑,吸引用户点击并探索故事真相。";
+        List<Float> vector = dashScopeEmbeddingApiService.embed(text, "qwen3-vl-embedding", 1024);
+        log.info("Vector: {}", vector);
+    }
+}