调整审计报告AI分析提示词

This commit is contained in:
2026-04-08 09:47:54 +08:00
parent 4865d170df
commit 2b07f9087c
3 changed files with 80 additions and 150 deletions

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.ai.controller; package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.ai.dto.AuditEvidenceRequest; import com.gxwebsoft.ai.dto.AuditEvidenceRequest;
import com.gxwebsoft.ai.entity.AuditEvidence; import com.gxwebsoft.ai.entity.AuditEvidence;
import com.gxwebsoft.ai.param.AuditEvidenceParam; import com.gxwebsoft.ai.param.AuditEvidenceParam;
@@ -126,6 +127,26 @@ public class AuditEvidenceController extends BaseController {
return fail("保存审计取证单异常:" + e.getMessage(), null); return fail("保存审计取证单异常:" + e.getMessage(), null);
} }
} }
/**
* 保存审计取证单到数据库
*/
@Operation(summary = "批量查询取证单接口")
@PostMapping("/batchQuery")
public ApiResult<List<AuditEvidence>> batchQueryEvidence(@RequestBody Map<String, List<Long>> request) {
List<Long> evidenceIds = request.get("evidenceIds");
if (evidenceIds == null || evidenceIds.isEmpty()) {
return success(new ArrayList<>());
}
LambdaQueryWrapper<AuditEvidence> wrapper = new LambdaQueryWrapper<>();
wrapper.in(AuditEvidence::getId, evidenceIds)
.eq(AuditEvidence::getDeleted, 0);
List<AuditEvidence> evidences = auditEvidenceService.list(wrapper);
return success(evidences);
}
/** /**
* 下载审计取证单Word文档 * 下载审计取证单Word文档

View File

@@ -1,7 +1,6 @@
package com.gxwebsoft.ai.controller; package com.gxwebsoft.ai.controller;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
@@ -17,16 +16,20 @@ import javax.servlet.http.HttpServletResponse;
import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.ai.entity.AuditEvidence; import com.gxwebsoft.ai.entity.AuditEvidence;
import com.gxwebsoft.ai.mapper.AuditEvidenceMapper; import com.gxwebsoft.ai.mapper.AuditEvidenceMapper;
import com.gxwebsoft.ai.service.AiCloudDocService;
import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.service.AuditEvidenceService;
import com.gxwebsoft.pwl.entity.PwlProject; import com.gxwebsoft.pwl.entity.PwlProject;
import com.gxwebsoft.pwl.service.PwlProjectService; import com.gxwebsoft.pwl.service.PwlProjectService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.util.ZipSecureFile; import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.BreakType; import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFRun;
@@ -37,7 +40,6 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@@ -74,30 +76,28 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@Tag(name = "审计报告") @Tag(name = "审计报告")
@RestController @RestController
@RequestMapping("/api/ai/auditReport") @RequestMapping("/api/ai/auditReport")
@RequiredArgsConstructor
@Slf4j @Slf4j
public class AuditReportController extends BaseController { public class AuditReportController extends BaseController {
@Autowired private final TemplateConfig templateConfig;
private TemplateConfig templateConfig;
private final KnowledgeBaseService knowledgeBaseService;
@Autowired
private KnowledgeBaseService knowledgeBaseService; private final AuditReportService auditReportService;
@Autowired private final PwlProjectService pwlProjectService;
private AuditReportService auditReportService;
private final AuditEvidenceMapper auditEvidenceMapper;
private final AuditEvidenceService auditEvidenceService;
private final AiHistoryService aiHistoryService;
private final AiCloudFileService aiCloudFileService;
private final AiCloudDocService aiCloudDocService;
@Autowired
private PwlProjectService pwlProjectService;
@Autowired
private AuditEvidenceMapper auditEvidenceMapper;
// @Autowired
// private AuditEvidenceService auditEvidenceService;
@Autowired
private AiHistoryService aiHistoryService;
private String invok(String query, String knowledge, String history, String suggestion, String title, String userName) { private String invok(String query, String knowledge, String history, String suggestion, String title, String userName) {
// 构建请求体 // 构建请求体
JSONObject requestBody = new JSONObject(); JSONObject requestBody = new JSONObject();
@@ -1286,24 +1286,7 @@ public class AuditReportController extends BaseController {
document.createParagraph(); document.createParagraph();
document.createParagraph(); document.createParagraph();
} }
/**
* 添加主标题
*/
private void addMainTitle(XWPFDocument document, String title) throws IOException {
XWPFParagraph titlePara = document.createParagraph();
titlePara.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleRun = titlePara.createRun();
titleRun.setText(title);
titleRun.setBold(true);
titleRun.setFontSize(16); // 三号
titleRun.setFontFamily("仿宋_GB2312");
// 添加 2 个空行
document.createParagraph();
document.createParagraph();
}
/** /**
* 添加文号(右对齐,蓝色) * 添加文号(右对齐,蓝色)
*/ */
@@ -1384,91 +1367,6 @@ public class AuditReportController extends BaseController {
document.createParagraph(); document.createParagraph();
document.createParagraph(); document.createParagraph();
} }
/**
* 添加标题
*/
private void addTitle(XWPFDocument document, String title) throws IOException {
XWPFParagraph titlePara = document.createParagraph();
titlePara.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleRun = titlePara.createRun();
titleRun.setText(title);
titleRun.setBold(true);
titleRun.setFontSize(16); // 三号
titleRun.setFontFamily("仿宋_GB2312");
// 添加空行
document.createParagraph();
}
/**
* 添加章节
*/
private void addSection(XWPFDocument document, String sectionTitle, List<String> subSections) throws IOException {
// 一级标题仿宋_GB2312三号加粗
XWPFParagraph sectionPara = document.createParagraph();
sectionPara.setAlignment(ParagraphAlignment.LEFT);
XWPFRun sectionRun = sectionPara.createRun();
sectionRun.setText(sectionTitle);
sectionRun.setBold(true);
sectionRun.setFontSize(16); // 三号
sectionRun.setFontFamily("仿宋_GB2312");
// 添加子章节
if (subSections != null && !subSections.isEmpty()) {
for (String subSection : subSections) {
if (subSection != null && !subSection.trim().isEmpty()) {
// 按换行符分割内容
String[] lines = subSection.split("\\n");
for (String line : lines) {
if (!line.trim().isEmpty()) {
XWPFParagraph contentPara = document.createParagraph();
contentPara.setAlignment(ParagraphAlignment.LEFT);
XWPFRun contentRun = contentPara.createRun();
contentRun.setText(line.trim());
contentRun.setFontSize(12); // 小四
contentRun.setFontFamily("仿宋_GB2312");
// 设置首行缩进 1 个中文字符
contentPara.setIndentationFirstLine(480);
}
}
}
}
}
// 添加空行
document.createParagraph();
}
/**
* 添加章节内容(只显示内容,不显示标题)
*/
private void addSectionContent(XWPFDocument document, String content) throws IOException {
if (content == null || content.trim().isEmpty()) {
return;
}
// 按换行符分割内容
String[] lines = content.split("\\n");
for (String line : lines) {
if (!line.trim().isEmpty()) {
XWPFParagraph contentPara = document.createParagraph();
contentPara.setAlignment(ParagraphAlignment.LEFT);
XWPFRun contentRun = contentPara.createRun();
contentRun.setText(line.trim());
contentRun.setFontSize(12); // 小四
contentRun.setFontFamily("仿宋_GB2312");
// 设置首行缩进 2 个中文字符
contentPara.setIndentationFirstLine(480);
}
}
// 添加空行
document.createParagraph();
}
/** /**
* 添加章节(带标题和前缀,支持子章节) * 添加章节(带标题和前缀,支持子章节)
*/ */
@@ -1533,20 +1431,20 @@ public class AuditReportController extends BaseController {
* 根据 formCommit 获取子章节标题 * 根据 formCommit 获取子章节标题
*/ */
private String getSubsectionTitle(Integer formCommit, PwlProject project) { private String getSubsectionTitle(Integer formCommit, PwlProject project) {
switch (formCommit) { return switch (formCommit) {
case 10: return "(一)审计依据"; case 10 -> "(一)审计依据";
case 41: return String.format("(二)%s概况", project.getName()); case 41 -> String.format("(二)%s概况", project.getName());
case 42: return String.format("(三)%s任职及分工情况", project.getPersonName()); case 42 -> String.format("(三)%s任职及分工情况", project.getPersonName());
case 43: return "(四)实施审计的基本情况"; case 43 -> "(四)实施审计的基本情况";
case 51: return "(一)贯彻执行党和国家经济方针政策、决策部署情况"; case 51 -> "(一)贯彻执行党和国家经济方针政策、决策部署情况";
case 52: return "(二)企业发展战略规划的制定、执行和效果情况"; case 52 -> "(二)企业发展战略规划的制定、执行和效果情况";
case 53: return "(三)重大经济事项的决策、执行和效果情况"; case 53 -> "(三)重大经济事项的决策、执行和效果情况";
case 54: return "(四)企业法人治理结构的建立、健全和运行情况,内部控制制度的制定和执行情况"; case 54 -> "(四)企业法人治理结构的建立、健全和运行情况,内部控制制度的制定和执行情况";
case 55: return "(五)企业财务的真实合法效益情况,风险管控情况,境外资产管理情况,生态环境保护情况"; case 55 -> "(五)企业财务的真实合法效益情况,风险管控情况,境外资产管理情况,生态环境保护情况";
case 56: return "(六)在经济活动中落实有关党风廉政建设责任和遵守廉洁从业规定情况"; case 56 -> "(六)在经济活动中落实有关党风廉政建设责任和遵守廉洁从业规定情况";
case 57: return "(七)以往审计发现问题的整改情况"; case 57 -> "(七)以往审计发现问题的整改情况";
default: return ""; default -> "";
} };
} }
/** /**
@@ -1715,7 +1613,7 @@ public class AuditReportController extends BaseController {
} }
String companyName = project.getName(); String companyName = project.getName();
String personName = project.getPersonName(); String personName = project.getPersonName();
String prompt; String prompt = "";
if (request.getFormCommit() == 20) { if (request.getFormCommit() == 20) {
// 二、总体评价的特殊提示词模板 // 二、总体评价的特殊提示词模板
// 查询该项目的所有取证单,判断是否有发现问题 // 查询该项目的所有取证单,判断是否有发现问题
@@ -1762,7 +1660,7 @@ public class AuditReportController extends BaseController {
StringBuilder promptBuilder = new StringBuilder(); StringBuilder promptBuilder = new StringBuilder();
// 只传递取证单 ID 列表,让 AI 自行从数据库读取 // 只传递取证单 ID 列表,让 AI 自行从数据库读取
if (evidenceIds != null && !evidenceIds.isEmpty()) { if (!evidenceIds.isEmpty()) {
// 将 ID 列表转换为逗号分隔的字符串 // 将 ID 列表转换为逗号分隔的字符串
String evidenceIdsStr = evidenceIds.stream() String evidenceIdsStr = evidenceIds.stream()
.map(String::valueOf) .map(String::valueOf)
@@ -1778,15 +1676,22 @@ public class AuditReportController extends BaseController {
promptBuilder.append("2. 原因分析\n"); promptBuilder.append("2. 原因分析\n");
promptBuilder.append("3. 责任界定\n"); promptBuilder.append("3. 责任界定\n");
promptBuilder.append("\n注意输出内容中不要显示取证单编号直接生成正式的审计报告内容。\n"); promptBuilder.append("\n注意输出内容中不要显示取证单编号直接生成正式的审计报告内容。\n");
prompt = promptBuilder.toString(); prompt = promptBuilder.toString();
} }
else {
// 其他章节使用通用 prompt - 查询审计相关法规 // 其他章节使用通用 prompt - 查询审计相关法规
prompt = String.format("请查询与'%s'相关的所有审计法规、制度和政策文件。要求1.列出完整的法规名称2.注明颁布单位3.注明发文字号如有4.列出相关条款5.按重要性排序6.使用规范的格式。", title); // 注意AI工作流限制query不能超过512字符因此提示词必须精简
} // 详细信息通过evidenceIds参数和知识库检索获取
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append(String.format("请为审计报告章节'%s'生成内容。\n", title));
promptBuilder.append("数据源1)取证单(已通过evidenceIds传入) 2)阿里云资料库(自动检索)\n");
promptBuilder.append("要求:优先用取证单事实,结合资料库制度,不足时生成框架内容,勿编造数据。\n");
prompt = promptBuilder.toString();
prompt += "\n重要提示数据源必须严格来自页面上选择的取证单数据,不能从其他地方获取数据。)"; // prompt += "\n重要提示数据源必须严格来自传入接口的取证单数据,或者在本项目配置的阿里云资料库中的文件必须保存在ai_cloud_doc和ai_cloud_file表中(根据pwl_project.company_id),不能凭空捏造或者从互联网上获取数据。)";
log.info("生成审计报告标题:{}AI 提示词:{}", request.getChapterTitle(), prompt); log.info("生成审计报告标题:{}AI 提示词:{}", request.getChapterTitle(), prompt);
// 调用 AI 接口,同时传递取证单 ID 列表 // 调用 AI 接口,同时传递取证单 ID 列表
@@ -1882,11 +1787,15 @@ public class AuditReportController extends BaseController {
// 如果有取证单 ID加入到请求中 // 如果有取证单 ID加入到请求中
if (evidenceIds != null && !evidenceIds.isEmpty()) { if (evidenceIds != null && !evidenceIds.isEmpty()) {
inputs.put("evidenceIds", evidenceIds); inputs.put("evidenceIds", evidenceIds);
List<AuditEvidence> evidences = auditEvidenceService.listByIds(evidenceIds);
inputs.put("evidences", evidences);
} }
requestBody.put("inputs", inputs); requestBody.put("inputs", inputs);
requestBody.put("response_mode", "blocking"); requestBody.put("response_mode", "blocking");
requestBody.put("user", userName); requestBody.put("user", userName);
log.info("生成审计报告AI请求参数{}", JSON.toJSONString(requestBody));
try { try {
// 发送 POST 请求 // 发送 POST 请求

View File

@@ -1,6 +1,6 @@
package com.gxwebsoft.ai.service; package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.ai.dto.AuditEvidenceRequest; import com.gxwebsoft.ai.dto.AuditEvidenceRequest;
import com.gxwebsoft.ai.entity.AuditEvidence; import com.gxwebsoft.ai.entity.AuditEvidence;
import com.gxwebsoft.ai.param.AuditEvidenceParam; import com.gxwebsoft.ai.param.AuditEvidenceParam;
@@ -8,7 +8,7 @@ import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
public interface AuditEvidenceService { public interface AuditEvidenceService extends IService<AuditEvidence> {
/** /**
* 生成审计取证单 * 生成审计取证单
*/ */