1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
@Slf4j @Service public class AiChatServiceImpl implements AiChatService {
@Resource private DeepSeekClient deepSeekClient;
private static final List<ModelConfigDto> MODEL_CONFIGS = Collections.unmodifiableList(Arrays.asList( new ModelConfigDto("deepseek-v4-pro", 10, 1.0f), new ModelConfigDto("deepseek-v4-flash", 8, 0.9f) ));
private static final ExecutorService MODEL_EXECUTOR = Executors.newCachedThreadPool( new ThreadFactoryBuilder().setNameFormat("ai-detection-%d").setDaemon(true).build() );
@Override public DetectionStatusEnum aiCheckWord(String word) { if (StringUtils.isEmpty(word)) { return DetectionStatusEnum.CLEAR; } if (word.length() < 5) { return checkWithSingleModel(word, MODEL_CONFIGS.get(1)); } return checkWithOptimizedModels(word); }
private DetectionStatusEnum checkWithOptimizedModels(String content) { List<ModelConfigDto> sortedModels = MODEL_CONFIGS.stream() .sorted(Comparator.comparingInt(ModelConfigDto::getPriority).reversed()) .collect(Collectors.toList()); List<CompletableFuture<DetectionStatusEnum>> futures = sortedModels.stream() .map(config -> CompletableFuture.supplyAsync( () -> checkWithSingleModel(content, config), MODEL_EXECUTOR ).exceptionally(e -> { log.warn("模型检测异常: {}", e.getMessage()); return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; })).collect(Collectors.toList()); CompletableFuture<Void> allFutures = CompletableFuture.allOf( futures.toArray(new CompletableFuture[0]) ); try { allFutures.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { log.warn("部分模型检测未能在5秒内完成,继续处理已完成结果"); } catch (Exception e) { log.error("多模型检测发生异常", e); } List<DetectionStatusEnum> results = futures.stream() .map(future -> { try { return future.getNow(DetectionStatusEnum.SUGGEST_CLOUD_CHECK); } catch (Exception e) { return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } }).collect(Collectors.toList());
return evaluateConsensusResults(results); }
private DetectionStatusEnum evaluateConsensusResults(List<DetectionStatusEnum> results) { if (results.isEmpty()) { return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } Map<DetectionStatusEnum, Long> countMap = results.stream() .collect(Collectors.groupingBy( status -> status, Collectors.counting() )); long sensitiveCount = countMap.getOrDefault(DetectionStatusEnum.SENSITIVE, 0L); long clearCount = countMap.getOrDefault(DetectionStatusEnum.CLEAR, 0L); long totalModels = results.size(); if (sensitiveCount > totalModels / 2) { log.info("AI多模型判定结果为:超过半数模型明确判定敏感"); return DetectionStatusEnum.SENSITIVE; } if (clearCount > totalModels * 0.7) { log.info("AI多模型判定结果为:超过70%模型明确判定非敏感"); return DetectionStatusEnum.CLEAR; } if (sensitiveCount > 0 && (sensitiveCount + clearCount) * 0.3 < sensitiveCount) { log.info("AI多模型判定结果为:存在敏感判定且总占比超过30%"); return DetectionStatusEnum.SENSITIVE; } return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; }
private DetectionStatusEnum checkWithSingleModel(String content, ModelConfigDto config) { try { long startTime = System.currentTimeMillis(); String prompt = AiPromptTemplateUtils.buildSensitiveCheckPrompt(content); ChatCompletionRequest request = ChatCompletionRequest.builder() .addUserMessage(prompt) .model(config.getName()) .stream(false) .temperature(0.0) .maxCompletionTokens(30) .reasoningEffort("low") .build(); CompletableFuture<ChatCompletionResponse> future = CompletableFuture.supplyAsync( () -> deepSeekClient.chatCompletion(request).execute() ); ChatCompletionResponse response = future.get(10000, TimeUnit.MILLISECONDS); if (response == null || response.choices() == null || response.choices().isEmpty()) { log.warn("模型 {} 返回空响应", config.getName()); return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } String answer = response.choices().get(0).message().content().trim() .replace("\uFEFF", "") .replaceAll("^```json|```$", ""); try { JsonNode json = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .readTree(answer); boolean sensitive = json.path("sensitive").asBoolean(); float confidence = (float) json.path("confidence").asDouble(0.5); log.info("模型 {} 检测结果: {}, 置信度: {}, 检测耗时: {}ms", config.getName(), sensitive, confidence, System.currentTimeMillis() - startTime); if (sensitive) { return confidence >= 0.8 ? DetectionStatusEnum.SENSITIVE : DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } else { return confidence >= 0.7 ? DetectionStatusEnum.CLEAR : DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } } catch (Exception e) { log.warn("解析模型 {} 响应失败: {}", config.getName(), answer); return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } } catch (TimeoutException e) { log.warn("模型 {} 检测超时", config.getName()); return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } catch (Exception e) { log.error("模型 {} 检测异常: {}", config.getName(), e.getMessage()); return DetectionStatusEnum.SUGGEST_CLOUD_CHECK; } } }
|