Files
java-10561/src/main/java/com/gxwebsoft/ai/service/impl/AuditContent3TripleServiceImpl.java

279 lines
14 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent3TripleConstants;
import com.gxwebsoft.ai.service.AuditContent3TripleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent3TripleServiceImpl extends AbstractAuditContentService implements AuditContent3TripleService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-tjXbmHDE6daMbYOT4O13ev2X";
// 三重一大分类定义 - 按照要求的顺序
private static final List<String> CATEGORY_ORDER = Arrays.asList(
AuditContent3TripleConstants.CATEGORY_MAJOR_DECISION,
AuditContent3TripleConstants.CATEGORY_PERSONNEL_APPOINTMENT,
AuditContent3TripleConstants.CATEGORY_MAJOR_PROJECT,
AuditContent3TripleConstants.CATEGORY_LARGE_FUND_OPERATION,
AuditContent3TripleConstants.CATEGORY_DECISION_PROCEDURE
);
@Override
public JSONObject generateTripleOneTableData(String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
log.info("开始生成三重一大制度对比分析表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 异步并行处理每个分类
Map<String, CompletableFuture<JSONArray>> futures = processCategoriesAsync(
CATEGORY_ORDER,
category -> generateCategoryDataAsync(category, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion)
);
// 等待所有异步任务完成
CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
// 合并所有分类的结果
JSONArray allData = mergeCategoryResults(CATEGORY_ORDER, futures);
log.info("三重一大制度对比分析表生成成功 - 记录数: {}, 处理时间: {}ms", allData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(allData, startTime, "triple_one_audit");
} catch (Exception e) {
log.error("生成三重一大制度对比分析表失败", e);
return buildErrorResponse("生成三重一大制度对比分析表失败: " + e.getMessage());
}
}
/**
* 异步生成单个分类的数据
*/
@Async
public CompletableFuture<JSONArray> generateCategoryDataAsync(String category, String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
return CompletableFuture.supplyAsync(() -> {
try {
log.info("开始生成分类 {} 的数据", category);
// 1. 为当前分类召回相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForCategory(
category, kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文(包含固定内容和动态内容)
String knowledgeContext = buildCompleteKnowledgeContext(
category, knowledgeSources, history, suggestion
);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray categoryData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "三重一大-" + category);
log.info("分类 {} 数据生成完成,生成 {} 条记录", category, categoryData.size());
return categoryData;
} catch (Exception e) {
log.error("生成分类 {} 数据失败", category, e);
return new JSONArray();
}
});
}
/**
* 为单个分类检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForCategory(String category, String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建当前分类的查询词
List<String> categoryQueries = buildCategoryQueries(category);
// 企业单位库检索
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, categoryQueries, 100)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, categoryQueries, 80)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, categoryQueries, 60));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::tripleOneComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("分类 {} 知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条",
category,
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size());
return knowledgeSources;
}
/**
* 构建分类特定的查询词
*/
private List<String> buildCategoryQueries(String category) {
switch (category) {
case AuditContent3TripleConstants.CATEGORY_MAJOR_DECISION:
return Arrays.asList("重大决策事项 决策范围 决策程序", "重大决策制度 集体决策规定");
case AuditContent3TripleConstants.CATEGORY_PERSONNEL_APPOINTMENT:
return Arrays.asList("重要人事任免 人事任免范围", "中层管理人员 领导班子成员 任免");
case AuditContent3TripleConstants.CATEGORY_MAJOR_PROJECT:
return Arrays.asList("重大项目安排 项目安排范围", "年度投资计划 融资担保项目");
case AuditContent3TripleConstants.CATEGORY_LARGE_FUND_OPERATION:
return Arrays.asList("大额度资金运作 资金运作范围", "年度预算 大额度资金使用");
case AuditContent3TripleConstants.CATEGORY_DECISION_PROCEDURE:
return Arrays.asList("决策权力主体 决策程序", "集体决策 前置程序");
default:
return Arrays.asList(category + " 制度规定");
}
}
/**
* 构建完整的知识上下文 - 包含固定内容和动态内容
*/
private String buildCompleteKnowledgeContext(String category, Map<String, List<String>> knowledgeSources, String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 三重一大制度对比分析要求
context.append("## 三重一大制度对比分析要求 - ").append(category).append("\n");
context.append("请基于以下知识生成").append(category).append("相关的三重一大制度对比分析表数据:\n\n");
context.append("1. 仅关注与").append(category).append("直接相关的制度内容,过滤不相关制度\n");
context.append("2. 对比分析政策内容、集团制度、公司制度的差异\n");
context.append("3. 重点关注决策范围、金额标准、程序要求的差异\n");
context.append("4. 识别制度执行中的风险和问题\n");
context.append("5. 严格判断测试结果,只有证据充分才能判定为通过,证据不足或存在差异必须判定为不通过\n\n");
// 2. 数据格式要求
context.append("## 数据格式要求\n");
context.append("需要生成").append(category).append("分类的数据,尽可能生成多个实例、多条记录:\n");
context.append("- ").append(category).append("").append(AuditContent3TripleConstants.CATEGORY_DESCRIPTIONS.get(category)).append("\n");
context.append("\n");
context.append("每条记录应包含6个字段\n");
context.append("- policyContent国家法律法规和政策规定需引用具体法规名称和条款\n");
context.append("- groupSystem集团层面的三重一大相关制度规定非相关制度不得纳入\n");
context.append("- companyFormulation公司层面的三重一大相关制度规定及执行情况需包含详细分析过程和查阅依据\n");
context.append("- checkEvidence审计检查的证据需详细描述查阅过程、查阅的具体文件和内容\n");
context.append("- testResult审计测试的结果通过/不通过),严格判断,从严掌握通过标准\n");
context.append("- workPaperIndex相关《参考文件名FileId》必须是实际存在的完整文件FileId不能使用附表标题确保能在文件夹中搜索到\n");
context.append("\n注意\n");
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
context.append("2. 公司执行情况分析需包含:查阅了哪些文件、发现了什么内容、与制度的差异点、分析判断过程\n");
context.append("3. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
context.append("4. 测试结果判定需严格,对于制度不一致、执行不到位、证据不充分的情况必须判定为不通过\n");
context.append("5. 审计检查的证据主要按公司制度为主,政策内容和集团制度为次要\n");
context.append("6. 审计检查的证据增加判断公司制度是否与政策内容和集团制度相符\n\n");
// 3. 参考数据(从常量类中获取)
context.append("## 参考数据\n");
context.append("### 政策内容\n").append(AuditContent3TripleConstants.POLICY_CONTENTS.get(category)).append("\n\n");
context.append("### 集团制度\n").append(AuditContent3TripleConstants.GROUP_SYSTEMS.get(category)).append("\n\n");
context.append("### 公司制度\n").append(AuditContent3TripleConstants.COMPANY_FORMULATIONS.get(category)).append("\n\n");
// 4. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化:\n");
context.append(history).append("\n\n");
}
// 5. 用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 6. 企业单位知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 7. 法律法规知识
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规知识\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 8. 审计案例知识
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例知识\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append(knowledge).append("\n"));
}
return context.toString();
}
/**
* 三重一大相关性比较器
*/
private int tripleOneComparator(String reg1, String reg2) {
int score1 = calculateTripleOneRelevanceScore(reg1);
int score2 = calculateTripleOneRelevanceScore(reg2);
return Integer.compare(score2, score1);
}
/**
* 计算三重一大相关性分数
*/
private int calculateTripleOneRelevanceScore(String content) {
return AuditContent3TripleConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 100;
case "regulation": return 80;
case "auditCase": return 60;
default: return 50;
}
}
}