三重一大生成接口优化

This commit is contained in:
2025-10-30 16:55:29 +08:00
parent 74b37fdbd0
commit 8b841767e2
10 changed files with 445 additions and 277 deletions

View File

@@ -1,21 +1,36 @@
package com.gxwebsoft.ai.controller; package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.ai.dto.AuditContentRequest; import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.entity.AiCloudDoc;
import com.gxwebsoft.ai.entity.AiCloudFile;
import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import com.gxwebsoft.ai.service.AiCloudDocService;
import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.service.AuditContentService3; import com.gxwebsoft.ai.service.AuditContentService3;
import com.gxwebsoft.ai.service.KnowledgeBaseService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.*;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
/** /**
* 审计内容3控制器 - 重大经济决策调查表 * 审计内容3控制器 - 三重一大制度对比分析
*/ */
@Tag(name = "审计内容3-重大经济决策") @Slf4j
@Tag(name = "审计内容3-三重一大制度对比")
@RestController @RestController
@RequestMapping("/api/ai/auditContent3") @RequestMapping("/api/ai/auditContent3")
public class AuditContentController3 extends BaseController { public class AuditContentController3 extends BaseController {
@@ -23,18 +38,34 @@ public class AuditContentController3 extends BaseController {
@Autowired @Autowired
private AuditContentService3 auditContentService3; private AuditContentService3 auditContentService3;
@Autowired
private AiCloudDocService aiCloudDocService;
@Autowired
private AiCloudFileService aiCloudFileService;
@Autowired
private KnowledgeBaseService knowledgeBaseService;
/** /**
* 生成重大经济决策调查表数据 * 生成三重一大制度对比分析表数据
*/ */
@Operation(summary = "生成重大经济决策调查") @Operation(summary = "生成三重一大制度对比分析")
@PostMapping("/generateDecisionTable") @PostMapping("/generateTripleOneTable")
public ApiResult<?> generateDecisionTable(@RequestBody AuditContentRequest request) { public ApiResult<?> generateTripleOneTable(@RequestBody AuditContentRequest request) {
final User loginUser = getLoginUser(); final User loginUser = getLoginUser();
String kbIdTmp = "";
try { try {
// 生成重大经济决策调查表数据 // 创建临时知识库(如果需要)
JSONObject result = auditContentService3.generateDecisionTableData( if (!request.getDocList().isEmpty() || !request.getFileList().isEmpty()) {
request.getKbIds(), kbIdTmp = createTempKnowledgeBase(request);
}
// 生成三重一大制度对比分析表数据
String knowledgeBaseId = StrUtil.isNotBlank(kbIdTmp) ? kbIdTmp : request.getKbIds();
JSONObject result = auditContentService3.generateTripleOneTableData(
knowledgeBaseId,
request.getLibraryIds(), request.getLibraryIds(),
request.getProjectLibrary(), request.getProjectLibrary(),
loginUser.getUsername(), loginUser.getUsername(),
@@ -44,8 +75,55 @@ public class AuditContentController3 extends BaseController {
return success(result); return success(result);
} catch (Exception e) { } catch (Exception e) {
return fail("生成重大经济决策调查表失败: " + e.getMessage()); log.error("生成三重一大制度对比分析表失败", e);
return fail("生成三重一大制度对比分析表失败: " + e.getMessage());
} finally {
cleanupTempKnowledgeBase(kbIdTmp);
} }
} }
/**
* 创建临时知识库并提交文档
*/
private String createTempKnowledgeBase(AuditContentRequest request) {
String kbIdTmp = knowledgeBaseService.createKnowledgeBaseTemp();
// 收集文档ID
Set<Integer> docIds = request.getDocList().stream()
.flatMap(docId -> aiCloudDocService.getSelfAndChildren(docId).stream())
.map(AiCloudDoc::getId)
.collect(Collectors.toSet());
// 查询相关文件
LambdaQueryWrapper<AiCloudFile> queryWrapper = new LambdaQueryWrapper<AiCloudFile>()
.in(!docIds.isEmpty(), AiCloudFile::getDocId, docIds)
.or(!request.getFileList().isEmpty())
.in(!request.getFileList().isEmpty(), AiCloudFile::getId, request.getFileList());
List<AiCloudFile> fileList = aiCloudFileService.list(queryWrapper);
// 提取文件ID并提交到知识库
Set<String> kbFileIds = fileList.stream()
.map(AiCloudFile::getFileId)
.collect(Collectors.toSet());
if (!kbFileIds.isEmpty()) {
knowledgeBaseService.submitDocuments(kbIdTmp, new ArrayList<>(kbFileIds));
}
return kbIdTmp;
}
/**
* 清理临时知识库
*/
private void cleanupTempKnowledgeBase(String kbId) {
if (StrUtil.isNotBlank(kbId)) {
try {
knowledgeBaseService.deleteIndex(kbId);
} catch (Exception e) {
log.warn("删除临时知识库失败: {}", kbId, e);
}
}
}
} }

View File

@@ -1,5 +1,7 @@
package com.gxwebsoft.ai.dto; package com.gxwebsoft.ai.dto;
import java.util.List;
import lombok.Data; import lombok.Data;
/** /**
@@ -32,4 +34,14 @@ public class AuditContentRequest {
* 优化建议 * 优化建议
*/ */
private String suggestion; private String suggestion;
/**
* 目录列表
*/
private List<Integer> docList;
/**
* 文件列表
*/
private List<Integer> fileList;
} }

View File

@@ -5,7 +5,8 @@ import com.alibaba.fastjson.JSONObject;
public interface AuditContentService3 { public interface AuditContentService3 {
/** /**
* 生成重大经济决策调查表数据 * 生成三重一大制度对比分析表数据
*/ */
JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary, String userName, String history, String suggestion); JSONObject generateTripleOneTableData(String kbIds, String libraryIds, String projectLibrary,
String userName, String history, String suggestion);
} }

View File

@@ -2,6 +2,7 @@ package com.gxwebsoft.ai.service;
import com.gxwebsoft.ai.dto.KnowledgeBaseRequest; import com.gxwebsoft.ai.dto.KnowledgeBaseRequest;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -24,6 +25,11 @@ public interface KnowledgeBaseService {
*/ */
String createKnowledgeBase(String companyName, String companyCode); String createKnowledgeBase(String companyName, String companyCode);
/**
* 创建临时知识库
*/
String createKnowledgeBaseTemp();
/** /**
* 检查知识库是否存 * 检查知识库是否存
*/ */
@@ -39,6 +45,11 @@ public interface KnowledgeBaseService {
*/ */
Map<String,Object> listDocuments(String kbId, Integer pageSize, Integer pageNumber); Map<String,Object> listDocuments(String kbId, Integer pageSize, Integer pageNumber);
/**
* 删除知识库
*/
boolean deleteIndex(String kbId);
/** /**
* 删除知识库下的文档 * 删除知识库下的文档
*/ */
@@ -53,4 +64,9 @@ public interface KnowledgeBaseService {
* 知识库追加导入已解析的文档 * 知识库追加导入已解析的文档
*/ */
void submitDocuments(String kbId, String fileId); void submitDocuments(String kbId, String fileId);
/**
* 知识库追加导入已解析的文档
*/
void submitDocuments(String kbId, List<String> fileIds);
} }

View File

@@ -6,6 +6,8 @@ import com.aliyun.bailian20231229.models.RetrieveResponseBody;
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyData; import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyData;
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes; import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.config.KnowledgeBaseConfig; import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
@@ -38,105 +40,98 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
@Autowired @Autowired
private PwlProjectLibraryService pwlProjectLibraryService; private PwlProjectLibraryService pwlProjectLibraryService;
// 工作流配置 // 工作流配置
private static final String DECISION_TABLE_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run"; private static final String TRIPLE_ONE_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
private static final String DECISION_TABLE_TOKEN = "Bearer app-yN7Q8GEN9E7SCMkhI6HaAagW"; private static final String TRIPLE_ONE_TOKEN = "Bearer app-tjXbmHDE6daMbYOT4O13ev2X";
// 缓存 // 三重一大分类定义
private final Map<String, Set<String>> knowledgeCache = new ConcurrentHashMap<>(); private static final Map<String, String> TRIPLE_ONE_CATEGORIES = new LinkedHashMap<>();
private static final long CACHE_EXPIRE_TIME = 5 * 60 * 1000;
private final Map<String, Long> cacheTimestamps = new ConcurrentHashMap<>();
// 决策程序类型
private static final Map<String, String> DECISION_PROCEDURES = new HashMap<>();
static { static {
DECISION_PROCEDURES.put("会议决策", "通过召开专题会议进行集体决策,会议纪要完整"); TRIPLE_ONE_CATEGORIES.put("重大决策", "重大决策事项的定义和范围");
DECISION_PROCEDURES.put("会签决策", "通过会签方式进行决策,相关人员签字确认"); TRIPLE_ONE_CATEGORIES.put("重要人事任免", "重要人事任免事项的定义和范围");
DECISION_PROCEDURES.put("书面决策", "通过书面请示报告方式进行决策"); TRIPLE_ONE_CATEGORIES.put("重大项目安排", "重大项目安排事项的定义和范围");
DECISION_PROCEDURES.put("授权决策", "在授权范围内由负责人直接决策"); TRIPLE_ONE_CATEGORIES.put("大额度资金运作", "大额度资金运作事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("决策权力主体和程序", "决策权力主体和程序的规定");
} }
// 关键词权重
private static final Map<String, Integer> KEYWORD_WEIGHTS; private static final Map<String, Integer> KEYWORD_WEIGHTS;
static { static {
Map<String, Integer> map = new HashMap<>(); Map<String, Integer> map = new HashMap<>();
map.put("三重一大", 10); map.put("三重一大", 10);
map.put("重大决策", 9);
map.put("重要人事任免", 9);
map.put("重大项目安排", 9);
map.put("大额度资金运作", 9);
map.put("决策程序", 8);
map.put("党委会", 7);
map.put("董事会", 7);
map.put("总经理办公会", 7);
map.put("集体决策", 8); map.put("集体决策", 8);
map.put("重大经济决策", 9); map.put("会议纪要", 6);
map.put("会议纪要", 7); map.put("金额标准", 6);
map.put("决策程序", 7);
map.put("决策标准", 6);
map.put("审计方法", 6);
map.put("重大预算", 5);
map.put("重大项目", 5);
map.put("重大采购", 5);
map.put("重大投资", 5);
KEYWORD_WEIGHTS = Collections.unmodifiableMap(map); KEYWORD_WEIGHTS = Collections.unmodifiableMap(map);
} }
@Override @Override
public JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary, String userName, String history, String suggestion) { public JSONObject generateTripleOneTableData(String kbIds, String libraryIds, String projectLibrary,
log.info("开始生成重大经济决策调查表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", userName, kbIds, libraryIds, projectLibrary); String userName, String history, String suggestion) {
log.info("开始生成三重一大制度对比分析表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryIds, projectLibrary);
JSONObject result = new JSONObject(); JSONObject result = new JSONObject();
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
try { try {
// 1. 从不同知识库召回相关内容 // 1. 从不同知识库召回相关内容
Map<String, List<String>> knowledgeSources = retrieveDecisionKnowledgeSeparated(kbIds, libraryIds, projectLibrary); Map<String, List<String>> knowledgeSources = retrieveTripleOneKnowledge(kbIds, libraryIds, projectLibrary);
// 2. 生成重大经济决策调查表数据 // 2. 生成三重一大制度对比分析表数据
JSONArray decisionTableData = generateDecisionTable(knowledgeSources, userName, history, suggestion); JSONArray comparisonTableData = generateComparisonTable(knowledgeSources, userName, history, suggestion);
// 3. 数据质量检查 // 3. 数据质量检查
decisionTableData = validateAndEnhanceData(decisionTableData); comparisonTableData = validateAndEnhanceComparisonData(comparisonTableData);
// 4. 构建返回结果 // 4. 构建返回结果
result.put("success", true); result.put("success", true);
result.put("data", decisionTableData); result.put("data", comparisonTableData);
result.put("total_records", decisionTableData.size()); result.put("total_records", comparisonTableData.size());
result.put("generated_time", new Date().toString()); result.put("generated_time", new Date().toString());
result.put("core_knowledge_count", knowledgeSources.get("core").size());
result.put("case_knowledge_count", knowledgeSources.get("case").size());
result.put("regulation_knowledge_count", knowledgeSources.get("regulation").size());
result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms"); result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms");
log.info("重大经济决策调查表生成成功 - 记录数: {}, 处理时间: {}ms", log.info("三重一大制度对比分析表生成成功 - 记录数: {}, 处理时间: {}ms",
decisionTableData.size(), (System.currentTimeMillis() - startTime)); comparisonTableData.size(), (System.currentTimeMillis() - startTime));
} catch (Exception e) { } catch (Exception e) {
log.error("生成重大经济决策调查表失败", e); log.error("生成三重一大制度对比分析表失败", e);
// 直接抛出异常,不返回默认数据 result.put("success", false);
throw new RuntimeException("生成重大经济决策调查表失败: " + e.getMessage(), e); result.put("error", e.getMessage());
throw new RuntimeException("生成三重一大制度对比分析表失败: " + e.getMessage(), e);
} }
return result; return result;
} }
/** /**
* 分离不同知识库的检索策略 * 检索三重一大相关知识
*/ */
private Map<String, List<String>> retrieveDecisionKnowledgeSeparated(String kbIds, String libraryIds, String projectLibrary) { private Map<String, List<String>> retrieveTripleOneKnowledge(String kbIds, String libraryIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>(); Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("core", new ArrayList<>()); knowledgeSources.put("enterprise", new ArrayList<>()); // 企业单位库
knowledgeSources.put("case", new ArrayList<>()); knowledgeSources.put("regulation", new ArrayList<>()); // 公共法律法规库
knowledgeSources.put("regulation", new ArrayList<>()); knowledgeSources.put("auditCase", new ArrayList<>()); // 审计案例库
// 核心审计库 - 主要来源 // 企业单位库检索 - 主要来源
if (StrUtil.isNotBlank(kbIds)) { if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(",")) Arrays.stream(kbIds.split(","))
.map(String::trim) .map(String::trim)
.filter(StrUtil::isNotBlank) .filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("core") .forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBaseWithCache(kbId, buildCoreQueries(), 150))); .addAll(queryKnowledgeBase(kbId, buildEnterpriseQueries(), 200)));
} }
// 案例库 - 辅助参考 // 公共法律法规库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("case").addAll(queryKnowledgeBaseWithCache(projectLibrary, buildCaseQueries(), 100));
}
// 法规库 - 制度校验
if (StrUtil.isNotBlank(libraryIds)) { if (StrUtil.isNotBlank(libraryIds)) {
List<String> idList = StrUtil.split(libraryIds, ','); List<String> idList = StrUtil.split(libraryIds, ',');
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list( List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(
@@ -147,14 +142,20 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
.map(String::trim) .map(String::trim)
.filter(StrUtil::isNotBlank) .filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation") .forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBaseWithCache(libId, buildRegulationQueries(), 80))); .addAll(queryKnowledgeBase(libId, buildRegulationQueries(), 150)));
} }
// 分别进行智能去重和排序 // 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, buildAuditCaseQueries(), 100));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> { knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream() List<String> processed = list.stream()
.distinct() .distinct()
.sorted(this::regulationsComparator) .sorted(this::tripleOneComparator)
.limit(getLimitBySourceType(key)) .limit(getLimitBySourceType(key))
.collect(Collectors.toList()); .collect(Collectors.toList());
knowledgeSources.put(key, processed); knowledgeSources.put(key, processed);
@@ -164,34 +165,37 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
} }
/** /**
* 构建核心审计库查询 * 构建企业单位库查询
*/ */
private List<String> buildCoreQueries() { private List<String> buildEnterpriseQueries() {
return Arrays.asList( return Arrays.asList(
"三重一大 集体决策 会议纪要 决策程序", "三重一大制度 集体决策规定",
"重大经济决策 资本性支出 费用性支出", "重大决策范围 人事任免范围 项目安排范围 资金运作范围",
"重大项目 重大投资 重大采购" "决策程序 权力主体 会议规则",
"集团制度 公司制定 内部规定"
); );
} }
/** /**
* 构建案例库查询 * 构建法律法规库查询
*/
private List<String> buildCaseQueries() {
return Arrays.asList(
"类似案例 参考案例 最佳实践",
"决策效果 执行结果 经验教训"
);
}
/**
* 构建法规库查询
*/ */
private List<String> buildRegulationQueries() { private List<String> buildRegulationQueries() {
return Arrays.asList( return Arrays.asList(
"三重一大制度 集体决策规定", "三重一大政策 国家法律法规",
"重大经济决策程序 审批权限", "重大决策法规 人事任免法规",
"审计法规 审计标准" "项目安排规定 资金运作规定",
"决策程序法律要求"
);
}
/**
* 构建审计案例库查询
*/
private List<String> buildAuditCaseQueries() {
return Arrays.asList(
"三重一大审计案例 检查证据",
"决策程序测试 执行效果",
"工作底稿 审计测试结果"
); );
} }
@@ -200,111 +204,94 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
*/ */
private int getLimitBySourceType(String sourceType) { private int getLimitBySourceType(String sourceType) {
switch (sourceType) { switch (sourceType) {
case "core": return 300; case "enterprise": return 300;
case "case": return 150; case "regulation": return 200;
case "regulation": return 100; case "auditCase": return 150;
default: return 100; default: return 100;
} }
} }
/** /**
* 带缓存的知识库查询 * 生成三重一大制度对比分析表
*/ */
private Set<String> queryKnowledgeBaseWithCache(String kbId, List<String> queries, int topK) { private JSONArray generateComparisonTable(Map<String, List<String>> knowledgeSources, String userName, String history, String suggestion) {
Set<String> allResults = new LinkedHashSet<>();
queries.forEach(query -> {
String cacheKey = kbId + ":" + query;
long currentTime = System.currentTimeMillis();
if (knowledgeCache.containsKey(cacheKey) &&
cacheTimestamps.containsKey(cacheKey) &&
(currentTime - cacheTimestamps.get(cacheKey)) < CACHE_EXPIRE_TIME) {
allResults.addAll(knowledgeCache.get(cacheKey));
} else {
Set<String> results = queryKnowledgeBase(kbId, query, topK);
knowledgeCache.put(cacheKey, new LinkedHashSet<>(results));
cacheTimestamps.put(cacheKey, currentTime);
allResults.addAll(results);
}
});
return allResults;
}
/**
* 生成重大经济决策调查表
*/
private JSONArray generateDecisionTable(Map<String, List<String>> knowledgeSources,
String userName, String history, String suggestion) {
// 构建优化的知识上下文 // 构建优化的知识上下文
String knowledgeContext = buildOptimizedKnowledgeContext(knowledgeSources, history, suggestion); String knowledgeContext = buildKnowledgeContext(knowledgeSources, history, suggestion);
JSONObject requestBody = buildDecisionTableRequest(knowledgeContext, userName); JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray rawData = callDecisionTableWorkflow(requestBody); JSONArray rawData = callTripleOneWorkflow(requestBody);
// 后处理:数据清洗和格式化 // 后处理:数据清洗和格式化
return postProcessTableData(rawData); return postProcessComparisonData(rawData);
} }
/** /**
* 构建优化的知识上下文 * 构建知识上下文
*/ */
private String buildOptimizedKnowledgeContext(Map<String, List<String>> knowledgeSources, private String buildKnowledgeContext(Map<String, List<String>> knowledgeSources, String history, String suggestion) {
String history, String suggestion) {
StringBuilder context = new StringBuilder(); StringBuilder context = new StringBuilder();
// 1. 核心审计要求 // 1. 分析要求
context.append("## 核心审计要求\n"); context.append("## 三重一大制度对比分析要求\n");
context.append("请基于以下审计要求生成重大经济决策调查表数据:\n\n"); context.append("请基于以下知识生成三重一大制度对比分析表数据:\n\n");
context.append("1. 检查\"三重一大\"集体决策制度建立和执行情况\n"); context.append("1. 对比分析政策内容、集团制度、公司制定的差异\n");
context.append("2. 验证重大经济事项集体决策的程序完整性\n"); context.append("2. 重点关注决策范围、金额标准、程序要求的差异\n");
context.append("3. 确认决策内容符合相关规定\n"); context.append("3. 识别制度执行中的风险和问题\n\n");
context.append("4. 评估决策执行情况和效果\n\n");
// 2. 数据格式要求 // 2. 数据格式要求
context.append("## 数据格式要求\n"); context.append("## 数据格式要求\n");
context.append("每条记录应包含:序号、事项名称、会议时间、决策金额、程序、执行情况、执行效果\n"); context.append("需要生成5个分类的数据每个分类尽可能多的生成多个实例、多条记录尽可能三重一大的五个方面都包含\n");
context.append("- 程序字段:描述具体的决策程序,如:会议决策(党委会/董事会/总经理办公会)、会签决策等\n"); TRIPLE_ONE_CATEGORIES.forEach((category, desc) ->
context.append("- 决策金额:根据实际情况使用正确单位(元/万元/亿元)\n"); context.append("- ").append(category).append("").append(desc).append("\n"));
context.append("- 执行效果需在'好、一般、差'中选择一项标记为'是'\n\n"); context.append("\n");
// 3. 历史内容(用于优化调整) 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相关《参考文件名》以及工作底稿的索引编号\n");
context.append("\n注意每个分类下可以有多个条目请根据知识库内容尽可能全面地生成所有相关制度规定和检查点。\n\n");
// 3. 历史内容
if (StrUtil.isNotBlank(history)) { if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n"); context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化:\n"); context.append("以下是之前生成的内容,请基于此进行优化:\n");
context.append(history).append("\n\n"); context.append(history).append("\n\n");
} }
// 4. 用户建议(用于定向优化) // 4. 用户建议
if (StrUtil.isNotBlank(suggestion)) { if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n"); context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n"); context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n"); context.append(suggestion).append("\n\n");
} }
// 5. 核心审计知识 // 5. 企业单位知识
if (!knowledgeSources.get("core").isEmpty()) { if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 核心审计知识\n"); context.append("## 企业单位知识\n");
knowledgeSources.get("core").stream() knowledgeSources.get("enterprise").stream()
.limit(250)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
context.append("\n");
}
// 6. 法律法规知识
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规知识\n");
knowledgeSources.get("regulation").stream()
.limit(200) .limit(200)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n")); .forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
context.append("\n");
} }
// 6. 参考案例 // 7. 审计案例知识
if (!knowledgeSources.get("case").isEmpty()) { if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 参考案例\n"); context.append("## 审计案例知识\n");
knowledgeSources.get("case").stream() knowledgeSources.get("auditCase").stream()
.limit(100) .limit(150)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
}
// 7. 法规要求
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法规要求\n");
knowledgeSources.get("regulation").stream()
.limit(80)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n")); .forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
} }
@@ -314,9 +301,9 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
/** /**
* 数据验证和增强 * 数据验证和增强
*/ */
private JSONArray validateAndEnhanceData(JSONArray data) { private JSONArray validateAndEnhanceComparisonData(JSONArray data) {
if (data == null || data.isEmpty()) { if (data == null || data.isEmpty()) {
return new JSONArray(); // 返回空数组,不提供默认数据 return createDefaultComparisonData();
} }
JSONArray enhancedData = new JSONArray(); JSONArray enhancedData = new JSONArray();
@@ -326,126 +313,143 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
if (item == null) continue; if (item == null) continue;
// 数据验证 // 数据验证
if (!validateDataItem(item)) { if (!validateComparisonDataItem(item)) {
log.warn("数据验证失败,跳过记录: {}", item); log.warn("数据验证失败,跳过记录: {}", item);
continue; continue;
} }
// 数据增强 // 数据增强
enhanceDataItem(item, i); enhanceComparisonDataItem(item, i);
enhancedData.add(item); enhancedData.add(item);
} }
return enhancedData; return enhancedData;
} }
/**
* 创建默认的对比分析数据
*/
private JSONArray createDefaultComparisonData() {
JSONArray defaultData = new JSONArray();
for (String category : TRIPLE_ONE_CATEGORIES.keySet()) {
JSONObject item = new JSONObject();
item.put("category", category);
item.put("policyContent", "待补充相关政策内容");
item.put("groupSystem", "待补充集团制度规定");
item.put("companyFormulation", "待补充公司制定内容");
item.put("checkEvidence", "待补充检查证据");
item.put("testResult", "待检查");
item.put("workPaperIndex", Collections.singletonList("待关联工作底稿"));
defaultData.add(item);
}
return defaultData;
}
/** /**
* 数据项验证 * 数据项验证
*/ */
private boolean validateDataItem(JSONObject item) { private boolean validateComparisonDataItem(JSONObject item) {
return item.containsKey("name") && return item.containsKey("category") &&
item.containsKey("meetingTime") && item.containsKey("policyContent") &&
item.containsKey("decisionAmount") && item.containsKey("groupSystem") &&
item.containsKey("procedure") && item.containsKey("companyFormulation");
item.containsKey("executionStatus");
} }
/** /**
* 数据项增强 * 数据项增强
*/ */
private void enhanceDataItem(JSONObject item, int index) { private void enhanceComparisonDataItem(JSONObject item, int index) {
// 确保序号正确 // 确保分类正确
item.put("index", String.valueOf(index + 1)); if (!item.containsKey("category") || StrUtil.isBlank(item.getString("category"))) {
List<String> categories = new ArrayList<>(TRIPLE_ONE_CATEGORIES.keySet());
// 增强程序描述 if (index < categories.size()) {
String procedure = item.getString("procedure"); item.put("category", categories.get(index));
if (StrUtil.isBlank(procedure) || procedure.length() < 10) { }
item.put("procedure", generateProcedureDescription());
} }
// 增强执行效果结构 // 确保所有字段都存在
if (!item.containsKey("executionEffect")) { String[] requiredFields = {"policyContent", "groupSystem", "companyFormulation",
JSONObject effect = new JSONObject(); "checkEvidence", "testResult", "workPaperIndex"};
effect.put("good", ""); for (String field : requiredFields) {
effect.put("normal", ""); if (!item.containsKey(field) || item.get(field) == null) {
effect.put("bad", ""); if ("workPaperIndex".equals(field)) {
item.put("executionEffect", effect); item.put(field, Collections.singletonList("待关联工作底稿"));
} } else if ("testResult".equals(field)) {
item.put(field, "待检查");
// 标准化金额格式
String amount = item.getString("decisionAmount");
if (amount != null) {
item.put("decisionAmount", normalizeAmount(amount));
}
}
/**
* 生成程序描述
*/
private String generateProcedureDescription() {
Random random = new Random();
List<String> procedures = new ArrayList<>(DECISION_PROCEDURES.keySet());
String procedureType = procedures.get(random.nextInt(procedures.size()));
return DECISION_PROCEDURES.get(procedureType);
}
/**
* 标准化金额格式
*/
private String normalizeAmount(String amount) {
if (amount == null) return "0元";
// 如果已经包含单位,直接返回
if (amount.contains("万元") || amount.contains("") || amount.contains("亿")) {
return amount;
}
// 尝试解析数字
try {
String cleanAmount = amount.replaceAll("[^\\d.]", "");
if (StrUtil.isNotBlank(cleanAmount)) {
double value = Double.parseDouble(cleanAmount);
if (value >= 100000000) {
return String.format("%.2f亿元", value / 100000000);
} else if (value >= 10000) {
return String.format("%.2f万元", value / 10000);
} else { } else {
return String.format("%.0f元", value); item.put(field, "");
} }
} }
} catch (NumberFormatException e) {
log.debug("金额解析失败: {}", amount);
} }
return amount + "";
} }
/** private JSONArray postProcessComparisonData(JSONArray rawData) {
* 后处理表格数据
*/
private JSONArray postProcessTableData(JSONArray rawData) {
if (rawData == null || rawData.isEmpty()) { if (rawData == null || rawData.isEmpty()) {
return new JSONArray(); return createDefaultComparisonData();
} }
return rawData; // 简化处理,直接返回原始数据 // 使用列表来存储所有条目,避免覆盖
JSONArray processedData = new JSONArray();
Map<String, List<JSONObject>> categoryDataMap = new LinkedHashMap<>();
// 初始化分类映射
for (String category : TRIPLE_ONE_CATEGORIES.keySet()) {
categoryDataMap.put(category, new ArrayList<>());
}
// 按分类分组所有条目
for (int i = 0; i < rawData.size(); i++) {
JSONObject item = rawData.getJSONObject(i);
if (item != null && item.containsKey("category")) {
String category = item.getString("category");
if (categoryDataMap.containsKey(category)) {
categoryDataMap.get(category).add(item);
} else {
// 如果分类不在预定义列表中,添加到其他分类
log.warn("发现未预定义的分类: {}", category);
categoryDataMap.computeIfAbsent(category, k -> new ArrayList<>()).add(item);
}
}
}
// 按照固定顺序输出所有条目
for (String category : TRIPLE_ONE_CATEGORIES.keySet()) {
List<JSONObject> categoryItems = categoryDataMap.get(category);
if (categoryItems != null && !categoryItems.isEmpty()) {
// 添加该分类下的所有条目
processedData.addAll(categoryItems);
}
}
// 处理其他未预定义的分类
for (Map.Entry<String, List<JSONObject>> entry : categoryDataMap.entrySet()) {
String category = entry.getKey();
if (!TRIPLE_ONE_CATEGORIES.containsKey(category)) {
processedData.addAll(entry.getValue());
}
}
log.info("后处理完成 - 输入数据条数: {}, 输出数据条数: {}", rawData.size(), processedData.size());
return processedData;
} }
/** /**
* 法规内容比较器 * 三重一大内容比较器
*/ */
private int regulationsComparator(String reg1, String reg2) { private int tripleOneComparator(String reg1, String reg2) {
int score1 = calculateRelevanceScore(reg1); int score1 = calculateTripleOneRelevanceScore(reg1);
int score2 = calculateRelevanceScore(reg2); int score2 = calculateTripleOneRelevanceScore(reg2);
return Integer.compare(score2, score1); return Integer.compare(score2, score1);
} }
/** /**
* 计算相关性分数 * 计算三重一大相关性分数
*/ */
private int calculateRelevanceScore(String regulation) { private int calculateTripleOneRelevanceScore(String content) {
return KEYWORD_WEIGHTS.entrySet().stream() return KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> regulation.contains(entry.getKey())) .filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue) .mapToInt(Map.Entry::getValue)
.sum(); .sum();
} }
@@ -453,28 +457,31 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
/** /**
* 查询知识库 * 查询知识库
*/ */
private Set<String> queryKnowledgeBase(String kbId, String query, int topK) { private List<String> queryKnowledgeBase(String kbId, List<String> queries, int topK) {
Set<String> results = new LinkedHashSet<>(); Set<String> results = new LinkedHashSet<>();
String workspaceId = config.getWorkspaceId(); String workspaceId = config.getWorkspaceId();
try { try {
Client client = clientFactory.createClient(); Client client = clientFactory.createClient();
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
Optional.ofNullable(resp) for (String query : queries) {
.map(RetrieveResponse::getBody) RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
.map(RetrieveResponseBody::getData)
.map(RetrieveResponseBodyData::getNodes) Optional.ofNullable(resp)
.orElse(Collections.emptyList()) .map(RetrieveResponse::getBody)
.stream() .map(RetrieveResponseBody::getData)
.limit(topK) .map(RetrieveResponseBodyData::getNodes)
.forEach(node -> processNode(node, results)); .orElse(Collections.emptyList())
.stream()
.limit(topK)
.forEach(node -> processNode(node, results));
}
} catch (Exception e) { } catch (Exception e) {
log.error("查询知识库失败 - kbId: {}, query: {}", kbId, query, e); log.error("查询知识库失败 - kbId: {}, queries: {}", kbId, queries, e);
} }
return results; return new ArrayList<>(results);
} }
/** /**
@@ -514,35 +521,39 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
} }
/** /**
* 调用决策表生成工作流 * 调用三重一大工作流
*/ */
private JSONArray callDecisionTableWorkflow(JSONObject requestBody) { private JSONArray callTripleOneWorkflow(JSONObject requestBody) {
try { try {
String result = HttpUtil.createPost(DECISION_TABLE_WORKFLOW_URL) String result = HttpUtil.createPost(TRIPLE_ONE_WORKFLOW_URL)
.header("Authorization", DECISION_TABLE_TOKEN) .header("Authorization", TRIPLE_ONE_TOKEN)
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.body(requestBody.toString()) .body(requestBody.toString())
.timeout(120000) .timeout(5*60*1000)
.execute() .execute()
.body(); .body();
JSONObject jsonResponse = JSONObject.parseObject(result); ObjectMapper objectMapper = new ObjectMapper();
String outputText = jsonResponse.getJSONObject("data") JsonNode rootNode = objectMapper.readTree(result);
.getJSONObject("outputs") String outputText = rootNode.path("data")
.getString("result"); .path("outputs")
.path("result")
.asText();
return JSONArray.parseArray(outputText); // 使用Jackson解析数组
JsonNode arrayNode = objectMapper.readTree(outputText);
return JSONArray.parseArray(arrayNode.toString());
} catch (Exception e) { } catch (Exception e) {
log.error("调用决策表生成工作流失败", e); log.error("调用三重一大工作流失败", e);
throw new RuntimeException("调用决策表生成工作流失败: " + e.getMessage(), e); throw new RuntimeException("调用三重一大工作流失败: " + e.getMessage(), e);
} }
} }
/** /**
* 构建决策表生成请求 * 构建工作流请求
*/ */
private JSONObject buildDecisionTableRequest(String knowledge, String userName) { private JSONObject buildWorkflowRequest(String knowledge, String userName) {
JSONObject requestBody = new JSONObject(); JSONObject requestBody = new JSONObject();
JSONObject inputs = new JSONObject(); JSONObject inputs = new JSONObject();
@@ -554,15 +565,4 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
return requestBody; return requestBody;
} }
/**
* 清理缓存
*/
public void clearExpiredCache() {
long currentTime = System.currentTimeMillis();
cacheTimestamps.entrySet().removeIf(entry ->
(currentTime - entry.getValue()) >= CACHE_EXPIRE_TIME
);
knowledgeCache.keySet().removeIf(key -> !cacheTimestamps.containsKey(key));
}
} }

