wangyunpeng 2 days ago
parent
commit
d2b79886c6

+ 3 - 3
core/src/main/java/com/tzld/videoVector/api/AigcApiService.java

@@ -147,18 +147,18 @@ public class AigcApiService {
                 }
                 JSONArray dataArray = res.getJSONArray("data");
                 if (dataArray == null || dataArray.isEmpty()) {
-                    log.warn("任务回调详情 data 为空,taskInstanceId: {}", taskInstanceId);
+                    log.info("任务回调详情 data 为空,taskInstanceId: {}", taskInstanceId);
                     return null;
                 }
                 // 取第一条记录
                 JSONObject data = dataArray.getJSONObject(0);
                 if (data == null) {
-                    log.warn("任务回调详情 data[0] 为空,taskInstanceId: {}", taskInstanceId);
+                    log.info("任务回调详情 data[0] 为空,taskInstanceId: {}", taskInstanceId);
                     return null;
                 }
                 String dataContent = data.getString("dataContent");
                 if (dataContent == null || dataContent.trim().isEmpty()) {
-                    log.warn("taskInstanceId: {} 的 dataContent 为空", taskInstanceId);
+                    log.info("taskInstanceId: {} 的 dataContent 为空", taskInstanceId);
                     return null;
                 }
                 return JSON.parseObject(dataContent);

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

