279 lines
14 KiB
Java
279 lines
14 KiB
Java
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;
|
||
}
|
||
}
|
||
} |