View File

@@ -3,6 +3,7 @@ package com.gxwebsoft.ai.service.impl;
import com.aliyun.bailian20231229.Client; import com.aliyun.bailian20231229.Client;
import com.aliyun.bailian20231229.models.CreateIndexResponse; import com.aliyun.bailian20231229.models.CreateIndexResponse;
import com.aliyun.bailian20231229.models.DeleteIndexDocumentResponse; import com.aliyun.bailian20231229.models.DeleteIndexDocumentResponse;
import com.aliyun.bailian20231229.models.DeleteIndexResponse;
import com.aliyun.bailian20231229.models.ListIndexDocumentsResponse; import com.aliyun.bailian20231229.models.ListIndexDocumentsResponse;
import com.aliyun.bailian20231229.models.ListIndicesResponse; import com.aliyun.bailian20231229.models.ListIndicesResponse;
import com.aliyun.bailian20231229.models.RetrieveResponse; import com.aliyun.bailian20231229.models.RetrieveResponse;
@@ -21,6 +22,8 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@@ -82,6 +85,12 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
throw new RuntimeException("创建知识库失败: " + e.getMessage(), e); throw new RuntimeException("创建知识库失败: " + e.getMessage(), e);
} }
} }
@Override
public String createKnowledgeBaseTemp() {
String code = "Temp_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("MMddHHmmssSSS"));
return createKnowledgeBase(code, code);
}
@Override @Override
public boolean existsKnowledgeBase(String companyCode) { public boolean existsKnowledgeBase(String companyCode) {
@@ -129,6 +138,18 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
return ret; return ret;
} }
@Override
public boolean deleteIndex(String kbId) {
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
DeleteIndexResponse indexDocumentResponse = KnowledgeBaseUtil.deleteIndex(client, workspaceId, kbId);
return indexDocumentResponse.getBody().getSuccess();
} catch (Exception e) {
throw new RuntimeException("删除知识库失败: " + e.getMessage(), e);
}
}
@Override @Override
public boolean deleteIndexDocument(String kbId, String fileIds) { public boolean deleteIndexDocument(String kbId, String fileIds) {
String workspaceId = config.getWorkspaceId(); String workspaceId = config.getWorkspaceId();
@@ -170,6 +191,17 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
throw new RuntimeException("添加文档到知识库失败: " + e.getMessage(), e); throw new RuntimeException("添加文档到知识库失败: " + e.getMessage(), e);
} }
} }
@Override
public void submitDocuments(String kbId, List<String> fileIds) {
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
AiCloudKnowledgeBaseUtil.submitIndexAddDocumentsJob(client, workspaceId, kbId, fileIds);
} catch (Exception e) {
throw new RuntimeException("添加文档到知识库失败: " + e.getMessage(), e);
}
}
} }

