添加生成的内容历史记录、抽象实现类共用方法

This commit is contained in:
2025-11-14 16:03:21 +08:00
parent 1c7f5c878e
commit ea75d02abf
16 changed files with 1324 additions and 1105 deletions

View File

@@ -0,0 +1,116 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
public class AuditConstants {
// 工作流配置
public static class Workflow {
// 三重一大工作流
public static final String TRIPLE_ONE_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
public static final String TRIPLE_ONE_TOKEN = "Bearer app-tjXbmHDE6daMbYOT4O13ev2X";
// 重大经济决策调查表工作流
public static final String DECISION_TABLE_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
public static final String DECISION_TABLE_TOKEN = "Bearer app-yN7Q8GEN9E7SCMkhI6HaAagW";
}
// 三重一大分类定义
public static final List<String> TRIPLE_ONE_CATEGORY_ORDER = Arrays.asList(
"重大决策", "重要人事任免", "重大项目安排", "大额度资金运作", "决策权力主体和程序"
);
public static final Map<String, String> TRIPLE_ONE_CATEGORIES = new LinkedHashMap<>();
static {
TRIPLE_ONE_CATEGORIES.put("重大决策", "重大决策事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("重要人事任免", "重要人事任免事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("重大项目安排", "重大项目安排事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("大额度资金运作", "大额度资金运作事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("决策权力主体和程序", "决策权力主体和程序的规定");
}
// 三重一大Excel数据映射
public static final Map<String, String[]> TRIPLE_ONE_EXCEL_DATA_MAP = new HashMap<>();
static {
// 重大决策
TRIPLE_ONE_EXCEL_DATA_MAP.put("重大决策", new String[]{
"1.重大决策事项:是指依照《中华人民共和国公司法》、《中华人民共和国全民所有制工业企业法》、《中华人民共和国企业国有资产法》、《中华人民共和国商业银行法》、《中华人民共和国证券法》、《中华人民共和国保险法》以及其他有关法律法规和党内法规规定的应当由股东大会(股东会)、董事会、未设董事会的经理班子、职工代表大会和党委(党组)决定的事项。主要包括企业贯彻执行党和国家的路线方针政策、法律法规和上级重要决定的重大措施,企业发展战略、破产、改制、兼并重组、资产调整、产权转让、对外投资、利益调配、机构调整等方面的重大决策,企业党的建设和安全稳定的重大决策,以及其他重大决策事项。",
"第四条重大决策的范围(一)集团公司贯彻执行国家法律法规,自治区战略部署及重要决策,以及上级主管部门重要决定等的重大举措;(二)集团公司章程制订和重要修订;集团公司重大基本管理制度,包括\"三重一大\"决策、投资、担保、资产交易、收入分配、人事、财务理,授权管理以及责任追究等重大管理制度的制订和重大修订;(三)集团公司生产经营方针、发展战略和中长期发展规划,以及重大投融资规划;(四)集团公司及重要子企业主业确定及变更;集团公司投资设立各类二级企业方案;集团公司及二级子公司发生分立、合并、重组,破产、解散及产权变更、增减资本方案;集团公司及所属子公司改制、股份制改造、混合所有制改革等方案;(五)集团公司重大财务管理事项,包括年度财务预算、年度财务决算、利润分配方案、亏损弥补方案;(六)集团公司内部收入分配事项,包括年度工资总额方案、职工工资、奖金、分流安置、劳动保护和劳动保险等事关职工切身利益的重大事项;集团公司所属部门、二级企业负责人年度考核结果及年度薪酬兑现方案;(七)集团公司制订或实施股权激励和员工持股计划;(八)集团公司及所属企业国有股权比例由控股变为非控股或国有股权由参股变为控股的事项;(九)集团公司及所属企业单笔金额为300万元及以上对外重大担保事项集团公司及所属企业重大关联交易事项、内部借款单笔金额为2000万元及以上事项;(十)集团公司及所属企业产权(资产)对外非公开协议转让、无偿划转及公开进场转让单笔金额为300万元及以上的事项;集团公司内部重组整合进行的产权(资产)非公开协议转让、无偿划转单笔金额为300万元及以上的事项;(十一)集团公司及所属企业重大资产损失、大额不良资产、核销单笔金额为20万元及以上的事项;集团公司及所属企业单笔放弃金额为30万元及以上的重大权益事项;(十二)集团公司内部机构改革方案,内部管理机构设立和调整方案,内部定岗、定编,定员、定责方案;(十三)集团公司党建群团工作的重大事项、方案;(十四)集团公司董事会年度工作报告、经理层年度工作报告、年度依法治企工作报告,年度内部控制体系工作报告等重要报告;(十五)集团公司应对重大法律纠纷、安全稳定,重大突发事件的重大措施及方案;(十六)法律法规和企业章程规定的事项,以及集团公司认为需要集体决策的关系到企业全局性、方向性、战略性的其他重大事项。",
"(一)贯彻执行国家法律法规、自治区战略部署及集团公司的重要决策,以及上级主管部门重要决定等的重大举措;(二)章程制订和重要修订;重大基本管理制度,包括\"三重一大\"决策、投资、担保、资产交易、收入分配、人事、财务管理、授权管理以及责任追究等重大管理制度的制订和重大修订生产经营方针、发展战略和中长期发展规划以及重大投融资规划公司主业确定及变更投资设立各类企业方案发生分立、合并、重组、破产、解散及产权变更、增减资本方案公司及所属企业改制、股份制改造、混合所有制改革等方案重大财务管理事项包括年度财务预算、年度财务决算、利润分配方案、亏损弥补方案内部收入分配事项包括年度工资总额方案、职工工资、奖金、分流安置、劳动保护和劳动保险等事关职工切身利益的重大事项所属部门年度考核结果及年度薪酬兑现方案制订或实施股权激励和员工持股计划公司国有股权比例由控股变为非控股或国有股权由参股变为控股的事项公司对外担保事项公司重大关联交易事项和内部借款单笔100万元及以上的事项公司产权资产对外非公开协议转让、无偿划转及公开进场转让公司内部重组整合进行的产权资产非公开协议转让、无偿划转的事项十一公司重大资产损失、大额不良资产核销单笔金额为1万元及以上的事项公司单笔放弃1万元及以上的重大权益事项十二公司内部机构改革方案内部管理机构设立和调整方案内部定岗、定编、定员、定责方案十三公司党建群团工作的重大事项、方案十四公司年度工作报告、经理层年度工作报告、年度依法治企工作报告、年度内部控制体系工作报告等重要报告十五公司应对重大法律纠纷、安全稳定、重大突发事件的措施及方案十六法律法规和企业章程规定的事项以及公司认为需要集体决策的关系到企业全局性、方向性、战略性的其他重大事项。"
});
// 重要人事任免
TRIPLE_ONE_EXCEL_DATA_MAP.put("重要人事任免", new String[]{
"2.重要人事任免事项:是指企业直接管理的领导人员以及其他经营管理人员的职务调整事项。主要包括企业中层以上经营管理人员和下属企业、单位领导班子成员的任免、聘用、解除聘用和后备人选的确定,向控股和参股企业委派股东代表,推荐董事会、监事会成员和经理、财务负责人,以及其他重要人事任免事项。",
"第五条重要人事任免的范围(一)对集团公司中层管理人员、二级子公司领导班子成员的任免或聘用、解聘;相当于集团公司中层副职及以上的职业经理人的选聘、解聘;(二)按照企业章程约定,委派、提名、推荐集团公司非全资二级企业董事会、监事会成员和高级经营管理人员;(三)提名或委派集团公司三级企业董事长或执行董事、总经理人选;(四)集团公司中层管理人员后备人选;(五)涉及集团公司总部中层管理人员以及二级子公司班子成员的重要奖惩,对违犯党纪政纪干部职工的处理;(六)重大人事变动及其他人事管理的重要事项。",
"(一)对公司中层管理人员(包括重大项目负责人)的任免或聘用、解除聘用和后备人选的推荐、确定;(二)委派、提名、推荐董事、监事和经理层、财务负责人;(三)干部员工的奖惩;(四)重大人事变动及其他人事管理的重要事项。"
});
// 重大项目安排
TRIPLE_ONE_EXCEL_DATA_MAP.put("重大项目安排", new String[]{
"3、重大项目安排事项是指对企业资产规模、资本结构、盈利能力以及生产装备、技术状况等产生重要影响的项目的设立和安排。主要包括年度投资计划融资、担保项目期权、期货等金融衍生业务重要设备和技术引进采购大宗物资和购买服务重大工程建设项目以及其他重大项目安排事项。",
"(一)集团公司年度投资计划方案;(二)集团公司年度融资计划方案;(三)集团公司及所属企业总投资额为3000万元及以上的投资项目(投资项目范围按集团公司投资管理办法明确的投资项目范围) ;(四)应当向自治区国资委报告的重大投资管理事项;(五)其他需要集体研究决定的重要项目安排事项。",
"企业年度投资计划和投资方案企业年度融资计划和融资方案包括银行借贷、上市、发行债券等企业50万元及以上的投资项目以及非主业投资项目企业的重大技术改造方案、重要技术设备引进项目重大、关键性的设备引进和重要物资设备购置等重大招投标管理项目应当向自治区国资委或广西旅游发展集团有限公司以下简称\"集团公司\")报告的重大投资管理事项;(七)其他需要集体研究决定的重要项目安排事项。"
});
// 大额度资金运作
TRIPLE_ONE_EXCEL_DATA_MAP.put("大额度资金运作", new String[]{
"4.大额度资金运作事项:是指超过由企业或者履行国有资产出资人职责的机构所规定的企业领导人员有权调动、使用的资金限额的资金调动和使用。主要包括年度预算内大额度资金调动和使用,超预算的资金调动和使用,对外大额捐赠、赞助,以及其他大额度资金运作事项。",
"(一)除重大决策事项、重大项目安排事项外涉及单笔7000万元及以上的年度预算内大额度资金使用事项;(二)除重大决策事项、重大项目安排事项外涉及单笔5000万元及以上的预算外大额度经营性资金的使用事项;(三)预算外非经营性单笔100万元及以上、广西美术馆艺术品收藏单件或单次收藏一批100万元及以上的大额资金使用事项(四)集团公司及所属企业10万元及以上的对外捐赠、财务资助、公益慈善及用于脱贫攻坚(乡村振兴)等涉及企业政治责任和社会责任方面的重要事项;(五)公司单份工程签证涉及工程造价变更金额为500万元及以上的项目资金支出和其他大额度资金运作事项。",
"除重大决策事项、重大项目安排事项外涉及单笔500万元及以上的年度预算内大额度资金调动和使用除重大决策事项、重大项目安排事项外涉及单笔50万元及以上的预算外大额度资金调动和使用除重大决策事项、重大项目安排事项外涉及单笔10万元及以上的非生产性支出单份工程签证及造价变更额度为10万元及以上的企业对外捐赠、赞助在1万元及以上的事项其他大额度资金运作事项。"
});
// 决策权力主体和程序
TRIPLE_ONE_EXCEL_DATA_MAP.put("决策权力主体和程序", new String[]{
"",
"第十一条 凡属\"三重一大\"事项,应按规定程序决策,除遇重大突发事件和紧急情况外,应由领导班子以党委会、董事会或经理层会议形式集体讨论决定,不得以传阅会签或个别征求意见等方式代替集体决策。第十二条 集团公司决策主体权力运行必须坚持落实党组织的法定地位,规范党组织参与\"三重一大\"决策程序,确保党组织的领导核心和政治核心作用有效发挥。要坚持把党委研究讨论作为董事会、经理层决策重大问题的前置程序,在集团公司董事会决策前,对涉及企业改革发展稳定,重大经营管理和职工切身利益的\"三重一大\"事项决策事项,集团公司党委应当组织有关人员对决策事项进行调研和论证,提出意见建议,充分体现党组织对决策的定向把关作用,确保决策的合法性科学性、准确性。在董事会决策中,进入董事会的党委班子成员要按照党委的决定在董事会上充分发表意见,保证党委的意图在决策中得到体现。在董事会决策后,党委要建立\"三重一大\"决策事项跟踪问效制度、定期汇报制度、事后考核制度等,确保党的决策部署在企业贯彻好、执行好、落实好。第十三条 集团公司党委会、董事会,经理层对\"三重一大\"事项进行决策的具体程序和议题准备、表决、记录等事项严格按照集团公司党委会议事规则、董事会议事规则、总经理办公会议事规则规定的程序和要求执行。第十四条 集团公司研究决定企业改制及经营管理方面的重大问题、涉及职工切身利益的重大事项、制定重要的规章制度,应当听取企业工会的意见,并通过职工代表大会或者其他形式听取职工群众的意见和建议。按照国家有关规定须经职工代表大会或者职工大会审议通过的事项,履行相关程序后董事会或经理层方可批准或者作出决议。涉及重大决策、重大项目、大额度资金的使用,有合同意向的,应将合同的主要条款提交会议讨论。第十五条 \"三重一大\"事项经集体决策后,企业领导人员应当按照分工和职责组织实施。遇有分工和职责交叉的,应明确牵头落实人员。个人对集体决策有不同意见的,可以保留,但在作出新的决策前,应无条件执行。同时,可按组织程序向上级组织反映意见。第十六条 企业\"三重一大\"事项经集体决策后,应及时向自治区国资委报告有关决策情况。特别是属于重大报告事项的应按要求及时上报自治区国资委备案。自治区人民政府、自治区国资委另有规定需要报审、报批和备案的,按规定程序办理。",
"第十一条 凡属\"三重一大\"事项,党支部委员会成员应参加党支部委员会议对议题进行前置研究审议,保证党组织的意图在决策中得到体现。不得以传阅会签或个别征求意见等方式代替集体决策。第十二条 公司决策主体权力运行必须坚持落实党组织的法定地位,规范党组织参与\"三重一大\"决策程序,确保党组织的领导核心和政治核心作用有效发挥。要坚持把党支部研究讨论作为总经理办公会决策重大问题的前置程序。在总经理办公会会议决策前,对涉及企业改革发展稳定、重大经营管理和职工切身利益的\"三重一大\"事项决策事项,党支部应当组织有关人员对决策事项进行调研和论证,提出意见建议,充分体现党支部对决策的定向把关作用,确保决策的合法性、科学性、准确性。在总经理办公会的决策中,担任执行董事的党支部领导班子成员要按照党支部的决定在总经理办公会上充分发表意见,保证党支部的意图在决策中得到体现。在总经理办公会决策后,党支部要建立\"三重一大\"决策事项跟踪问效制度、定期汇报制度、事后考核制度等,确保党的决策部署在企业贯彻好、执行好、落实好。第十三条 公司党支部、经理层对\"三重一大\"事项进行决策的具体程序和议题准备、表决、记录等事项严格按照公司相关议事规则规定的程序和要求执行。第十四条 公司研究决定企业改制及经营管理方面的重大问题、涉及职工切身利益的重大事项、制定重要的规章制度,应当听取企业工会的意见,并通过职工代表大会或者其他形式听取职工群众的意见和建议。按照国家有关规定须经职工代表大会或者职工大会审议通过的事项,履行相关程序后经理层方可批准或者作出决议。涉及重大决策、重大项目、大额度资金的使用,有合同意向的,应将合同的主要条款提交会议讨论。第十五条 \"三重一大\"事项经集体决策后,企业领导人员应当按照分工和职责组织实施。遇有分工和职责交叉的,应明确牵头落实人员。个人对集体决策有不同意见的,可以保留,但在作出新的决策前,应无条件执行。同时,可按组织程序向上级组织反映意见。"
});
}
// 重大经济决策调查表 - Excel Sheet1 中的条件信息
public static final String DECISION_TABLE_EXCEL_SHEET1_CONDITIONS =
"## 重大经济决策调查表审计重点\n" +
"重大经济事项的决策、执行和效果情况,具体包括重大预算管理、重大项目实施、重大采购项目、重大投资项目、重大外包业务、重大资产处置、大额资金使用的决策和执行情况等。\n\n" +
"## 重点关注\n" +
"\"三重一大\"集体决策制度是否建立健全。重大经济、经营活动必须进行集体决策的标准和必须参加决策的人员是否制定有规定,规定的集体决策的程序(签到表、决策纪要、最终形成的决策、决策人员的签字确认意见等)是否完整,是否有应集体决策而未集体决策的问题,是否有应参加集体决策的人因不合理理由不得参加集体决策的问题,形成的集体决策意见是否符合国家、自治区规定。\n\n" +
"## 审计方法及步骤\n" +
"1. 查阅单位制度,检查议事制度是否建立,查看重大事项进行集体决策的规定,查阅相关会议记录资料,检查会议签到表、会议纪要、会议决定内容及决策参与人员签字确认意见,以确认会议集体决策程序的完整性;对照重大决策内容,检查相关对应资料,确认集体决策内容是否符合国家、自治区规定。\n" +
"2. 抽查一些重大经济决策事项,比如重大建设项目、维修、大宗物资采购、企业投资运营等,审查其决策的背景、决策的过程、决策的执行和落实情况,决策的效果情况,以此来确定是否符合国家、自治区相关规定,执行是否有效。";
// 关键词权重
public static final Map<String, Integer> TRIPLE_ONE_KEYWORD_WEIGHTS;
static {
Map<String, Integer> map = new HashMap<>();
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("会议纪要", 6);
map.put("金额标准", 6);
TRIPLE_ONE_KEYWORD_WEIGHTS = Collections.unmodifiableMap(map);
}
// 知识库检索限制
public static class KnowledgeBaseLimit {
public static final int ENTERPRISE_PER_ITEM = 10;
public static final int ENTERPRISE_TOTAL = 200;
public static final int REGULATION_TOTAL = 100;
public static final int AUDIT_CASE_TOTAL = 50;
public static final int ENTERPRISE_DEFAULT = 100;
public static final int REGULATION_DEFAULT = 80;
public static final int AUDIT_CASE_DEFAULT = 60;
}
// 审计内容类型
public static class AuditContentType {
public static final String TRIPLE_ONE = "TRIPLE_ONE";
public static final String DECISION_TABLE = "DECISION_TABLE";
}
}

View File

@@ -0,0 +1,33 @@
package com.gxwebsoft.ai.constants;
/**
* 重大经济决策调查表常量类
*/
public class AuditContent3DecisionConstants {
// 审计关键点、审计方法步骤
public static final String AUDIT_FOCUS_AND_METHODS =
"## 重大经济决策调查表审计重点\n" +
"重大经济事项的决策、执行和效果情况,具体包括重大预算管理、重大项目实施、重大采购项目、重大投资项目、重大外包业务、重大资产处置、大额资金使用的决策和执行情况等。\n\n" +
"## 重点关注\n" +
"\"三重一大\"集体决策制度是否建立健全。重大经济、经营活动必须进行集体决策的标准和必须参加决策的人员是否制定有规定,规定的集体决策的程序(签到表、决策纪要、最终形成的决策、决策人员的签字确认意见等)是否完整,是否有应集体决策而未集体决策的问题,是否有应参加集体决策的人因不合理理由不得参加集体决策的问题,形成的集体决策意见是否符合国家、自治区规定。\n\n" +
"## 审计方法及步骤\n" +
"1. 查阅单位制度,检查议事制度是否建立,查看重大事项进行集体决策的规定,查阅相关会议记录资料,检查会议签到表、会议纪要、会议决定内容及决策参与人员签字确认意见,以确认会议集体决策程序的完整性;对照重大决策内容,检查相关对应资料,确认集体决策内容是否符合国家、自治区规定。\n" +
"2. 抽查一些重大经济决策事项,比如重大建设项目、维修、大宗物资采购、企业投资运营等,审查其决策的背景、决策的过程、决策的执行和落实情况,决策的效果情况,以此来确定是否符合国家、自治区相关规定,执行是否有效。";
// 通用查询词
public static final String[] GLOBAL_REGULATION_QUERIES = {
"重大经济决策 法律法规",
"三重一大 政策规定",
"集体决策 制度规定"
};
public static final String[] GLOBAL_AUDIT_CASE_QUERIES = {
"重大经济决策 审计案例",
"三重一大 检查方法"
};
private AuditContent3DecisionConstants() {
// 防止实例化
}
}

View File

@@ -0,0 +1,105 @@
package com.gxwebsoft.ai.constants;
import java.util.HashMap;
import java.util.Map;
/**
* 三重一大制度常量类
*/
public class AuditContent3TripleConstants {
// 分类定义
public static final String CATEGORY_MAJOR_DECISION = "重大决策";
public static final String CATEGORY_PERSONNEL_APPOINTMENT = "重要人事任免";
public static final String CATEGORY_MAJOR_PROJECT = "重大项目安排";
public static final String CATEGORY_LARGE_FUND_OPERATION = "大额度资金运作";
public static final String CATEGORY_DECISION_PROCEDURE = "决策权力主体和程序";
// 分类描述
public static final Map<String, String> CATEGORY_DESCRIPTIONS = new HashMap<>();
static {
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_DECISION, "重大决策事项的定义和范围");
CATEGORY_DESCRIPTIONS.put(CATEGORY_PERSONNEL_APPOINTMENT, "重要人事任免事项的定义和范围");
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_PROJECT, "重大项目安排事项的定义和范围");
CATEGORY_DESCRIPTIONS.put(CATEGORY_LARGE_FUND_OPERATION, "大额度资金运作事项的定义和范围");
CATEGORY_DESCRIPTIONS.put(CATEGORY_DECISION_PROCEDURE, "决策权力主体和程序的规定");
}
// 政策内容
public static final Map<String, String> POLICY_CONTENTS = new HashMap<>();
static {
POLICY_CONTENTS.put(CATEGORY_MAJOR_DECISION,
"1.重大决策事项:是指依照《中华人民共和国公司法》、《中华人民共和国全民所有制工业企业法》、《中华人民共和国企业国有资产法》、《中华人民共和国商业银行法》、《中华人民共和国证券法》、《中华人民共和国保险法》以及其他有关法律法规和党内法规规定的应当由股东大会(股东会)、董事会、未设董事会的经理班子、职工代表大会和党委(党组)决定的事项。");
POLICY_CONTENTS.put(CATEGORY_PERSONNEL_APPOINTMENT,
"2.重要人事任免事项:是指企业直接管理的领导人员以及其他经营管理人员的职务调整事项。主要包括企业中层以上经营管理人员和下属企业、单位领导班子成员的任免、聘用、解除聘用和后备人选的确定,向控股和参股企业委派股东代表,推荐董事会、监事会成员和经理、财务负责人,以及其他重要人事任免事项。");
POLICY_CONTENTS.put(CATEGORY_MAJOR_PROJECT,
"3、重大项目安排事项是指对企业资产规模、资本结构、盈利能力以及生产装备、技术状况等产生重要影响的项目的设立和安排。主要包括年度投资计划融资、担保项目期权、期货等金融衍生业务重要设备和技术引进采购大宗物资和购买服务重大工程建设项目以及其他重大项目安排事项。");
POLICY_CONTENTS.put(CATEGORY_LARGE_FUND_OPERATION,
"4.大额度资金运作事项:是指超过由企业或者履行国有资产出资人职责的机构所规定的企业领导人员有权调动、使用的资金限额的资金调动和使用。主要包括年度预算内大额度资金调动和使用,超预算的资金调动和使用,对外大额捐赠、赞助,以及其他大额度资金运作事项。");
POLICY_CONTENTS.put(CATEGORY_DECISION_PROCEDURE,
"");
}
// 集团制度
public static final Map<String, String> GROUP_SYSTEMS = new HashMap<>();
static {
GROUP_SYSTEMS.put(CATEGORY_MAJOR_DECISION,
"第四条重大决策的范围(一)集团公司贯彻执行国家法律法规,自治区战略部署及重要决策,以及上级主管部门重要决定等的重大举措;(二)集团公司章程制订和重要修订;集团公司重大基本管理制度,包括\"三重一大\"决策、投资、担保、资产交易、收入分配、人事、财务理,授权管理以及责任追究等重大管理制度的制订和重大修订;(三)集团公司生产经营方针、发展战略和中长期发展规划,以及重大投融资规划;(四)集团公司及重要子企业主业确定及变更;集团公司投资设立各类二级企业方案;集团公司及二级子公司发生分立、合并、重组,破产、解散及产权变更、增减资本方案;集团公司及所属子公司改制、股份制改造、混合所有制改革等方案;(五)集团公司重大财务管理事项,包括年度财务预算、年度财务决算、利润分配方案、亏损弥补方案;(六)集团公司内部收入分配事项,包括年度工资总额方案、职工工资、奖金、分流安置、劳动保护和劳动保险等事关职工切身利益的重大事项;集团公司所属部门、二级企业负责人年度考核结果及年度薪酬兑现方案;(七)集团公司制订或实施股权激励和员工持股计划;(八)集团公司及所属企业国有股权比例由控股变为非控股或国有股权由参股变为控股的事项;(九)集团公司及所属企业单笔金额为300万元及以上对外重大担保事项集团公司及所属企业重大关联交易事项、内部借款单笔金额为2000万元及以上事项;(十)集团公司及所属企业产权(资产)对外非公开协议转让、无偿划转及公开进场转让单笔金额为300万元及以上的事项;集团公司内部重组整合进行的产权(资产)非公开协议转让、无偿划转单笔金额为300万元及以上的事项;(十一)集团公司及所属企业重大资产损失、大额不良资产、核销单笔金额为20万元及以上的事项;集团公司及所属企业单笔放弃金额为30万元及以上的重大权益事项;(十二)集团公司内部机构改革方案,内部管理机构设立和调整方案,内部定岗、定编,定员、定责方案;(十三)集团公司党建群团工作的重大事项、方案;(十四)集团公司董事会年度工作报告、经理层年度工作报告、年度依法治企工作报告,年度内部控制体系工作报告等重要报告;(十五)集团公司应对重大法律纠纷、安全稳定,重大突发事件的重大措施及方案;(十六)法律法规和企业章程规定的事项,以及集团公司认为需要集体决策的关系到企业全局性、方向性、战略性的其他重大事项。");
GROUP_SYSTEMS.put(CATEGORY_PERSONNEL_APPOINTMENT,
"第五条重要人事任免的范围(一)对集团公司中层管理人员、二级子公司领导班子成员的任免或聘用、解聘;相当于集团公司中层副职及以上的职业经理人的选聘、解聘;(二)按照企业章程约定,委派、提名、推荐集团公司非全资二级企业董事会、监事会成员和高级经营管理人员;(三)提名或委派集团公司三级企业董事长或执行董事、总经理人选;(四)集团公司中层管理人员后备人选;(五)涉及集团公司总部中层管理人员以及二级子公司班子成员的重要奖惩,对违犯党纪政纪干部职工的处理;(六)重大人事变动及其他人事管理的重要事项。");
GROUP_SYSTEMS.put(CATEGORY_MAJOR_PROJECT,
"(一)集团公司年度投资计划方案;(二)集团公司年度融资计划方案;(三)集团公司及所属企业总投资额为3000万元及以上的投资项目(投资项目范围按集团公司投资管理办法明确的投资项目范围) ;(四)应当向自治区国资委报告的重大投资管理事项;(五)其他需要集体研究决定的重要项目安排事项。");
GROUP_SYSTEMS.put(CATEGORY_LARGE_FUND_OPERATION,
"(一)除重大决策事项、重大项目安排事项外涉及单笔7000万元及以上的年度预算内大额度资金使用事项;(二)除重大决策事项、重大项目安排事项外涉及单笔5000万元及以上的预算外大额度经营性资金的使用事项;(三)预算外非经营性单笔100万元及以上、广西美术馆艺术品收藏单件或单次收藏一批100万元及以上的大额资金使用事项(四)集团公司及所属企业10万元及以上的对外捐赠、财务资助、公益慈善及用于脱贫攻坚(乡村振兴)等涉及企业政治责任和社会责任方面的重要事项;(五)公司单份工程签证涉及工程造价变更金额为500万元及以上的项目资金支出和其他大额度资金运作事项。");
GROUP_SYSTEMS.put(CATEGORY_DECISION_PROCEDURE,
"第十一条 凡属\"三重一大\"事项,应按规定程序决策,除遇重大突发事件和紧急情况外,应由领导班子以党委会、董事会或经理层会议形式集体讨论决定,不得以传阅会签或个别征求意见等方式代替集体决策。第十二条 集团公司决策主体权力运行必须坚持落实党组织的法定地位,规范党组织参与\"三重一大\"决策程序,确保党组织的领导核心和政治核心作用有效发挥。要坚持把党委研究讨论作为董事会、经理层决策重大问题的前置程序,在集团公司董事会决策前,对涉及企业改革发展稳定,重大经营管理和职工切身利益的\"三重一大\"事项决策事项,集团公司党委应当组织有关人员对决策事项进行调研和论证,提出意见建议,充分体现党组织对决策的定向把关作用,确保决策的合法性科学性、准确性。在董事会决策中,进入董事会的党委班子成员要按照党委的决定在董事会上充分发表意见,保证党委的意图在决策中得到体现。在董事会决策后,党委要建立\"三重一大\"决策事项跟踪问效制度、定期汇报制度、事后考核制度等,确保党的决策部署在企业贯彻好、执行好、落实好。第十三条 集团公司党委会、董事会,经理层对\"三重一大\"事项进行决策的具体程序和议题准备、表决、记录等事项严格按照集团公司党委会议事规则、董事会议事规则、总经理办公会议事规则规定的程序和要求执行。第十四条 集团公司研究决定企业改制及经营管理方面的重大问题、涉及职工切身利益的重大事项、制定重要的规章制度,应当听取企业工会的意见,并通过职工代表大会或者其他形式听取职工群众的意见和建议。按照国家有关规定须经职工代表大会或者职工大会审议通过的事项,履行相关程序后董事会或经理层方可批准或者作出决议。涉及重大决策、重大项目、大额度资金的使用,有合同意向的,应将合同的主要条款提交会议讨论。第十五条 \"三重一大\"事项经集体决策后,企业领导人员应当按照分工和职责组织实施。遇有分工和职责交叉的,应明确牵头落实人员。个人对集体决策有不同意见的,可以保留,但在作出新的决策前,应无条件执行。同时,可按组织程序向上级组织反映意见。第十六条 企业\"三重一大\"事项经集体决策后,应及时向自治区国资委报告有关决策情况。特别是属于重大报告事项的应按要求及时上报自治区国资委备案。自治区人民政府、自治区国资委另有规定需要报审、报批和备案的,按规定程序办理。");
}
// 公司制度
public static final Map<String, String> COMPANY_FORMULATIONS = new HashMap<>();
static {
COMPANY_FORMULATIONS.put(CATEGORY_MAJOR_DECISION,
"(一)贯彻执行国家法律法规、自治区战略部署及集团公司的重要决策,以及上级主管部门重要决定等的重大举措;(二)章程制订和重要修订;重大基本管理制度,包括\"三重一大\"决策、投资、担保、资产交易、收入分配、人事、财务管理、授权管理以及责任追究等重大管理制度的制订和重大修订生产经营方针、发展战略和中长期发展规划以及重大投融资规划公司主业确定及变更投资设立各类企业方案发生分立、合并、重组、破产、解散及产权变更、增减资本方案公司及所属企业改制、股份制改造、混合所有制改革等方案重大财务管理事项包括年度财务预算、年度财务决算、利润分配方案、亏损弥补方案内部收入分配事项包括年度工资总额方案、职工工资、奖金、分流安置、劳动保护和劳动保险等事关职工切身利益的重大事项所属部门年度考核结果及年度薪酬兑现方案制订或实施股权激励和员工持股计划公司国有股权比例由控股变为非控股或国有股权由参股变为控股的事项公司对外担保事项公司重大关联交易事项和内部借款单笔100万元及以上的事项公司产权资产对外非公开协议转让、无偿划转及公开进场转让公司内部重组整合进行的产权资产非公开协议转让、无偿划转的事项十一公司重大资产损失、大额不良资产核销单笔金额为1万元及以上的事项公司单笔放弃1万元及以上的重大权益事项十二公司内部机构改革方案内部管理机构设立和调整方案内部定岗、定编、定员、定责方案十三公司党建群团工作的重大事项、方案十四公司年度工作报告、经理层年度工作报告、年度依法治企工作报告、年度内部控制体系工作报告等重要报告十五公司应对重大法律纠纷、安全稳定、重大突发事件的措施及方案十六法律法规和企业章程规定的事项以及公司认为需要集体决策的关系到企业全局性、方向性、战略性的其他重大事项。");
COMPANY_FORMULATIONS.put(CATEGORY_PERSONNEL_APPOINTMENT,
"(一)对公司中层管理人员(包括重大项目负责人)的任免或聘用、解除聘用和后备人选的推荐、确定;(二)委派、提名、推荐董事、监事和经理层、财务负责人;(三)干部员工的奖惩;(四)重大人事变动及其他人事管理的重要事项。");
COMPANY_FORMULATIONS.put(CATEGORY_MAJOR_PROJECT,
"企业年度投资计划和投资方案企业年度融资计划和融资方案包括银行借贷、上市、发行债券等企业50万元及以上的投资项目以及非主业投资项目企业的重大技术改造方案、重要技术设备引进项目重大、关键性的设备引进和重要物资设备购置等重大招投标管理项目应当向自治区国资委或广西旅游发展集团有限公司以下简称\"集团公司\")报告的重大投资管理事项;(七)其他需要集体研究决定的重要项目安排事项。");
COMPANY_FORMULATIONS.put(CATEGORY_LARGE_FUND_OPERATION,
"除重大决策事项、重大项目安排事项外涉及单笔500万元及以上的年度预算内大额度资金调动和使用除重大决策事项、重大项目安排事项外涉及单笔50万元及以上的预算外大额度资金调动和使用除重大决策事项、重大项目安排事项外涉及单笔10万元及以上的非生产性支出单份工程签证及造价变更额度为10万元及以上的企业对外捐赠、赞助在1万元及以上的事项其他大额度资金运作事项。");
COMPANY_FORMULATIONS.put(CATEGORY_DECISION_PROCEDURE,
"第十一条 凡属\"三重一大\"事项,党支部委员会成员应参加党支部委员会议对议题进行前置研究审议,保证党组织的意图在决策中得到体现。不得以传阅会签或个别征求意见等方式代替集体决策。第十二条 公司决策主体权力运行必须坚持落实党组织的法定地位,规范党组织参与\"三重一大\"决策程序,确保党组织的领导核心和政治核心作用有效发挥。要坚持把党支部研究讨论作为总经理办公会决策重大问题的前置程序。在总经理办公会会议决策前,对涉及企业改革发展稳定、重大经营管理和职工切身利益的\"三重一大\"事项决策事项,党支部应当组织有关人员对决策事项进行调研和论证,提出意见建议,充分体现党支部对决策的定向把关作用,确保决策的合法性、科学性、准确性。在总经理办公会的决策中,担任执行董事的党支部领导班子成员要按照党支部的决定在总经理办公会上充分发表意见,保证党支部的意图在决策中得到体现。在总经理办公会决策后,党支部要建立\"三重一大\"决策事项跟踪问效制度、定期汇报制度、事后考核制度等,确保党的决策部署在企业贯彻好、执行好、落实好。第十三条 公司党支部、经理层对\"三重一大\"事项进行决策的具体程序和议题准备、表决、记录等事项严格按照公司相关议事规则规定的程序和要求执行。第十四条 公司研究决定企业改制及经营管理方面的重大问题、涉及职工切身利益的重大事项、制定重要的规章制度,应当听取企业工会的意见,并通过职工代表大会或者其他形式听取职工群众的意见和建议。按照国家有关规定须经职工代表大会或者职工大会审议通过的事项,履行相关程序后经理层方可批准或者作出决议。涉及重大决策、重大项目、大额度资金的使用,有合同意向的,应将合同的主要条款提交会议讨论。第十五条 \"三重一大\"事项经集体决策后,企业领导人员应当按照分工和职责组织实施。遇有分工和职责交叉的,应明确牵头落实人员。个人对集体决策有不同意见的,可以保留,但在作出新的决策前,应无条件执行。同时,可按组织程序向上级组织反映意见。");
}
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("三重一大", 10);
KEYWORD_WEIGHTS.put("重大决策", 9);
KEYWORD_WEIGHTS.put("重要人事任免", 9);
KEYWORD_WEIGHTS.put("重大项目安排", 9);
KEYWORD_WEIGHTS.put("大额度资金运作", 9);
KEYWORD_WEIGHTS.put("决策程序", 8);
KEYWORD_WEIGHTS.put("党委会", 7);
KEYWORD_WEIGHTS.put("董事会", 7);
KEYWORD_WEIGHTS.put("总经理办公会", 7);
KEYWORD_WEIGHTS.put("集体决策", 8);
KEYWORD_WEIGHTS.put("会议纪要", 6);
KEYWORD_WEIGHTS.put("金额标准", 6);
}
private AuditContent3TripleConstants() {
// 防止实例化
}
}

