优化审计内容3生成方法

This commit is contained in:
2025-10-23 16:01:51 +08:00
parent 1fcaf3f68a
commit f0ef08f0e7
3 changed files with 444 additions and 148 deletions

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.User;
@@ -27,15 +28,19 @@ public class AuditContentController3 extends BaseController {
*/
@Operation(summary = "生成重大经济决策调查表")
@PostMapping("/generateDecisionTable")
public ApiResult<?> generateDecisionTable(
@RequestParam(value = "kbIds", required = false) String kbIds,
@RequestParam(value = "libraryIds", required = false) String libraryIds,
@RequestParam(value = "projectLibrary", required = false) String projectLibrary) {
public ApiResult<?> generateDecisionTable(@RequestBody AuditContentRequest request) {
final User loginUser = getLoginUser();
try {
// 生成重大经济决策调查表数据
JSONObject result = auditContentService3.generateDecisionTableData(kbIds, libraryIds, projectLibrary, loginUser.getUsername());
JSONObject result = auditContentService3.generateDecisionTableData(
request.getKbIds(),
request.getLibraryIds(),
request.getProjectLibrary(),
loginUser.getUsername(),
request.getHistory(),
request.getSuggestion()
);
return success(result);
} catch (Exception e) {

View File

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

View File

@@ -17,13 +17,16 @@ import com.gxwebsoft.pwl.service.PwlProjectLibraryService;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContentServiceImpl3 implements AuditContentService3 {
@@ -36,122 +39,480 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
@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";
// 缓存
private final Map<String, Set<String>> knowledgeCache = new ConcurrentHashMap<>();
private static final long CACHE_EXPIRE_TIME = 5 * 60 * 1000;
private final Map<String, Long> cacheTimestamps = new ConcurrentHashMap<>();
// 决策程序类型
private static final Map<String, String> DECISION_PROCEDURES = new HashMap<>();
static {
DECISION_PROCEDURES.put("会议决策", "通过召开专题会议进行集体决策,会议纪要完整");
DECISION_PROCEDURES.put("会签决策", "通过会签方式进行决策,相关人员签字确认");
DECISION_PROCEDURES.put("书面决策", "通过书面请示报告方式进行决策");
DECISION_PROCEDURES.put("授权决策", "在授权范围内由负责人直接决策");
}
private static final Map<String, Integer> KEYWORD_WEIGHTS;
static {
Map<String, Integer> map = new HashMap<>();
map.put("三重一大", 10);
map.put("集体决策", 8);
map.put("重大经济决策", 9);
map.put("会议纪要", 7);
map.put("决策程序", 7);
map.put("决策标准", 6);
map.put("审计方法", 6);
map.put("重大预算", 5);
map.put("重大项目", 5);
map.put("重大采购", 5);
map.put("重大投资", 5);
KEYWORD_WEIGHTS = Collections.unmodifiableMap(map);
}
@Override
public JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary, String userName) {
public JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary, String userName, String history, String suggestion) {
log.info("开始生成重大经济决策调查表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", userName, kbIds, libraryIds, projectLibrary);
JSONObject result = new JSONObject();
long startTime = System.currentTimeMillis();
try {
// 1. 从知识库召回相关规定和案例
List<String> regulations = retrieveDecisionRegulations(kbIds, libraryIds, projectLibrary);
// 1. 从不同知识库召回相关内容
Map<String, List<String>> knowledgeSources = retrieveDecisionKnowledgeSeparated(kbIds, libraryIds, projectLibrary);
// 2. 生成重大经济决策调查表数据
JSONArray decisionTableData = generateDecisionTable(regulations, userName);
JSONArray decisionTableData = generateDecisionTable(knowledgeSources, userName, history, suggestion);
// 3. 构建返回结果
// 3. 数据质量检查
decisionTableData = validateAndEnhanceData(decisionTableData);
// 4. 构建返回结果
result.put("success", true);
result.put("data", decisionTableData);
result.put("total_records", decisionTableData.size());
result.put("generated_time", new Date().toString());
result.put("regulations_count", regulations.size());
result.put("core_knowledge_count", knowledgeSources.get("core").size());
result.put("case_knowledge_count", knowledgeSources.get("case").size());
result.put("regulation_knowledge_count", knowledgeSources.get("regulation").size());
result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms");
log.info("重大经济决策调查表生成成功 - 记录数: {}, 处理时间: {}ms",
decisionTableData.size(), (System.currentTimeMillis() - startTime));
} catch (Exception e) {
result.put("success", false);
result.put("error", e.getMessage());
// 返回默认数据避免前端报错
result.put("data", createDefaultDecisionData());
log.error("生成重大经济决策调查表失败", e);
// 直接抛出异常,不返回默认数据
throw new RuntimeException("生成重大经济决策调查表失败: " + e.getMessage(), e);
}
return result;
}
/**
* 从知识库召回重大经济决策相关规定
* 分离不同知识库的检索策略
*/
private List<String> retrieveDecisionRegulations(String kbIds, String libraryIds, String projectLibrary) {
List<String> regulations = new ArrayList<>();
String query = buildDecisionQuery();
private Map<String, List<String>> retrieveDecisionKnowledgeSeparated(String kbIds, String libraryIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("core", new ArrayList<>());
knowledgeSources.put("case", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
// 主知识库列表
// 核心审计库 - 主要来源
if (StrUtil.isNotBlank(kbIds)) {
for (String kbId : kbIds.split(",")) {
if (StrUtil.isNotBlank(kbId.trim())) {
regulations.addAll(queryKnowledgeBase(kbId.trim(), query, 100));
}
}
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("core")
.addAll(queryKnowledgeBaseWithCache(kbId, buildCoreQueries(), 150)));
}
// 公共库
// 案例库 - 辅助参考
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("case").addAll(queryKnowledgeBaseWithCache(projectLibrary, buildCaseQueries(), 100));
}
// 法规库 - 制度校验
if (StrUtil.isNotBlank(libraryIds)) {
List<String> idList = StrUtil.split(libraryIds, ',');
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(
new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
String libraryKbIds = ret.stream().map(PwlProjectLibrary::getKbId).collect(Collectors.joining(","));
for (String libId : libraryKbIds.split(",")) {
if (StrUtil.isNotBlank(libId.trim())) {
regulations.addAll(queryKnowledgeBase(libId.trim(), query, 100));
}
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBaseWithCache(libId, buildRegulationQueries(), 80)));
}
// 分别进行智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::regulationsComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
return knowledgeSources;
}
/**
* 构建核心审计库查询
*/
private List<String> buildCoreQueries() {
return Arrays.asList(
"三重一大 集体决策 会议纪要 决策程序",
"重大经济决策 资本性支出 费用性支出",
"重大项目 重大投资 重大采购"
);
}
/**
* 构建案例库查询
*/
private List<String> buildCaseQueries() {
return Arrays.asList(
"类似案例 参考案例 最佳实践",
"决策效果 执行结果 经验教训"
);
}
/**
* 构建法规库查询
*/
private List<String> buildRegulationQueries() {
return Arrays.asList(
"三重一大制度 集体决策规定",
"重大经济决策程序 审批权限",
"审计法规 审计标准"
);
}
/**
* 根据知识库类型获取限制数量
*/
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "core": return 300;
case "case": return 150;
case "regulation": return 100;
default: return 100;
}
}
/**
* 带缓存的知识库查询
*/
private Set<String> queryKnowledgeBaseWithCache(String kbId, List<String> queries, int topK) {
Set<String> allResults = new LinkedHashSet<>();
queries.forEach(query -> {
String cacheKey = kbId + ":" + query;
long currentTime = System.currentTimeMillis();
if (knowledgeCache.containsKey(cacheKey) &&
cacheTimestamps.containsKey(cacheKey) &&
(currentTime - cacheTimestamps.get(cacheKey)) < CACHE_EXPIRE_TIME) {
allResults.addAll(knowledgeCache.get(cacheKey));
} else {
Set<String> results = queryKnowledgeBase(kbId, query, topK);
knowledgeCache.put(cacheKey, new LinkedHashSet<>(results));
cacheTimestamps.put(cacheKey, currentTime);
allResults.addAll(results);
}
}
});
// 案例库
if (StrUtil.isNotBlank(projectLibrary)) {
regulations.addAll(queryKnowledgeBase(projectLibrary, query, 100));
}
return regulations.stream().distinct().collect(Collectors.toList());
return allResults;
}
/**
* 生成重大经济决策调查表
*/
private JSONArray generateDecisionTable(List<String> regulations, String userName) {
// 构建知识上下文
String knowledgeContext = buildDecisionContext(regulations);
private JSONArray generateDecisionTable(Map<String, List<String>> knowledgeSources,
String userName, String history, String suggestion) {
// 构建优化的知识上下文
String knowledgeContext = buildOptimizedKnowledgeContext(knowledgeSources, history, suggestion);
JSONObject requestBody = buildDecisionTableRequest(knowledgeContext, userName);
return callDecisionTableWorkflow(requestBody);
JSONArray rawData = callDecisionTableWorkflow(requestBody);
// 后处理:数据清洗和格式化
return postProcessTableData(rawData);
}
/**
* 构建决策查询
* 构建优化的知识上下文
*/
private String buildDecisionQuery() {
String[] keywords = {
"重大经济决策", "三重一大", "集体决策", "重大预算", "重大项目",
"重大采购", "重大投资", "大额资金", "资产处置", "外包业务",
"决策程序", "会议纪要", "决策标准", "审计方法", "时间", "日期"
};
return String.join(" ", keywords);
}
/**
* 构建决策上下文
*/
private String buildDecisionContext(List<String> regulations) {
private String buildOptimizedKnowledgeContext(Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
context.append("重大经济决策审计要求:\n");
context.append("重点关注\"三重一大\"集体决策制度是否建立健全。重大经济、经营活动必须进行集体决策的标准和必须参加决策的人员是否制定有规定,规定的集体决策的程序(签到表、决策纪要、最终形成的决策、决策人员的签字确认意见等)是否完整,是否有应集体决策而未集体决策的问题,是否有应参加集体决策的人因不合理理由不得参加集体决策的问题,形成的集体决策意见是否符合国家、自治区规定。\n\n");
context.append("审计方法及步骤:\n");
context.append("1. 查阅单位制度,检查议事制度是否建立,查看重大事项进行集体决策的规定\n");
context.append("2. 查阅相关会议记录资料,检查会议签到表、会议纪要、会议决定内容及决策参与人员签字确认意见\n");
context.append("3. 确认会议集体决策程序的完整性\n");
context.append("4. 对照重大决策内容,检查相关对应资料,确认集体决策内容是否符合国家、自治区规定\n");
context.append("5. 抽查重大经济决策事项,审查决策背景、决策过程、执行落实情况、决策效果情况\n\n");
// 1. 核心审计要求
context.append("## 核心审计要求\n");
context.append("请基于以下审计要求生成重大经济决策调查表数据:\n\n");
context.append("1. 检查\"三重一大\"集体决策制度建立和执行情况\n");
context.append("2. 验证重大经济事项集体决策的程序完整性\n");
context.append("3. 确认决策内容符合相关规定\n");
context.append("4. 评估决策执行情况和效果\n\n");
if (!regulations.isEmpty()) {
context.append("相关法规和案例:\n");
regulations.forEach(reg -> context.append("- ").append(reg).append("\n"));
// 2. 数据格式要求
context.append("## 数据格式要求\n");
context.append("每条记录应包含:序号、事项名称、会议时间、决策金额、程序、执行情况、执行效果\n");
context.append("- 程序字段:描述具体的决策程序,如:会议决策(党委会/董事会/总经理办公会)、会签决策等\n");
context.append("- 决策金额:根据实际情况使用正确单位(元/万元/亿元)\n");
context.append("- 执行效果需在'好、一般、差'中选择一项标记为'是'\n\n");
// 3. 历史内容(用于优化调整)
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化:\n");
context.append(history).append("\n\n");
}
// 4. 用户建议(用于定向优化)
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 5. 核心审计知识
if (!knowledgeSources.get("core").isEmpty()) {
context.append("## 核心审计知识\n");
knowledgeSources.get("core").stream()
.limit(200)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
}
// 6. 参考案例
if (!knowledgeSources.get("case").isEmpty()) {
context.append("## 参考案例\n");
knowledgeSources.get("case").stream()
.limit(100)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
}
// 7. 法规要求
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法规要求\n");
knowledgeSources.get("regulation").stream()
.limit(80)
.forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
}
return context.toString();
}
/**
* 数据验证和增强
*/
private JSONArray validateAndEnhanceData(JSONArray data) {
if (data == null || data.isEmpty()) {
return new JSONArray(); // 返回空数组,不提供默认数据
}
JSONArray enhancedData = new JSONArray();
for (int i = 0; i < data.size(); i++) {
JSONObject item = data.getJSONObject(i);
if (item == null) continue;
// 数据验证
if (!validateDataItem(item)) {
log.warn("数据验证失败,跳过记录: {}", item);
continue;
}
// 数据增强
enhanceDataItem(item, i);
enhancedData.add(item);
}
return enhancedData;
}
/**
* 数据项验证
*/
private boolean validateDataItem(JSONObject item) {
return item.containsKey("name") &&
item.containsKey("meetingTime") &&
item.containsKey("decisionAmount") &&
item.containsKey("procedure") &&
item.containsKey("executionStatus");
}
/**
* 数据项增强
*/
private void enhanceDataItem(JSONObject item, int index) {
// 确保序号正确
item.put("index", String.valueOf(index + 1));
// 增强程序描述
String procedure = item.getString("procedure");
if (StrUtil.isBlank(procedure) || procedure.length() < 10) {
item.put("procedure", generateProcedureDescription());
}
// 增强执行效果结构
if (!item.containsKey("executionEffect")) {
JSONObject effect = new JSONObject();
effect.put("good", "");
effect.put("normal", "");
effect.put("bad", "");
item.put("executionEffect", effect);
}
// 标准化金额格式
String amount = item.getString("decisionAmount");
if (amount != null) {
item.put("decisionAmount", normalizeAmount(amount));
}
}
/**
* 生成程序描述
*/
private String generateProcedureDescription() {
Random random = new Random();
List<String> procedures = new ArrayList<>(DECISION_PROCEDURES.keySet());
String procedureType = procedures.get(random.nextInt(procedures.size()));
return DECISION_PROCEDURES.get(procedureType);
}
/**
* 标准化金额格式
*/
private String normalizeAmount(String amount) {
if (amount == null) return "0元";
// 如果已经包含单位,直接返回
if (amount.contains("万元") || amount.contains("") || amount.contains("亿")) {
return amount;
}
// 尝试解析数字
try {
String cleanAmount = amount.replaceAll("[^\\d.]", "");
if (StrUtil.isNotBlank(cleanAmount)) {
double value = Double.parseDouble(cleanAmount);
if (value >= 100000000) {
return String.format("%.2f亿元", value / 100000000);
} else if (value >= 10000) {
return String.format("%.2f万元", value / 10000);
} else {
return String.format("%.0f元", value);
}
}
} catch (NumberFormatException e) {
log.debug("金额解析失败: {}", amount);
}
return amount + "";
}
/**
* 后处理表格数据
*/
private JSONArray postProcessTableData(JSONArray rawData) {
if (rawData == null || rawData.isEmpty()) {
return new JSONArray();
}
return rawData; // 简化处理,直接返回原始数据
}
/**
* 法规内容比较器
*/
private int regulationsComparator(String reg1, String reg2) {
int score1 = calculateRelevanceScore(reg1);
int score2 = calculateRelevanceScore(reg2);
return Integer.compare(score2, score1);
}
/**
* 计算相关性分数
*/
private int calculateRelevanceScore(String regulation) {
return KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> regulation.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
/**
* 查询知识库
*/
private Set<String> queryKnowledgeBase(String kbId, String query, int topK) {
Set<String> results = new LinkedHashSet<>();
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
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: {}, query: {}", kbId, query, e);
}
return 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 "相关文档";
}
/**
* 调用决策表生成工作流
*/
@@ -161,7 +522,7 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
.header("Authorization", DECISION_TABLE_TOKEN)
.header("Content-Type", "application/json")
.body(requestBody.toString())
.timeout(600000)
.timeout(120000)
.execute()
.body();
@@ -170,10 +531,10 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
.getJSONObject("outputs")
.getString("result");
// 解析JSON数组
return JSONArray.parseArray(outputText);
} catch (Exception e) {
log.error("调用决策表生成工作流失败", e);
throw new RuntimeException("调用决策表生成工作流失败: " + e.getMessage(), e);
}
}
@@ -195,83 +556,13 @@ public class AuditContentServiceImpl3 implements AuditContentService3 {
}
/**
* 创建默认的决策数据
* 清理缓存
*/
private JSONArray createDefaultDecisionData() {
JSONArray defaultData = new JSONArray();
// 添加3条默认数据
for (int i = 1; i <= 3; i++) {
JSONObject item = new JSONObject();
item.put("index", String.valueOf(i));
item.put("name", "重大经济决策事项示例 " + i);
item.put("meetingTime", "2024-01-0" + i);
item.put("decisionAmount", (i * 100) + "万元");
item.put("procedure", "集体决策程序完整");
item.put("executionStatus", "");
JSONObject effect = new JSONObject();
effect.put("good", i == 1 ? "" : "");
effect.put("normal", i == 2 ? "" : "");
effect.put("bad", i == 3 ? "" : "");
item.put("executionEffect", effect);
defaultData.add(item);
}
return defaultData;
}
/**
* 查询知识库
*/
private Set<String> queryKnowledgeBase(String kbId, String query, int topK) {
Set<String> results = new LinkedHashSet<>();
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
// 使用Optional和Stream API简化空值检查和循环
Optional.ofNullable(resp)
.map(RetrieveResponse::getBody)
.map(RetrieveResponseBody::getData)
.map(RetrieveResponseBodyData::getNodes)
.orElse(Collections.emptyList())
.stream()
.limit(topK) // 使用limit替代手动break
.forEach(node -> processNode(node, results));
} catch (Exception e) {
// 使用printStackTrace打印异常堆栈
e.printStackTrace();
throw new RuntimeException("查询知识库失败, kbId: " + kbId + ", query: " + query);
}
return results;
}
/**
* 处理单个节点,提取文本信息
*/
private void processNode(RetrieveResponseBodyDataNodes node, Set<String> results) {
try {
// 安全地将Object类型的metadata转换为Map
Object metadataObj = node.getMetadata();
if (!(metadataObj instanceof Map)) {
// System.err.println("节点metadata不是Map类型跳过处理");
return;
}
Map<?, ?> metadata = (Map<?, ?>) metadataObj;
Object docNameObj = metadata.get("doc_name");
String docName = docNameObj != null ? docNameObj.toString() : "未知文档";
String formattedText = String.format("《%s》%s", docName, node.getText());
results.add(formattedText);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("处理知识库节点失败: " + e.getMessage());
}
public void clearExpiredCache() {
long currentTime = System.currentTimeMillis();
cacheTimestamps.entrySet().removeIf(entry ->
(currentTime - entry.getValue()) >= CACHE_EXPIRE_TIME
);
knowledgeCache.keySet().removeIf(key -> !cacheTimestamps.containsKey(key));
}
}