Jelajahi Sumber

利用AI审核违规内容定时任务

Lhaibo 2 minggu lalu
induk
melakukan
06b86b745c

+ 8 - 0
alien-entity/src/main/java/shop/alien/entity/store/LifeUserDynamics.java

@@ -129,4 +129,12 @@ public class LifeUserDynamics {
     @ApiModelProperty(value = "达人动态实际浏览数")
     @TableField("reality_count")
     private Integer realityCount;
+
+    @ApiModelProperty(value = "是否审核(未审核:0,审核中:1,审核完成:2)")
+    @TableField("check_flag")
+    private Integer checkFlag;
+
+    @ApiModelProperty(value = "AI审核结果查询id")
+    @TableField("ai_task_id")
+    private Integer aiTaskId;
 }

+ 128 - 10
alien-job/src/main/java/shop/alien/job/store/AiTagJob.java

@@ -2,6 +2,10 @@ package shop.alien.job.store;
 
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.xxl.job.core.context.XxlJobHelper;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
@@ -14,19 +18,14 @@ import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.StoreCommentSummary;
-import shop.alien.entity.store.StoreCommentSummaryInterest;
-import shop.alien.entity.store.TagsMain;
-import shop.alien.entity.store.TagsSynonym;
-import shop.alien.mapper.StoreCommentSummaryInterestMapper;
-import shop.alien.mapper.StoreCommentSummaryMapper;
-import shop.alien.mapper.TagsMainMapper;
-import shop.alien.mapper.TagsSynonymMapper;
+import shop.alien.entity.store.*;
+import shop.alien.mapper.*;
 
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+
+import static com.alipay.api.internal.util.AlipayUtils.getFileSuffix;
 
 /**
  * 调用AI标签数据服务类
@@ -39,6 +38,8 @@ import java.util.List;
 @RequiredArgsConstructor
 public class AiTagJob {
 
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
     private final RestTemplate restTemplate;
 
     private final TagsMainMapper tagsMainMapper;
@@ -49,6 +50,8 @@ public class AiTagJob {
 
     private final StoreCommentSummaryInterestMapper storeCommentSummaryInterestMapper;
 
+    private final LifeUserDynamicsMapper lifeUserDynamicsMapper;
+
     // 第三方接口地址 获取所有标签主表信息
     @Value("${third-party-tag.base-url}")
     private String tagMainUrl;
@@ -73,6 +76,10 @@ public class AiTagJob {
     @Value("${third-party-savetag.base-url}")
     private String saveTagUrl;
 
+    // 第三方接口地址 内容合规检测接口
+    @Value("${third-party-content-check.base-url:http://192.168.2.250:9000/ai/auto-review/api/v1/content_compliance/check}")
+    private String contentComplianceUrl;
+
     //用户名
     @Value("${third-party-user-name.base-url}")
     private String userName;
@@ -567,6 +574,117 @@ public class AiTagJob {
         return R.success("任务执行失败 状态码" + responseEntity.getStatusCodeValue());
     }
 
+    /**
+     * 利用AI审核违规内容
+     */
+    @XxlJob("contentComplianceCheckTask")
+    public R<String> contentComplianceCheckTask() {
+        List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
+                .eq(LifeUserDynamics::getCheckFlag, 0).eq(LifeUserDynamics::getDeleteFlag, 0));
+
+        // 常见图片后缀(可按需添加,如 .heic、.svg 等)
+        HashSet<String> IMAGE_SUFFIXES = new HashSet<>(Arrays.asList(
+                ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".heic", ".svg", ".tiff"
+        ));
+        // 常见视频后缀(可按需添加,如 .avi、.flv 等)
+        HashSet<String> VIDEO_SUFFIXES = new HashSet<>(Arrays.asList(
+                ".mp4", ".mov", ".mkv", ".avi", ".flv", ".wmv", ".mpeg", ".mpg", ".webm"
+        ));
+
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            String imagePath = lifeUserDynamic.getImagePath();
+
+            List<String> imageList = new ArrayList<>();
+            List<String> videoList = new ArrayList<>();
+            // 按分隔符拆分路径数组(处理连续分隔符如 ",," 产生的空字符串)
+            String[] allPaths = imagePath.split(imagePath);
+            for (String path : allPaths) {
+                // 去除路径前后空格(避免 " a.jpg " 这类情况)
+                String trimmedPath = path.trim();
+                if (trimmedPath.isEmpty()) {
+                    continue; // 跳过空路径
+                }
+                // 获取文件后缀(忽略大小写)
+                // 找到最后一个 "." 的位置
+                int lastDotIndex = trimmedPath.lastIndexOf('.');
+                // 截取后缀(从 "." 后一位到结尾)
+                String suffix = trimmedPath.substring(lastDotIndex + 1);
+                // 分类添加到对应列表
+                if (IMAGE_SUFFIXES.contains(suffix)) {
+                    imageList.add(trimmedPath);
+                } else if (VIDEO_SUFFIXES.contains(suffix)) {
+                    videoList.add(trimmedPath);
+                }
+                try {
+                    log.info("登录Ai服务获取token..." + loginUrl);
+                    MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+                    formData.add("username", userName);
+                    formData.add("password", passWord);
+
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+                    HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+                    ResponseEntity<String> postForEntity = null;
+                    try {
+                        log.info("请求Ai服务登录接口===================>");
+                        postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+                    } catch (Exception e) {
+                        log.error("请求AI服务登录接口失败", e);
+                    }
+
+                    if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
+                        log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+                        String responseBody = postForEntity.getBody();
+                        JSONObject jsonObject = JSONObject.parseObject(responseBody);
+                        if (jsonObject != null) {
+                            JSONObject dataJson = jsonObject.getJSONObject("data");
+                            String accessToken = dataJson.getString("access_token");
+
+                            HttpHeaders aiHeaders = new HttpHeaders();
+                            aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+                            aiHeaders.set("Authorization", "Bearer " + accessToken);
+
+                            Map<String, Object> jsonBody = new HashMap<>();
+                            jsonBody.put("text", lifeUserDynamic.getContext());
+                            jsonBody.put("imgUrl", imageList);
+                            jsonBody.put("video", videoList);
+
+                            HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
+                            ResponseEntity<String> response = null;
+                            try {
+                                response = restTemplate.postForEntity(contentComplianceUrl, request, String.class);
+                                if (response.getStatusCodeValue() != 200) {
+                                    log.error("AI内容审核接口调用失败 http状态:" + response.getStatusCode());
+                                }
+                                JsonNode responseNode = OBJECT_MAPPER.readTree(response.getBody());
+                                int code = responseNode.has("code") ? responseNode.get("code").asInt() : 0;
+                                if (code != 200) {
+                                    throw new RuntimeException("AI接口调用失败" + code);
+                                }
+                                JsonNode dataNode = responseNode.get("data");
+
+                                if (dataNode.has("is_compliant")) {
+                                    LifeUserDynamics dynamics = new LifeUserDynamics();
+                                    dynamics.setId(lifeUserDynamic.getId());
+                                    dynamics.setCheckFlag(1);
+                                    lifeUserDynamicsMapper.updateById(dynamics);
+                                }
+                                log.info("动态审核成功,AI返回内容: {}", response.getBody());
+                                XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
+                            } catch (Exception e) {
+                                log.error("调用AI内容审核接口失败", e);
+                            }
+                        }
+                    }
+                } catch (RuntimeException ex) {
+                    XxlJobHelper.handleFail("动态内容审核任务执行失败:" + ex.getMessage());
+                    return R.fail("动态内容审核任务执行失败:" + ex.getMessage());
+                }
+            }
+        }
+        return R.success("动态内容审核任务执行成功");
+    }
+
     class AnalysisRequest {
         private String start_time;
         private String end_time;