View File

@@ -0,0 +1,127 @@
package com.gxwebsoft.ai.controller;
import com.gxwebsoft.ai.entity.AiHistory;
import com.gxwebsoft.ai.param.AiHistoryParam;
import com.gxwebsoft.ai.service.AiHistoryService;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* AI审计历史记录表控制器
*
* @author yc
*/
@Tag(name = "AI审计历史记录表管理")
@RestController
@RequestMapping("/api/ai/history")
public class AiHistoryController extends BaseController {
@Resource
private AiHistoryService aiHistoryService;
//@PreAuthorize("hasAuthority('ai:aiHistory:list')")
@Operation(summary = "分页查询AI审计历史记录表")
@GetMapping("/page")
public ApiResult<PageResult<AiHistory>> page(AiHistoryParam param) {
// 使用关联查询
return success(aiHistoryService.pageRel(param));
}
//@PreAuthorize("hasAuthority('ai:aiHistory:list')")
@Operation(summary = "查询全部AI审计历史记录表")
@GetMapping()
public ApiResult<List<AiHistory>> list(AiHistoryParam param) {
// 使用关联查询
return success(aiHistoryService.listRel(param));
}
//@PreAuthorize("hasAuthority('ai:aiHistory:list')")
@Operation(summary = "根据id查询AI审计历史记录表")
@GetMapping("/{id}")
public ApiResult<AiHistory> get(@PathVariable("id") Long id) {
// 使用关联查询
return success(aiHistoryService.getByIdRel(id));
}
//@PreAuthorize("hasAuthority('ai:aiHistory:save')")
@Operation(summary = "添加AI审计历史记录表")
@PostMapping()
public ApiResult<?> save(@RequestBody AiHistory aiHistory) {
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser != null) {
aiHistory.setUserId(loginUser.getUserId());
aiHistory.setUsername(loginUser.getUsername());
}
if (aiHistoryService.save(aiHistory)) {
return success("添加成功");
}
return fail("添加失败");
}
//@PreAuthorize("hasAuthority('ai:aiHistory:update')")
@Operation(summary = "修改AI审计历史记录表")
@PutMapping()
public ApiResult<?> update(@RequestBody AiHistory aiHistory) {
if (aiHistoryService.updateById(aiHistory)) {
return success("修改成功");
}
return fail("修改失败");
}
//@PreAuthorize("hasAuthority('ai:aiHistory:remove')")
@Operation(summary = "删除AI审计历史记录表")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Long id) {
if (aiHistoryService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
//@PreAuthorize("hasAuthority('ai:aiHistory:save')")
@Operation(summary = "批量添加AI审计历史记录表")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<AiHistory> list) {
User loginUser = getLoginUser();
if (loginUser != null) {
for (AiHistory history : list) {
history.setUserId(loginUser.getUserId());
history.setUsername(loginUser.getUsername());
}
}
if (aiHistoryService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
//@PreAuthorize("hasAuthority('ai:aiHistory:update')")
@Operation(summary = "批量修改AI审计历史记录表")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<AiHistory> batchParam) {
if (batchParam.update(aiHistoryService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
//@PreAuthorize("hasAuthority('ai:aiHistory:remove')")
@Operation(summary = "批量删除AI审计历史记录表")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Long> ids) {
if (aiHistoryService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
}

View File

@@ -7,6 +7,7 @@ import com.gxwebsoft.ai.dto.export.TripleOneExportEntity;
import com.gxwebsoft.ai.dto.export.DecisionTableExportEntity;
import com.gxwebsoft.ai.entity.AiCloudDoc;
import com.gxwebsoft.ai.entity.AiCloudFile;
import com.gxwebsoft.ai.service.AiHistoryService;
import com.gxwebsoft.ai.utils.ExcelExportTool;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
@@ -24,9 +25,12 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -56,48 +60,23 @@ public class AuditContent3Controller extends BaseController {
@Autowired
private PwlProjectLibraryService pwlProjectLibraryService;
@Autowired
private AiHistoryService aiHistoryService;
// 历史记录有效期(分钟)
private static final int HISTORY_EXPIRE_MINUTES = 10;
/**
* 生成三重一大制度对比分析表数据
*/
@Operation(summary = "生成三重一大制度对比分析表")
@PostMapping("/generateTripleOneTable")
public ApiResult<?> generateTripleOneTable(@RequestBody AuditContentRequest request) {
final User loginUser = getLoginUser();
String kbIdTmp = "";
String libraryKbIds = "";
try {
// 创建临时知识库(如果需要)
if (!request.getDocList().isEmpty() || !request.getFileList().isEmpty()) {
kbIdTmp = createTempKnowledgeBase(request);
}
// 提前查询项目库信息
if (StrUtil.isNotBlank(request.getLibraryIds())) {
List<String> idList = StrUtil.split(request.getLibraryIds(), ',');
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(
new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
libraryKbIds = ret.stream().map(PwlProjectLibrary::getKbId).collect(Collectors.joining(","));
}
// 生成三重一大制度对比分析表数据
String knowledgeBaseId = StrUtil.isNotBlank(kbIdTmp) ? kbIdTmp : request.getKbIds();
JSONObject result = auditContent3TripleService.generateTripleOneTableData(
knowledgeBaseId,
libraryKbIds,
request.getProjectLibrary(),
loginUser.getUsername(),
request.getHistory(),
request.getSuggestion()
);
return success(result);
} catch (Exception e) {
log.error("生成三重一大制度对比分析表失败", e);
return fail("生成三重一大制度对比分析表失败: " + e.getMessage());
} finally {
cleanupTempKnowledgeBase(kbIdTmp);
}
public ApiResult<?> generateTripleOneTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent3TripleService.generateTripleOneTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
@@ -105,69 +84,134 @@ public class AuditContent3Controller extends BaseController {
*/
@Operation(summary = "生成重大经济决策调查表")
@PostMapping("/generateDecisionTable")
public ApiResult<?> generateDecisionTable(@RequestBody AuditContentRequest request) {
public ApiResult<?> generateDecisionTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent3DecisionService.generateDecisionTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion, request.getData()
));
}
/**
* 通用的表格数据生成方法
*/
private ApiResult<?> generateTableData(AuditContentRequest request, String interfaceName, Function<GenerateParams, JSONObject> generateFunction) {
final User loginUser = getLoginUser();
String requestHistory = request.getHistory();
request.setHistory("");
// 检查历史记录
String requestHash = generateRequestHash(request, interfaceName);
var history = aiHistoryService.getValidHistory(requestHash, interfaceName, HISTORY_EXPIRE_MINUTES);
if (history != null) {
log.info("返回历史数据,请求哈希: {}", requestHash);
return success(JSONObject.parseObject(history.getResponseData()));
}
request.setHistory(requestHistory);
String kbIdTmp = "";
String libraryKbIds = "";
try {
// 创建临时知识库(如果需要)
if (!request.getDocList().isEmpty() || !request.getFileList().isEmpty()) {
if (hasUploadedFiles(request)) {
kbIdTmp = createTempKnowledgeBase(request);
}
// 生成重大经济决策调查表数据
String knowledgeBaseId = StrUtil.isNotBlank(kbIdTmp) ? kbIdTmp : request.getKbIds();
JSONObject result = auditContent3DecisionService.generateDecisionTableData(
knowledgeBaseId,
request.getLibraryIds(),
request.getProjectLibrary(),
loginUser.getUsername(),
request.getHistory(),
request.getSuggestion(),
request.getData()
);
// 查询项目库信息
libraryKbIds = getLibraryKbIds(request.getLibraryIds());
// 生成数据
String knowledgeBaseId = getKnowledgeBaseId(kbIdTmp, request.getKbIds());
GenerateParams params = new GenerateParams(knowledgeBaseId, libraryKbIds, request.getProjectLibrary(), loginUser.getUsername(), request.getHistory(), request.getSuggestion());
JSONObject result = generateFunction.apply(params);
// 保存到历史记录
saveToHistory(request, interfaceName, requestHash, result, loginUser);
return success(result);
} catch (Exception e) {
log.error("生成重大经济决策调查表失败", e);
return fail("生成重大经济决策调查表失败: " + e.getMessage());
log.error("生成表格数据失败,接口: {}", interfaceName, e);
return fail("生成表格数据失败: " + e.getMessage());
} finally {
cleanupTempKnowledgeBase(kbIdTmp);
}
}
/**
* 生成请求哈希
*/
private String generateRequestHash(AuditContentRequest request, String interfaceName) {
String requestJson = JSONObject.toJSONString(request);
return DigestUtil.md5Hex(interfaceName + ":" + requestJson);
}
/**
* 保存到历史记录
*/
private void saveToHistory(AuditContentRequest request, String interfaceName, String requestHash, JSONObject result, User loginUser) {
try {
aiHistoryService.saveHistory(requestHash, interfaceName, JSONObject.toJSONString(request), result.toJSONString(), loginUser.getUserId(), loginUser.getUsername(), loginUser.getTenantId());
} catch (Exception e) {
log.warn("保存历史记录失败", e);
}
}
/**
* 检查是否有上传的文件
*/
private boolean hasUploadedFiles(AuditContentRequest request) {
return !request.getDocList().isEmpty() || !request.getFileList().isEmpty();
}
/**
* 获取知识库ID
*/
private String getKnowledgeBaseId(String tempKbId, String requestKbIds) {
return StrUtil.isNotBlank(tempKbId) ? tempKbId : requestKbIds;
}
/**
* 获取项目库KB IDs
*/
private String getLibraryKbIds(String libraryIds) {
if (StrUtil.isBlank(libraryIds)) {
return "";
}
List<String> idList = StrUtil.split(libraryIds, ',');
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
return ret.stream().map(PwlProjectLibrary::getKbId).filter(StrUtil::isNotBlank).collect(Collectors.joining(","));
}
/**
* 创建临时知识库并提交文档
*/
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());
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);
List<AiCloudFile> fileList = getRelatedFiles(docIds, request.getFileList());
// 提取文件ID并提交到知识库
Set<String> kbFileIds = fileList.stream()
.map(AiCloudFile::getFileId)
.collect(Collectors.toSet());
Set<String> kbFileIds = fileList.stream().map(AiCloudFile::getFileId).collect(Collectors.toSet());
if (!kbFileIds.isEmpty()) {
knowledgeBaseService.submitDocuments(kbIdTmp, new ArrayList<>(kbFileIds));
}
return kbIdTmp;
}
/**
* 获取相关文件列表
*/
private List<AiCloudFile> getRelatedFiles(Set<Integer> docIds, List<Integer> fileList) {
LambdaQueryWrapper<AiCloudFile> queryWrapper = new LambdaQueryWrapper<AiCloudFile>()
.in(!docIds.isEmpty(), AiCloudFile::getDocId, docIds)
.or(!fileList.isEmpty())
.in(!fileList.isEmpty(), AiCloudFile::getId, fileList);
return aiCloudFileService.list(queryWrapper);
}
/**
* 清理临时知识库
*/
@@ -187,17 +231,8 @@ public class AuditContent3Controller extends BaseController {
@Operation(summary = "导出三重一大制度对比分析表到Excel")
@PostMapping("/exportTripleOneTable")
public void exportTripleOneTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
// 转换为实体列表
List<TripleOneExportEntity> exportData = convertToTripleOneEntityList(dataList);
// 使用工具类导出
String fileName = "三重一大制度对比分析表_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - 三重一大制度对比分析表" : "三重一大制度对比分析表";
ExcelExportTool.exportExcel(exportData, TripleOneExportEntity.class, fileName, "三重一大制度对比分析表", title, response);
exportToExcel(request, response, "三重一大制度对比分析表",
this::convertToTripleOneEntityList, TripleOneExportEntity.class);
}
/**
@@ -206,36 +241,58 @@ public class AuditContent3Controller extends BaseController {
@Operation(summary = "导出重大经济决策调查表到Excel")
@PostMapping("/exportDecisionTable")
public void exportDecisionTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "重大经济决策调查表",
this::convertToDecisionTableEntityList, DecisionTableExportEntity.class);
}
/**
* 通用的Excel导出方法
*/
private <T> void exportToExcel(Map<String, Object> request, HttpServletResponse response,
String sheetName, Function<List<Map<String, Object>>, List<T>> converter,
Class<T> entityClass) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
// 转换为实体列表
List<DecisionTableExportEntity> exportData = convertToDecisionTableEntityList(dataList);
List<T> exportData = converter.apply(dataList);
// 使用工具类导出
String fileName = "重大经济决策调查表_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - 重大经济决策调查表" : "重大经济决策调查表";
String fileName = sheetName + "_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - " + sheetName : sheetName;
ExcelExportTool.exportExcel(exportData, DecisionTableExportEntity.class, fileName, "重大经济决策调查表", title, response);
ExcelExportTool.exportExcel(exportData, entityClass, fileName, sheetName, title, response);
}
/**
* 转换为三重一大实体列表
* 参数包装类
*/
private static class GenerateParams {
final String knowledgeBaseId;
final String libraryKbIds;
final String projectLibrary;
final String username;
final String history;
final String suggestion;
GenerateParams(String knowledgeBaseId, String libraryKbIds, String projectLibrary, String username, String history, String suggestion) {
this.knowledgeBaseId = knowledgeBaseId;
this.libraryKbIds = libraryKbIds;
this.projectLibrary = projectLibrary;
this.username = username;
this.history = history;
this.suggestion = suggestion;
}
}
// ========== 数据转换方法 ==========
private List<TripleOneExportEntity> convertToTripleOneEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToTripleOneEntity).collect(Collectors.toList());
}
/**
* 转换为重大经济决策调查表实体列表
*/
private List<DecisionTableExportEntity> convertToDecisionTableEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToDecisionTableEntity).collect(Collectors.toList());
}
/**
* 单个Map转换为三重一大实体
*/
private TripleOneExportEntity convertToTripleOneEntity(Map<String, Object> item) {
TripleOneExportEntity entity = new TripleOneExportEntity();
entity.setCategory(getStringValue(item, "category"));
@@ -247,10 +304,7 @@ public class AuditContent3Controller extends BaseController {
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
/**
* 单个Map转换为重大经济决策调查表实体
*/
private DecisionTableExportEntity convertToDecisionTableEntity(Map<String, Object> item) {
DecisionTableExportEntity entity = new DecisionTableExportEntity();
entity.setIndex(getStringValue(item, "index"));
@@ -264,18 +318,12 @@ public class AuditContent3Controller extends BaseController {
entity.setBad(getStringValue(item, "bad"));
return entity;
}
/**
* 安全获取字符串值
*/
private String getStringValue(Map<String, Object> map, String key) {
Object value = map.get(key);
return value != null ? value.toString() : "";
}
/**
* 格式化工作底稿索引(如果是数组则转换为字符串)
*/
private String formatWorkPaperIndex(Object workPaperIndex) {
if (workPaperIndex == null) {
return "";

View File

@@ -0,0 +1,60 @@
package com.gxwebsoft.ai.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* AI审计历史记录表
*
* @author yc
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(name = "AiHistory对象", description = "AI审计历史记录表")
@TableName("ai_history")
public class AiHistory implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@Schema(description = "请求哈希值")
private String requestHash;
@Schema(description = "接口名称")
private String interfaceName;
@Schema(description = "请求参数序列化数据")
private String requestData;
@Schema(description = "响应结果序列化数据")
private String responseData;
@Schema(description = "用户ID")
private Integer userId;
@Schema(description = "用户名")
private String username;
@Schema(description = "状态, 0正常, 1冻结")
private Integer status;
@Schema(description = "是否删除, 0否, 1是")
@TableLogic
private Integer deleted;
@Schema(description = "租户id")
private Integer tenantId;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "修改时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,35 @@
package com.gxwebsoft.ai.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.ai.entity.AiHistory;
import com.gxwebsoft.ai.param.AiHistoryParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* AI审计历史记录表Mapper
*
* @author yc
*/
public interface AiHistoryMapper extends BaseMapper<AiHistory> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<AiHistory>
*/
List<AiHistory> selectPageRel(@Param("page") IPage<AiHistory> page,
@Param("param") AiHistoryParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<AiHistory>
*/
List<AiHistory> selectListRel(@Param("param") AiHistoryParam param);
}

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gxwebsoft.ai.mapper.AiHistoryMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM ai_history a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.requestHash != null">
AND a.request_hash = #{param.requestHash}
</if>
<if test="param.interfaceName != null">
AND a.interface_name = #{param.interfaceName}
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.username != null">
AND a.username LIKE CONCAT('%', #{param.username}, '%')
</if>
<if test="param.status != null">
AND a.status = #{param.status}
</if>
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.tenantId != null">
AND a.tenant_id = #{param.tenantId}
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null">
AND (a.request_hash LIKE CONCAT('%', #{param.keywords}, '%')
OR a.interface_name LIKE CONCAT('%', #{param.keywords}, '%')
OR a.username LIKE CONCAT('%', #{param.keywords}, '%'))
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.ai.entity.AiHistory">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.ai.entity.AiHistory">
<include refid="selectSql"></include>
</select>
</mapper>

View File

@@ -0,0 +1,53 @@
package com.gxwebsoft.ai.param;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* AI审计历史记录表查询参数
*
* @author yc
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "AiHistoryParam对象", description = "AI审计历史记录表查询参数")
public class AiHistoryParam extends BaseParam {
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
@QueryField(type = QueryType.EQ)
private Long id;
@Schema(description = "请求哈希值")
@QueryField(type = QueryType.EQ)
private String requestHash;
@Schema(description = "接口名称")
@QueryField(type = QueryType.EQ)
private String interfaceName;
@Schema(description = "用户ID")
@QueryField(type = QueryType.EQ)
private Integer userId;
@Schema(description = "用户名")
private String username;
@Schema(description = "状态, 0正常, 1冻结")
@QueryField(type = QueryType.EQ)
private Integer status;
@Schema(description = "是否删除, 0否, 1是")
@QueryField(type = QueryType.EQ)
private Integer deleted;
@Schema(description = "租户id")
@QueryField(type = QueryType.EQ)
private Integer tenantId;
}

View File

@@ -0,0 +1,62 @@
package com.gxwebsoft.ai.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.ai.entity.AiHistory;
import com.gxwebsoft.ai.param.AiHistoryParam;
import com.gxwebsoft.common.core.web.PageResult;
import java.util.List;
/**
* AI审计历史记录表Service
*
* @author yc
*/
public interface AiHistoryService extends IService<AiHistory> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<AiHistory>
*/
PageResult<AiHistory> pageRel(AiHistoryParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<AiHistory>
*/
List<AiHistory> listRel(AiHistoryParam param);
/**
* 根据id查询
*
* @param id ID
* @return AiHistory
*/
AiHistory getByIdRel(Long id);
/**
* 获取有效的历史记录
*
* @param requestHash 请求哈希值
* @param interfaceName 接口名称
* @param minutes 有效时间(分钟)
* @return AiHistory
*/
AiHistory getValidHistory(String requestHash, String interfaceName, int minutes);
/**
* 保存历史记录
*
* @param requestHash 请求哈希值
* @param interfaceName 接口名称
* @param requestData 请求数据
* @param responseData 响应数据
* @param userId 用户ID
* @param username 用户名
*/
void saveHistory(String requestHash, String interfaceName, String requestData, String responseData, Integer userId, String username, Integer tenantId);
}

View File

@@ -10,6 +10,5 @@ public interface AuditContent3DecisionService {
/**
* 生成重大经济决策调查表数据
*/
JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary,
String userName, String history, String suggestion, Object tripleOneData);
JSONObject generateDecisionTableData(String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion, Object tripleOneData);
}

View File

@@ -10,6 +10,5 @@ public interface AuditContent3TripleService {
/**
* 生成三重一大制度对比分析表数据
*/
JSONObject generateTripleOneTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion);
JSONObject generateTripleOneTableData(String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion);
}

View File

@@ -0,0 +1,244 @@
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.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.util.KnowledgeBaseUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@Slf4j
public abstract class AbstractAuditContentService {
@Autowired
protected KnowledgeBaseClientFactory clientFactory;
@Autowired
protected KnowledgeBaseConfig config;
protected static final String DIFY_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
/**
* 调用工作流通用方法
*/
protected JSONArray callWorkflow(String url, String token, JSONObject requestBody, String workflowName) {
try {
log.info("调用{}工作流,请求体长度: {}", workflowName, requestBody.toString().length());
String result = HttpUtil.createPost(url)
.header("Authorization", token)
.header("Content-Type", "application/json")
.body(requestBody.toString())
.timeout(10 * 60 * 1000)
.execute()
.body();
log.info("{}工作流返回结果长度: {}", workflowName, result.length());
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(result);
String outputText = rootNode.path("data")
.path("outputs")
.path("result")
.asText();
if (StrUtil.isBlank(outputText)) {
log.warn("{}工作流返回结果为空", workflowName);
return new JSONArray();
}
JsonNode arrayNode = objectMapper.readTree(outputText);
JSONArray jsonArray = JSONArray.parseArray(arrayNode.toString());
log.info("成功解析{}工作流返回数据,记录数: {}", workflowName, jsonArray.size());
return jsonArray;
} catch (Exception e) {
log.error("调用{}工作流失败", workflowName, e);
throw new RuntimeException("调用" + workflowName + "工作流失败: " + e.getMessage(), e);
}
}
/**
* 构建工作流请求通用方法
*/
protected JSONObject buildWorkflowRequest(String knowledge, String userName) {
return buildWorkflowRequest(knowledge, userName, null);
}
protected JSONObject buildWorkflowRequest(String knowledge, String userName, Integer timeout) {
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);
if (timeout != null) {
requestBody.put("timeout", timeout);
}
return requestBody;
}
/**
* 查询知识库通用方法
*/
protected 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 -> processKnowledgeNode(node, results));
} catch (Exception e) {
log.warn("查询知识库失败 - kbId: {}, query: {}", kbId, query, e);
}
}
} catch (Exception e) {
log.error("创建知识库客户端失败", e);
}
return new ArrayList<>(results);
}
/**
* 处理知识库节点通用方法
*/
protected void processKnowledgeNode(RetrieveResponseBodyDataNodes node, Set<String> results) {
try {
String text = node.getText();
if (StrUtil.isBlank(text) || text.length() < 10) {
return;
}
String docName = extractDocumentName(node);
String formattedText = String.format("《%s》%s", docName, text);
results.add(formattedText);
} catch (Exception e) {
log.warn("处理知识库节点失败", e);
}
}
/**
* 提取文档名称通用方法
*/
protected 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) {
return docNameObj.toString();
}
}
} catch (Exception e) {
log.debug("提取文档名称失败", e);
}
return "相关文档";
}
/**
* 构建成功响应通用方法
*/
protected JSONObject buildSuccessResponse(JSONArray data, long startTime) {
return buildSuccessResponse(data, startTime, null);
}
protected JSONObject buildSuccessResponse(JSONArray data, long startTime, String dataSource) {
JSONObject result = new JSONObject();
result.put("success", true);
result.put("data", data);
result.put("total_records", data.size());
result.put("generated_time", new Date().toString());
result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms");
if (dataSource != null) {
result.put("data_source", dataSource);
}
return result;
}
/**
* 构建失败响应通用方法
*/
protected JSONObject buildErrorResponse(String errorMessage) {
JSONObject result = new JSONObject();
result.put("success", false);
result.put("error", errorMessage);
return result;
}
/**
* 异步处理分类数据通用方法
*/
protected Map<String, CompletableFuture<JSONArray>> processCategoriesAsync(
List<String> categories,
CategoryProcessor processor) {
Map<String, CompletableFuture<JSONArray>> futures = new LinkedHashMap<>();
for (String category : categories) {
CompletableFuture<JSONArray> future = processor.processCategory(category);
futures.put(category, future);
}
return futures;
}
/**
* 合并分类结果通用方法
*/
protected JSONArray mergeCategoryResults(List<String> categoryOrder,
Map<String, CompletableFuture<JSONArray>> futures) {
JSONArray allData = new JSONArray();
for (String category : categoryOrder) {
try {
JSONArray categoryData = futures.get(category).get();
if (categoryData != null && !categoryData.isEmpty()) {
allData.addAll(categoryData);
}
} catch (Exception e) {
log.error("获取分类 {} 数据失败", category, e);
}
}
return allData;
}
/**
* 分类处理器函数式接口
*/
@FunctionalInterface
public interface CategoryProcessor {
CompletableFuture<JSONArray> processCategory(String category);
}
}

