三重一大、重大经济决策调查表数据生成优化
This commit is contained in:
@@ -0,0 +1,510 @@
|
||||
package com.gxwebsoft.ai.service.impl;
|
||||
|
||||
import com.aliyun.bailian20231229.Client;
|
||||
import com.aliyun.bailian20231229.models.RetrieveResponse;
|
||||
import com.aliyun.bailian20231229.models.RetrieveResponseBody;
|
||||
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyData;
|
||||
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes;
|
||||
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.JSONObject;
|
||||
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
|
||||
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
|
||||
import com.gxwebsoft.ai.service.AuditContent3DecisionService;
|
||||
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
|
||||
import com.gxwebsoft.pwl.entity.PwlProjectLibrary;
|
||||
import com.gxwebsoft.pwl.service.PwlProjectLibraryService;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AuditContent3DecisionServiceImpl implements AuditContent3DecisionService {
|
||||
|
||||
@Autowired
|
||||
private KnowledgeBaseClientFactory clientFactory;
|
||||
|
||||
@Autowired
|
||||
private KnowledgeBaseConfig config;
|
||||
|
||||
@Autowired
|
||||
private PwlProjectLibraryService pwlProjectLibraryService;
|
||||
|
||||
// 工作流配置 - 重大经济决策调查表
|
||||
private static final String DECISION_TABLE_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
|
||||
private static final String DECISION_TABLE_TOKEN = "Bearer app-yN7Q8GEN9E7SCMkhI6HaAagW";
|
||||
|
||||
@Override
|
||||
public JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary,
|
||||
String userName, String history, String suggestion, Object data) {
|
||||
log.info("开始生成重大经济决策调查表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
|
||||
userName, kbIds, libraryIds, projectLibrary);
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
// 1. 从不同知识库召回相关内容
|
||||
Map<String, List<String>> knowledgeSources = retrieveDecisionKnowledge(kbIds, libraryIds, projectLibrary);
|
||||
|
||||
// 2. 分析三重一大数据,确定审计重点
|
||||
Map<String, List<JSONObject>> auditFocusAreas = analyzeTripleOneData(data);
|
||||
|
||||
// 3. 生成重大经济决策调查表数据
|
||||
JSONArray decisionTableData = generateDecisionTable(knowledgeSources, auditFocusAreas, userName, history, suggestion);
|
||||
|
||||
// 4. 构建返回结果
|
||||
result.put("success", true);
|
||||
result.put("data", decisionTableData);
|
||||
result.put("total_records", decisionTableData.size());
|
||||
result.put("generated_time", new Date().toString());
|
||||
result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms");
|
||||
|
||||
log.info("重大经济决策调查表生成成功 - 记录数: {}, 处理时间: {}ms",
|
||||
decisionTableData.size(), (System.currentTimeMillis() - startTime));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("生成重大经济决策调查表失败", e);
|
||||
result.put("success", false);
|
||||
result.put("error", e.getMessage());
|
||||
throw new RuntimeException("生成重大经济决策调查表失败: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分析三重一大数据,确定审计重点领域
|
||||
*/
|
||||
private Map<String, List<JSONObject>> analyzeTripleOneData(Object data) {
|
||||
Map<String, List<JSONObject>> auditFocus = new HashMap<>();
|
||||
|
||||
if (data == null) {
|
||||
log.info("未传入三重一大数据");
|
||||
return auditFocus;
|
||||
}
|
||||
|
||||
try {
|
||||
// 解析三重一大数据
|
||||
JSONArray tripleData;
|
||||
if (data instanceof JSONArray) {
|
||||
tripleData = (JSONArray) data;
|
||||
} else if (data instanceof List) {
|
||||
tripleData = JSONArray.parseArray(JSONObject.toJSONString(data));
|
||||
} else {
|
||||
// 尝试从JSONObject中提取data字段
|
||||
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(data));
|
||||
if (jsonObject.containsKey("data") && jsonObject.get("data") instanceof JSONArray) {
|
||||
tripleData = jsonObject.getJSONArray("data");
|
||||
} else {
|
||||
log.warn("无法解析三重一大数据结构: {}", data.getClass().getSimpleName());
|
||||
return auditFocus;
|
||||
}
|
||||
}
|
||||
|
||||
// 按分类分组不通过的测试结果
|
||||
for (int i = 0; i < tripleData.size(); i++) {
|
||||
JSONObject item = tripleData.getJSONObject(i);
|
||||
if (item != null && "不通过".equals(item.getString("testResult"))) {
|
||||
String category = item.getString("category");
|
||||
if (category != null) {
|
||||
auditFocus.computeIfAbsent(category, k -> new ArrayList<>()).add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info("三重一大分析完成 - 发现 {} 个分类存在不通过项", auditFocus.size());
|
||||
auditFocus.forEach((category, items) ->
|
||||
log.info("分类 {}: {} 个不通过项", category, items.size()));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("分析三重一大数据失败", e);
|
||||
}
|
||||
|
||||
return auditFocus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检索重大经济决策相关知识
|
||||
*/
|
||||
private Map<String, List<String>> retrieveDecisionKnowledge(String kbIds, String libraryIds, String projectLibrary) {
|
||||
Map<String, List<String>> knowledgeSources = new HashMap<>();
|
||||
knowledgeSources.put("enterprise", new ArrayList<>()); // 企业单位库
|
||||
knowledgeSources.put("regulation", new ArrayList<>()); // 公共法律法规库
|
||||
knowledgeSources.put("auditCase", new ArrayList<>()); // 审计案例库
|
||||
|
||||
// 企业单位库检索 - 主要来源
|
||||
if (StrUtil.isNotBlank(kbIds)) {
|
||||
Arrays.stream(kbIds.split(","))
|
||||
.map(String::trim)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.forEach(kbId -> knowledgeSources.get("enterprise")
|
||||
.addAll(queryKnowledgeBase(kbId, buildEnterpriseQueries(), 200)));
|
||||
}
|
||||
|
||||
// 公共法律法规库检索
|
||||
if (StrUtil.isNotBlank(libraryIds)) {
|
||||
List<String> idList = StrUtil.split(libraryIds, ',');
|
||||
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(
|
||||
new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
|
||||
String libraryKbIds = ret.stream().map(PwlProjectLibrary::getKbId).collect(Collectors.joining(","));
|
||||
|
||||
Arrays.stream(libraryKbIds.split(","))
|
||||
.map(String::trim)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.forEach(libId -> knowledgeSources.get("regulation")
|
||||
.addAll(queryKnowledgeBase(libId, buildRegulationQueries(), 150)));
|
||||
}
|
||||
|
||||
// 审计案例库检索
|
||||
if (StrUtil.isNotBlank(projectLibrary)) {
|
||||
knowledgeSources.get("auditCase").addAll(
|
||||
queryKnowledgeBase(projectLibrary, buildAuditCaseQueries(), 100));
|
||||
}
|
||||
|
||||
// 智能去重和排序
|
||||
knowledgeSources.forEach((key, list) -> {
|
||||
List<String> processed = list.stream()
|
||||
.distinct()
|
||||
.limit(getLimitBySourceType(key))
|
||||
.collect(Collectors.toList());
|
||||
knowledgeSources.put(key, processed);
|
||||
});
|
||||
|
||||
return knowledgeSources;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建企业单位库查询
|
||||
*/
|
||||
private List<String> buildEnterpriseQueries() {
|
||||
return Arrays.asList(
|
||||
"重大经济决策事项 会议记录 会议纪要",
|
||||
"决策程序 集体决策 会议纪要 签到表",
|
||||
"重大投资项目 采购项目 资产处置 预算管理",
|
||||
"资金使用 外包业务 经济决策",
|
||||
"总经理办公会 董事会 党委会 决策会议"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建法律法规库查询
|
||||
*/
|
||||
private List<String> buildRegulationQueries() {
|
||||
return Arrays.asList(
|
||||
"重大经济决策 集体决策规定",
|
||||
"决策程序 法律法规要求",
|
||||
"三重一大 经济决策 程序要求"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建审计案例库查询
|
||||
*/
|
||||
private List<String> buildAuditCaseQueries() {
|
||||
return Arrays.asList(
|
||||
"重大经济决策审计案例 检查方法",
|
||||
"决策程序检查 执行效果评估",
|
||||
"经济决策测试 审计步骤"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据知识库类型获取限制数量
|
||||
*/
|
||||
private int getLimitBySourceType(String sourceType) {
|
||||
switch (sourceType) {
|
||||
case "enterprise": return 300;
|
||||
case "regulation": return 200;
|
||||
case "auditCase": return 150;
|
||||
default: return 100;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成重大经济决策调查表
|
||||
*/
|
||||
private JSONArray generateDecisionTable(Map<String, List<String>> knowledgeSources,
|
||||
Map<String, List<JSONObject>> auditFocusAreas,
|
||||
String userName, String history, String suggestion) {
|
||||
// 构建优化的知识上下文
|
||||
String knowledgeContext = buildKnowledgeContext(knowledgeSources, auditFocusAreas, history, suggestion);
|
||||
|
||||
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
|
||||
|
||||
JSONArray rawData = callDecisionWorkflow(requestBody);
|
||||
|
||||
// 后处理:数据清洗和格式化
|
||||
return postProcessDecisionData(rawData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建知识上下文
|
||||
*/
|
||||
private String buildKnowledgeContext(Map<String, List<String>> knowledgeSources,
|
||||
Map<String, List<JSONObject>> auditFocusAreas,
|
||||
String history, String suggestion) {
|
||||
StringBuilder context = new StringBuilder();
|
||||
|
||||
// 1. 分析要求
|
||||
context.append("## 重大经济决策调查表生成要求\n");
|
||||
context.append("请基于以下知识生成重大经济决策调查表数据:\n\n");
|
||||
context.append("1. 重点关注重大预算管理、重大项目实施、重大采购项目、重大投资项目、重大外包业务、重大资产处置、大额资金使用的决策和执行情况\n");
|
||||
context.append("2. 检查决策程序的完整性(签到表、决策纪要、决策人员签字确认等)\n");
|
||||
context.append("3. 评估决策执行情况和效果\n");
|
||||
context.append("4. 程序字段要详细描述具体的决策程序,包括会议类型、参与人员、决策依据文件等\n\n");
|
||||
|
||||
// 2. 数据格式要求
|
||||
context.append("## 数据格式要求\n");
|
||||
context.append("需要生成JSON数组格式的数据,每条记录包含以下字段:\n");
|
||||
context.append("[\n");
|
||||
context.append(" {\n");
|
||||
context.append(" \"decisionItem\": \"重大经济决策事项名称(具体描述)\",\n");
|
||||
context.append(" \"meetingTime\": \"会议时间(YYYY-MM-DD格式)\",\n");
|
||||
context.append(" \"decisionAmount\": \"决策事项金额(包含单位)\",\n");
|
||||
context.append(" \"procedure\": \"详细的决策程序描述,包括会议类型、参会人员、决策依据文件等\",\n");
|
||||
context.append(" \"executionStatus\": \"执行情况(是/否)\",\n");
|
||||
context.append(" \"executionEffect\": {\n");
|
||||
context.append(" \"good\": \"好(是/否)\",\n");
|
||||
context.append(" \"normal\": \"一般(是/否)\",\n");
|
||||
context.append(" \"bad\": \"差(是/否)\"\n");
|
||||
context.append(" }\n");
|
||||
context.append(" }\n");
|
||||
context.append("]\n\n");
|
||||
|
||||
// 3. 三重一大分析结果 - 审计重点
|
||||
if (!auditFocusAreas.isEmpty()) {
|
||||
context.append("## 三重一大制度分析结果 - 审计重点领域\n");
|
||||
context.append("基于三重一大制度对比分析,发现以下问题领域,请重点关注这些领域的决策事项:\n\n");
|
||||
|
||||
auditFocusAreas.forEach((category, items) -> {
|
||||
context.append("### ").append(category).append("领域\n");
|
||||
context.append("发现").append(items.size()).append("个不通过项:\n");
|
||||
|
||||
for (int i = 0; i < items.size() && i < 3; i++) { // 限制显示数量
|
||||
JSONObject item = items.get(i);
|
||||
context.append(i + 1).append(". ")
|
||||
.append(item.getString("checkEvidence")).append("\n");
|
||||
context.append(" 公司制度问题: ").append(item.getString("companyFormulation")).append("\n");
|
||||
context.append(" 政策要求: ").append(item.getString("policyContent")).append("\n\n");
|
||||
}
|
||||
});
|
||||
context.append("\n");
|
||||
} else {
|
||||
context.append("## 三重一大分析\n");
|
||||
context.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");
|
||||
context.append("以下是从企业单位库检索到的相关知识:\n");
|
||||
knowledgeSources.get("enterprise").stream()
|
||||
.limit(200)
|
||||
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
|
||||
context.append("\n");
|
||||
}
|
||||
|
||||
// 7. 法律法规知识
|
||||
if (!knowledgeSources.get("regulation").isEmpty()) {
|
||||
context.append("## 法律法规知识\n");
|
||||
context.append("以下是从公共法律法规库检索到的相关知识:\n");
|
||||
knowledgeSources.get("regulation").stream()
|
||||
.limit(150)
|
||||
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
|
||||
context.append("\n");
|
||||
}
|
||||
|
||||
// 8. 审计案例知识
|
||||
if (!knowledgeSources.get("auditCase").isEmpty()) {
|
||||
context.append("## 审计案例知识\n");
|
||||
context.append("以下是从审计案例库检索到的相关知识:\n");
|
||||
knowledgeSources.get("auditCase").stream()
|
||||
.limit(100)
|
||||
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
|
||||
}
|
||||
|
||||
log.debug("构建的知识上下文长度: {}", context.length());
|
||||
return context.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 后处理决策数据
|
||||
*/
|
||||
private JSONArray postProcessDecisionData(JSONArray rawData) {
|
||||
JSONArray processedData = new JSONArray();
|
||||
|
||||
for (int i = 0; i < rawData.size(); i++) {
|
||||
JSONObject item = rawData.getJSONObject(i);
|
||||
if (item != null) {
|
||||
processedData.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("后处理完成 - 输入数据条数: {}, 输出数据条数: {}", rawData.size(), processedData.size());
|
||||
return processedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询知识库
|
||||
*/
|
||||
private List<String> queryKnowledgeBase(String kbId, List<String> queries, int topK) {
|
||||
Set<String> results = new LinkedHashSet<>();
|
||||
String workspaceId = config.getWorkspaceId();
|
||||
|
||||
try {
|
||||
Client client = clientFactory.createClient();
|
||||
|
||||
for (String query : queries) {
|
||||
try {
|
||||
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
|
||||
|
||||
Optional.ofNullable(resp)
|
||||
.map(RetrieveResponse::getBody)
|
||||
.map(RetrieveResponseBody::getData)
|
||||
.map(RetrieveResponseBodyData::getNodes)
|
||||
.orElse(Collections.emptyList())
|
||||
.stream()
|
||||
.limit(topK)
|
||||
.forEach(node -> processNode(node, results));
|
||||
} catch (Exception e) {
|
||||
log.warn("查询知识库失败 - kbId: {}, query: {}", kbId, query, e);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("创建知识库客户端失败", e);
|
||||
}
|
||||
|
||||
return new ArrayList<>(results);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理知识库节点
|
||||
*/
|
||||
private void processNode(RetrieveResponseBodyDataNodes node, Set<String> results) {
|
||||
try {
|
||||
String text = node.getText();
|
||||
if (StrUtil.isBlank(text) || text.length() < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 限制文本长度,避免上下文过长
|
||||
if (text.length() > 500) {
|
||||
text = text.substring(0, 500) + "...";
|
||||
}
|
||||
|
||||
String docName = extractDocumentName(node);
|
||||
String formattedText = String.format("《%s》%s", docName, text);
|
||||
results.add(formattedText);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("处理知识库节点失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取文档名称
|
||||
*/
|
||||
private String extractDocumentName(RetrieveResponseBodyDataNodes node) {
|
||||
try {
|
||||
Object metadataObj = node.getMetadata();
|
||||
if (metadataObj instanceof Map) {
|
||||
Map<?, ?> metadata = (Map<?, ?>) metadataObj;
|
||||
Object docNameObj = metadata.get("doc_name");
|
||||
if (docNameObj != null) {
|
||||
String docName = docNameObj.toString();
|
||||
return docName.length() > 50 ? docName.substring(0, 50) + "..." : docName;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("提取文档名称失败", e);
|
||||
}
|
||||
return "相关文档";
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用重大经济决策工作流
|
||||
*/
|
||||
private JSONArray callDecisionWorkflow(JSONObject requestBody) {
|
||||
try {
|
||||
log.info("调用重大经济决策工作流,请求体长度: {}", requestBody.toString().length());
|
||||
|
||||
String result = HttpUtil.createPost(DECISION_TABLE_WORKFLOW_URL)
|
||||
.header("Authorization", DECISION_TABLE_TOKEN)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(requestBody.toString())
|
||||
.timeout(10 * 60 * 1000) // 10分钟超时
|
||||
.execute()
|
||||
.body();
|
||||
|
||||
log.info("工作流返回结果长度: {}", result.length());
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode rootNode = objectMapper.readTree(result);
|
||||
|
||||
// 简化的返回结构处理 - 参考 AuditContentServiceImpl3 的写法
|
||||
String outputText = rootNode.path("data")
|
||||
.path("outputs")
|
||||
.path("result")
|
||||
.asText();
|
||||
|
||||
if (StrUtil.isBlank(outputText)) {
|
||||
log.warn("工作流返回结果为空");
|
||||
return new JSONArray();
|
||||
}
|
||||
|
||||
// 使用Jackson解析数组
|
||||
JsonNode arrayNode = objectMapper.readTree(outputText);
|
||||
JSONArray jsonArray = JSONArray.parseArray(arrayNode.toString());
|
||||
|
||||
log.info("成功解析工作流返回数据,记录数: {}", jsonArray.size());
|
||||
return jsonArray;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("调用重大经济决策工作流失败", e);
|
||||
throw new RuntimeException("调用重大经济决策工作流失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建工作流请求
|
||||
*/
|
||||
private JSONObject buildWorkflowRequest(String knowledge, String userName) {
|
||||
JSONObject requestBody = new JSONObject();
|
||||
JSONObject inputs = new JSONObject();
|
||||
|
||||
inputs.put("knowledge", knowledge);
|
||||
|
||||
requestBody.put("inputs", inputs);
|
||||
requestBody.put("response_mode", "blocking");
|
||||
requestBody.put("user", userName);
|
||||
requestBody.put("timeout", 600); // 10分钟超时
|
||||
|
||||
return requestBody;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user