View File

@@ -156,4 +156,24 @@ public class AiCloudKnowledgeBaseUtil {
RuntimeOptions runtime = new RuntimeOptions(); RuntimeOptions runtime = new RuntimeOptions();
return client.submitIndexAddDocumentsJobWithOptions(workspaceId, submitIndexAddDocumentsJobRequest, headers, runtime); return client.submitIndexAddDocumentsJobWithOptions(workspaceId, submitIndexAddDocumentsJobRequest, headers, runtime);
} }
/**
* 向一个非结构化知识库追加导入已解析的文档
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param fileId 文档ID
* @param sourceType 数据类型
* @return 阿里云百炼服务的响应
*/
public static SubmitIndexAddDocumentsJobResponse submitIndexAddDocumentsJob(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, List<String> fileIds) throws Exception {
Map<String, String> headers = new HashMap<>();
SubmitIndexAddDocumentsJobRequest submitIndexAddDocumentsJobRequest = new SubmitIndexAddDocumentsJobRequest();
submitIndexAddDocumentsJobRequest.setIndexId(indexId);
submitIndexAddDocumentsJobRequest.setDocumentIds(fileIds);
submitIndexAddDocumentsJobRequest.setSourceType("DATA_CENTER_FILE");
RuntimeOptions runtime = new RuntimeOptions();
return client.submitIndexAddDocumentsJobWithOptions(workspaceId, submitIndexAddDocumentsJobRequest, headers, runtime);
}
} }

View File

@@ -31,6 +31,9 @@ public class PwlProject implements Serializable {
@Schema(description = "ID") @Schema(description = "ID")
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;
@Schema(description = "公司id")
private Integer companyId;
@Schema(description = "项目名称") @Schema(description = "项目名称")
private String name; private String name;

View File

@@ -12,6 +12,9 @@
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
</if> </if>
<if test="param.companyId != null">
AND a.company_id = #{param.companyId}
</if>
<if test="param.name != null"> <if test="param.name != null">
AND a.name LIKE CONCAT('%', #{param.name}, '%') AND a.name LIKE CONCAT('%', #{param.name}, '%')
</if> </if>

View File

@@ -30,6 +30,9 @@ public class PwlProjectParam extends BaseParam {
@Schema(description = "ID") @Schema(description = "ID")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer id; private Integer id;
@Schema(description = "公司id")
private Integer companyId;
@Schema(description = "项目名称") @Schema(description = "项目名称")
private String name; private String name;