View File

@@ -0,0 +1,74 @@
package com.gxwebsoft.ai.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.ai.entity.AiHistory;
import com.gxwebsoft.ai.mapper.AiHistoryMapper;
import com.gxwebsoft.ai.param.AiHistoryParam;
import com.gxwebsoft.ai.service.AiHistoryService;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
* AI审计历史记录表Service实现
*
* @author yc
*/
@Service
public class AiHistoryServiceImpl extends ServiceImpl<AiHistoryMapper, AiHistory> implements AiHistoryService {
@Override
public PageResult<AiHistory> pageRel(AiHistoryParam param) {
PageParam<AiHistory, AiHistoryParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<AiHistory> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<AiHistory> listRel(AiHistoryParam param) {
List<AiHistory> list = baseMapper.selectListRel(param);
// 排序
PageParam<AiHistory, AiHistoryParam> page = new PageParam<>();
page.setDefaultOrder("create_time desc");
return page.sortRecords(list);
}
@Override
public AiHistory getByIdRel(Long id) {
AiHistoryParam param = new AiHistoryParam();
param.setId(id);
return param.getOne(baseMapper.selectListRel(param));
}
@Override
public AiHistory getValidHistory(String requestHash, String interfaceName, int minutes) {
LambdaQueryWrapper<AiHistory> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AiHistory::getRequestHash, requestHash)
.eq(AiHistory::getInterfaceName, interfaceName)
.eq(AiHistory::getStatus, 0)
.eq(AiHistory::getDeleted, 0)
.ge(AiHistory::getCreateTime, LocalDateTime.now().minusMinutes(minutes));
return getOne(queryWrapper, false);
}
@Override
public void saveHistory(String requestHash, String interfaceName, String requestData, String responseData, Integer userId, String username, Integer tenantId) {
AiHistory history = new AiHistory();
history.setRequestHash(requestHash);
history.setInterfaceName(interfaceName);
history.setRequestData(requestData);
history.setResponseData(responseData);
history.setUserId(userId);
history.setUsername(username);
history.setStatus(0);
history.setDeleted(0);
history.setTenantId(tenantId);
save(history);
}
}

