Browse Source

增加文本审核plus

glx_phase2
glx 1 week ago
parent
commit
3b7760051e
  1. 2
      pom.xml
  2. 4
      src/main/java/com/youlai/boot/admin/model/entity/MiniContentAudit.java
  3. 18
      src/main/java/com/youlai/boot/admin/model/entity/MiniContentAuditTask.java
  4. 2
      src/main/java/com/youlai/boot/admin/model/form/AuditConfigForm.java
  5. 4
      src/main/java/com/youlai/boot/admin/service/AuditExecutorService.java
  6. 4
      src/main/java/com/youlai/boot/admin/service/ContentAuditService.java
  7. 18
      src/main/java/com/youlai/boot/admin/service/impl/AuditExecutorServiceImpl.java
  8. 4
      src/main/java/com/youlai/boot/admin/service/impl/ContentAuditServiceImpl.java
  9. 37
      src/main/java/com/youlai/boot/common/util/AliyunContentAuditUtil.java
  10. 4
      src/main/java/com/youlai/boot/mini/model/entity/MiniContentAuditAppeal.java
  11. 4
      src/main/java/com/youlai/boot/mini/model/entity/MiniReport.java
  12. 20
      src/main/java/com/youlai/boot/mini/service/impl/UserPostServiceImpl.java
  13. 5
      src/main/resources/application-dev.yml

2
pom.xml

@ -73,7 +73,7 @@
<javacv.platform.version>1.5.13</javacv.platform.version> <javacv.platform.version>1.5.13</javacv.platform.version>
<!-- 阿里内容审核 --> <!-- 阿里内容审核 -->
<aliyun.green20220302.version>2.20.0</aliyun.green20220302.version> <aliyun.green20220302.version>3.3.3</aliyun.green20220302.version>
<!-- 阿里fastjson --> <!-- 阿里fastjson -->
<alibaba.fastjson.version>2.0.56</alibaba.fastjson.version> <alibaba.fastjson.version>2.0.56</alibaba.fastjson.version>

4
src/main/java/com/youlai/boot/admin/model/entity/MiniContentAudit.java