@@ -54,7 +54,7 @@ public class DashScopeEmbeddingApiService {
      */
     public List<Float> embed(String text, String model, Integer dimension) {
         if (text == null || text.trim().isEmpty()) {
-            log.warn("输入文本为空,返回空向量");
+            log.info("输入文本为空,返回空向量");
             return Collections.emptyList();
         }
 

+ 1 - 1
core/src/main/java/com/tzld/videoVector/api/EmbeddingApiService.java

@@ -53,7 +53,7 @@ public class EmbeddingApiService {
      */
     public List<Float> embed(String text) {
         if (text == null || text.trim().isEmpty()) {
-            log.warn("输入文本为空,返回空向量");
+            log.info("输入文本为空,返回空向量");
             return Collections.emptyList();
         }
 

+ 2 - 2
core/src/main/java/com/tzld/videoVector/job/ChannelDemandMatchJob.java

@@ -83,7 +83,7 @@ public class ChannelDemandMatchJob {
             // 2. 读取所有启用的渠道配置
             List<ChannelDemandMatchConfig> configs = getEnabledConfigs();
             if (CollectionUtils.isEmpty(configs)) {
-                log.warn("未找到启用的渠道需求匹配配置");
+                log.info("未找到启用的渠道需求匹配配置");
                 return ReturnT.SUCCESS;
             }
             log.info("加载 {} 个渠道配置", configs.size());
@@ -201,7 +201,7 @@ public class ChannelDemandMatchJob {
         executor.shutdown();
         try {
             if (!executor.awaitTermination(30, TimeUnit.MINUTES)) {
-                log.warn("渠道 {} 匹配任务超时,强制终止", channelName);
+                log.error("渠道 {} 匹配任务超时,强制终止", channelName);
                 executor.shutdownNow();
             }
         } catch (InterruptedException e) {

+ 0 - 439
core/src/main/java/com/tzld/videoVector/job/DataMigrationJob.java

@@ -1,439 +0,0 @@
-package com.tzld.videoVector.job;
-
-import com.tzld.videoVector.common.constant.VectorConstants;
-import com.tzld.videoVector.dao.mapper.pgVector.ext.ContentVectorMapperExt;
-import com.tzld.videoVector.dao.mapper.pgVector.DeconstructContentMapper;
-import com.tzld.videoVector.dao.mapper.pgVector.DeconstructVectorConfigMapper;
-import com.tzld.videoVector.dao.mapper.pgVector.ext.VideoVectorMapperExt;
-import com.tzld.videoVector.dao.mapper.videoVector.deconstruct.MysqlDeconstructContentVectorMapper;
-import com.tzld.videoVector.dao.mapper.videoVector.deconstruct.MysqlDeconstructContentMapper;
-import com.tzld.videoVector.dao.mapper.videoVector.deconstruct.MysqlDeconstructVectorConfigMapper;
-import com.tzld.videoVector.model.po.pgVector.DeconstructContent;
-import com.tzld.videoVector.model.po.pgVector.DeconstructVectorConfig;
-import com.tzld.videoVector.model.po.pgVector.DeconstructVectorConfigExample;
-import com.tzld.videoVector.model.po.videoVector.deconstruct.*;
-import com.xxl.job.core.biz.model.ReturnT;
-import com.xxl.job.core.handler.annotation.XxlJob;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
-
-import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * 数据迁移任务
- * 1. MySQL deconstruct_content / deconstruct_vector_config → PG
- * 2. MySQL deconstruct_content_vector → PG content_vectors
- * 3. Redis 视频向量缓存 → PG video_vectors
- */
-@Slf4j
-@Component
-public class DataMigrationJob {
-
-    // ==================== MySQL 数据源 Mapper ====================
-    @Resource
-    private MysqlDeconstructContentMapper mysqlContentMapper;
-
-    @Resource
-    private MysqlDeconstructVectorConfigMapper mysqlConfigMapper;
-
-    @Resource
-    private MysqlDeconstructContentVectorMapper mysqlContentVectorMapper;
-
-    // ==================== PG 数据源 Mapper ====================
-    @Resource
-    private DeconstructContentMapper deconstructContentMapper;
-
-    @Resource
-    private DeconstructVectorConfigMapper deconstructVectorConfigMapper;
-
-    @Resource
-    private ContentVectorMapperExt contentVectorMapperExt;
-
-    @Resource
-    private VideoVectorMapperExt videoVectorMapperExt;
-
-    // ==================== Redis ====================
-    @Resource
-    private RedisTemplate<String, Object> redisTemplate;
-
-    // 向量值是纯 JSON 字符串,没有 Jackson 类型信息,需用 StringRedisTemplate 读取
-    @Resource
-    private StringRedisTemplate stringRedisTemplate;
-
-    // ==================== 迁移批次大小 ====================
-    private static final int BATCH_SIZE = 200;
-
-    /**
-     * MySQL deconstruct_content 表迁移到 PG
-     */
-    @XxlJob("migrateContentToPgJob")
-    public ReturnT<String> migrateContentToPgJob(String param) {
-        log.info("开始迁移 deconstruct_content 数据到 PG, param: {}", param);
-
-        try {
-            // 从 MySQL 分页读取
-            MysqlDeconstructContentExample example =
-                    new MysqlDeconstructContentExample();
-            example.setOrderByClause("id ASC");
-            List<MysqlDeconstructContent> allRecords =
-                    mysqlContentMapper.selectByExampleWithBLOBs(example);
-
-            if (CollectionUtils.isEmpty(allRecords)) {
-                log.info("MySQL deconstruct_content 无数据,跳过");
-                return ReturnT.SUCCESS;
-            }
-
-            log.info("查询到 {} 条 deconstruct_content 记录待迁移", allRecords.size());
-
-            int successCount = 0;
-            int skipCount = 0;
-            int failCount = 0;
-
-            for (MysqlDeconstructContent mysql : allRecords) {
-                try {
-                    // 转换为 PG 实体
-                    DeconstructContent pg = convertContent(mysql);
-                    // 插入 PG(使用 insertSelective 避免主键冲突时可手动处理)
-                    deconstructContentMapper.insertSelective(pg);
-                    successCount++;
-                } catch (Exception e) {
-                    if (e.getMessage() != null && e.getMessage().contains("duplicate key")) {
-                        skipCount++;
-                    } else {
-                        failCount++;
-                        log.error("迁移 content id={} 失败: {}", mysql.getId(), e.getMessage());
-                    }
-                }
-            }
-
-            log.info("deconstruct_content 迁移完成,成功: {}, 跳过(已存在): {}, 失败: {}",
-                    successCount, skipCount, failCount);
-            return ReturnT.SUCCESS;
-        } catch (Exception e) {
-            log.error("deconstruct_content 迁移失败: {}", e.getMessage(), e);
-            return new ReturnT<>(ReturnT.FAIL_CODE, "迁移失败: " + e.getMessage());
-        }
-    }
-
-    /**
-     * MySQL deconstruct_vector_config 表迁移到 PG
-     */
-    @XxlJob("migrateVectorConfigToPgJob")
-    public ReturnT<String> migrateVectorConfigToPgJob(String param) {
-        log.info("开始迁移 deconstruct_vector_config 数据到 PG, param: {}", param);
-
-        try {
-            MysqlDeconstructVectorConfigExample example =
-                    new MysqlDeconstructVectorConfigExample();
-            example.setOrderByClause("id ASC");
-            List<MysqlDeconstructVectorConfig> allRecords =
-                    mysqlConfigMapper.selectByExample(example);
-
-            if (CollectionUtils.isEmpty(allRecords)) {
-                log.info("MySQL deconstruct_vector_config 无数据,跳过");
-                return ReturnT.SUCCESS;
-            }
-
-            log.info("查询到 {} 条 deconstruct_vector_config 记录待迁移", allRecords.size());
-
-            int successCount = 0;
-            int skipCount = 0;
-            int failCount = 0;
-
-            for (MysqlDeconstructVectorConfig mysql : allRecords) {
-                try {
-                    DeconstructVectorConfig pg = convertVectorConfig(mysql);
-                    deconstructVectorConfigMapper.insertSelective(pg);
-                    successCount++;
-                } catch (Exception e) {
-                    if (e.getMessage() != null && e.getMessage().contains("duplicate key")) {
-                        skipCount++;
-                    } else {
-                        failCount++;
-                        log.error("迁移 vector_config id={} 失败: {}", mysql.getId(), e.getMessage());
-                    }
-                }
-            }
-
-            log.info("deconstruct_vector_config 迁移完成,成功: {}, 跳过(已存在): {}, 失败: {}",
-                    successCount, skipCount, failCount);
-            return ReturnT.SUCCESS;
-        } catch (Exception e) {
-            log.error("deconstruct_vector_config 迁移失败: {}", e.getMessage(), e);
-            return new ReturnT<>(ReturnT.FAIL_CODE, "迁移失败: " + e.getMessage());
-        }
-    }
-
-    /**
-     * MySQL deconstruct_content_vector 表迁移到 PG content_vectors
-     * 将 vector_data(JSON 数组)转为 pgvector embedding
-     */
-    @XxlJob("migrateContentVectorToPgJob")
-    public ReturnT<String> migrateContentVectorToPgJob(String param) {
-        log.info("开始迁移 deconstruct_content_vector 数据到 PG content_vectors, param: {}", param);
-
-        try {
-            MysqlDeconstructContentVectorExample example = new MysqlDeconstructContentVectorExample();
-            example.setOrderByClause("id ASC");
-            List<MysqlDeconstructContentVector> allRecords = mysqlContentVectorMapper.selectByExampleWithBLOBs(example);
-
-            if (CollectionUtils.isEmpty(allRecords)) {
-                log.info("MySQL deconstruct_content_vector 无数据,跳过");
-                return ReturnT.SUCCESS;
-            }
-
-            log.info("查询到 {} 条 deconstruct_content_vector 记录待迁移", allRecords.size());
-
-            int successCount = 0;
-            int skipCount = 0;
-            int failCount = 0;
-
-            for (MysqlDeconstructContentVector mysql : allRecords) {
-                try {
-                    String vectorData = mysql.getVectorData();
-                    if (!StringUtils.hasText(vectorData)) {
-                        log.info("content_vector id={} vectorData 为空,跳过", mysql.getId());
-                        skipCount++;
-                        continue;
-                    }
-
-                    // vectorData 是 JSON 数组格式 "[0.1,0.2,...]",pgvector 接受此格式
-                    contentVectorMapperExt.upsertWithEmbedding(
-                            mysql.getContentId(),
-                            mysql.getTaskId(),
-                            mysql.getConfigCode(),
-                            mysql.getSourceField(),
-                            mysql.getSourcePath(),
-                            mysql.getTextHash(),
-                            mysql.getEmbeddingModel(),
-                            mysql.getSegmentIndex(),
-                            mysql.getSegmentTotal(),
-                            mysql.getSourceText(),
-                            vectorData
-                    );
-                    successCount++;
-                } catch (Exception e) {
-                    if (e.getMessage() != null && e.getMessage().contains("duplicate key")) {
-                        skipCount++;
-                    } else {
-                        failCount++;
-                        log.error("迁移 content_vector id={} 失败: {}", mysql.getId(), e.getMessage());
-                    }
-                }
-            }
-
-            log.info("deconstruct_content_vector → content_vectors 迁移完成,成功: {}, 跳过: {}, 失败: {}",
-                    successCount, skipCount, failCount);
-            return ReturnT.SUCCESS;
-        } catch (Exception e) {
-            log.error("content_vector 迁移失败: {}", e.getMessage(), e);
-            return new ReturnT<>(ReturnT.FAIL_CODE, "迁移失败: " + e.getMessage());
-        }
-    }
-
-    /**
-     * Redis 视频向量缓存迁移到 PG video_vectors
-     * Redis 存储结构:
-     *   Key: video:vector:{configCode}:{videoId}  Value: JSON 数组字符串
-     *   Key: video:vector:{configCode}:ids        类型: Set(存储所有 videoId)
-     */
-    @XxlJob("migrateRedisVectorToPgJob")
-    public ReturnT<String> migrateRedisVectorToPgJob(String param) {
-        log.info("开始迁移 Redis 视频向量缓存到 PG video_vectors, param: {}", param);
-
-        try {
-            // 1. 获取所有启用的配置编码
-            List<String> configCodes = getAllConfigCodes();
-            if (configCodes.isEmpty()) {
-                log.warn("未获取到任何配置编码");
-                return ReturnT.SUCCESS;
-            }
-            log.info("待迁移的配置编码: {}", configCodes);
-
-            int totalSuccess = 0;
-            int totalSkip = 0;
-            int totalFail = 0;
-
-            // 2. 逐个配置迁移
-            for (String configCode : configCodes) {
-                int[] counts = migrateRedisVectorsForConfig(configCode);
-                totalSuccess += counts[0];
-                totalSkip += counts[1];
-                totalFail += counts[2];
-            }
-
-            log.info("Redis 视频向量迁移完成,总成功: {}, 总跳过: {}, 总失败: {}",
-                    totalSuccess, totalSkip, totalFail);
-            return ReturnT.SUCCESS;
-        } catch (Exception e) {
-            log.error("Redis 向量迁移失败: {}", e.getMessage(), e);
-            return new ReturnT<>(ReturnT.FAIL_CODE, "迁移失败: " + e.getMessage());
-        }
-    }
-
-    /**
-     * 迁移单个 configCode 下的 Redis 向量到 PG
-     *
-     * @return int[]{成功数, 跳过数, 失败数}
-     */
-    private int[] migrateRedisVectorsForConfig(String configCode) {
-        log.info("开始迁移配置 {} 的向量数据", configCode);
-
-        String idsKey = VectorConstants.VECTOR_KEY_PREFIX + configCode + ":ids";
-        Set<Object> idMembers = redisTemplate.opsForSet().members(idsKey);
-
-        if (idMembers == null || idMembers.isEmpty()) {
-            log.info("配置 {} 在 Redis 中无 videoId 索引,跳过", configCode);
-            return new int[]{0, 0, 0};
-        }
-
-        log.info("配置 {} 共有 {} 个 videoId 待迁移", configCode, idMembers.size());
-
-        List<String> idList = new ArrayList<>();
-        for (Object member : idMembers) {
-            idList.add(String.valueOf(member));
-        }
-
-        int success = 0, skip = 0, fail = 0;
-
-        for (int i = 0; i < idList.size(); i += BATCH_SIZE) {
-            int end = Math.min(i + BATCH_SIZE, idList.size());
-            List<String> batch = idList.subList(i, end);
-
-            for (String idStr : batch) {
-                int result = migrateSingleRedisVector(configCode, idStr);
-                if (result == 1) success++;
-                else if (result == 0) skip++;
-                else fail++;
-            }
-
-            log.info("配置 {} 进度: {}/{}", configCode, end, idList.size());
-        }
-
-        return new int[]{success, skip, fail};
-    }
-
-    /**
-     * 迁移单个 videoId 的 Redis 向量到 PG
-     *
-     * @return 1=成功, 0=跳过, -1=失败
-     */
-    private int migrateSingleRedisVector(String configCode, String idStr) {
-        try {
-            Long videoId = Long.parseLong(idStr);
-            String vectorKey = VectorConstants.VECTOR_KEY_PREFIX + configCode + ":" + videoId;
-            String vectorJson = stringRedisTemplate.opsForValue().get(vectorKey);
-
-            if (!StringUtils.hasText(vectorJson)) {
-                return 0;
-            }
-
-            videoVectorMapperExt.upsertVector(videoId, configCode, 0, vectorJson, null, null);
-            return 1;
-        } catch (NumberFormatException e) {
-            log.warn("非法 videoId: {}", idStr);
-            return 0;
-        } catch (Exception e) {
-            if (e.getMessage() != null && e.getMessage().contains("duplicate key")) {
-                return 0;
-            }
-            log.error("迁移 Redis 向量失败,configCode={}, videoId={}, error={}",
-                    configCode, idStr, e.getMessage());
-            return -1;
-        }
-    }
-
-    // ==================== 工具方法 ====================
-
-    /**
-     * 获取所有非多点模式的配置编码(从 PG 查询 + 默认编码)
-     * 多点模式(extract_rule 非空)的数据不迁移,由 Job 重新生成
-     */
-    private List<String> getAllConfigCodes() {
-        Set<String> codes = new LinkedHashSet<>();
-        codes.add(VectorConstants.DEFAULT_CONFIG_CODE);
-
-        try {
-            DeconstructVectorConfigExample example = new DeconstructVectorConfigExample();
-            example.createCriteria().andEnabledEqualTo((short) 1);
-            List<DeconstructVectorConfig> configs = deconstructVectorConfigMapper.selectByExample(example);
-            if (configs != null) {
-                for (DeconstructVectorConfig config : configs) {
-                    if (StringUtils.hasText(config.getConfigCode())
-                            && !StringUtils.hasText(config.getExtractRule())) {
-                        // 仅迁移非多点模式(extract_rule 为空)的配置
-                        codes.add(config.getConfigCode());
-                    } else if (StringUtils.hasText(config.getExtractRule())) {
-                        log.info("跳过多点模式配置: {}(extract_rule 非空,由 Job 重新生成)", config.getConfigCode());
-                    }
-                }
-            }
-        } catch (Exception e) {
-            log.error("获取配置编码失败: {}", e.getMessage());
-        }
-
-        return new ArrayList<>(codes);
-    }
-
-    /**
-     * MySQL DeconstructContent → PG DeconstructContent 实体转换
-     * 主要差异:Byte → Short
-     */
-    private DeconstructContent convertContent(
-            MysqlDeconstructContent mysql) {
-        DeconstructContent pg = new DeconstructContent();
-        // 不设置 id,让 PG 自增生成
-        pg.setTaskId(mysql.getTaskId());
-        pg.setBizType(mysql.getBizType() != null ? mysql.getBizType().shortValue() : null);
-        pg.setContentType(mysql.getContentType() != null ? mysql.getContentType().shortValue() : null);
-        pg.setChannelContentId(mysql.getChannelContentId());
-        pg.setTitle(mysql.getTitle());
-        pg.setBodyText(mysql.getBodyText());
-        pg.setVideoUrl(mysql.getVideoUrl());
-        pg.setImages(mysql.getImages());
-        pg.setChannelAccountId(mysql.getChannelAccountId());
-        pg.setChannelAccountName(mysql.getChannelAccountName());
-        pg.setStatus(mysql.getStatus() != null ? mysql.getStatus().shortValue() : null);
-        pg.setResultJson(mysql.getResultJson());
-        pg.setFailureReason(mysql.getFailureReason());
-        pg.setPointUrl(mysql.getPointUrl());
-        pg.setWeightUrl(mysql.getWeightUrl());
-        pg.setPatternUrl(mysql.getPatternUrl());
-        pg.setCreateTime(mysql.getCreateTime());
-        pg.setUpdateTime(mysql.getUpdateTime());
-        return pg;
-    }
-
-    /**
-     * MySQL DeconstructVectorConfig → PG DeconstructVectorConfig 实体转换
-     */
-    private DeconstructVectorConfig convertVectorConfig(
-            MysqlDeconstructVectorConfig mysql) {
-        DeconstructVectorConfig pg = new DeconstructVectorConfig();
-        pg.setConfigCode(mysql.getConfigCode());
-        pg.setConfigName(mysql.getConfigName());
-        pg.setBizType(mysql.getBizType() != null ? mysql.getBizType().shortValue() : null);
-        pg.setContentType(mysql.getContentType() != null ? mysql.getContentType().shortValue() : null);
-        pg.setSourceField(mysql.getSourceField());
-        pg.setSourcePath(mysql.getSourcePath());
-        pg.setExtractRule(mysql.getExtractRule());
-        pg.setEmbeddingModel(mysql.getEmbeddingModel());
-        pg.setDimension(mysql.getDimension());
-        pg.setMaxLength(mysql.getMaxLength());
-        pg.setEnableSegment(mysql.getEnableSegment() != null ? mysql.getEnableSegment().shortValue() : null);
-        pg.setSegmentSize(mysql.getSegmentSize());
-        pg.setPriority(mysql.getPriority());
-        pg.setEnabled(mysql.getEnabled() != null ? mysql.getEnabled().shortValue() : null);
-        pg.setCreateTime(mysql.getCreateTime());
-        pg.setUpdateTime(mysql.getUpdateTime());
-        return pg;
-    }
-}

+ 3 - 3
core/src/main/java/com/tzld/videoVector/job/MaterialDeconstructCheckJob.java

@@ -121,13 +121,13 @@ public class MaterialDeconstructCheckJob {
         try {
             String taskId = content.getTaskId();
             if (!StringUtils.hasText(taskId)) {
-                log.warn("contentId={} 的 taskId 为空,跳过", content.getId());
+                log.info("contentId={} 的 taskId 为空,跳过", content.getId());
                 return 0;
             }
 
             DeconstructResult result = deconstructService.getDeconstructResult(taskId);
             if (result == null) {
-                log.warn("查询解构结果返回空,taskId={}", taskId);
+                log.info("查询解构结果返回空,taskId={}", taskId);
                 return 0;
             }
 
@@ -154,7 +154,7 @@ public class MaterialDeconstructCheckJob {
             if (newStatus == 2) {
                 return 1;
             } else if (newStatus == 3) {
-                log.warn("解构失败,contentId={}, taskId={}, reason={}",
+                log.error("解构失败,contentId={}, taskId={}, reason={}",
                         content.getId(), taskId, result.getReason());
                 return -1;
             }

+ 2 - 2
core/src/main/java/com/tzld/videoVector/job/VideoTitleVectorJob.java

@@ -157,7 +157,7 @@ public class VideoTitleVectorJob {
         // 批量获取视频详情
         Map<Long, VideoDetail> detailMap = videoApiService.getVideoDetail(new HashSet<>(videoIds));
         if (detailMap == null || detailMap.isEmpty()) {
-            log.warn("批量获取视频详情返回空,videoIds数量: {}", videoIds.size());
+            log.error("批量获取视频详情返回空,videoIds数量: {}", videoIds.size());
             totalSkip.addAndGet(videoIds.size());
             return;
         }
@@ -190,7 +190,7 @@ public class VideoTitleVectorJob {
                 // 优先通过 text_hash 复用已有 embedding
                 List<Float> vector = getOrEmbed(title, config);
                 if (vector == null || vector.isEmpty()) {
-                    log.warn("videoId={} 标题向量化失败,title={}", videoId, title);
+                    log.error("videoId={} 标题向量化失败,title={}", videoId, title);
                     totalFail.incrementAndGet();
                     continue;
                 }

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

@@ -98,7 +98,7 @@ public class VideoVectorJob {
             // 1. 获取 result_json 来源的向量化配置
             List<DeconstructVectorConfig> configs = getEnabledConfigsBySourceField("result_json");
             if (CollectionUtils.isEmpty(configs)) {
-                log.warn("未找到启用的向量化配置");
+                log.info("未找到启用的向量化配置");
                 return ReturnT.SUCCESS;
             }
             log.info("加载 {} 个向量化配置", configs.size());
@@ -337,7 +337,7 @@ public class VideoVectorJob {
             double confidenceThreshold = rule.getDoubleValue("confidence_threshold");
 
             if (!StringUtils.hasText(textField) || !StringUtils.hasText(confidenceField)) {
-                log.warn("extract_rule 缺少必要字段: text_field={}, confidence_field={}", textField, confidenceField);
+                log.error("extract_rule 缺少必要字段: text_field={}, confidence_field={}", textField, confidenceField);
                 return texts;
             }
 
@@ -456,7 +456,7 @@ public class VideoVectorJob {
                 // 优先通过 text_hash 复用已有 embedding,避免重复调用 API
                 List<Float> vector = getOrEmbed(text, config);
                 if (vector == null || vector.isEmpty()) {
-                    log.warn("videoId={} 配置 {} 第{}个文本向量化失败", videoId, configCode, i);
+                    log.error("videoId={} 配置 {} 第{}个文本向量化失败", videoId, configCode, i);
                     continue;
                 }
                 vectorStoreService.save(configCode, videoId, i, vector, text);
@@ -483,7 +483,7 @@ public class VideoVectorJob {
             // 优先通过 text_hash 复用已有 embedding,避免重复调用 API
             List<Float> vector = getOrEmbed(text, config);
             if (vector == null || vector.isEmpty()) {
-                log.warn("videoId={} 配置 {} 文本向量化失败", videoId, configCode);
+                log.error("videoId={} 配置 {} 文本向量化失败", videoId, configCode);
                 return 0;
             }
             vectorStoreService.save(configCode, videoId, vector, text);
@@ -540,7 +540,7 @@ public class VideoVectorJob {
             // 1. 获取 aigc_deconstruct 专用的向量化配置
             List<DeconstructVectorConfig> configs = getEnabledConfigsBySourceField("aigc_deconstruct");
             if (CollectionUtils.isEmpty(configs)) {
-                log.warn("未找到 aigc_deconstruct 来源的向量化配置");
+                log.info("未找到 aigc_deconstruct 来源的向量化配置");
                 return ReturnT.SUCCESS;
             }
 
@@ -757,7 +757,7 @@ public class VideoVectorJob {
                         DeconstructResult result = deconstructService.getDeconstructResult(taskId);
 
                         if (result == null) {
-                            log.warn("重试解构任务失败,API返回空,taskId={}", taskId);
+                            log.error("重试解构任务失败,API返回空,taskId={}", taskId);
                             updateContentStatus(content, (byte) 3, "API返回空");
                             failCount.incrementAndGet();
                             return;
@@ -780,7 +780,7 @@ public class VideoVectorJob {
                                 // 失败
                                 updateContentStatus(content, (short) 3, result.getReason());
                                 failCount.incrementAndGet();
-                                log.warn("重试解构任务失败,taskId={}, reason={}", taskId, result.getReason());
+                                log.error("重试解构任务失败,taskId={}, reason={}", taskId, result.getReason());
                             }
                         } else {
                             // 仍在处理中,更新状态
@@ -906,7 +906,7 @@ public class VideoVectorJob {
             // 1. 获取 source_field = 'result_log' 的启用配置
             List<DeconstructVectorConfig> configs = getEnabledConfigsBySourceField("result_log");
             if (CollectionUtils.isEmpty(configs)) {
-                log.warn("未找到 result_log 来源的向量化配置");
+                log.info("未找到 result_log 来源的向量化配置");
                 return ReturnT.SUCCESS;
             }
             log.info("加载 {} 个 result_log 向量化配置", configs.size());
@@ -1117,7 +1117,7 @@ public class VideoVectorJob {
         }
 
         if (hasFailure) {
-            log.warn("聚合视频向量化任务完成,部分子任务失败: {}", failMessages);
+            log.error("聚合视频向量化任务完成,部分子任务失败: {}", failMessages);
             return new ReturnT<>(ReturnT.FAIL_CODE, "部分子任务失败: " + failMessages);
         }
 
@@ -1300,7 +1300,7 @@ public class VideoVectorJob {
                             batch.add(r);
                         }
                     } catch (Exception e) {
-                        log.warn("同步 aigc videoId={} 失败: {}", videoId, e.getMessage());
+                        log.error("同步 aigc videoId={} 失败: {}", videoId, e.getMessage());
                     }
                 }));
             }

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

@@ -56,7 +56,7 @@ public class EmbeddingServiceImpl implements EmbeddingService {
     @Override
     public List<Float> embed(String text, DeconstructVectorConfig config) {
         if (text == null || text.trim().isEmpty()) {
-            log.warn("输入文本为空,返回空向量");
+            log.info("输入文本为空,返回空向量");
             return Collections.emptyList();
         }
 
@@ -77,7 +77,7 @@ public class EmbeddingServiceImpl implements EmbeddingService {
                     }
                 }
             } catch (Exception e) {
-                log.warn("读取 embedding 缓存失败,key={},继续调用 API", cacheKey, e);
+                log.info("读取 embedding 缓存失败,key={},继续调用 API", cacheKey, e);
             }
         }
 
@@ -98,7 +98,7 @@ public class EmbeddingServiceImpl implements EmbeddingService {
                 redisUtils.set(cacheKey, JSON.toJSONString(vector), cacheExpireSeconds);
                 log.info("embedding 结果已缓存,key={}, 维度={}", cacheKey, vector.size());
             } catch (Exception e) {
-                log.warn("写入 embedding 缓存失败,key={}", cacheKey, e);
+                log.info("写入 embedding 缓存失败,key={}", cacheKey, e);
             }
         }
 

+ 4 - 4
core/src/main/java/com/tzld/videoVector/service/impl/MaterialSearchServiceImpl.java

@@ -183,14 +183,14 @@ public class MaterialSearchServiceImpl implements MaterialSearchService {
         if (ALL_CONFIG_CODE.equalsIgnoreCase(configCode)) {
             searchConfigs = getEnabledConfigs();
             if (searchConfigs.isEmpty()) {
-                log.warn("素材搜索:未找到任何启用的向量化配置");
+                log.info("素材搜索:未找到任何启用的向量化配置");
                 return Collections.emptyList();
             }
             log.info("素材搜索 ALL 模式,加载 {} 个配置", searchConfigs.size());
         } else {
             DeconstructVectorConfig singleConfig = getVectorConfigByCode(configCode);
             if (singleConfig == null) {
-                log.warn("素材搜索:未找到 configCode={} 的配置", configCode);
+                log.info("素材搜索:未找到 configCode={} 的配置", configCode);
                 return Collections.emptyList();
             }
             searchConfigs = Collections.singletonList(singleConfig);
@@ -206,7 +206,7 @@ public class MaterialSearchServiceImpl implements MaterialSearchService {
                 // 解析查询向量
                 List<Float> queryVector = resolveQueryVector(param, config, embeddingCache);
                 if (queryVector == null || queryVector.isEmpty()) {
-                    log.warn("配置 {} 无法获取查询向量,跳过", cfgCode);
+                    log.error("配置 {} 无法获取查询向量,跳过", cfgCode);
                     continue;
                 }
 
@@ -317,7 +317,7 @@ public class MaterialSearchServiceImpl implements MaterialSearchService {
                 embeddingCache.put(cacheKey, vector);
                 return vector;
             }
-            log.warn("配置 {} embedding 失败", config.getConfigCode());
+            log.error("配置 {} embedding 失败", config.getConfigCode());
         }
 
         return null;

+ 1 - 1
core/src/main/java/com/tzld/videoVector/service/impl/PgVectorStoreServiceImpl.java

@@ -49,7 +49,7 @@ public class PgVectorStoreServiceImpl implements VectorStoreService {
     @Override
     public void save(String configCode, Long videoId, int pointIndex, List<Float> vector, String text) {
         if (videoId == null || vector == null || vector.isEmpty()) {
-            log.warn("save 参数非法,configCode={}, videoId={}", configCode, videoId);
+            log.error("save 参数非法,configCode={}, videoId={}", configCode, videoId);
             return;
         }
         if (configCode == null || configCode.isEmpty()) {

+ 1 - 1
core/src/main/java/com/tzld/videoVector/service/impl/RedisVectorStoreServiceImpl.java

@@ -73,7 +73,7 @@ public class RedisVectorStoreServiceImpl implements VectorStoreService {
     @Override
     public void save(String configCode, Long videoId, int pointIndex, List<Float> vector, String text) {
         if (videoId == null || vector == null || vector.isEmpty()) {
-            log.warn("save 参数非法,configCode={}, videoId={}", configCode, videoId);
+            log.error("save 参数非法,configCode={}, videoId={}", configCode, videoId);
             return;
         }
         if (configCode == null || configCode.isEmpty()) {

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

@@ -60,7 +60,7 @@ public class VectorizeServiceImpl implements VectorizeService {
         );
 
         if (CollectionUtils.isEmpty(configs)) {
-            log.warn("未找到向量化配置,bizType={}, contentType={}",
+            log.info("未找到向量化配置,bizType={}, contentType={}",
                     content.getBizType(), content.getContentType());
             return new ArrayList<>();
         }
@@ -130,7 +130,7 @@ public class VectorizeServiceImpl implements VectorizeService {
                 // 未命中缓存,调用 embedding API
                 vectorData = embeddingService.embed(truncatedText, config);
                 if (CollectionUtils.isEmpty(vectorData)) {
-                    log.warn("向量化失败,text={}", truncatedText.substring(0, Math.min(50, truncatedText.length())));
+                    log.error("向量化失败,text={}", truncatedText.substring(0, Math.min(50, truncatedText.length())));
                     continue;
                 }
             }

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

@@ -508,7 +508,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
             try {
                 jsonResult.put("result", JSONObject.parseObject(content.getResultJson()));
             } catch (Exception e) {
-                log.warn("buildResultFromContent parseJson failed, taskId={}, resultJson={}",
+                log.error("buildResultFromContent parseJson failed, taskId={}, resultJson={}",
                         content.getTaskId(), content.getResultJson(), e);
                 jsonResult.put("result", content.getResultJson());
             }
@@ -552,7 +552,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
             try {
                 jsonResult.put("result", JSONObject.parseObject(result.getResult()));
             } catch (Exception e) {
-                log.warn("buildResultFromApiResult parseJson failed, taskId={}, result={}",
+                log.error("buildResultFromApiResult parseJson failed, taskId={}, result={}",
                         result.getTaskId(), result.getResult(), e);
                 jsonResult.put("result", result.getResult());
             }
@@ -615,7 +615,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
         if (VectorConstants.ALL_CONFIG_CODE.equalsIgnoreCase(configCode)) {
             searchConfigs = getEnabledConfigs();
             if (searchConfigs.isEmpty()) {
-                log.warn("未找到任何启用的向量化配置");
+                log.info("未找到任何启用的向量化配置");
                 return Collections.emptyList();
             }
             log.info("all 模式,加载 {} 个启用的向量化配置", searchConfigs.size());
@@ -626,7 +626,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
                     : Collections.emptyList();
             // 兼容:如果查不到配置记录,仍按原始逻辑用 configCode 搜索(不做多点解码)
             if (searchConfigs.isEmpty()) {
-                log.warn("未找到 configCode={} 的配置记录,降级为原始搜索", configCode);
+                log.info("未找到 configCode={} 的配置记录,降级为原始搜索", configCode);
                 return matchTopNVideoLegacy(param, configCode, topN);
             }
         }
@@ -644,7 +644,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
                 // 解析查询向量(按配置的 embeddingModel 分组缓存)
                 List<Float> queryVector = resolveQueryVectorForConfig(param, config, embeddingCache);
                 if (queryVector == null || queryVector.isEmpty()) {
-                    log.warn("配置 {} 无法获取查询向量,跳过", cfgCode);
+                    log.error("配置 {} 无法获取查询向量,跳过", cfgCode);
                     continue;
                 }
 
@@ -766,7 +766,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
                 embeddingCache.put(cacheKey, vector);
                 return vector;
             }
-            log.warn("配置 {} embedding 失败", config.getConfigCode());
+            log.error("配置 {} embedding 失败", config.getConfigCode());
             return null;
         }
 
@@ -871,7 +871,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
             if (configs != null && !configs.isEmpty()) {
                 return configs.get(0);
             }
-            log.warn("未找到 configCode={} 对应的向量配置,将使用默认 embedding 参数", configCode);
+            log.info("未找到 configCode={} 对应的向量配置,将使用默认 embedding 参数", configCode);
         } catch (Exception e) {
             log.error("查询向量配置失败,configCode={}, error={}", configCode, e.getMessage(), e);
         }
@@ -1444,7 +1444,7 @@ public class VideoSearchServiceImpl implements VideoSearchService {
             }
             return Double.parseDouble(rovObj.toString());
         } catch (NumberFormatException e) {
-            log.warn("extractRov 解析失败, rovObj={}", rovObj);
+            log.info("extractRov 解析失败, rovObj={}", rovObj);
             return 0.0;
         }
     }

+ 3 - 3
core/src/main/java/com/tzld/videoVector/service/recall/impl/VectorRecallTestServiceImpl.java

@@ -96,7 +96,7 @@ public class VectorRecallTestServiceImpl implements VectorRecallTestService {
     public RecallResultVO matchByText(MatchByTextParam param) {
         RecallResultVO empty = emptyResult();
         if (param == null || !StringUtils.hasText(param.getQueryText())) {
-            log.warn("matchByText: queryText 为空");
+            log.info("matchByText: queryText 为空");
             return empty;
         }
 
@@ -214,7 +214,7 @@ public class VectorRecallTestServiceImpl implements VectorRecallTestService {
             vo.setVideoNarration(null);
             return vo;
         } catch (Exception e) {
-            log.warn("getAiUnderstanding: redis read/parse failed, videoId={}, err={}",
+            log.error("getAiUnderstanding: redis read/parse failed, videoId={}, err={}",
                     videoId, e.getMessage());
             return null;
         }
@@ -396,7 +396,7 @@ public class VectorRecallTestServiceImpl implements VectorRecallTestService {
             }
             return result;
         } catch (Exception e) {
-            log.warn("parseImages fail, json={}, err={}", imagesJson, e.getMessage());
+            log.info("parseImages fail, json={}, err={}", imagesJson, e.getMessage());
             return Collections.emptyList();
         }
     }

+ 2 - 2
core/src/main/java/com/tzld/videoVector/util/AliOssFileTool.java

@@ -668,7 +668,7 @@ public class AliOssFileTool extends AliOssConfig {
                 if (file != null) {
                     stream = new ByteArrayInputStream(file);
                 } else {
-                    logger.warn("图片上传有误");
+                    logger.error("图片上传有误");
                     return null;
                 }
             } catch (Exception e) {
@@ -1500,7 +1500,7 @@ public class AliOssFileTool extends AliOssConfig {
             }
             byte[] fileData = HttpUtil.downloadBytes(url);
             if (fileData == null || fileData.length == 0) {
-                log.warn("downloadAndSaveInOSS 下载media失败,URL: {}", url);
+                log.error("downloadAndSaveInOSS 下载media失败,URL: {}", url);
                 return null;
             }
             InputStream inputStream = new ByteArrayInputStream(fileData);

+ 0 - 73
server/src/test/java/DataMigrationTest.java

@@ -1,73 +0,0 @@
-import com.tzld.videoVector.Application;
-import com.tzld.videoVector.job.DataMigrationJob;
-import com.xxl.job.core.biz.model.ReturnT;
-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;
-
-@SpringBootTest(classes = Application.class)
-@Slf4j
-public class DataMigrationTest {
-
-    @Autowired
-    private DataMigrationJob dataMigrationJob;
-
-    /**
-     * 迁移 deconstruct_vector_config(建议最先执行)
-     */
-    @Test
-    public void testMigrateVectorConfig() {
-        ReturnT<String> result = dataMigrationJob.migrateVectorConfigToPgJob("");
-        log.info("migrateVectorConfigToPgJob 结果: code={}", result.getCode());
-    }
-
-    /**
-     * 迁移 deconstruct_content
-     */
-    @Test
-    public void testMigrateContent() {
-        ReturnT<String> result = dataMigrationJob.migrateContentToPgJob("");
-        log.info("migrateContentToPgJob 结果: code={}", result.getCode());
-    }
-
-    /**
-     * 迁移 deconstruct_content_vector → content_vectors
-     */
-    @Test
-    public void testMigrateContentVector() {
-        ReturnT<String> result = dataMigrationJob.migrateContentVectorToPgJob("");
-        log.info("migrateContentVectorToPgJob 结果: code={}", result.getCode());
-    }
-
-    /**
-     * 迁移 Redis 视频向量 → video_vectors(跳过多点模式)
-     */
-    @Test
-    public void testMigrateRedisVector() {
-        ReturnT<String> result = dataMigrationJob.migrateRedisVectorToPgJob("");
-        log.info("migrateRedisVectorToPgJob 结果: code={}", result.getCode());
-    }
-
-    /**
-     * 一键执行全部迁移(按依赖顺序)
-     */
-    @Test
-    public void testMigrateAll() {
-        log.info("===== 开始全量数据迁移 =====");
-
-        log.info("--- 1. 迁移向量化配置 ---");
-        dataMigrationJob.migrateVectorConfigToPgJob("");
-
-        log.info("--- 2. 迁移解构内容 ---");
-        dataMigrationJob.migrateContentToPgJob("");
-
-        log.info("--- 3. 迁移素材向量 ---");
-        dataMigrationJob.migrateContentVectorToPgJob("");
-
-        log.info("--- 4. 迁移Redis视频向量 ---");
-        dataMigrationJob.migrateRedisVectorToPgJob("");
-
-        log.info("===== 全量数据迁移完成 =====");
-    }
-}