View File

@@ -1,64 +1,28 @@
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.constants.AuditContent3DecisionConstants;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
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 {
public class AuditContent3DecisionServiceImpl extends AbstractAuditContentService 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";
// Excel Sheet1 中的条件信息
private static final String EXCEL_SHEET1_CONDITIONS =
"## 重大经济决策调查表审计重点\n" +
"重大经济事项的决策、执行和效果情况,具体包括重大预算管理、重大项目实施、重大采购项目、重大投资项目、重大外包业务、重大资产处置、大额资金使用的决策和执行情况等。\n\n" +
"## 重点关注\n" +
"\"三重一大\"集体决策制度是否建立健全。重大经济、经营活动必须进行集体决策的标准和必须参加决策的人员是否制定有规定,规定的集体决策的程序(签到表、决策纪要、最终形成的决策、决策人员的签字确认意见等)是否完整,是否有应集体决策而未集体决策的问题,是否有应参加集体决策的人因不合理理由不得参加集体决策的问题,形成的集体决策意见是否符合国家、自治区规定。\n\n" +
"## 审计方法及步骤\n" +
"1. 查阅单位制度,检查议事制度是否建立,查看重大事项进行集体决策的规定,查阅相关会议记录资料,检查会议签到表、会议纪要、会议决定内容及决策参与人员签字确认意见,以确认会议集体决策程序的完整性;对照重大决策内容,检查相关对应资料,确认集体决策内容是否符合国家、自治区规定。\n" +
"2. 抽查一些重大经济决策事项,比如重大建设项目、维修、大宗物资采购、企业投资运营等,审查其决策的背景、决策的过程、决策的执行和落实情况,决策的效果情况,以此来确定是否符合国家、自治区相关规定,执行是否有效。";
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-yN7Q8GEN9E7SCMkhI6HaAagW";
@Override
public JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary,
public JSONObject generateDecisionTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion, Object data) {
log.info("开始生成重大经济决策调查表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryIds, projectLibrary);
log.info("开始生成重大经济决策调查表数据 - 用户: {}", userName);
JSONObject result = new JSONObject();
long startTime = System.currentTimeMillis();
@@ -74,80 +38,64 @@ public class AuditContent3DecisionServiceImpl implements AuditContent3DecisionSe
return result;
}
// 2. 基于三重一大数据同步检索相关知识库内容
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForTripleOne(kbIds, libraryIds, projectLibrary, tripleOneData);
// 3. 构建完整的上下文并调用工作流
String knowledgeContext = buildCompleteContext(tripleOneData, knowledgeSources, history, suggestion);
// 2. 检索相关知识库内容
Map<String, List<String>> knowledgeSources = retrieveKnowledge(kbIds, libraryKbIds, projectLibrary, tripleOneData);
// 3. 构建上下文并调用工作流
String knowledgeContext = buildKnowledgeContext(tripleOneData, knowledgeSources, history, suggestion);
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray decisionTableData = callDecisionWorkflow(requestBody);
JSONArray decisionTableData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "重大经济决策调查表");
// 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");
result.put("data_source", "triple_one_primary");
log.info("重大经济决策调查表生成成功 - 记录数: {}, 处理时间: {}ms",
decisionTableData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(decisionTableData, startTime, "triple_one_primary");
} catch (Exception e) {
log.error("生成重大经济决策调查表失败", e);
result.put("success", false);
result.put("error", e.getMessage());
throw new RuntimeException("生成重大经济决策调查表失败: " + e.getMessage(), e);
return buildErrorResponse("生成重大经济决策调查表失败: " + e.getMessage());
}
return result;
}
/**
* 为三重一大数据同步检索相关知识
* 检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForTripleOne(String kbIds, String libraryIds,
String projectLibrary, JSONArray tripleOneData) {
private Map<String, List<String>> retrieveKnowledge(String kbIds, String libraryKbIds, String projectLibrary, JSONArray tripleOneData) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 企业单位知识每个三重一大数据项同步检索前10条
for (int i = 0; i < tripleOneData.size(); i++) {
JSONObject tripleItem = tripleOneData.getJSONObject(i);
if (tripleItem != null) {
List<String> enterpriseKnowledge = retrieveEnterpriseKnowledgeForItem(tripleItem, kbIds);
knowledgeSources.get("enterprise").addAll(enterpriseKnowledge);
}
// 企业单位知识检索
if (StrUtil.isNotBlank(kbIds)) {
List<String> enterpriseQueries = buildEnterpriseQueries(tripleOneData);
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, enterpriseQueries, 20)));
}
// 法律法规知识全局检索100条所有tripleItem共享
if (StrUtil.isNotBlank(libraryIds)) {
List<String> regulationKnowledge = retrieveGlobalRegulationKnowledge(libraryIds, tripleOneData);
knowledgeSources.get("regulation").addAll(regulationKnowledge);
// 法律法规知识检索
if (StrUtil.isNotBlank(libraryKbIds)) {
List<String> regulationQueries = buildRegulationQueries(tripleOneData);
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, regulationQueries, 100)));
}
// 审计案例知识全局检索50条所有tripleItem共享
// 审计案例知识检索
if (StrUtil.isNotBlank(projectLibrary)) {
List<String> auditCaseKnowledge = retrieveGlobalAuditCaseKnowledge(projectLibrary, tripleOneData);
knowledgeSources.get("auditCase").addAll(auditCaseKnowledge);
List<String> auditCaseQueries = buildAuditCaseQueries(tripleOneData);
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, auditCaseQueries, 50));
}
// 去重和限制数量
knowledgeSources.put("enterprise", knowledgeSources.get("enterprise").stream()
.distinct()
.limit(200)
.collect(Collectors.toList()));
knowledgeSources.put("regulation", knowledgeSources.get("regulation").stream()
.distinct()
.limit(100)
.collect(Collectors.toList()));
knowledgeSources.put("auditCase", knowledgeSources.get("auditCase").stream()
.distinct()
.limit(50)
.collect(Collectors.toList()));
// 智能去重
knowledgeSources.forEach((sourceType, knowledgeList) -> {
List<String> distinctList = knowledgeList.stream().distinct().collect(Collectors.toList());
knowledgeSources.put(sourceType, distinctList);
});
log.info("知识库检索完成 - 企业单位: {}条, 法律法规: {}条, 审计案例: {}条",
knowledgeSources.get("enterprise").size(),
@@ -158,216 +106,137 @@ public class AuditContent3DecisionServiceImpl implements AuditContent3DecisionSe
}
/**
* 为单个三重一大项检索企业单位知识限制10条
* 构建企业单位查询
*/
private List<String> retrieveEnterpriseKnowledgeForItem(JSONObject tripleItem, String kbIds) {
List<String> enterpriseKnowledge = new ArrayList<>();
try {
List<String> queries = buildQueriesForTripleOneItem(tripleItem);
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> enterpriseKnowledge
.addAll(queryKnowledgeBaseForItem(kbId, queries, tripleItem, 10)));
}
} catch (Exception e) {
log.error("检索企业单位知识失败", e);
}
return enterpriseKnowledge.stream()
.distinct()
.limit(10)
.collect(Collectors.toList());
}
/**
* 全局检索法律法规知识100条
*/
private List<String> retrieveGlobalRegulationKnowledge(String libraryIds, JSONArray tripleOneData) {
List<String> regulationKnowledge = new ArrayList<>();
try {
List<String> globalQueries = buildGlobalRegulationQueries(tripleOneData);
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 -> regulationKnowledge
.addAll(queryKnowledgeBaseForGlobal(libId, globalQueries, 100)));
} catch (Exception e) {
log.error("全局检索法律法规知识失败", e);
}
return regulationKnowledge;
}
/**
* 全局检索审计案例知识50条
*/
private List<String> retrieveGlobalAuditCaseKnowledge(String projectLibrary, JSONArray tripleOneData) {
List<String> auditCaseKnowledge = new ArrayList<>();
try {
List<String> globalQueries = buildGlobalAuditCaseQueries(tripleOneData);
auditCaseKnowledge.addAll(
queryKnowledgeBaseForGlobal(projectLibrary, globalQueries, 50));
} catch (Exception e) {
log.error("全局检索审计案例知识失败", e);
}
return auditCaseKnowledge;
}
/**
* 构建全局法律法规查询
*/
private List<String> buildGlobalRegulationQueries(JSONArray tripleOneData) {
private List<String> buildEnterpriseQueries(JSONArray tripleOneData) {
List<String> queries = new ArrayList<>();
// 从所有tripleItem中提取共性关键词
Set<String> categories = new HashSet<>();
Set<String> policyKeywords = new HashSet<>();
for (int i = 0; i < tripleOneData.size(); i++) {
JSONObject item = tripleOneData.getJSONObject(i);
if (item != null) {
String category = item.getString("category");
String policyContent = item.getString("policyContent");
if (StrUtil.isNotBlank(category)) {
categories.add(category);
queries.add(category + " 会议记录 决策事项");
queries.add(category + " 经济决策 程序");
}
String policyContent = item.getString("policyContent");
if (StrUtil.isNotBlank(policyContent)) {
if (policyContent.contains("公司法")) policyKeywords.add("公司法");
if (policyContent.contains("国有资产")) policyKeywords.add("国有资产法");
if (policyContent.contains("党组织")) policyKeywords.add("党组织");
if (policyContent.contains("投资")) queries.add("投资项目 决策");
if (policyContent.contains("采购")) queries.add("采购项目 决策");
if (policyContent.contains("资产")) queries.add("资产处置 决策");
}
}
}
// 构建通用查询
queries.add("重大经济决策 法律法规");
queries.add("三重一大 政策规定");
queries.add("集体决策 制度规定");
return queries;
}
/**
* 构建法律法规查询
*/
private List<String> buildRegulationQueries(JSONArray tripleOneData) {
List<String> queries = new ArrayList<>(Arrays.asList(AuditContent3DecisionConstants.GLOBAL_REGULATION_QUERIES));
// 提取分类信息
Set<String> categories = new HashSet<>();
for (int i = 0; i < tripleOneData.size(); i++) {
JSONObject item = tripleOneData.getJSONObject(i);
if (item != null) {
String category = item.getString("category");
if (StrUtil.isNotBlank(category)) {
categories.add(category);
}
}
}
// 添加分类相关查询
for (String category : categories) {
queries.add(category + " 法律法规");
}
// 添加政策关键词相关查询
for (String keyword : policyKeywords) {
queries.add(keyword + " 决策规定");
}
return queries;
}
/**
* 构建全局审计案例查询
* 构建审计案例查询
*/
private List<String> buildGlobalAuditCaseQueries(JSONArray tripleOneData) {
List<String> queries = new ArrayList<>();
private List<String> buildAuditCaseQueries(JSONArray tripleOneData) {
List<String> queries = new ArrayList<>(Arrays.asList(AuditContent3DecisionConstants.GLOBAL_AUDIT_CASE_QUERIES));
// 从所有tripleItem中提取共性信息
// 提取分类信息
Set<String> categories = new HashSet<>();
boolean hasFailedCases = false;
for (int i = 0; i < tripleOneData.size(); i++) {
JSONObject item = tripleOneData.getJSONObject(i);
if (item != null) {
String category = item.getString("category");
String testResult = item.getString("testResult");
if (StrUtil.isNotBlank(category)) {
categories.add(category);
}
if ("不通过".equals(testResult)) {
hasFailedCases = true;
}
}
}
// 构建通用查询
queries.add("重大经济决策 审计案例");
queries.add("三重一大 检查方法");
// 添加分类相关查询
for (String category : categories) {
queries.add(category + " 审计案例");
}
// 如果有不通过的案例,添加相关查询
if (hasFailedCases) {
queries.add("决策程序缺陷 案例");
queries.add("集体决策问题 审计");
}
return queries;
}
/**
* 全局知识库查询不关联特定tripleItem
* 构建知识上下文
*/
private List<String> queryKnowledgeBaseForGlobal(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 -> processNodeForGlobal(node, results));
} catch (Exception e) {
log.warn("全局查询知识库失败 - kbId: {}, query: {}", kbId, query, e);
}
private String buildKnowledgeContext(JSONArray tripleOneData, Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 核心指令
context.append("## 核心生成指令\n");
context.append("请基于三重一大制度对比分析数据生成重大经济决策调查表。\n\n");
context.append(AuditContent3DecisionConstants.AUDIT_FOCUS_AND_METHODS).append("\n\n");
// 2. 三重一大数据
context.append("## 三重一大制度对比分析数据\n");
for (int i = 0; i < tripleOneData.size(); i++) {
JSONObject item = tripleOneData.getJSONObject(i);
if (item != null) {
context.append("### 三重一大事项 ").append(i + 1).append("\n");
context.append(JSONObject.toJSONString(item, true)).append("\n\n");
}
} catch (Exception e) {
log.error("创建知识库客户端失败", e);
}
return new ArrayList<>(results);
}
/**
* 处理全局知识库节点
*/
private void processNodeForGlobal(RetrieveResponseBodyDataNodes node, Set<String> results) {
try {
String text = node.getText();
if (StrUtil.isBlank(text) || text.length() < 10) {
return;
}
String docName = extractDocumentName(node);
String formattedText = String.format("《%s》%s", docName, text);
results.add(formattedText);
} catch (Exception e) {
log.warn("处理全局知识库节点失败", e);
// 3. 知识库内容
context.append("## 相关知识库内容\n");
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("### 企业单位知识\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append("- ").append(knowledge).append("\n"));
}
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("### 法律法规知识\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append("- ").append(knowledge).append("\n"));
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("### 审计案例知识\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append("- ").append(knowledge).append("\n"));
}
// 4. 历史内容和用户建议
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n").append(history).append("\n");
}
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n").append(suggestion).append("\n");
}
return context.toString();
}
/**
@@ -402,317 +271,4 @@ public class AuditContent3DecisionServiceImpl implements AuditContent3DecisionSe
return null;
}
}
/**
* 为单个三重一大项构建查询
*/
private List<String> buildQueriesForTripleOneItem(JSONObject tripleItem) {
List<String> queries = new ArrayList<>();
String category = tripleItem.getString("category");
String policyContent = tripleItem.getString("policyContent");
String checkEvidence = tripleItem.getString("checkEvidence");
String companyFormulation = tripleItem.getString("companyFormulation");
// 基于分类构建查询
if (category != null) {
queries.add(category + " 会议记录 决策事项");
queries.add(category + " 经济决策 程序");
}
// 从政策内容提取关键词
if (policyContent != null) {
if (policyContent.contains("投资")) queries.add("投资项目 决策");
if (policyContent.contains("采购")) queries.add("采购项目 决策");
if (policyContent.contains("资产")) queries.add("资产处置 决策");
if (policyContent.contains("预算")) queries.add("预算管理 决策");
if (policyContent.contains("人事")) queries.add("人事任免 决策");
}
// 从检查证据提取具体事项
if (checkEvidence != null) {
String[] evidenceKeywords = extractKeywordsFromEvidence(checkEvidence);
for (String keyword : evidenceKeywords) {
if (keyword.length() > 2) {
queries.add(keyword + " 会议纪要");
queries.add(keyword + " 决策程序");
}
}
}
// 从公司制度问题提取关键词
if (companyFormulation != null) {
if (companyFormulation.contains("权限")) queries.add("决策权限 授权");
if (companyFormulation.contains("程序")) queries.add("决策程序 流程");
if (companyFormulation.contains("审批")) queries.add("审批流程 决策");
}
return queries;
}
/**
* 从检查证据中提取关键词
*/
private String[] extractKeywordsFromEvidence(String checkEvidence) {
if (checkEvidence == null) return new String[0];
List<String> keywords = new ArrayList<>();
// 提取可能的项目名称(包含《》的文件名)
if (checkEvidence.contains("") && checkEvidence.contains("")) {
int start = checkEvidence.indexOf("");
int end = checkEvidence.indexOf("");
if (start < end) {
String fileName = checkEvidence.substring(start + 1, end);
keywords.add(fileName);
}
}
// 提取可能的金额数字
if (checkEvidence.matches(".*\\d+(\\.\\d+)?万.*")) {
keywords.add("金额");
}
// 提取常见项目类型
String[] projectTypes = {"项目", "投资", "采购", "建设", "改造", "扩建", "维修"};
for (String type : projectTypes) {
if (checkEvidence.contains(type)) {
keywords.add(type);
}
}
return keywords.toArray(new String[0]);
}
/**
* 构建完整的上下文
*/
private String buildCompleteContext(JSONArray tripleOneData, Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 核心指令
context.append("## 核心生成指令\n");
context.append("请基于以下三重一大制度对比分析数据为主要依据,结合相关知识库内容,生成重大经济决策调查表。\n\n");
context.append("**数据优先级**: 三重一大数据 > 知识库内容 > 通用审计规则\n\n");
// 2. Excel Sheet1 条件信息
context.append(EXCEL_SHEET1_CONDITIONS).append("\n\n");
// 3. 三重一大数据(主要依据)
context.append("## 三重一大制度对比分析数据(主要依据)\n");
context.append("请基于以下三重一大数据生成对应的重大经济决策调查记录,每条三重一大数据都应生成对应的调查表记录:\n\n");
for (int i = 0; i < tripleOneData.size(); i++) {
JSONObject item = tripleOneData.getJSONObject(i);
if (item != null) {
context.append("### 三重一大事项 ").append(i + 1).append("\n");
context.append("```json\n");
context.append(JSONObject.toJSONString(item, true));
context.append("\n```\n\n");
}
}
// 4. 知识库内容(辅助信息)
context.append("## 相关知识库内容(辅助信息)\n");
context.append("以下是从知识库中检索到的相关信息,用于补充决策事项的细节:\n\n");
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("### 企业单位知识\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append("- ").append(knowledge).append("\n"));
context.append("\n");
}
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("### 法律法规知识\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append("- ").append(knowledge).append("\n"));
context.append("\n");
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("### 审计案例知识\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append("- ").append(knowledge).append("\n"));
context.append("\n");
}
// 5. 历史内容和用户建议
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append(history).append("\n\n");
}
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append(suggestion).append("\n\n");
}
log.debug("完整上下文长度: {}", context.length());
return context.toString();
}
/**
* 为单个项查询知识库
*/
private List<String> queryKnowledgeBaseForItem(String kbId, List<String> queries, JSONObject tripleItem, 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 -> processNodeForItem(node, results, tripleItem));
} catch (Exception e) {
log.warn("查询知识库失败 - kbId: {}, query: {}", kbId, query, e);
}
}
} catch (Exception e) {
log.error("创建知识库客户端失败", e);
}
return new ArrayList<>(results);
}
/**
* 处理知识库节点(针对特定三重一项)
*/
private void processNodeForItem(RetrieveResponseBodyDataNodes node, Set<String> results, JSONObject tripleItem) {
try {
String text = node.getText();
if (StrUtil.isBlank(text) || text.length() < 10) {
return;
}
// 检查文本是否与当前三重一项相关
if (isTextRelevantToItem(text, tripleItem)) {
String docName = extractDocumentName(node);
String formattedText = String.format("《%s》%s", docName, text);
results.add(formattedText);
}
} catch (Exception e) {
log.warn("处理知识库节点失败", e);
}
}
/**
* 检查文本是否与三重一项相关
*/
private boolean isTextRelevantToItem(String text, JSONObject tripleItem) {
String category = tripleItem.getString("category");
String checkEvidence = tripleItem.getString("checkEvidence");
String policyContent = tripleItem.getString("policyContent");
// 基于分类检查相关性
if (category != null && text.contains(category)) {
return true;
}
// 基于检查证据中的关键词检查相关性
if (checkEvidence != null) {
String[] keywords = extractKeywordsFromEvidence(checkEvidence);
for (String keyword : keywords) {
if (keyword.length() > 2 && text.contains(keyword)) {
return true;
}
}
}
// 基于政策内容中的关键词检查相关性
if (policyContent != null) {
if (policyContent.contains("投资") && text.contains("投资")) return true;
if (policyContent.contains("采购") && text.contains("采购")) return true;
if (policyContent.contains("资产") && text.contains("资产")) return true;
if (policyContent.contains("预算") && text.contains("预算")) return true;
}
return false;
}
/**
* 提取文档名称
*/
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) {
return docNameObj.toString();
}
}
} 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)
.execute()
.body();
log.info("工作流返回结果长度: {}", result.length());
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(result);
String outputText = rootNode.path("data")
.path("outputs")
.path("result")
.asText();
if (StrUtil.isBlank(outputText)) {
log.warn("工作流返回结果为空");
return new JSONArray();
}
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);
return requestBody;
}
}
}