@ -33,8 +33,8 @@ public class MiniContentAudit implements Serializable {
private String moduleCode; private String moduleCode;
@TableField("biz_id") @TableField("biz_id")
@Schema(description = "业务数据ID(日记ID或评论ID)") @Schema(description = "业务数据主键ID(日记ID或评论ID)")
private String bizId; private Long bizId;
@TableField("audit_type") @TableField("audit_type")
@Schema(description = "审核类型(从config快照)") @Schema(description = "审核类型(从config快照)")

18
src/main/java/com/youlai/boot/admin/model/entity/MiniContentAuditTask.java

@ -49,9 +49,25 @@ public class MiniContentAuditTask implements Serializable {
private String status; private String status;
@TableField("risk_level") @TableField("risk_level")
@Schema(description = "风险等级: none无 / medium中 / high高") @Schema(description = "机审风险等级: none无 / medium中 / high高")
private String riskLevel; private String riskLevel;
@TableField("label")
@Schema(description = "机审标签")
private String label;
@TableField("confidence")
@Schema(description = "机审信任度")
private Integer confidence;
@TableField("description")
@Schema(description = "机审描述")
private String description;
@TableField("request_id")
@Schema(description = "机审请求ID")
private String requestId;
@TableField("machine_result") @TableField("machine_result")
@Schema(description = "机审结果JSON") @Schema(description = "机审结果JSON")
private String machineResult; private String machineResult;

2
src/main/java/com/youlai/boot/admin/model/form/AuditConfigForm.java

@ -22,7 +22,7 @@ public class AuditConfigForm {
@Schema(description = "审核类型: machine / manual / mixed") @Schema(description = "审核类型: machine / manual / mixed")
private String auditType; private String auditType;
@Schema(description = "机器审核风险策略: none / medium / high") @Schema(description = "机器审核风险策略: 机审风险策略:auto--none转passed,medium转failed, high转failed;normal--none转passed,medium转to_manual, high转failed;cautious--none转passed,medium转to_manual, high转to_manual;")
private String riskStrategy; private String riskStrategy;
} }

4
src/main/java/com/youlai/boot/admin/service/AuditExecutorService.java

@ -11,10 +11,10 @@ public interface AuditExecutorService {
* *
* @param moduleCode 业务模块: animal_note / adoption_diary / user_post / *_comment / user_avatar / user_nickname / user_introduction * @param moduleCode 业务模块: animal_note / adoption_diary / user_post / *_comment / user_avatar / user_nickname / user_introduction
* @param bizId 业务数据ID * @param bizId 业务数据ID
* @param content 待审核内容 {text, images[], video} * @param content 待审核内容 {text[], images[], video[]}
* @return {status: "passed"|"failed"|"manual_review", auditId: Long}配置关闭或无配置时返回null * @return {status: "passed"|"failed"|"manual_review", auditId: Long}配置关闭或无配置时返回null
*/ */
Map<String, Object> executeAudit(String moduleCode, String bizId, AuditContentDTO content); Map<String, Object> executeAudit(String moduleCode, Long bizId, AuditContentDTO content);
/** /**
* 轮询所有待处理的视频审核异步结果更新任务和汇总状态 * 轮询所有待处理的视频审核异步结果更新任务和汇总状态

4
src/main/java/com/youlai/boot/admin/service/ContentAuditService.java

@ -5,10 +5,10 @@ import com.youlai.boot.admin.model.entity.MiniContentAudit;
public interface ContentAuditService extends IService<MiniContentAudit> { public interface ContentAuditService extends IService<MiniContentAudit> {
MiniContentAudit createAudit(String moduleCode, String bizId, String auditType); MiniContentAudit createAudit(String moduleCode, Long bizId, String auditType);
void updateAuditStatus(Long auditId, String status, String finalResult); void updateAuditStatus(Long auditId, String status, String finalResult);
MiniContentAudit getByModuleAndBizId(String moduleCode, String bizId); MiniContentAudit getByModuleAndBizId(String moduleCode, Long bizId);
} }

18
src/main/java/com/youlai/boot/admin/service/impl/AuditExecutorServiceImpl.java

@ -2,10 +2,7 @@ package com.youlai.boot.admin.service.impl;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.aliyun.green20220302.models.ImageModerationResponse; import com.aliyun.green20220302.models.*;
import com.aliyun.green20220302.models.TextModerationResponse;
import com.aliyun.green20220302.models.VideoModerationResponse;
import com.aliyun.green20220302.models.VideoModerationResultResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.youlai.boot.admin.constant.AuditConstants; import com.youlai.boot.admin.constant.AuditConstants;
import com.youlai.boot.admin.model.dto.AuditContentDTO; import com.youlai.boot.admin.model.dto.AuditContentDTO;
@ -46,7 +43,7 @@ public class AuditExecutorServiceImpl implements AuditExecutorService {
* @return {status, auditId}配置关闭或无配置时返回 null调用方以此判断是否跳过审核 * @return {status, auditId}配置关闭或无配置时返回 null调用方以此判断是否跳过审核
*/ */
@Override @Override
public Map<String, Object> executeAudit(String moduleCode, String bizId, AuditContentDTO content) { public Map<String, Object> executeAudit(String moduleCode, Long bizId, AuditContentDTO content) {
// 1) 查询对应模块的审核配置 // 1) 查询对应模块的审核配置
MiniContentAuditConfig config = findAuditConfig(moduleCode); MiniContentAuditConfig config = findAuditConfig(moduleCode);
if (config == null || isAuditDisabled(config)) { if (config == null || isAuditDisabled(config)) {
@ -124,7 +121,7 @@ public class AuditExecutorServiceImpl implements AuditExecutorService {
switch (contentType) { switch (contentType) {
case "text" -> { case "text" -> {
TextModerationResponse r = aliyunContentAuditUtil.textModeration(contentValue); TextModerationPlusResponse r = aliyunContentAuditUtil.textModerationPlus(contentValue);
String riskLevel = extractRiskLevelFromResponse(r); String riskLevel = extractRiskLevelFromResponse(r);
contentAuditTaskService.updateTaskMachineResult( contentAuditTaskService.updateTaskMachineResult(
task.getId(), JSON.toJSONString(r), riskLevel, null, null); task.getId(), JSON.toJSONString(r), riskLevel, null, null);
@ -192,7 +189,7 @@ public class AuditExecutorServiceImpl implements AuditExecutorService {
* 文本审核同步 * 文本审核同步
*/ */
private void handleTextAudit(MiniContentAuditTask task, String textContent, String strictness) { private void handleTextAudit(MiniContentAuditTask task, String textContent, String strictness) {
TextModerationResponse response = aliyunContentAuditUtil.textModeration(textContent); TextModerationPlusResponse response = aliyunContentAuditUtil.textModerationPlus(textContent);
String riskLevel = extractRiskLevelFromResponse(response); String riskLevel = extractRiskLevelFromResponse(response);
String machineResultJson = JSON.toJSONString(response); String machineResultJson = JSON.toJSONString(response);
applyAuditResultToTask(task, riskLevel, machineResultJson, strictness); applyAuditResultToTask(task, riskLevel, machineResultJson, strictness);
@ -248,6 +245,9 @@ public class AuditExecutorServiceImpl implements AuditExecutorService {
*/ */
private void applyAuditResultToTask(MiniContentAuditTask task, String riskLevel, String machineResultJson, String strictness) { private void applyAuditResultToTask(MiniContentAuditTask task, String riskLevel, String machineResultJson, String strictness) {
if (riskLevel == null) { if (riskLevel == null) {
log.warn("机审riskLevel为null, 转人工处理, taskId={}", task.getId());
contentAuditTaskService.updateTaskMachineResult(
task.getId(), machineResultJson, null, null, AuditConstants.TASK_TO_MANUAL);
return; return;
} }
@ -255,7 +255,7 @@ public class AuditExecutorServiceImpl implements AuditExecutorService {
String result = applyStrategy(riskLevel, strictness); String result = applyStrategy(riskLevel, strictness);
// 2. result 决定任务最终状态 // 2. result 决定任务最终状态
String taskStatus = AuditConstants.TASK_SUCCESS.equals(result) String taskStatus = AuditConstants.RESULT_PASSED.equals(result)
? AuditConstants.TASK_SUCCESS : AuditConstants.TASK_TO_MANUAL; ? AuditConstants.TASK_SUCCESS : AuditConstants.TASK_TO_MANUAL;
// 回填任务表:machine_result(JSON) / risk_level / result / status // 回填任务表:machine_result(JSON) / risk_level / result / status
@ -522,7 +522,7 @@ public class AuditExecutorServiceImpl implements AuditExecutorService {
} }
String result = applyStrategy(riskLevel, strictness); String result = applyStrategy(riskLevel, strictness);
String taskStatus = AuditConstants.TASK_SUCCESS.equals(result) String taskStatus = AuditConstants.RESULT_PASSED.equals(result)
? AuditConstants.TASK_SUCCESS : AuditConstants.TASK_TO_MANUAL; ? AuditConstants.TASK_SUCCESS : AuditConstants.TASK_TO_MANUAL;
contentAuditTaskService.updateTaskMachineResult( contentAuditTaskService.updateTaskMachineResult(

4
src/main/java/com/youlai/boot/admin/service/impl/ContentAuditServiceImpl.java

@ -16,7 +16,7 @@ import java.util.Date;
public class ContentAuditServiceImpl extends ServiceImpl<MiniContentAuditMapper, MiniContentAudit> implements ContentAuditService { public class ContentAuditServiceImpl extends ServiceImpl<MiniContentAuditMapper, MiniContentAudit> implements ContentAuditService {
@Override @Override
public MiniContentAudit createAudit(String moduleCode, String bizId, String auditType) { public MiniContentAudit createAudit(String moduleCode, Long bizId, String auditType) {
MiniContentAudit entity = new MiniContentAudit(); MiniContentAudit entity = new MiniContentAudit();
entity.setUuid(IdUtil.fastSimpleUUID()); entity.setUuid(IdUtil.fastSimpleUUID());
entity.setModuleCode(moduleCode); entity.setModuleCode(moduleCode);
@ -43,7 +43,7 @@ public class ContentAuditServiceImpl extends ServiceImpl<MiniContentAuditMapper,
} }
@Override @Override
public MiniContentAudit getByModuleAndBizId(String moduleCode, String bizId) { public MiniContentAudit getByModuleAndBizId(String moduleCode, Long bizId) {
return this.getOne(new LambdaQueryWrapper<MiniContentAudit>() return this.getOne(new LambdaQueryWrapper<MiniContentAudit>()
.eq(MiniContentAudit::getModuleCode, moduleCode) .eq(MiniContentAudit::getModuleCode, moduleCode)
.eq(MiniContentAudit::getBizId, bizId)); .eq(MiniContentAudit::getBizId, bizId));

37
src/main/java/com/youlai/boot/common/util/AliyunContentAuditUtil.java

@ -100,29 +100,55 @@ public class AliyunContentAuditUtil {
} }
// ===================== 文本审核 ===================== // ===================== 文本审核 =====================
//
public TextModerationResponse textModeration(String content) { public TextModerationResponse textModeration(String content) {
return executeWithFailover(client -> { return executeWithFailover(client -> {
JSONObject params = new JSONObject(); JSONObject params = new JSONObject();
params.put("content", content); params.put("content", content);
TextModerationRequest request = new TextModerationRequest() TextModerationRequest request = new TextModerationRequest()
.setService("commentDetection") .setService("comment_detection")
.setServiceParameters(params.toJSONString()); .setServiceParameters(params.toJSONString());
return client.textModeration(request); return client.textModeration(request);
}); });
} }
// ===================== 文本审核Plus =====================
//nickname_detection_pro 用户昵称检测_专业版(用户昵称) ;ugc_moderation_byllm_pro UGC场景文本审核大模型服务_专业版(个人简介 / 作品内容) ;
//comment_detection_pro 公聊评论内容检测_专业版(评论); ugc_moderation_byllm UGC场景文本审核大模型服务 (作品标题)
public TextModerationPlusResponse textModerationPlus(String content) {
return executeWithFailover(client -> {
JSONObject params = new JSONObject();
// params.put("content", content);
JSONArray arr = new JSONArray();
arr.add("狗日的");
arr.add(content);
params.put("content", arr);
TextModerationPlusRequest textModerationPlusRequest = new TextModerationPlusRequest ()
.setService("ugc_moderation_byllm_pro")
.setServiceParameters(params.toJSONString());
return client.textModerationPlus(textModerationPlusRequest);
});
}
// ===================== 图片审核 ===================== // ===================== 图片审核 =====================
// 头像图片检测:profilePhotoCheck (头像) ; AI生成图片鉴别_含隐式标识版:aigcDetectorFull(AI生成图片) ;
// 大小模型融合图片审核服务:postlmageCheckByVL (用户上传的图片) ; OSS基线检测(OSS普惠版专用):oss_baselineCheck
// 通用图片审核大模型服务:baselineCheckByVL(用户作品);图片万物识别:generalRecognition ;营销素材检测:advertisingCheck
public ImageModerationResponse imageModeration(String imageUrl) { public ImageModerationResponse imageModeration(String imageUrl) {
return executeWithFailover(client -> { return executeWithFailover(client -> {
JSONObject params = new JSONObject(); JSONObject params = new JSONObject();
JSONArray arr = new JSONArray(); // JSONArray arr = new JSONArray();
arr.add(imageUrl); // arr.add(imageUrl);
params.put("images", arr); // params.put("images", arr);
params.put("imageUrl", imageUrl);
ImageModerationRequest request = new ImageModerationRequest() ImageModerationRequest request = new ImageModerationRequest()
.setService("imageDetection") .setService("oss_baselineCheck")
.setServiceParameters(params.toJSONString()); .setServiceParameters(params.toJSONString());
return client.imageModeration(request); return client.imageModeration(request);
@ -130,6 +156,7 @@ public class AliyunContentAuditUtil {
} }
// ===================== 视频审核(异步) ===================== // ===================== 视频审核(异步) =====================
//视频文件检测:videoDetection ; AI生成视频判定:videoAigcDetector ; 视频文件检测_大模型版:videoDetectionByVL
public VideoModerationResponse videoModeration(String videoUrl) { public VideoModerationResponse videoModeration(String videoUrl) {
return executeWithFailover(client -> { return executeWithFailover(client -> {
JSONObject params = new JSONObject(); JSONObject params = new JSONObject();

4
src/main/java/com/youlai/boot/mini/model/entity/MiniContentAuditAppeal.java

@ -36,6 +36,10 @@ public class MiniContentAuditAppeal implements Serializable {
@Schema(description = "申诉人用户ID") @Schema(description = "申诉人用户ID")
private Long userId; private Long userId;
@TableField("evidence")
@Schema(description = "证据")
private String evidence;
@TableField("reason") @TableField("reason")
@Schema(description = "申诉原因") @Schema(description = "申诉原因")
private String reason; private String reason;

4
src/main/java/com/youlai/boot/mini/model/entity/MiniReport.java

@ -44,6 +44,10 @@ public class MiniReport implements Serializable {
@Schema(description = "举报原因:违法违规,侵权冒犯,垃圾虚假,违规操作,其他") @Schema(description = "举报原因:违法违规,侵权冒犯,垃圾虚假,违规操作,其他")
private String reasonCategory; private String reasonCategory;
@TableField("evidence")
@Schema(description = "证据")
private String evidence;
@TableField("description") @TableField("description")
@Schema(description = "举报补充描述") @Schema(description = "举报补充描述")
private String description; private String description;

20
src/main/java/com/youlai/boot/mini/service/impl/UserPostServiceImpl.java

@ -224,19 +224,19 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
} }
// 3. 创建内容审核任务(失败或异常降级为人工审核,不阻塞主流程) // 3. 创建内容审核任务(失败或异常降级为人工审核,不阻塞主流程)
String postUuid = post.getUuid(); Long postId = post.getId();
try { try {
AuditContentDTO auditContent = buildAuditContent(formData); AuditContentDTO auditContent = buildAuditContent(formData);
Map<String, Object> auditResult = auditExecutorService.executeAudit("user_post", postUuid, auditContent); Map<String, Object> auditResult = auditExecutorService.executeAudit("user_post", postId, auditContent);
if (auditResult != null) { if (auditResult != null) {
log.info("用户作品审核任务已创建, postUuid={}, auditResult={}", postUuid, auditResult); log.info("用户作品审核任务已创建, postId={}, auditResult={}", postId, auditResult);
} }
} catch (Exception e) { } catch (Exception e) {
log.error("创建用户作品审核任务失败, 降级为人工审核, postUuid={}", postUuid, e); log.error("创建用户作品审核任务失败, 降级为人工审核, postId={}", postId, e);
createManualReviewFallback(postUuid, formData); createManualReviewFallback(postId, formData);
} }
return postUuid; return post.getUuid();
} }
/** /**
@ -275,12 +275,12 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
/** /**
* 审核异常降级直接创建人工审核记录及对应任务确保不丢审 * 审核异常降级直接创建人工审核记录及对应任务确保不丢审
*/ */
private void createManualReviewFallback(String postUuid, UserPostForm formData) { private void createManualReviewFallback(Long postId, UserPostForm formData) {
try { try {
MiniContentAudit audit = new MiniContentAudit(); MiniContentAudit audit = new MiniContentAudit();
audit.setUuid(UUID.randomUUID().toString()); audit.setUuid(UUID.randomUUID().toString());
audit.setModuleCode("user_post"); audit.setModuleCode("user_post");
audit.setBizId(postUuid); audit.setBizId(postId);
audit.setAuditType("manual"); // 失败时 全转人工 audit.setAuditType("manual"); // 失败时 全转人工
audit.setStatus(AuditConstants.AUDIT_MANUAL_REVIEW); audit.setStatus(AuditConstants.AUDIT_MANUAL_REVIEW);
audit.setCreateBy(SecurityUtils.getUserId()); audit.setCreateBy(SecurityUtils.getUserId());
@ -298,9 +298,9 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
.set(MiniContentAuditTask::getStatus, AuditConstants.TASK_TO_MANUAL) .set(MiniContentAuditTask::getStatus, AuditConstants.TASK_TO_MANUAL)
.update(); .update();
log.info("降级人工审核记录已创建, postUuid={}, auditId={}", postUuid, audit.getId()); log.info("降级人工审核记录已创建, postId={}, auditId={}", postId, audit.getId());
} catch (Exception fallbackEx) { } catch (Exception fallbackEx) {
log.error("降级人工审核记录创建也失败了, postUuid={}, 作品将处于漏审状态!", postUuid, fallbackEx); log.error("降级人工审核记录创建也失败了, postId={}, 作品将处于漏审状态!", postId, fallbackEx);
} }
} }

5
src/main/resources/application-dev.yml

@ -163,6 +163,7 @@ springdoc:
- com.youlai.boot.auth.controller - com.youlai.boot.auth.controller
# - com.youlai.boot.system.controller # - com.youlai.boot.system.controller
- com.youlai.boot.mini.controller - com.youlai.boot.mini.controller
- com.youlai.boot.admin.controller
# - com.youlai.boot.module.file.controller # - com.youlai.boot.module.file.controller
# - com.youlai.boot.module.codegen.controller # - com.youlai.boot.module.codegen.controller
default-flat-param-object: true # 将对象参数扁平化显示在文档中 default-flat-param-object: true # 将对象参数扁平化显示在文档中
@ -240,8 +241,8 @@ bloom:
audit: audit:
aliyun: aliyun:
green: green:
accessKeyId: LTAI5tGpuYNRysEhC8sh1ntx accessKeyId: LTAI5t6MD29T6uwjvjA2ofxw
accessKeySecret: aMmHexhsZJODXBTujKPjl4NfMIsHgN accessKeySecret: Ud0q6dN4X4RbBALZ4x1aHA3egMpWEL
region-id: cn-shanghai region-id: cn-shanghai
#备用节点 green-cip.cn-beijing.aliyuncs.com #备用节点 green-cip.cn-beijing.aliyuncs.com
endpoint: green-cip.cn-shanghai.aliyuncs.com endpoint: green-cip.cn-shanghai.aliyuncs.com

Loading…
Cancel
Save