优化工作底稿索引
This commit is contained in:
@@ -192,8 +192,8 @@ public class AuditContent10PartyConductConstants {
|
|||||||
obj.put("detailCategory", detailCategory);
|
obj.put("detailCategory", detailCategory);
|
||||||
obj.put("content", content);
|
obj.put("content", content);
|
||||||
obj.put("executionStatus", "");
|
obj.put("executionStatus", "");
|
||||||
// obj.put("workPaperIndex", "[\"实际存在的完整文件名1\", \"实际存在的完整文件名2\", \"...\"]");
|
obj.put("workPaperIndex", "[\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", \"...\"]");
|
||||||
obj.put("workPaperIndex", "[\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", \"...\"]");
|
// obj.put("workPaperIndex", "[\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", \"...\"]");
|
||||||
FIXED_ORDER_EXAMPLE_DATA.add(obj);
|
FIXED_ORDER_EXAMPLE_DATA.add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ public class AuditContent1ExpenseConstants {
|
|||||||
" \"budgetRatio\": \"占年初预算比例\",\n" +
|
" \"budgetRatio\": \"占年初预算比例\",\n" +
|
||||||
" \"remark\": \"备注信息\",\n" +
|
" \"remark\": \"备注信息\",\n" +
|
||||||
" \"dataSource\": \"数据来源文件\",\n" +
|
" \"dataSource\": \"数据来源文件\",\n" +
|
||||||
" \"workPaperIndex\": [\"FileId1\", \"FileId2\"]\n" +
|
// " \"workPaperIndex\": [\"FileId1\", \"FileId2\"]\n" +
|
||||||
|
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\"]\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"]";
|
"]";
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ public class AuditContent1LeaderListConstants {
|
|||||||
"- tenurePeriod:任职期间(格式:YYYY.MM-YYYY.MM)\n" +
|
"- tenurePeriod:任职期间(格式:YYYY.MM-YYYY.MM)\n" +
|
||||||
"- mainResponsibilities:主要工作责任\n" +
|
"- mainResponsibilities:主要工作责任\n" +
|
||||||
"- remark:备注信息\n" +
|
"- remark:备注信息\n" +
|
||||||
"- workPaperIndex:[相关文件FileId]";
|
// "- workPaperIndex:[相关文件FileId]";
|
||||||
|
"- workPaperIndex:[\"实际存在的完整文件名1||FileUrl1\"]";
|
||||||
|
|
||||||
// 关键词权重
|
// 关键词权重
|
||||||
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
|
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ public class AuditContent4TargetConstants {
|
|||||||
"7. selfCompletion: 自定完成情况\n" +
|
"7. selfCompletion: 自定完成情况\n" +
|
||||||
"8. selfReason: 自定未完成原因\n" +
|
"8. selfReason: 自定未完成原因\n" +
|
||||||
"9. remark: 备注\n" +
|
"9. remark: 备注\n" +
|
||||||
"10. workPaperIndex: [相关文件FileId]";
|
// "10. workPaperIndex: [相关文件FileId]";
|
||||||
|
"10. workPaperIndex: [相关文件的完整文件名||FileUrl]";
|
||||||
|
|
||||||
// 获取分类的简要审计框架概述
|
// 获取分类的简要审计框架概述
|
||||||
public static String getBriefAuditFrameworkForCategory(String category) {
|
public static String getBriefAuditFrameworkForCategory(String category) {
|
||||||
@@ -112,7 +113,7 @@ public class AuditContent4TargetConstants {
|
|||||||
FIELD_DISPLAY_NAMES.put("selfCompletion", "自定完成情况");
|
FIELD_DISPLAY_NAMES.put("selfCompletion", "自定完成情况");
|
||||||
FIELD_DISPLAY_NAMES.put("selfReason", "自定未完成原因");
|
FIELD_DISPLAY_NAMES.put("selfReason", "自定未完成原因");
|
||||||
FIELD_DISPLAY_NAMES.put("remark", "备注");
|
FIELD_DISPLAY_NAMES.put("remark", "备注");
|
||||||
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引FileId");
|
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 审计证据要求
|
// 审计证据要求
|
||||||
@@ -138,7 +139,8 @@ public class AuditContent4TargetConstants {
|
|||||||
" \"selfCompletion\": \"自定目标完成情况(已完成/部分完成/未完成)\",\n" +
|
" \"selfCompletion\": \"自定目标完成情况(已完成/部分完成/未完成)\",\n" +
|
||||||
" \"selfReason\": \"自定目标未完成原因(如已完成,填'无未完成原因')\",\n" +
|
" \"selfReason\": \"自定目标未完成原因(如已完成,填'无未完成原因')\",\n" +
|
||||||
" \"remark\": \"备注\",\n" +
|
" \"remark\": \"备注\",\n" +
|
||||||
" \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
||||||
|
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"]\n\n" +
|
"]\n\n" +
|
||||||
"重要说明:\n" +
|
"重要说明:\n" +
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ public class AuditContent5BudgetExecutionConstants {
|
|||||||
" \"additionalBudgetAmount\": \"追加预算数\",\n" +
|
" \"additionalBudgetAmount\": \"追加预算数\",\n" +
|
||||||
" \"actualAppropriation\": \"实际拨款数\",\n" +
|
" \"actualAppropriation\": \"实际拨款数\",\n" +
|
||||||
" \"indicatorBalance\": \"指标结余\",\n" +
|
" \"indicatorBalance\": \"指标结余\",\n" +
|
||||||
" \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
||||||
|
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"]\n\n" +
|
"]\n\n" +
|
||||||
"**重要说明:**\n" +
|
"**重要说明:**\n" +
|
||||||
@@ -215,7 +216,7 @@ public class AuditContent5BudgetExecutionConstants {
|
|||||||
FIELD_DISPLAY_NAMES.put("additionalBudgetAmount", "追加预算数");
|
FIELD_DISPLAY_NAMES.put("additionalBudgetAmount", "追加预算数");
|
||||||
FIELD_DISPLAY_NAMES.put("actualAppropriation", "实际拨款数");
|
FIELD_DISPLAY_NAMES.put("actualAppropriation", "实际拨款数");
|
||||||
FIELD_DISPLAY_NAMES.put("indicatorBalance", "指标结余");
|
FIELD_DISPLAY_NAMES.put("indicatorBalance", "指标结余");
|
||||||
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引FileId");
|
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取分类的简要审计框架概述
|
// 获取分类的简要审计框架概述
|
||||||
|
|||||||
@@ -186,7 +186,8 @@ public class AuditContent5BudgetManageConstants {
|
|||||||
" \"governmentProcurement\": \"政府采购\",\n" +
|
" \"governmentProcurement\": \"政府采购\",\n" +
|
||||||
" \"payableToUnit\": \"应拨单位款\",\n" +
|
" \"payableToUnit\": \"应拨单位款\",\n" +
|
||||||
" \"other\": \"其他(可简要说明审计发现)\",\n" +
|
" \"other\": \"其他(可简要说明审计发现)\",\n" +
|
||||||
" \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
||||||
|
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"]\n\n" +
|
"]\n\n" +
|
||||||
"**重要说明:**\n" +
|
"**重要说明:**\n" +
|
||||||
@@ -235,7 +236,7 @@ public class AuditContent5BudgetManageConstants {
|
|||||||
FIELD_DISPLAY_NAMES.put("governmentProcurement", "政府采购");
|
FIELD_DISPLAY_NAMES.put("governmentProcurement", "政府采购");
|
||||||
FIELD_DISPLAY_NAMES.put("payableToUnit", "应拨单位款");
|
FIELD_DISPLAY_NAMES.put("payableToUnit", "应拨单位款");
|
||||||
FIELD_DISPLAY_NAMES.put("other", "其他(审计发现)");
|
FIELD_DISPLAY_NAMES.put("other", "其他(审计发现)");
|
||||||
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引FileId");
|
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取分类的简要审计框架概述
|
// 获取分类的简要审计框架概述
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ public class AuditContent6StateAssetsConstants {
|
|||||||
" \"approvalDoc\": \"国有资产出租的审批文件(如未出租填'未出租')\",\n" +
|
" \"approvalDoc\": \"国有资产出租的审批文件(如未出租填'未出租')\",\n" +
|
||||||
" \"inBudget\": \"是否纳入预算(是/否)\",\n" +
|
" \"inBudget\": \"是否纳入预算(是/否)\",\n" +
|
||||||
" \"remark\": \"备注(包含资产状态、使用情况、审计发现等)\",\n" +
|
" \"remark\": \"备注(包含资产状态、使用情况、审计发现等)\",\n" +
|
||||||
" \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
|
||||||
|
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"]\n\n" +
|
"]\n\n" +
|
||||||
"重要说明:\n" +
|
"重要说明:\n" +
|
||||||
@@ -141,7 +142,7 @@ public class AuditContent6StateAssetsConstants {
|
|||||||
FIELD_DISPLAY_NAMES.put("approvalDoc", "国有资产出租的审批文件");
|
FIELD_DISPLAY_NAMES.put("approvalDoc", "国有资产出租的审批文件");
|
||||||
FIELD_DISPLAY_NAMES.put("inBudget", "是否纳入预算");
|
FIELD_DISPLAY_NAMES.put("inBudget", "是否纳入预算");
|
||||||
FIELD_DISPLAY_NAMES.put("remark", "备注");
|
FIELD_DISPLAY_NAMES.put("remark", "备注");
|
||||||
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引FileId");
|
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取分类的简要审计框架概述
|
// 获取分类的简要审计框架概述
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public abstract class BaseAuditContentController extends BaseController {
|
|||||||
JSONObject result = generateFunction.apply(params);
|
JSONObject result = generateFunction.apply(params);
|
||||||
|
|
||||||
if(result.getBoolean("success")) {
|
if(result.getBoolean("success")) {
|
||||||
// 转换workPaperIndex,原数据:["FileId1", "FileId2"],转换后:["文件名1" + "||" + "下载地址1", "文件名2" + "||" + "下载地址2"]
|
// 转换workPaperIndex,原数据:["文件名1"+"||"+"下载地址1","文件名2"+"||"+"下载地址2"],转换后:["文件ID1"+"||"+"文件名1"+"||"+"下载地址1","文件ID2"+"||"+"文件名2"+"||"+"下载地址2"]
|
||||||
convertWorkPaperFileInfo(result);
|
convertWorkPaperFileInfo(result);
|
||||||
// 保存到历史记录
|
// 保存到历史记录
|
||||||
saveToHistory(request, interfaceName, requestHash, result, loginUser);
|
saveToHistory(request, interfaceName, requestHash, result, loginUser);
|
||||||
@@ -106,6 +106,20 @@ public abstract class BaseAuditContentController extends BaseController {
|
|||||||
|
|
||||||
private void convertWorkPaperFileInfo(JSONObject result) {
|
private void convertWorkPaperFileInfo(JSONObject result) {
|
||||||
JSONArray data = result.getJSONArray("data");
|
JSONArray data = result.getJSONArray("data");
|
||||||
|
for (int i = 0; i < data.size(); i++) {
|
||||||
|
JSONObject obj = data.getJSONObject(i);
|
||||||
|
JSONArray workPaperIndexFiles = obj.getJSONArray("workPaperIndex");
|
||||||
|
if (workPaperIndexFiles != null && !workPaperIndexFiles.isEmpty()) {
|
||||||
|
for (int j = 0; j < workPaperIndexFiles.size(); j++) {
|
||||||
|
String files = workPaperIndexFiles.getString(j);
|
||||||
|
workPaperIndexFiles.set(j, "FileId||" + files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void convertWorkPaperFileInfo2(JSONObject result) {
|
||||||
|
JSONArray data = result.getJSONArray("data");
|
||||||
|
|
||||||
for (int i = 0; i < data.size(); i++) {
|
for (int i = 0; i < data.size(); i++) {
|
||||||
JSONObject obj = data.getJSONObject(i);
|
JSONObject obj = data.getJSONObject(i);
|
||||||
|
|||||||
@@ -5,12 +5,15 @@ import com.aliyun.bailian20231229.models.RetrieveResponse;
|
|||||||
import com.aliyun.bailian20231229.models.RetrieveResponseBody;
|
import com.aliyun.bailian20231229.models.RetrieveResponseBody;
|
||||||
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyData;
|
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyData;
|
||||||
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes;
|
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
|
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
|
||||||
|
import com.gxwebsoft.ai.entity.AiCloudFile;
|
||||||
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
|
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
|
||||||
|
import com.gxwebsoft.ai.service.AiCloudFileService;
|
||||||
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
|
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
@@ -21,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class AbstractAuditContentService {
|
public abstract class AbstractAuditContentService {
|
||||||
@@ -31,6 +35,9 @@ public abstract class AbstractAuditContentService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected KnowledgeBaseConfig config;
|
protected KnowledgeBaseConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected AiCloudFileService aiCloudFileService;
|
||||||
|
|
||||||
protected static final String DIFY_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
|
protected static final String DIFY_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
|
||||||
|
|
||||||
// 用于同步的锁对象池
|
// 用于同步的锁对象池
|
||||||
@@ -103,62 +110,114 @@ public abstract class AbstractAuditContentService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询知识库通用方法
|
* 查询知识库通用方法
|
||||||
* 同一个kbId,全局线程情况下,只支持一个,不支持异步多并发,并按队列顺序执行
|
|
||||||
*/
|
*/
|
||||||
protected List<String> queryKnowledgeBase(String kbId, List<String> queries, int topK) {
|
protected List<String> queryKnowledgeBase(String kbId, List<String> queries, int topK) {
|
||||||
Set<String> results = new LinkedHashSet<>();
|
|
||||||
String workspaceId = config.getWorkspaceId();
|
|
||||||
|
|
||||||
// 获取或创建该kbId对应的锁对象
|
|
||||||
Object lock = kbLocks.computeIfAbsent(kbId, k -> new Object());
|
Object lock = kbLocks.computeIfAbsent(kbId, k -> new Object());
|
||||||
|
|
||||||
// 使用synchronized确保同一个kbId的查询串行执行
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
Client client = clientFactory.createClient();
|
// 1. 收集所有节点和文档ID
|
||||||
for (String query : queries) {
|
List<RetrieveResponseBodyDataNodes> allNodes = collectKnowledgeNodes(kbId, queries, topK);
|
||||||
try {
|
if (allNodes.isEmpty()) {
|
||||||
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
|
return new ArrayList<>();
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. 批量查询文件URL
|
||||||
|
Map<String, String> fileUrlMap = batchQueryFileUrls(allNodes);
|
||||||
|
|
||||||
|
// 3. 处理节点生成结果
|
||||||
|
return processNodesToResults(allNodes, fileUrlMap);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("创建知识库客户端失败", e);
|
log.error("查询知识库失败 - kbId: {}", kbId, e);
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ArrayList<>(results);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理知识库节点通用方法
|
* 收集知识库节点
|
||||||
*/
|
*/
|
||||||
protected void processKnowledgeNode(RetrieveResponseBodyDataNodes node, Set<String> results) {
|
private List<RetrieveResponseBodyDataNodes> collectKnowledgeNodes(String kbId, List<String> queries, int topK) {
|
||||||
|
List<RetrieveResponseBodyDataNodes> allNodes = new ArrayList<>();
|
||||||
|
String workspaceId = config.getWorkspaceId();
|
||||||
try {
|
try {
|
||||||
String text = node.getText();
|
Client client = clientFactory.createClient();
|
||||||
if (StrUtil.isBlank(text) || text.length() < 10) {
|
for (String query : queries) {
|
||||||
return;
|
try {
|
||||||
|
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
|
||||||
|
List<RetrieveResponseBodyDataNodes> nodes = Optional.ofNullable(resp)
|
||||||
|
.map(RetrieveResponse::getBody)
|
||||||
|
.map(RetrieveResponseBody::getData)
|
||||||
|
.map(RetrieveResponseBodyData::getNodes)
|
||||||
|
.orElse(Collections.emptyList())
|
||||||
|
.stream()
|
||||||
|
.limit(topK)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
allNodes.addAll(nodes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("查询知识库失败 - kbId: {}, query: {}", kbId, query, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String docName = extractDocumentName(node);
|
|
||||||
String docId = extractDocumentId(node);
|
|
||||||
// String formattedText = String.format("《%s》%s", docName, text);
|
|
||||||
String formattedText = String.format("【FileId:%s】《%s》%s", docId, docName, text);
|
|
||||||
results.add(formattedText);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("处理知识库节点失败", e);
|
log.error("创建知识库客户端失败", e);
|
||||||
}
|
}
|
||||||
|
return allNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询文件URL
|
||||||
|
*/
|
||||||
|
private Map<String, String> batchQueryFileUrls(List<RetrieveResponseBodyDataNodes> nodes) {
|
||||||
|
// 收集所有文档ID
|
||||||
|
Set<String> docIds = nodes.stream().map(this::extractDocumentId).filter(StrUtil::isNotBlank).collect(Collectors.toSet());
|
||||||
|
if (docIds.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 批量查询
|
||||||
|
List<AiCloudFile> files = aiCloudFileService.list(new LambdaQueryWrapper<AiCloudFile>().in(AiCloudFile::getFileId, docIds));
|
||||||
|
// 构建映射表
|
||||||
|
return files.stream()
|
||||||
|
.filter(file -> file.getFileUrl() != null)
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
AiCloudFile::getFileId,
|
||||||
|
AiCloudFile::getFileUrl
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("批量查询文件信息失败", e);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理节点生成结果
|
||||||
|
*/
|
||||||
|
private List<String> processNodesToResults(List<RetrieveResponseBodyDataNodes> nodes, Map<String, String> fileUrlMap) {
|
||||||
|
Set<String> results = new LinkedHashSet<>();
|
||||||
|
for (RetrieveResponseBodyDataNodes node : nodes) {
|
||||||
|
try {
|
||||||
|
// 检查文本有效性
|
||||||
|
String text = node.getText();
|
||||||
|
if (StrUtil.isBlank(text) || text.length() < 10) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文档信息
|
||||||
|
String docName = extractDocumentName(node);
|
||||||
|
String docId = extractDocumentId(node);
|
||||||
|
String fileUrl = fileUrlMap.get(docId);
|
||||||
|
|
||||||
|
// 处理文件URL为空的情况
|
||||||
|
String url = StrUtil.isNotBlank(fileUrl) ? fileUrl : "无";
|
||||||
|
// 格式化结果
|
||||||
|
String formattedText = String.format("《%s》【FileUrl:%s】%s", docName, url, text);
|
||||||
|
results.add(formattedText);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("处理知识库节点失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -248,7 +248,8 @@ public class AuditContent1EightRegServiceImpl extends AbstractAuditContentServic
|
|||||||
context.append("- content:审计内容(具体中共中央八项规定/具体中央八项规定实施细则)\n");
|
context.append("- content:审计内容(具体中共中央八项规定/具体中央八项规定实施细则)\n");
|
||||||
context.append("- testContent:审计检查的证据,需详细描述查阅过程、查阅的具体文件和内容\n");
|
context.append("- testContent:审计检查的证据,需详细描述查阅过程、查阅的具体文件和内容\n");
|
||||||
context.append("- result:审计测试的结果(通过/不通过),严格判断,从严掌握通过标准\n");
|
context.append("- result:审计测试的结果(通过/不通过),严格判断,从严掌握通过标准\n");
|
||||||
context.append("- workPaperIndex:相关《参考文件FileId》,必须是实际存在的完整文件FileId,不能使用附表标题,确保能在文件夹中搜索到\n");
|
// context.append("- workPaperIndex:相关《参考文件FileId》,必须是实际存在的完整文件FileId,不能使用附表标题,确保能在文件夹中搜索到\n");
|
||||||
|
context.append("- workPaperIndex:相关[\"实际存在的完整文件名||FileUrl\"],必须是实际存在的完整文件名,不能使用附表标题,确保能在文件夹中搜索到\n");
|
||||||
context.append("\n注意:\n");
|
context.append("\n注意:\n");
|
||||||
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
|
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
|
||||||
context.append("2. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
|
context.append("2. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
|
||||||
|
|||||||
@@ -217,7 +217,8 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
|
|||||||
context.append("## 特别提醒\n");
|
context.append("## 特别提醒\n");
|
||||||
context.append("1. 必须准确识别支出类型:只提取\"公务接待\"、\"出国\"、\"公车运行维护\"、\"会议培训费\"四类支出\n");
|
context.append("1. 必须准确识别支出类型:只提取\"公务接待\"、\"出国\"、\"公车运行维护\"、\"会议培训费\"四类支出\n");
|
||||||
context.append("2. 不要将《工程造价和概(预)算执行情况表》等工程类报表误识别为\"三公经费\"报表\n");
|
context.append("2. 不要将《工程造价和概(预)算执行情况表》等工程类报表误识别为\"三公经费\"报表\n");
|
||||||
context.append("3. 工作底稿索引必须使用实际存在的完整文件名称作为FileId\n\n");
|
// context.append("3. 工作底稿索引必须使用实际存在的完整文件名称作为FileId\n\n");
|
||||||
|
context.append("3. 工作底稿索引必须使用实际存在的完整文件名||FileUrl\n\n");
|
||||||
|
|
||||||
// 3. 历史内容
|
// 3. 历史内容
|
||||||
if (StrUtil.isNotBlank(history)) {
|
if (StrUtil.isNotBlank(history)) {
|
||||||
|
|||||||
@@ -117,13 +117,6 @@ public class AuditContent1LeaderListServiceImpl extends AbstractAuditContentServ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保工作底稿索引是数组格式
|
|
||||||
// if (!leaderData.containsKey("workPaperIndex") || leaderData.get("workPaperIndex") == null) {
|
|
||||||
// JSONArray workPaperIndex = new JSONArray();
|
|
||||||
// workPaperIndex.add("《千汇发〔2025〕6号千汇公司关于领导班子成员工作分工的通知》");
|
|
||||||
// leaderData.put("workPaperIndex", workPaperIndex);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ public class AuditContent2StrategyServiceImpl extends AbstractAuditContentServic
|
|||||||
context.append("1. auditContent: 具体审计内容(基于框架,结合企业实际)\n");
|
context.append("1. auditContent: 具体审计内容(基于框架,结合企业实际)\n");
|
||||||
context.append("2. checkEvidence: 检查证据(引用企业具体文件,必须包含执行结果分析)\n");
|
context.append("2. checkEvidence: 检查证据(引用企业具体文件,必须包含执行结果分析)\n");
|
||||||
context.append("3. testResult: 测试结果(通过/不通过)(基于充分证据严格判断)\n");
|
context.append("3. testResult: 测试结果(通过/不通过)(基于充分证据严格判断)\n");
|
||||||
context.append("4. workPaperIndex: 工作底稿索引(具体文件FileId)\n\n");
|
// context.append("4. workPaperIndex: 工作底稿索引(具体文件FileId)\n\n");
|
||||||
|
context.append("4. workPaperIndex: 工作底稿索引(具体文件完整文件名||FileUrl)\n\n");
|
||||||
|
|
||||||
// 7. 法规和案例参考(如果有)
|
// 7. 法规和案例参考(如果有)
|
||||||
if (!knowledgeSources.get("regulation").isEmpty()) {
|
if (!knowledgeSources.get("regulation").isEmpty()) {
|
||||||
|
|||||||
@@ -194,7 +194,8 @@ public class AuditContent3TripleServiceImpl extends AbstractAuditContentService
|
|||||||
context.append("- companyFormulation:公司层面的三重一大相关制度规定及执行情况,需包含详细分析过程和查阅依据\n");
|
context.append("- companyFormulation:公司层面的三重一大相关制度规定及执行情况,需包含详细分析过程和查阅依据\n");
|
||||||
context.append("- checkEvidence:审计检查的证据,需详细描述查阅过程、查阅的具体文件和内容\n");
|
context.append("- checkEvidence:审计检查的证据,需详细描述查阅过程、查阅的具体文件和内容\n");
|
||||||
context.append("- testResult:审计测试的结果(通过/不通过),严格判断,从严掌握通过标准\n");
|
context.append("- testResult:审计测试的结果(通过/不通过),严格判断,从严掌握通过标准\n");
|
||||||
context.append("- workPaperIndex:相关《参考文件名FileId》,必须是实际存在的完整文件FileId,不能使用附表标题,确保能在文件夹中搜索到\n");
|
// context.append("- workPaperIndex:相关《参考文件名FileId》,必须是实际存在的完整文件FileId,不能使用附表标题,确保能在文件夹中搜索到\n");
|
||||||
|
context.append("- workPaperIndex:相关[\"实际存在的完整文件名||FileUrl\"],必须是实际存在的完整文件名,不能使用附表标题,确保能在文件夹中搜索到\n");
|
||||||
context.append("\n注意:\n");
|
context.append("\n注意:\n");
|
||||||
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
|
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
|
||||||
context.append("2. 公司执行情况分析需包含:查阅了哪些文件、发现了什么内容、与制度的差异点、分析判断过程\n");
|
context.append("2. 公司执行情况分析需包含:查阅了哪些文件、发现了什么内容、与制度的差异点、分析判断过程\n");
|
||||||
|
|||||||
@@ -177,7 +177,8 @@ public class AuditContent4TargetServiceImpl extends AbstractAuditContentService
|
|||||||
// 9. 特别提醒(新增关键优化点)
|
// 9. 特别提醒(新增关键优化点)
|
||||||
context.append("## 特别提醒\n");
|
context.append("## 特别提醒\n");
|
||||||
context.append("1. 审计证据必须包含具体的查阅过程:查阅了哪些文件、文件中发现了什么内容\n");
|
context.append("1. 审计证据必须包含具体的查阅过程:查阅了哪些文件、文件中发现了什么内容\n");
|
||||||
context.append("2. workPaperIndex必须填写实际存在的完整文件FileId,确保能在文件夹中搜索到\n");
|
// context.append("2. workPaperIndex必须填写实际存在的完整文件FileId,确保能在文件夹中搜索到\n");
|
||||||
|
context.append("2. workPaperIndex必须填写实际存在的完整文件名||FileUrl,确保能在文件夹中搜索到\n");
|
||||||
context.append("3. 完成情况判定必须基于充分证据:只有证据充分且完全符合要求才能判定为已完成\n");
|
context.append("3. 完成情况判定必须基于充分证据:只有证据充分且完全符合要求才能判定为已完成\n");
|
||||||
context.append("4. 对于执行不到位、效果不佳、证据不充分的情况必须在备注中说明\n");
|
context.append("4. 对于执行不到位、效果不佳、证据不充分的情况必须在备注中说明\n");
|
||||||
context.append("5. 尽可能识别知识库中所有相关年度,生成对应的审计记录\n");
|
context.append("5. 尽可能识别知识库中所有相关年度,生成对应的审计记录\n");
|
||||||
|
|||||||
@@ -237,7 +237,8 @@ public class AuditContent5BudgetExecutionServiceImpl extends AbstractAuditConten
|
|||||||
context.append("1. 必须全面分析预算执行全过程,包括执行进度、执行效果、执行合规性\n");
|
context.append("1. 必须全面分析预算执行全过程,包括执行进度、执行效果、执行合规性\n");
|
||||||
context.append("2. 重点关注预算执行率、资金到位率、预算执行偏差等关键指标\n");
|
context.append("2. 重点关注预算执行率、资金到位率、预算执行偏差等关键指标\n");
|
||||||
context.append("3. 金额字段应填写具体数值,如\"1,000,000.00\",不能填写简单的\"有\"或\"无\"\n");
|
context.append("3. 金额字段应填写具体数值,如\"1,000,000.00\",不能填写简单的\"有\"或\"无\"\n");
|
||||||
context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
|
// context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
|
||||||
|
context.append("4. workPaperIndex必须填写实际存在的完整文件名||FileUrl\n");
|
||||||
context.append("5. 对于无数据的字段,可填写\"-\"或留空,但不能填写\"无\"\n");
|
context.append("5. 对于无数据的字段,可填写\"-\"或留空,但不能填写\"无\"\n");
|
||||||
context.append("6. 基于预算执行全流程进行审计分析,包括月度、季度、年度执行情况\n");
|
context.append("6. 基于预算执行全流程进行审计分析,包括月度、季度、年度执行情况\n");
|
||||||
context.append("7. 重点关注预算执行偏差原因分析和整改措施\n");
|
context.append("7. 重点关注预算执行偏差原因分析和整改措施\n");
|
||||||
|
|||||||
@@ -237,7 +237,8 @@ public class AuditContent5BudgetManageServiceImpl extends AbstractAuditContentSe
|
|||||||
context.append("1. 必须全面识别知识库中所有预算科目,包括:基本支出、项目支出、人员经费、公用经费等\n");
|
context.append("1. 必须全面识别知识库中所有预算科目,包括:基本支出、项目支出、人员经费、公用经费等\n");
|
||||||
context.append("2. 每个独立的预算科目都要生成独立的审计记录,不限制数量,尽可能多地生成\n");
|
context.append("2. 每个独立的预算科目都要生成独立的审计记录,不限制数量,尽可能多地生成\n");
|
||||||
context.append("3. 金额字段应填写具体数值,如\"1,000,000.00\",不能填写简单的\"有\"或\"无\"\n");
|
context.append("3. 金额字段应填写具体数值,如\"1,000,000.00\",不能填写简单的\"有\"或\"无\"\n");
|
||||||
context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
|
// context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
|
||||||
|
context.append("4. workPaperIndex必须填写实际存在的完整文件名||FileUrl\n");
|
||||||
context.append("5. 对于无数据的字段,可填写\"-\"或留空,但不能填写\"无\"\n");
|
context.append("5. 对于无数据的字段,可填写\"-\"或留空,但不能填写\"无\"\n");
|
||||||
context.append("6. 基于预算编制、调整、执行的全流程进行审计分析\n");
|
context.append("6. 基于预算编制、调整、执行的全流程进行审计分析\n");
|
||||||
context.append("7. 重点关注预算调整的合规性和预算执行的真实性\n\n");
|
context.append("7. 重点关注预算调整的合规性和预算执行的真实性\n\n");
|
||||||
|
|||||||
@@ -192,7 +192,8 @@ public class AuditContent6StateAssetsServiceImpl extends AbstractAuditContentSer
|
|||||||
context.append("1. 必须全面识别知识库中所有国有资产,包括:房屋、土地、车辆、机械设备、办公设备、电子设备、家具、无形资产等\n");
|
context.append("1. 必须全面识别知识库中所有国有资产,包括:房屋、土地、车辆、机械设备、办公设备、电子设备、家具、无形资产等\n");
|
||||||
context.append("2. 每个独立的资产都要生成独立的审计记录,不限制数量,尽可能多地生成\n");
|
context.append("2. 每个独立的资产都要生成独立的审计记录,不限制数量,尽可能多地生成\n");
|
||||||
context.append("3. 即使资产信息不完整,也要基于现有信息生成审计记录\n");
|
context.append("3. 即使资产信息不完整,也要基于现有信息生成审计记录\n");
|
||||||
context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
|
// context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
|
||||||
|
context.append("4. workPaperIndex必须填写实际存在的完整文件名||FileUrl\n");
|
||||||
context.append("5. 对于未出租资产,承租方、合同金额等字段填写\"未出租\"\n");
|
context.append("5. 对于未出租资产,承租方、合同金额等字段填写\"未出租\"\n");
|
||||||
context.append("6. 备注中应详细说明资产状况、使用情况、合规性评价\n");
|
context.append("6. 备注中应详细说明资产状况、使用情况、合规性评价\n");
|
||||||
context.append("7. 不能填写简单的\"无\",要提供有意义的描述\n\n");
|
context.append("7. 不能填写简单的\"无\",要提供有意义的描述\n\n");
|
||||||
|
|||||||
@@ -227,7 +227,8 @@ public class AuditContent7InvestmentServiceImpl extends AbstractAuditContentServ
|
|||||||
context.append(" • 通过:证据充分且完全符合要求\n");
|
context.append(" • 通过:证据充分且完全符合要求\n");
|
||||||
context.append(" • 不通过:制度不一致、执行不到位、证据不充分\n");
|
context.append(" • 不通过:制度不一致、执行不到位、证据不充分\n");
|
||||||
context.append(" • 待检查:无法确定,需要进一步检查\n");
|
context.append(" • 待检查:无法确定,需要进一步检查\n");
|
||||||
context.append("- **workPaperIndex**:相关《工作底稿索引FileId》,必须是实际存在的完整文件FileId,确保能在文件夹中搜索到\n");
|
// context.append("- **workPaperIndex**:相关《工作底稿索引FileId》,必须是实际存在的完整文件FileId,确保能在文件夹中搜索到\n");
|
||||||
|
context.append("- **workPaperIndex**:相关[\"实际存在的完整文件名||FileUrl\"],必须是实际存在的完整文件名,不能使用附表标题,确保能在文件夹中搜索到\n");
|
||||||
context.append("- **fileIndex**:相关《文件索引》,关联的支持文件\n\n");
|
context.append("- **fileIndex**:相关《文件索引》,关联的支持文件\n\n");
|
||||||
|
|
||||||
// 5. 审计内容模板(提供参考)
|
// 5. 审计内容模板(提供参考)
|
||||||
|
|||||||
@@ -233,7 +233,8 @@ public class AuditContent8InternalControlServiceImpl extends AbstractAuditConten
|
|||||||
context.append("- testSteps(测试步骤):**只包含当前步骤内容**,如\"(1)是否有制度规定\"\n");
|
context.append("- testSteps(测试步骤):**只包含当前步骤内容**,如\"(1)是否有制度规定\"\n");
|
||||||
context.append("- checkEvidence(检查证据):针对当前测试步骤的详细检查证据\n");
|
context.append("- checkEvidence(检查证据):针对当前测试步骤的详细检查证据\n");
|
||||||
context.append("- testResult(测试结果):基于当前测试步骤的检查证据严格判断,只有证据充分且完全符合要求才能判定为\"通过\",否则必须判定为\"不通过\"\n");
|
context.append("- testResult(测试结果):基于当前测试步骤的检查证据严格判断,只有证据充分且完全符合要求才能判定为\"通过\",否则必须判定为\"不通过\"\n");
|
||||||
context.append("- workPaperIndex(工作底稿索引FileId):实际存在的完整文件FileId,确保能在文件夹中搜索到\n\n");
|
// context.append("- workPaperIndex(工作底稿索引FileId):实际存在的完整文件FileId,确保能在文件夹中搜索到\n\n");
|
||||||
|
context.append("- workPaperIndex(工作底稿索引文件名):实际存在的完整文件名||FileUrl,确保能在文件夹中搜索到\n\n");
|
||||||
|
|
||||||
context.append("**生成规则:**\n");
|
context.append("**生成规则:**\n");
|
||||||
context.append("1. **每个测试步骤单独生成一条完整记录**\n");
|
context.append("1. **每个测试步骤单独生成一条完整记录**\n");
|
||||||
|
|||||||
@@ -267,7 +267,8 @@ public class AuditContent9PersonnelServiceImpl extends AbstractAuditContentServi
|
|||||||
context.append("- auditTarget:固定为'").append(subContent.getAuditTarget()).append("'\n");
|
context.append("- auditTarget:固定为'").append(subContent.getAuditTarget()).append("'\n");
|
||||||
context.append("- auditEvidence:固定为'").append(subContent.getAuditEvidence()).append("'\n");
|
context.append("- auditEvidence:固定为'").append(subContent.getAuditEvidence()).append("'\n");
|
||||||
context.append("- generationResult:审计发现和结论\n");
|
context.append("- generationResult:审计发现和结论\n");
|
||||||
context.append("- workPaperIndex:工作底稿索引,具体的文件FileId数组\n\n");
|
// context.append("- workPaperIndex:工作底稿索引,具体的文件FileId数组\n\n");
|
||||||
|
context.append("- workPaperIndex:工作底稿索引,具体的文件[\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]数组\n\n");
|
||||||
|
|
||||||
context.append("## generationResult格式\n");
|
context.append("## generationResult格式\n");
|
||||||
context.append("标题:在审计期间,[具体单位名称]存在[具体问题](如有充分证据)\n");
|
context.append("标题:在审计期间,[具体单位名称]存在[具体问题](如有充分证据)\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user