View File

@@ -1,183 +1,69 @@
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.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.constants.AuditContent3TripleConstants;
import com.gxwebsoft.ai.service.AuditContent3TripleService;
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
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.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 implements AuditContent3TripleService {
public class AuditContent3TripleServiceImpl extends AbstractAuditContentService implements AuditContent3TripleService {
@Autowired
private KnowledgeBaseClientFactory clientFactory;
@Autowired
private KnowledgeBaseConfig config;
// 工作流配置
private static final String TRIPLE_ONE_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
private static final String TRIPLE_ONE_TOKEN = "Bearer app-tjXbmHDE6daMbYOT4O13ev2X";
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
);
private static final Map<String, String> TRIPLE_ONE_CATEGORIES = new LinkedHashMap<>();
static {
TRIPLE_ONE_CATEGORIES.put("重大决策", "重大决策事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("重要人事任免", "重要人事任免事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("重大项目安排", "重大项目安排事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("大额度资金运作", "大额度资金运作事项的定义和范围");
TRIPLE_ONE_CATEGORIES.put("决策权力主体和程序", "决策权力主体和程序的规定");
}
// Excel数据映射 - 从提供的Excel中提取
private static final Map<String, String[]> EXCEL_DATA_MAP = new HashMap<>();
static {
// 重大决策
EXCEL_DATA_MAP.put("重大决策", new String[]{
"1.重大决策事项:是指依照《中华人民共和国公司法》、《中华人民共和国全民所有制工业企业法》、《中华人民共和国企业国有资产法》、《中华人民共和国商业银行法》、《中华人民共和国证券法》、《中华人民共和国保险法》以及其他有关法律法规和党内法规规定的应当由股东大会(股东会)、董事会、未设董事会的经理班子、职工代表大会和党委(党组)决定的事项。主要包括企业贯彻执行党和国家的路线方针政策、法律法规和上级重要决定的重大措施,企业发展战略、破产、改制、兼并重组、资产调整、产权转让、对外投资、利益调配、机构调整等方面的重大决策,企业党的建设和安全稳定的重大决策,以及其他重大决策事项。",
"第四条重大决策的范围(一)集团公司贯彻执行国家法律法规,自治区战略部署及重要决策,以及上级主管部门重要决定等的重大举措;(二)集团公司章程制订和重要修订;集团公司重大基本管理制度,包括“三重一大”决策、投资、担保、资产交易、收入分配、人事、财务理,授权管理以及责任追究等重大管理制度的制订和重大修订;(三)集团公司生产经营方针、发展战略和中长期发展规划,以及重大投融资规划;(四)集团公司及重要子企业主业确定及变更;集团公司投资设立各类二级企业方案;集团公司及二级子公司发生分立、合并、重组,破产、解散及产权变更、增减资本方案;集团公司及所属子公司改制、股份制改造、混合所有制改革等方案;(五)集团公司重大财务管理事项,包括年度财务预算、年度财务决算、利润分配方案、亏损弥补方案;(六)集团公司内部收入分配事项,包括年度工资总额方案、职工工资、奖金、分流安置、劳动保护和劳动保险等事关职工切身利益的重大事项;集团公司所属部门、二级企业负责人年度考核结果及年度薪酬兑现方案;(七)集团公司制订或实施股权激励和员工持股计划;(八)集团公司及所属企业国有股权比例由控股变为非控股或国有股权由参股变为控股的事项;(九)集团公司及所属企业单笔金额为300万元及以上对外重大担保事项集团公司及所属企业重大关联交易事项、内部借款单笔金额为2000万元及以上事项;(十)集团公司及所属企业产权(资产)对外非公开协议转让、无偿划转及公开进场转让单笔金额为300万元及以上的事项;集团公司内部重组整合进行的产权(资产)非公开协议转让、无偿划转单笔金额为300万元及以上的事项;(十一)集团公司及所属企业重大资产损失、大额不良资产、核销单笔金额为20万元及以上的事项;集团公司及所属企业单笔放弃金额为30万元及以上的重大权益事项;(十二)集团公司内部机构改革方案,内部管理机构设立和调整方案,内部定岗、定编,定员、定责方案;(十三)集团公司党建群团工作的重大事项、方案;(十四)集团公司董事会年度工作报告、经理层年度工作报告、年度依法治企工作报告,年度内部控制体系工作报告等重要报告;(十五)集团公司应对重大法律纠纷、安全稳定,重大突发事件的重大措施及方案;(十六)法律法规和企业章程规定的事项,以及集团公司认为需要集体决策的关系到企业全局性、方向性、战略性的其他重大事项。",
"贯彻执行国家法律法规、自治区战略部署及集团公司的重要决策以及上级主管部门重要决定等的重大举措章程制订和重要修订重大基本管理制度包括“三重一大”决策、投资、担保、资产交易、收入分配、人事、财务管理、授权管理以及责任追究等重大管理制度的制订和重大修订生产经营方针、发展战略和中长期发展规划以及重大投融资规划公司主业确定及变更投资设立各类企业方案发生分立、合并、重组、破产、解散及产权变更、增减资本方案公司及所属企业改制、股份制改造、混合所有制改革等方案重大财务管理事项包括年度财务预算、年度财务决算、利润分配方案、亏损弥补方案内部收入分配事项包括年度工资总额方案、职工工资、奖金、分流安置、劳动保护和劳动保险等事关职工切身利益的重大事项所属部门年度考核结果及年度薪酬兑现方案制订或实施股权激励和员工持股计划公司国有股权比例由控股变为非控股或国有股权由参股变为控股的事项公司对外担保事项公司重大关联交易事项和内部借款单笔100万元及以上的事项公司产权资产对外非公开协议转让、无偿划转及公开进场转让公司内部重组整合进行的产权资产非公开协议转让、无偿划转的事项十一公司重大资产损失、大额不良资产核销单笔金额为1万元及以上的事项公司单笔放弃1万元及以上的重大权益事项十二公司内部机构改革方案内部管理机构设立和调整方案内部定岗、定编、定员、定责方案十三公司党建群团工作的重大事项、方案十四公司年度工作报告、经理层年度工作报告、年度依法治企工作报告、年度内部控制体系工作报告等重要报告十五公司应对重大法律纠纷、安全稳定、重大突发事件的措施及方案十六法律法规和企业章程规定的事项以及公司认为需要集体决策的关系到企业全局性、方向性、战略性的其他重大事项。"
});
// 重要人事任免
EXCEL_DATA_MAP.put("重要人事任免", new String[]{
"2.重要人事任免事项:是指企业直接管理的领导人员以及其他经营管理人员的职务调整事项。主要包括企业中层以上经营管理人员和下属企业、单位领导班子成员的任免、聘用、解除聘用和后备人选的确定,向控股和参股企业委派股东代表,推荐董事会、监事会成员和经理、财务负责人,以及其他重要人事任免事项。",
"第五条重要人事任免的范围(一)对集团公司中层管理人员、二级子公司领导班子成员的任免或聘用、解聘;相当于集团公司中层副职及以上的职业经理人的选聘、解聘;(二)按照企业章程约定,委派、提名、推荐集团公司非全资二级企业董事会、监事会成员和高级经营管理人员;(三)提名或委派集团公司三级企业董事长或执行董事、总经理人选;(四)集团公司中层管理人员后备人选;(五)涉及集团公司总部中层管理人员以及二级子公司班子成员的重要奖惩,对违犯党纪政纪干部职工的处理;(六)重大人事变动及其他人事管理的重要事项。",
"(一)对公司中层管理人员(包括重大项目负责人)的任免或聘用、解除聘用和后备人选的推荐、确定;(二)委派、提名、推荐董事、监事和经理层、财务负责人;(三)干部员工的奖惩;(四)重大人事变动及其他人事管理的重要事项。"
});
// 重大项目安排
EXCEL_DATA_MAP.put("重大项目安排", new String[]{
"3、重大项目安排事项是指对企业资产规模、资本结构、盈利能力以及生产装备、技术状况等产生重要影响的项目的设立和安排。主要包括年度投资计划融资、担保项目期权、期货等金融衍生业务重要设备和技术引进采购大宗物资和购买服务重大工程建设项目以及其他重大项目安排事项。",
"(一)集团公司年度投资计划方案;(二)集团公司年度融资计划方案;(三)集团公司及所属企业总投资额为3000万元及以上的投资项目(投资项目范围按集团公司投资管理办法明确的投资项目范围) ;(四)应当向自治区国资委报告的重大投资管理事项;(五)其他需要集体研究决定的重要项目安排事项。",
"企业年度投资计划和投资方案企业年度融资计划和融资方案包括银行借贷、上市、发行债券等企业50万元及以上的投资项目以及非主业投资项目企业的重大技术改造方案、重要技术设备引进项目重大、关键性的设备引进和重要物资设备购置等重大招投标管理项目应当向自治区国资委或广西旅游发展集团有限公司以下简称“集团公司”报告的重大投资管理事项其他需要集体研究决定的重要项目安排事项。"
});
// 大额度资金运作
EXCEL_DATA_MAP.put("大额度资金运作", new String[]{
"4.大额度资金运作事项:是指超过由企业或者履行国有资产出资人职责的机构所规定的企业领导人员有权调动、使用的资金限额的资金调动和使用。主要包括年度预算内大额度资金调动和使用,超预算的资金调动和使用,对外大额捐赠、赞助,以及其他大额度资金运作事项。",
"(一)除重大决策事项、重大项目安排事项外涉及单笔7000万元及以上的年度预算内大额度资金使用事项;(二)除重大决策事项、重大项目安排事项外涉及单笔5000万元及以上的预算外大额度经营性资金的使用事项;(三)预算外非经营性单笔100万元及以上、广西美术馆艺术品收藏单件或单次收藏一批100万元及以上的大额资金使用事项(四)集团公司及所属企业10万元及以上的对外捐赠、财务资助、公益慈善及用于脱贫攻坚(乡村振兴)等涉及企业政治责任和社会责任方面的重要事项;(五)公司单份工程签证涉及工程造价变更金额为500万元及以上的项目资金支出和其他大额度资金运作事项。",
"除重大决策事项、重大项目安排事项外涉及单笔500万元及以上的年度预算内大额度资金调动和使用除重大决策事项、重大项目安排事项外涉及单笔50万元及以上的预算外大额度资金调动和使用除重大决策事项、重大项目安排事项外涉及单笔10万元及以上的非生产性支出单份工程签证及造价变更额度为10万元及以上的企业对外捐赠、赞助在1万元及以上的事项其他大额度资金运作事项。"
});
// 决策权力主体和程序
EXCEL_DATA_MAP.put("决策权力主体和程序", new String[]{
"",
"第十一条 凡属“三重一大”事项,应按规定程序决策,除遇重大突发事件和紧急情况外,应由领导班子以党委会、董事会或经理层会议形式集体讨论决定,不得以传阅会签或个别征求意见等方式代替集体决策。第十二条 集团公司决策主体权力运行必须坚持落实党组织的法定地位,规范党组织参与“三重一大”决策程序,确保党组织的领导核心和政治核心作用有效发挥。要坚持把党委研究讨论作为董事会、经理层决策重大问题的前置程序,在集团公司董事会决策前,对涉及企业改革发展稳定,重大经营管理和职工切身利益的“三重一大”事项决策事项,集团公司党委应当组织有关人员对决策事项进行调研和论证,提出意见建议,充分体现党组织对决策的定向把关作用,确保决策的合法性科学性、准确性。在董事会决策中,进入董事会的党委班子成员要按照党委的决定在董事会上充分发表意见,保证党委的意图在决策中得到体现。在董事会决策后,党委要建立“三重一大”决策事项跟踪问效制度、定期汇报制度、事后考核制度等,确保党的决策部署在企业贯彻好、执行好、落实好。第十三条 集团公司党委会、董事会,经理层对“三重一大”事项进行决策的具体程序和议题准备、表决、记录等事项严格按照集团公司党委会议事规则、董事会议事规则、总经理办公会议事规则规定的程序和要求执行。第十四条 集团公司研究决定企业改制及经营管理方面的重大问题、涉及职工切身利益的重大事项、制定重要的规章制度,应当听取企业工会的意见,并通过职工代表大会或者其他形式听取职工群众的意见和建议。按照国家有关规定须经职工代表大会或者职工大会审议通过的事项,履行相关程序后董事会或经理层方可批准或者作出决议。涉及重大决策、重大项目、大额度资金的使用,有合同意向的,应将合同的主要条款提交会议讨论。第十五条 “三重一大”事项经集体决策后,企业领导人员应当按照分工和职责组织实施。遇有分工和职责交叉的,应明确牵头落实人员。个人对集体决策有不同意见的,可以保留,但在作出新的决策前,应无条件执行。同时,可按组织程序向上级组织反映意见。第十六条 企业“三重一大”事项经集体决策后,应及时向自治区国资委报告有关决策情况。特别是属于重大报告事项的应按要求及时上报自治区国资委备案。自治区人民政府、自治区国资委另有规定需要报审、报批和备案的,按规定程序办理。",
"第十一条 凡属“三重一大”事项,党支部委员会成员应参加党支部委员会议对议题进行前置研究审议,保证党组织的意图在决策中得到体现。不得以传阅会签或个别征求意见等方式代替集体决策。第十二条 公司决策主体权力运行必须坚持落实党组织的法定地位,规范党组织参与“三重一大”决策程序,确保党组织的领导核心和政治核心作用有效发挥。要坚持把党支部研究讨论作为总经理办公会决策重大问题的前置程序。在总经理办公会会议决策前,对涉及企业改革发展稳定、重大经营管理和职工切身利益的“三重一大”事项决策事项,党支部应当组织有关人员对决策事项进行调研和论证,提出意见建议,充分体现党支部对决策的定向把关作用,确保决策的合法性、科学性、准确性。在总经理办公会的决策中,担任执行董事的党支部领导班子成员要按照党支部的决定在总经理办公会上充分发表意见,保证党支部的意图在决策中得到体现。在总经理办公会决策后,党支部要建立“三重一大”决策事项跟踪问效制度、定期汇报制度、事后考核制度等,确保党的决策部署在企业贯彻好、执行好、落实好。第十三条 公司党支部、经理层对“三重一大”事项进行决策的具体程序和议题准备、表决、记录等事项严格按照公司相关议事规则规定的程序和要求执行。第十四条 公司研究决定企业改制及经营管理方面的重大问题、涉及职工切身利益的重大事项、制定重要的规章制度,应当听取企业工会的意见,并通过职工代表大会或者其他形式听取职工群众的意见和建议。按照国家有关规定须经职工代表大会或者职工大会审议通过的事项,履行相关程序后经理层方可批准或者作出决议。涉及重大决策、重大项目、大额度资金的使用,有合同意向的,应将合同的主要条款提交会议讨论。第十五条 “三重一大”事项经集体决策后,企业领导人员应当按照分工和职责组织实施。遇有分工和职责交叉的,应明确牵头落实人员。个人对集体决策有不同意见的,可以保留,但在作出新的决策前,应无条件执行。同时,可按组织程序向上级组织反映意见。"
});
}
// 关键词权重
private static final Map<String, Integer> KEYWORD_WEIGHTS;
static {
Map<String, Integer> map = new HashMap<>();
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("会议纪要", 6);
map.put("金额标准", 6);
KEYWORD_WEIGHTS = Collections.unmodifiableMap(map);
}
@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);
public JSONObject generateTripleOneTableData(String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
log.info("开始生成三重一大制度对比分析表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", userName, kbIds, libraryKbIds, projectLibrary);
JSONObject result = new JSONObject();
long startTime = System.currentTimeMillis();
try {
// 1. 异步并行处理每个分类 - 按照指定顺序
Map<String, CompletableFuture<JSONArray>> futures = new LinkedHashMap<>();
// 异步并行处理每个分类
Map<String, CompletableFuture<JSONArray>> futures = processCategoriesAsync(
CATEGORY_ORDER,
category -> generateCategoryDataAsync(category, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion)
);
for (String category : CATEGORY_ORDER) {
CompletableFuture<JSONArray> future = generateCategoryDataAsync(
category, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion
);
futures.put(category, future);
}
// 2. 等待所有异步任务完成
// 等待所有异步任务完成
CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
// 3. 合并所有分类的结果 - 按照指定顺序
JSONArray allData = new JSONArray();
for (String category : CATEGORY_ORDER) {
try {
JSONArray categoryData = futures.get(category).get();
if (categoryData != null && !categoryData.isEmpty()) {
allData.addAll(categoryData);
}
} catch (Exception e) {
log.error("获取分类 {} 数据失败", category, e);
}
}
// 合并所有分类的结果
JSONArray allData = mergeCategoryResults(CATEGORY_ORDER, futures);
// 4. 数据质量检查
allData = validateAndEnhanceComparisonData(allData);
log.info("三重一大制度对比分析表生成成功 - 记录数: {}, 处理时间: {}ms", allData.size(), (System.currentTimeMillis() - startTime));
// 5. 构建返回结果
result.put("success", true);
result.put("data", allData);
result.put("total_records", allData.size());
result.put("generated_time", new Date().toString());
result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms");
log.info("三重一大制度对比分析表生成成功 - 记录数: {}, 处理时间: {}ms",
allData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(allData, startTime, "triple_one_audit");
} catch (Exception e) {
log.error("生成三重一大制度对比分析表失败", e);
result.put("success", false);
result.put("error", e.getMessage());
throw new RuntimeException("生成三重一大制度对比分析表失败: " + e.getMessage(), e);
return buildErrorResponse("生成三重一大制度对比分析表失败: " + e.getMessage());
}
return result;
}
/**
* 异步生成单个分类的数据
*/
@Async
public CompletableFuture<JSONArray> generateCategoryDataAsync(String category, String kbIds, String libraryKbIds,
String projectLibrary, String userName,
String history, String suggestion) {
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);
@@ -187,17 +73,20 @@ public class AuditContent3TripleServiceImpl implements AuditContent3TripleServic
category, kbIds, libraryKbIds, projectLibrary
);
// 2. 生成当前分类的数据
JSONArray categoryData = generateCategoryTable(
category, knowledgeSources, userName, history, suggestion
// 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();
}
});
@@ -206,8 +95,7 @@ public class AuditContent3TripleServiceImpl implements AuditContent3TripleServic
/**
* 为单个分类检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForCategory(String category, String kbIds,
String libraryKbIds, String projectLibrary) {
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<>());
@@ -264,69 +152,32 @@ public class AuditContent3TripleServiceImpl implements AuditContent3TripleServic
*/
private List<String> buildCategoryQueries(String category) {
switch (category) {
case "重大决策":
return Arrays.asList(
"重大决策事项 决策范围 决策程序",
"重大决策制度 集体决策规定",
"党委会 董事会 总经理办公会 决策"
);
case "重要人事任免":
return Arrays.asList(
"重要人事任免 人事任免范围",
"中层管理人员 领导班子成员 任免",
"人事任免程序 干部管理"
);
case "重大项目安排":
return Arrays.asList(
"重大项目安排 项目安排范围",
"年度投资计划 融资担保项目",
"重大工程建设项目 重要设备引进"
);
case "大额度资金运作":
return Arrays.asList(
"大额度资金运作 资金运作范围",
"年度预算 大额度资金使用",
"对外捐赠 赞助 资金调动"
);
case "决策权力主体和程序":
return Arrays.asList(
"决策权力主体 决策程序",
"集体决策 前置程序",
"党委会前置研究 三重一大决策程序"
);
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 JSONArray generateCategoryTable(String category, Map<String, List<String>> knowledgeSources,
String userName, String history, String suggestion) {
// 构建优化的知识上下文 - 包含Excel数据
String knowledgeContext = buildCategoryKnowledgeContext(category, knowledgeSources, history, suggestion);
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray rawData = callTripleOneWorkflow(requestBody);
// 后处理:数据清洗和格式化
return postProcessCategoryData(category, rawData);
}
/**
* 构建分类特定的知识上下文 - 新增Excel数据
*/
private String buildCategoryKnowledgeContext(String category, Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
private String buildCompleteKnowledgeContext(String category, Map<String, List<String>> knowledgeSources, String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 分析要求
// 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("2. 对比分析政策内容、集团制度、公司制的差异\n");
context.append("3. 重点关注决策范围、金额标准、程序要求的差异\n");
context.append("4. 识别制度执行中的风险和问题\n");
context.append("5. 严格判断测试结果,只有证据充分才能判定为通过,证据不足或存在差异必须判定为不通过\n\n");
@@ -334,7 +185,7 @@ public class AuditContent3TripleServiceImpl implements AuditContent3TripleServic
// 2. 数据格式要求
context.append("## 数据格式要求\n");
context.append("需要生成").append(category).append("分类的数据,尽可能生成多个实例、多条记录:\n");
context.append("- ").append(category).append("").append(TRIPLE_ONE_CATEGORIES.get(category)).append("\n");
context.append("- ").append(category).append("").append(AuditContent3TripleConstants.CATEGORY_DESCRIPTIONS.get(category)).append("\n");
context.append("\n");
context.append("每条记录应包含6个字段\n");
@@ -348,16 +199,15 @@ public class AuditContent3TripleServiceImpl implements AuditContent3TripleServic
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
context.append("2. 公司执行情况分析需包含:查阅了哪些文件、发现了什么内容、与制度的差异点、分析判断过程\n");
context.append("3. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
context.append("4. 测试结果判定需严格,对于制度不一致、执行不到位、证据不充分的情况必须判定为不通过\n\n");
context.append("4. 测试结果判定需严格,对于制度不一致、执行不到位、证据不充分的情况必须判定为不通过\n");
context.append("5. 审计检查的证据主要按公司制度为主,政策内容和集团制度为次要\n");
context.append("6. 审计检查的证据增加判断公司制度是否与政策内容和集团制度相符\n\n");
// 3. 参考数据(从Excel中获取)
if (EXCEL_DATA_MAP.containsKey(category)) {
String[] excelData = EXCEL_DATA_MAP.get(category);
context.append("## 参考数据Excel模板\n");
context.append("### 政策内容\n").append(excelData[0]).append("\n\n");
context.append("### 集团制度\n").append(excelData[1]).append("\n\n");
context.append("### 公司制定\n").append(excelData[2]).append("\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)) {
@@ -376,78 +226,48 @@ public class AuditContent3TripleServiceImpl implements AuditContent3TripleServic
// 6. 企业单位知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识\n");
knowledgeSources.get("enterprise").stream()
.limit(100)
.forEach(knowledge -> context.append("- ").append(knowledge).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").stream()
.limit(80)
.forEach(knowledge -> context.append("- ").append(knowledge).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").stream()
.limit(60)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append(knowledge).append("\n"));
}
return context.toString();
}
/**
* 后处理分类数据
* 三重一大相关性比较器
*/
private JSONArray postProcessCategoryData(String category, JSONArray rawData) {
if (rawData == null || rawData.isEmpty()) {
return createDefaultCategoryData(category);
}
JSONArray processedData = new JSONArray();
for (int i = 0; i < rawData.size(); i++) {
JSONObject item = rawData.getJSONObject(i);
if (item != null) {
// 确保分类正确
item.put("category", category);
// 确保所有字段都存在
enhanceComparisonDataItem(item, i);
processedData.add(item);
}
}
return processedData;
private int tripleOneComparator(String reg1, String reg2) {
int score1 = calculateTripleOneRelevanceScore(reg1);
int score2 = calculateTripleOneRelevanceScore(reg2);
return Integer.compare(score2, score1);
}
/**
* 创建默认的分类数据
* 计算三重一大相关性分数
*/
private JSONArray createDefaultCategoryData(String category) {
JSONArray defaultData = new JSONArray();
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 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;
@@ -456,177 +276,4 @@ public class AuditContent3TripleServiceImpl implements AuditContent3TripleServic
default: return 50;
}
}
private JSONArray validateAndEnhanceComparisonData(JSONArray data) {
if (data == null || data.isEmpty()) {
return createDefaultComparisonData();
}
JSONArray enhancedData = new JSONArray();
for (int i = 0; i < data.size(); i++) {
JSONObject item = data.getJSONObject(i);
if (item == null) continue;
if (!validateComparisonDataItem(item)) {
log.warn("数据验证失败,跳过记录: {}", item);
continue;
}
enhanceComparisonDataItem(item, i);
enhancedData.add(item);
}
return enhancedData;
}
private JSONArray createDefaultComparisonData() {
JSONArray defaultData = new JSONArray();
for (String category : CATEGORY_ORDER) {
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 validateComparisonDataItem(JSONObject item) {
return item.containsKey("category") &&
item.containsKey("policyContent") &&
item.containsKey("groupSystem") &&
item.containsKey("companyFormulation");
}
private void enhanceComparisonDataItem(JSONObject item, int index) {
String[] requiredFields = {"policyContent", "groupSystem", "companyFormulation",
"checkEvidence", "testResult", "workPaperIndex"};
for (String field : requiredFields) {
if (!item.containsKey(field) || item.get(field) == null) {
if ("workPaperIndex".equals(field)) {
item.put(field, Collections.singletonList("待关联工作底稿"));
} else if ("testResult".equals(field)) {
item.put(field, "待检查");
} else {
item.put(field, "");
}
}
}
}
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 KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
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) {
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.error("查询知识库失败 - kbId: {}, queries: {}", kbId, queries, 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 || text.length() > 1000) {
return;
}
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");
return docNameObj != null ? docNameObj.toString() : "相关文档";
}
} catch (Exception e) {
log.debug("提取文档名称失败", e);
}
return "相关文档";
}
private JSONArray callTripleOneWorkflow(JSONObject requestBody) {
try {
String result = HttpUtil.createPost(TRIPLE_ONE_WORKFLOW_URL)
.header("Authorization", TRIPLE_ONE_TOKEN)
.header("Content-Type", "application/json")
.body(requestBody.toString())
.timeout(10*60*1000)
.execute()
.body();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(result);
String outputText = rootNode.path("data")
.path("outputs")
.path("result")
.asText();
JsonNode arrayNode = objectMapper.readTree(outputText);
return JSONArray.parseArray(arrayNode.toString());
} 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);
return requestBody;
}
}