证据处理初版

topo_dev
DESKTOP-DDTUS3E\yaxin 5 months ago
parent 99706ceb05
commit 99bb5dea3f

@ -168,6 +168,12 @@
<version>1.70</version>
</dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>
</dependencies>
<dependencyManagement>

@ -0,0 +1,34 @@
package com.supervision.common.constant;
public class EvidenceConstants {
// 证据处理状态
/**
*
*/
public static final String PROCESS_STATUS_UNPROCESSED = "0";
/**
* OCR
*/
public static final String PROCESS_STATUS_OCR_OK = "1";
/**
*
*/
public static final String PROCESS_STATUS_TITLE_EXTRACT_OK = "2";
/**
*
*/
public static final String PROCESS_STATUS_ATTR_EXTRACT_OK = "3";
/**
*
*/
public static final String PROCESS_STATUS_SUCCESS = "4";
/**
*
*/
public static final String PROCESS_STATUS_FAILED = "5";
/**
*
*/
public static final String PROCESS_STATUS_VERIFIED = "6";
}

@ -0,0 +1,7 @@
package com.supervision.common.constant;
public class XxlJobConstants {
public static final String URL_LOGIN = "/login";
public static final String URL_JOB_INFO_PAGE_LIST = "/jobinfo/pageList";
public static final String URL_JOB_INFO_TRIGGER = "/jobinfo/trigger";
}

@ -0,0 +1,78 @@
package com.supervision.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* xxl-job config
*
* @author xuxueli 2017-04-28
*/
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* "spring-cloud-commons" "InetUtils" IP
*
* 1
* <dependency>
* <groupId>org.springframework.cloud</groupId>
* <artifactId>spring-cloud-commons</artifactId>
* <version>${version}</version>
* </dependency>
*
* 2
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3IP
* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}

@ -0,0 +1,31 @@
package com.supervision.job;
import com.supervision.police.service.CaseEvidenceService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class XxlJobTask {
@Autowired
private CaseEvidenceService caseEvidenceService;
/**
*
*/
@XxlJob("evidenceAnalysis")
public void evidenceAnalysis() {
String param = XxlJobHelper.getJobParam();
log.info("【证据解析】任务开始。ID: 【{}】", param);
try {
caseEvidenceService.evidenceAnalysis(param);
} catch (Exception e) {
log.error("任务执行失败", e);
} finally {
log.info("任务执行完成");
}
}
}

@ -6,10 +6,11 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.json.JSONArray;
/**
*
@ -29,6 +30,9 @@ public class CaseEvidence implements Serializable {
*/
private String caseId;
/**
* id
*/
private String directoryId;
/**
@ -49,7 +53,8 @@ public class CaseEvidence implements Serializable {
/**
*
*/
private JSONArray property;
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, String> property;
/**
*

@ -4,17 +4,18 @@ import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.supervision.police.dto.NotePromptExtractAttributesDto;
import com.supervision.police.dto.TripleInfoDTO;
import com.supervision.police.dto.TypeDTO;
import lombok.Data;
import org.json.JSONArray;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
@TableName(value = "note_prompt")
@TableName(value = "note_prompt", autoResultMap = true)
@Data
public class NotePrompt implements Serializable {
@ -116,18 +117,21 @@ public class NotePrompt implements Serializable {
/**
*
*/
private JSONArray keyword;
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> keyword;
/**
*
*/
private JSONArray extractAttributes;
@TableField(typeHandler = JacksonTypeHandler.class)
private List<NotePromptExtractAttributesDto> extractAttributes;
/**
*
*/
private String evidenceCategoryId;
@Serial
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -0,0 +1,47 @@
package com.supervision.police.domain;
import lombok.Data;
import java.util.Date;
/**
* xxl-job info
*
* @author xuxueli 2016-1-12 18:25:49
*/
@Data
public class XxlJobInfo {
private int id; // 主键ID
private int jobGroup; // 执行器主键ID
private String jobDesc;
private Date addTime;
private Date updateTime;
private String author; // 负责人
private String alarmEmail; // 报警邮件
private String scheduleType; // 调度类型
private String scheduleConf; // 调度配置,值含义取决于调度类型
private String misfireStrategy; // 调度过期策略
private String executorRouteStrategy; // 执行器路由策略
private String executorHandler; // 执行器任务Handler名称
private String executorParam; // 执行器,任务参数
private String executorBlockStrategy; // 阻塞处理策略
private int executorTimeout; // 任务执行超时时间,单位秒
private int executorFailRetryCount; // 失败重试次数
private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum
private String glueSource; // GLUE源代码
private String glueRemark; // GLUE备注
private Date glueUpdatetime; // GLUE更新时间
private String childJobId; // 子任务ID多个逗号分隔
private int triggerStatus; // 调度状态0-停止1-运行
private long triggerLastTime; // 上次调度时间
private long triggerNextTime; // 下次调度时间
}

@ -3,9 +3,11 @@ package com.supervision.police.dto;
import cn.hutool.core.util.StrUtil;
import com.supervision.constant.EvidencePropertyName;
import com.supervision.police.domain.CaseEvidence;
import com.supervision.police.domain.EvidenceFile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -43,6 +45,9 @@ public class CaseEvidenceDTO {
@Schema(description = "案件证据属性")
private Map<String,String> property= new HashMap<>();
@Schema(description = "案件证据文件列表")
private List<EvidenceFile> evidenceFileList = new ArrayList<>();
public CaseEvidence toCaseEvidence(){
CaseEvidence caseEvidence = new CaseEvidence();

@ -0,0 +1,17 @@
package com.supervision.police.dto;
import lombok.Data;
import java.util.List;
/**
* dto
*/
@Data
public class LLMExtractDto {
private String id;
private String prompt;
private String text;
private String title;
private List<NotePromptExtractAttributesDto> extractAttributes;
}

@ -0,0 +1,10 @@
package com.supervision.police.dto;
import lombok.Data;
@Data
public class NotePromptExtractAttributesDto {
private String attrName;
private String attrValue;
private String attrValueType;
}

@ -1,13 +0,0 @@
package com.supervision.police.dto;
import lombok.Data;
/**
* ocrdto
*/
@Data
public class OcrExtractDto {
private String id;
private String text;
private String title;
}

@ -49,4 +49,10 @@ public interface CaseEvidenceService extends IService<CaseEvidence> {
IPage<CaseEvidenceDetailDTO> pageListEvidence(String caseId,String evidenceName, Integer pageNum, Integer pageSize);
CaseEvidenceDetailDTO queryEvidenceDetail(String evidenceId);
/**
*
* @param evidenceId id
*/
void evidenceAnalysis(String evidenceId);
}

@ -0,0 +1,24 @@
package com.supervision.police.service;
import com.supervision.police.dto.LLMExtractDto;
import java.util.List;
public interface LLMExtractService {
/**
*
*
* @param LLMExtractDtoList ocrExtractDtoList
* @return List<OcrExtractDto>
*/
List<LLMExtractDto> extractTitle(List<LLMExtractDto> LLMExtractDtoList);
/**
*
*
* @param LLMExtractDtoList ocrExtractDtoList
* @return List<OcrExtractDto>
*/
List<LLMExtractDto> extractAttribute(List<LLMExtractDto> LLMExtractDtoList);
}

@ -1,16 +0,0 @@
package com.supervision.police.service;
import com.supervision.police.dto.OcrExtractDto;
import java.util.List;
public interface OcrExtractService {
/**
*
*
* @param ocrExtractDtoList ocrExtractDtoList
* @return List<OcrExtractDto>
*/
List<OcrExtractDto> extractTitle(List<OcrExtractDto> ocrExtractDtoList);
}

@ -0,0 +1,15 @@
package com.supervision.police.service;
import com.supervision.police.domain.XxlJobInfo;
import java.util.List;
public interface XxlJobService {
String login() throws Exception;
List<XxlJobInfo> pageList(XxlJobInfo xxlJobInfo) throws Exception;
void executeTaskById(String id, String param) throws Exception;
void executeTaskByJobHandler(String jobHandler, String param);
}

@ -6,24 +6,18 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.police.dto.RecordFileDTO;
import com.supervision.police.service.*;
import com.supervision.police.domain.CaseEvidence;
import com.supervision.police.domain.ComDictionary;
import com.supervision.police.domain.EvidenceFile;
import com.supervision.police.dto.CaseEvidenceDetailDTO;
import com.supervision.police.dto.EvidenceFileDTO;
import com.supervision.common.constant.EvidenceConstants;
import com.supervision.police.domain.*;
import com.supervision.police.dto.*;
import com.supervision.police.mapper.CaseEvidenceMapper;
import com.supervision.police.dto.CaseEvidenceDTO;
import com.supervision.police.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@ -41,9 +35,17 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
@Autowired
private OCREvidenceService ocrEvidenceService;
@Autowired
private LLMExtractService llmExtractService;
@Autowired
private EvidenceDirectoryService evidenceDirectoryService;
@Autowired
private EvidenceCategoryService evidenceCategoryService;
@Autowired
private NotePromptService notePromptService;
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public String saveEvidence(CaseEvidenceDTO caseEvidenceDTO) {
// 必填校验
caseEvidencePersistenceAssert(caseEvidenceDTO);
@ -64,18 +66,18 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
}
private void caseEvidencePersistenceAssert(CaseEvidenceDTO caseEvidenceDTO) {
Assert.notEmpty(caseEvidenceDTO.getCaseId(),"案件id不能为空");
Assert.notEmpty(caseEvidenceDTO.getEvidenceName(),"证据名称不能为空");
Assert.notEmpty(caseEvidenceDTO.getEvidenceType(),"证据类型不能为空");
Assert.notEmpty(caseEvidenceDTO.getCaseId(), "案件id不能为空");
Assert.notEmpty(caseEvidenceDTO.getEvidenceName(), "证据名称不能为空");
Assert.notEmpty(caseEvidenceDTO.getEvidenceType(), "证据类型不能为空");
//Assert.notEmpty(caseEvidenceDTO.getProvider(),"证据提供人不能为空");
Assert.notEmpty(caseEvidenceDTO.getFileIdList(),"文件id不能为空");
Assert.notEmpty(caseEvidenceDTO.getFileIdList(), "文件id不能为空");
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public String updateEvidence(CaseEvidenceDTO caseEvidenceDTO) {
Assert.notEmpty(caseEvidenceDTO.getId(),"证据id不能为空");
Assert.notEmpty(caseEvidenceDTO.getId(), "证据id不能为空");
caseEvidencePersistenceAssert(caseEvidenceDTO);
super.getOptById(caseEvidenceDTO.getId()).orElseThrow(() -> new IllegalArgumentException("证据信息不存在"));
@ -84,7 +86,7 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
super.updateById(caseEvidence);
// 更新文件关联信息
evidenceFileService.lambdaUpdate().eq(EvidenceFile::getEvidenceId,caseEvidence.getId()).remove();
evidenceFileService.lambdaUpdate().eq(EvidenceFile::getEvidenceId, caseEvidence.getId()).remove();
caseEvidenceDTO.getFileIdList().forEach(fileId -> {
EvidenceFile evidenceFile = new EvidenceFile();
evidenceFile.setFileId(fileId);
@ -96,45 +98,45 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
// 更新证据属性信息
for (String fileId : caseEvidenceDTO.getFileIdList()) {
caseEvidenceDTO.setTitleProperty();
ocrEvidenceService.saveEvidenceProperty(caseEvidence.getId(),fileId,caseEvidenceDTO.getProperty());
ocrEvidenceService.saveEvidenceProperty(caseEvidence.getId(), fileId, caseEvidenceDTO.getProperty());
}
return caseEvidenceDTO.getId();
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public boolean deleteEvidence(String evidenceId) {
CaseEvidence caseEvidence = super.getOptById(evidenceId).orElseThrow(() -> new IllegalArgumentException("证据信息不存在"));
boolean remove = super.lambdaUpdate().eq(CaseEvidence::getId, evidenceId).remove();
if (remove){
evidenceFileService.lambdaUpdate().eq(EvidenceFile::getEvidenceId,evidenceId).remove();
if (remove) {
evidenceFileService.lambdaUpdate().eq(EvidenceFile::getEvidenceId, evidenceId).remove();
caseStatusManageService.whenUpdateEvidence(caseEvidence.getCaseId());
}
return remove;
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public List<CaseEvidenceDetailDTO> queryEvidenceList(String caseId) {
return super.getBaseMapper().queryEvidenceList(caseId);
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public IPage<CaseEvidenceDetailDTO> pageListEvidence(String caseId,String evidenceName, Integer pageNum, Integer pageSize) {
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public IPage<CaseEvidenceDetailDTO> pageListEvidence(String caseId, String evidenceName, Integer pageNum, Integer pageSize) {
Assert.notEmpty(caseId,"案件id不能为空");
Assert.notEmpty(caseId, "案件id不能为空");
Page<CaseEvidence> caseEvidencePage = super.lambdaQuery().eq(CaseEvidence::getCaseId, caseId)
.like(StrUtil.isNotEmpty(evidenceName), CaseEvidence::getEvidenceName,evidenceName)
.orderBy(true, false,CaseEvidence::getUpdateTime)
.like(StrUtil.isNotEmpty(evidenceName), CaseEvidence::getEvidenceName, evidenceName)
.orderBy(true, false, CaseEvidence::getUpdateTime)
.page(new Page<>(pageNum, pageSize));
if (caseEvidencePage.getTotal() == 0){
return PageDTO.of(pageNum,pageSize,0);
if (caseEvidencePage.getTotal() == 0) {
return PageDTO.of(pageNum, pageSize, 0);
}
// 查询文件信息
@ -162,4 +164,70 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
return super.getBaseMapper().queryEvidenceDetail(evidenceId);
}
@Override
public void evidenceAnalysis(String evidenceId) {
log.info("证据解析开始。证据ID:【{}】", evidenceId);
long start = System.currentTimeMillis();
LLMExtractDto llmExtractDto = new LLMExtractDto();
// 查出证据、文件、如果证据
CaseEvidence caseEvidence = getById(evidenceId);
if (caseEvidence == null) {
log.error("证据不存在");
return;
}
List<EvidenceFile> evidenceFiles = evidenceFileService.lambdaQuery().eq(EvidenceFile::getEvidenceId, evidenceId).list();
if (evidenceFiles.isEmpty()) {
log.error("证据文件不存在");
return;
}
try {
// 根据rank升序排序
evidenceFiles.sort(Comparator.comparing(EvidenceFile::getRank));
log.info("OCR识别开始。证据文件ID:【{}】", evidenceFiles.stream().map(EvidenceFile::getFileId).toList());
long ocrStart = System.currentTimeMillis();
List<FileOcrProcess> fileOcrProcesses = fileOcrProcessService.syncSubmitOCR(evidenceFiles.stream().map(EvidenceFile::getFileId).toList());
log.info("OCR识别完成。更新证据处理状态为【OCR识别完成】。耗时:【{}】ms", System.currentTimeMillis() - ocrStart);
caseEvidence.setProcessStatus(EvidenceConstants.PROCESS_STATUS_OCR_OK);
updateById(caseEvidence);
// 遍历OCR结果拼接ocrText并赋值给lLMExtractDto的text
StringBuilder ocrText = new StringBuilder();
fileOcrProcesses.forEach(fileOcrProcess -> ocrText.append(fileOcrProcess.getOcrText()));
llmExtractDto.setText(ocrText.toString());
log.info("标题提取开始。");
long titleStart = System.currentTimeMillis();
llmExtractDto = llmExtractService.extractTitle(Collections.singletonList(llmExtractDto)).get(0);
log.info("标题提取完成。更新证据处理状态为【标题提取完成】。标题:【{}】。耗时:【{}】ms", llmExtractDto.getTitle(), System.currentTimeMillis() - titleStart);
caseEvidence.setProcessStatus(EvidenceConstants.PROCESS_STATUS_TITLE_EXTRACT_OK);
updateById(caseEvidence);
// 根据证据目录id查询提示词
EvidenceDirectory directory = evidenceDirectoryService.getById(caseEvidence.getDirectoryId());
EvidenceCategory category = evidenceCategoryService.getById(directory.getCategoryId());
NotePrompt notePrompt = notePromptService.getById(category.getPromptId());
if (notePrompt != null) {
log.info("属性提取开始。");
long attrStart = System.currentTimeMillis();
llmExtractDto.setPrompt(notePrompt.getPrompt());
llmExtractDto.setExtractAttributes(notePrompt.getExtractAttributes());
llmExtractDto = llmExtractService.extractAttribute(Collections.singletonList(llmExtractDto)).get(0);
Map<String, String> map = new HashMap<>();
llmExtractDto.getExtractAttributes().forEach(notePromptExtractAttribute -> map.put(notePromptExtractAttribute.getAttrName(), notePromptExtractAttribute.getAttrValue()));
caseEvidence.setProperty(map);
log.info("属性提取完成。更新证据处理状态为【属性提取完成】。属性:【{}】。耗时:【{}】", caseEvidence.getProperty(), System.currentTimeMillis() - attrStart);
caseEvidence.setProcessStatus(EvidenceConstants.PROCESS_STATUS_ATTR_EXTRACT_OK);
updateById(caseEvidence);
} else {
log.info("没有关联提示词,不提取属性");
}
log.info("证据解析完成。更新证据处理状态为【处理成功】。");
caseEvidence.setProcessStatus(EvidenceConstants.PROCESS_STATUS_SUCCESS);
updateById(caseEvidence);
} catch (Exception e) {
log.error("证据解析失败。更新证据处理状态为【处理失败】。");
caseEvidence.setProcessStatus(EvidenceConstants.PROCESS_STATUS_FAILED);
updateById(caseEvidence);
} finally {
log.info("证据解析完成。证据ID:【{}】耗时:【{}】ms", evidenceId, System.currentTimeMillis() - start);
}
}
}

@ -0,0 +1,167 @@
package com.supervision.police.service.impl;
import cn.hutool.core.util.StrUtil;
import com.supervision.police.dto.LLMExtractDto;
import com.supervision.police.dto.NotePromptExtractAttributesDto;
import com.supervision.police.service.LLMExtractService;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class LLMExtractServiceImpl implements LLMExtractService {
@Autowired
private OllamaChatClient ollamaChatClient;
/*
====================
40
###
1. JSON
2. {"title":""}
3. 40
4.
5.
{ocr_txt}
json{"title":"*****"},{"title":""}
json
*/
@Override
public List<LLMExtractDto> extractTitle(List<LLMExtractDto> LLMExtractDtoList) {
List<LLMExtractDto> result = new ArrayList<>();
// 遍历ocrExtractDtoList调用接口提取标题
LLMExtractDtoList.forEach(ocrExtractDto -> {
HashMap<String, String> paramMap = new HashMap<>();
paramMap.put("ocr_txt", ocrExtractDto.getText());
String template = "提取下面文本中前40个字中明显的标题\n" +
"### 注意事项:\n" +
"1. 将结果以JSON格式返回。不需要进行解释。\n" +
"2. 如果某字段提取不到,则返回\"\"。\n" +
"3. 文本原文可能为空,返回\"\"。\n" +
"4. 标题只会出现在前40个字中\n" +
"5. 非常明确是标题的文本,才能返回结果。\n" +
"6. 有可能很大概率是没有标题的。\n" +
"\n" +
"文本原文:\n" +
"{ocr_txt}\n" +
"输出json格式{{\"title\":\"*****\"}},如果没有明显标题:{{\"title\":\"\"}}。\n" +
"\n" +
"回溯你输出的结果确保你的输出结果符合json格式。";
ChatResponse call = ollamaChatClient.call(new Prompt(new UserMessage(StrUtil.format(template, paramMap))));
String content = call.getResult().getOutput().getContent();
log.info("标题提取结果: {}", content);
//判断content是否为JSON格式如果是则尝试转换为JSON格式并获取title属性的值
try {
JSONObject jsonObject = new JSONObject(content);
String title = jsonObject.getString("title");
ocrExtractDto.setTitle(title);
result.add(ocrExtractDto);
} catch (Exception e) {
log.error("解析标题失败", e);
}
});
return result;
}
/*
====================
:
"
5000
8346
20221130
20221212023121
20221123
"
:
{
"甲方名称": "张三公司",
"乙方名称": "",
"数量": "5000吨水泥",
"合同金额": "8346.00",
"支付时间": "2022-11-30",
"履行期限": "2022年12月1日至2023年12月1日",
"签订日期": "2022-11-23"
}
{ocr_txt}
{attr_define}
###
1. JSON
2. ""
3. yyyy-MM-dd
4. 使
5. 使
json
*/
@Override
public List<LLMExtractDto> extractAttribute(List<LLMExtractDto> LLMExtractDtoList) {
List<LLMExtractDto> result = new ArrayList<>();
try {
for (LLMExtractDto LLMExtractDto : LLMExtractDtoList) {
List<NotePromptExtractAttributesDto> extractAttributes = LLMExtractDto.getExtractAttributes();
StringBuilder requirementBuilder = new StringBuilder();
// extractAttributes不为空时先转mapkey是属性名称value是属性值类型再遍历map拼接为JSON字符串
requirementBuilder.append("{\n");
Map<String, String> extractAttributesMap = new HashMap<>();
if (extractAttributes != null && !extractAttributes.isEmpty()) {
extractAttributes.forEach(extractAttribute -> extractAttributesMap.put(extractAttribute.getAttrName(), extractAttribute.getAttrValueType()));
extractAttributesMap.forEach((key, value) -> requirementBuilder.append("\"").append(key).append("\"").append("").append("\"").append(value).append("\"").append("\n"));
}
requirementBuilder.append("}");
String prompt = StrUtil.format(LLMExtractDto.getPrompt(), Map.of(
"attr_define", requirementBuilder.toString(),
"ocr_txt", LLMExtractDto.getText()
));
log.info("属性提取请求\n:{}", prompt);
ChatResponse call = ollamaChatClient.call(new Prompt(new UserMessage(prompt)));
String content = call.getResult().getOutput().getContent();
JSONObject jsonObject = new JSONObject(content);
List<NotePromptExtractAttributesDto> extractAttributesList = LLMExtractDto.getExtractAttributes();
extractAttributesMap.forEach((key, value) -> {
String attrValue = jsonObject.getString(key);
log.info("属性提取结果: 【{}】。Key【{}】", attrValue, key);
NotePromptExtractAttributesDto extractAttributesDto = new NotePromptExtractAttributesDto();
extractAttributesDto.setAttrName(key);
extractAttributesDto.setAttrValue(attrValue);
extractAttributesList.add(extractAttributesDto);
});
LLMExtractDto.setExtractAttributes(extractAttributesList);
result.add(LLMExtractDto);
}
} catch (Exception e) {
log.error("提取属性失败", e);
}
return result;
}
}

@ -41,7 +41,7 @@ public class OCREvidenceServiceImpl implements OCREvidenceService {
private final CaseEvidenceService caseEvidenceService;
private final OcrExtractService ocrExtractService;
private final LLMExtractService LLMExtractService;
private final TimedCache<String, DateTime> timedCache = CacheUtil.newTimedCache(5*60*1000);
@Override
@ -242,20 +242,20 @@ public class OCREvidenceServiceImpl implements OCREvidenceService {
return;
}
List<OcrExtractDto> dtoList = recordFileDTOS.stream().map(recordFileDTO -> {
OcrExtractDto dto = new OcrExtractDto();
List<LLMExtractDto> dtoList = recordFileDTOS.stream().map(recordFileDTO -> {
LLMExtractDto dto = new LLMExtractDto();
dto.setId(recordFileDTO.getFileId());
dto.setText(recordFileDTO.getOcrText());
return dto;
}).toList();
log.info("doRetrieveTitle,extractTitle参数是{}", JSONUtil.toJsonStr(dtoList));
List<OcrExtractDto> result = ocrExtractService.extractTitle(dtoList);
List<LLMExtractDto> result = LLMExtractService.extractTitle(dtoList);
log.info("doRetrieveTitle,extractTitle返回结果是{}", JSONUtil.toJsonStr(result));
if (CollUtil.isEmpty(result)){
log.warn("retrieveTitle:文件id:{} 提取标题失败", StrUtil.join(",", fileIdList));
}
for (OcrExtractDto dto : result) {
for (LLMExtractDto dto : result) {
this.saveEvidenceProperty(null, dto.getId(),
Map.of(EvidencePropertyName.TITLE.getName(), dto.getTitle()));
}

@ -1,60 +0,0 @@
package com.supervision.police.service.impl;
import cn.hutool.core.util.StrUtil;
import com.supervision.police.dto.OcrExtractDto;
import com.supervision.police.service.OcrExtractService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@Slf4j
@Service
public class OcrExtractServiceImpl implements OcrExtractService {
@Autowired
private OllamaChatClient ollamaChatClient;
@Override
public List<OcrExtractDto> extractTitle(List<OcrExtractDto> ocrExtractDtoList) {
List<OcrExtractDto> result = new ArrayList<>();
// 遍历ocrExtractDtoList调用接口提取标题
ocrExtractDtoList.forEach(ocrExtractDto -> {
HashMap<String, String> paramMap = new HashMap<>();
paramMap.put("text", ocrExtractDto.getText());
paramMap.put("requirement", "1.尝试提取图中明显的标题。2.始终输出json格式{\"title\":\"*****\"},没有明显标题则返回:{\"title\":\"\"}。3.只提取title属性不需要任何其他输出。");
String template = "要求如下:\n{requirement}\n文本内容如下\n{text}";
ChatResponse call = ollamaChatClient.call(new Prompt(new UserMessage(StrUtil.format(template, paramMap))));
String content = call.getResult().getOutput().getContent();
log.info("content: {}", content);
//将text置为空减少返回数据量
ocrExtractDto.setText("");
//判断content是否为JSON格式如果是则尝试转换为JSON格式并获取title属性的值
try {
JSONObject jsonObject = new JSONObject(content);
String title = jsonObject.getString("title");
ocrExtractDto.setTitle(title);
} catch (Exception e) {
log.error("解析标题失败", e);
} finally {
//如果未提取到标题则使用result中最后一个节点的title
if (StringUtils.isEmpty(ocrExtractDto.getTitle())) {
if (!result.isEmpty()) {
ocrExtractDto.setTitle(result.get(result.size() - 1).getTitle());
}
}
result.add(ocrExtractDto);
}
});
return result;
}
}

@ -0,0 +1,142 @@
package com.supervision.police.service.impl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.supervision.common.constant.XxlJobConstants;
import com.supervision.common.utils.StringUtils;
import com.supervision.police.domain.XxlJobInfo;
import com.supervision.police.service.XxlJobService;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class XxlJobServiceImpl implements XxlJobService {
public static String token = "";
private static final Map<String, String> jobHandlerIdMap = new HashMap<>();
@Value("${xxl.job.admin.addresses}")
private String xxlJobAdminAddress;
@Value("${xxl.job.admin.username}")
private String username;
@Value("${xxl.job.admin.password}")
private String password;
@Override
public String login() throws Exception {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(xxlJobAdminAddress + XxlJobConstants.URL_LOGIN);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
String params = "userName=" + username + "&password=" + password + "&ifRemember=on";
StringEntity entity = new StringEntity(params, ContentType.APPLICATION_FORM_URLENCODED);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
if (response.getCode() == 200) {
Header[] headers = response.getHeaders();
for (Header header : headers) {
if ("Set-Cookie".equals(header.getName())) {
token = header.getValue();
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return token;
}
public String getLoginToken() throws Exception {
if (StringUtils.isEmpty(token)) {
return login();
}
return token;
}
@Override
public List<XxlJobInfo> pageList(XxlJobInfo xxlJobInfo) throws Exception {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(xxlJobAdminAddress + XxlJobConstants.URL_JOB_INFO_PAGE_LIST);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
httpPost.setHeader(HttpHeaders.COOKIE, getLoginToken());
String params = "jobGroup=-1&triggerStatus=-1&executorHandler=" + xxlJobInfo.getExecutorHandler() + "&start=0&length=10";
StringEntity entity = new StringEntity(params, ContentType.APPLICATION_FORM_URLENCODED);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
String responseBody = EntityUtils.toString(response.getEntity());
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> responseMap = objectMapper.readValue(responseBody, new TypeReference<Map<String, Object>>() {
});
log.info("Response Body: {}", responseMap);
if (responseMap.get("data") != null) {
return objectMapper.convertValue(responseMap.get("data"), new TypeReference<List<XxlJobInfo>>() {
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
@Override
public void executeTaskById(String id, String param) throws Exception {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 查询任务
HttpPost httpPost = new HttpPost(xxlJobAdminAddress + XxlJobConstants.URL_JOB_INFO_TRIGGER);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
httpPost.setHeader(HttpHeaders.COOKIE, getLoginToken());
String params = "id=" + id + "&executorParam=" + param;
StringEntity entity = new StringEntity(params, ContentType.APPLICATION_FORM_URLENCODED);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
log.info("Task executed: {}", EntityUtils.toString(response.getEntity()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void executeTaskByJobHandler(String jobHandler, String param) {
try {
//尝试从缓存中获取任务id获取不到则查询任务后再执行
String jobId = jobHandlerIdMap.get(jobHandler);
if (jobId != null) {
log.info("根据任务名称【{}】获取到任务id【{}】,直接开始执行任务。", jobHandler, jobId);
executeTaskById(jobId, param);
} else {
log.info("根据任务名称【{}】未获取到任务id尝试远程获取任务信息。", jobHandler);
XxlJobInfo xxlJobInfo = new XxlJobInfo();
xxlJobInfo.setExecutorHandler(jobHandler);
List<XxlJobInfo> xxlJobInfoList = pageList(xxlJobInfo);
if (xxlJobInfoList != null && !xxlJobInfoList.isEmpty()) {
log.info("根据任务名称【{}】获取到任务信息【{}】,加入缓存并开始执行任务。", jobHandler, xxlJobInfoList.get(0));
jobId = String.valueOf(xxlJobInfoList.get(0).getId());
jobHandlerIdMap.put(jobHandler, jobId);
executeTaskById(jobId, param);
} else {
log.info("未找到名称匹配的任务【{}】", xxlJobInfo.getExecutorHandler());
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

@ -0,0 +1,55 @@
package com.supervision.utils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author: JCccc
* @Date: 2022-6-22 9:51
* @Description:
*/
@Component
public class XxlJobUtil {
private static String cookie = "";
@Value("${xxl.job.admin.addresses}")
private String xxlJobAdminAddress;
public void executeTask(String taskName) throws Exception {
String taskQueryUrl = xxlJobAdminAddress + "/xxl-job-admin/api/jobinfo/load";
String taskExecuteUrl = xxlJobAdminAddress + "/xxl-job-admin/api/job/trigger";
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 查询任务
HttpGet httpGet = new HttpGet(taskQueryUrl + "?jobName=" + taskName);
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
String jsonResponse = EntityUtils.toString(response.getEntity());
// 处理任务信息,例如提取 jobId
// 假设 jsonResponse 中有一个字段 "jobId"
String jobId = extractJobId(jsonResponse);
// 执行任务
HttpPost httpPost = new HttpPost(taskExecuteUrl);
httpPost.setHeader("Content-Type", "application/json");
String jsonBody = "{\"jobId\": \"" + jobId + "\"}";
httpPost.setEntity(new StringEntity(jsonBody));
try (CloseableHttpResponse executeResponse = httpClient.execute(httpPost)) {
System.out.println("Task executed: " + EntityUtils.toString(executeResponse.getEntity()));
}
}
}
}
private String extractJobId(String jsonResponse) {
// 解析 JSON 响应并提取 jobId
// 这里需要使用 JSON 解析库,比如 Jackson 或 Gson
// 示例代码略
return "yourJobId"; // 请替换为实际提取的 jobId
}
}

@ -78,3 +78,18 @@ ocr:
url: http://192.168.10.137:8866/
pool:
max-size: 20
xxl:
job:
admin:
username: admin
password: 123456
addresses: http://192.168.10.137:8080/xxl-job-admin
accessToken: default_token
executor:
address:
appname: nx-llm-xxljob
ip:
port: 9999
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30

@ -0,0 +1,169 @@
package com.supervision.demo;
import com.supervision.police.dto.LLMExtractDto;
import com.supervision.police.dto.NotePromptExtractAttributesDto;
import com.supervision.police.service.LLMExtractService;
import com.supervision.police.service.NotePromptService;
import com.supervision.police.service.XxlJobService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
@SpringBootTest
public class LLMExtractTest {
@Autowired
private LLMExtractService llmExtractService;
@Autowired
private NotePromptService notePromptService;
@Autowired
private XxlJobService xxlJobService;
@Test
public void testExtractTitle() {
List<LLMExtractDto> LLMExtractDtoList = new ArrayList<>();
LLMExtractDto LLMExtractDto = new LLMExtractDto();
LLMExtractDto.setId("1833322433007398913");
LLMExtractDto.setText("关于李社辉等人涉嫌合同诈骗罪的\n" +
"报案材料\n" +
"报案人许锋8。年\n" +
"一月\n" +
"/旦,汉族,\n" +
"号:-640/2119001012218\n" +
"电话1837571888。\n" +
"被报案人:\n" +
"李社辉年月1/日,汉族,住\n" +
"址西安市间良7x公园路7株号身份证号610114195505110513\n" +
"电话1810537777。\n" +
"宁夏博金特立体泊车设备有限公司,住所地:青铜峡市嘉宝\n" +
"工业园区7-8号。\n" +
"法定代表人:李社辉,该公司总经理。\n" +
"报案请求:\n" +
"因被报案人李社辉等人涉嫌合同诈骗罪,报案人现向贵局报\n" +
"案,请求立案侦查。\n" +
"事实与理由:\n" +
"一、背景事实\n" +
"2017年4月左右罗静给报案人打电话称其时任宁夏博金\n" +
"特立体泊车设备有限公司副总,公司项目的发拨、资金的发放均\n" +
"由他决定,将会有好的项目给报案人介绍。\n" +
"2017年5月10日罗静给报案人打电话说有一个很好的立\n" +
"体停车场的项目欲承包给报案人,让报案人准备二十万元保证金\n" +
"交到公司,并强调必须是现金。因此,当天下午报案人从银行卡\n" +
"里取出二十万元现金交至被报案人李社辉处,对方给报案人出具");
LLMExtractDtoList.add(LLMExtractDto);
LLMExtractDto LLMExtractDto2 = new LLMExtractDto();
LLMExtractDto2.setId("1833322459494428674");
LLMExtractDto2.setText("了《收据》一张,并与报案人签订了《协议书》一份,约定报案\n" +
"人同意向宁夏博金特立体泊车设备有限公司以现金方式进行担\n" +
"保,交纳质量及施工保证金,即人民币二十万元整。该保证金交\n" +
"至甲方账户后,宁夏博金特立体泊车设备有限公司须确保凯尔福\n" +
"邸项目由报案人完成。\n" +
"二、李社辉涉嫌合同诈骗罪的犯罪事实非常明确、证据确凿,\n" +
"应予认定\n" +
"在报案人与被报案人宁夏博金特立体泊车设备有限公司签订\n" +
"《协议书》后,报案人积极起草项目施工合同,期待与被报案人\n" +
"宁夏博金特立体泊车设备有限公司签订合同,完成合作,但对方\n" +
"总是以各种理由推脱。之后,报案人经多方打听,才知道被报案\n" +
"人宁夏博金特根本没有关于凯尔福邸的项目,报案人才知道上当\n" +
"受骗。报案人就开始向被报案人李社辉索要报案人交的二十万元\n" +
"保证金,被报案人李社辉等人以各种理由推,并且一直欺骗报\n" +
"案人说要给报案人介绍其他工程项目。但是这已经过去了两年,\n" +
"对方并没有给报案人退还保证金,也没有给报案人介绍其他项目。\n" +
"直到现在,被报案人李社辉等人不接听电话,也不出现与报案人\n" +
"处理,报案人深感受骗!\n" +
"李社辉等人骗取报案人钱财是合谋诈骗,是有预谋团伙作案,\n" +
"通过签订假协议的方式诈骗他人财物,涉案数额特别巨大,其行\n" +
"为严重扰乱了正常的市场经济秩序。\n" +
"三、李社辉等人行为已构成犯罪,符合立案标准。\n" +
"(一)立案标准明确\n" +
"《最高人民检察院公安部关于公安机关管辖的刑事案件立案\n" +
"2");
// LLMExtractDtoList.add(LLMExtractDto2);
for (int i = 0; i < 10; i++) {
List<LLMExtractDto> result = llmExtractService.extractTitle(LLMExtractDtoList);
}
}
@Test
public void testExtractAttr() {
long start = System.currentTimeMillis();
LLMExtractDto llmExtractDto = new LLMExtractDto();
llmExtractDto.setId("1833322433007398913");
llmExtractDto.setText("抵顶购房协议\\n甲方卖房方\\n夏双合房地产开发有限公司\\n身份证号642/021P67020P0\\n乙方买房方叶占文\\n丙方王国旗\\n圣国旗\\n身份证号64212198203150339\\n经甲乙丙三方协商由于乙丙双方给原大成欧景花园14#楼前\\n期承包人高宏做分包项目现为了解决乙丙双方的剩余工程款经三\\n方协商同意甲方将位于大成欧景花园 14-1-1402 房产抵顶给乙方,三\\n方达成的协议如下\\n1、位于大成欧景花园 14-1-1402 房产的面积为 115.38,双方协商的\\n房款总价为肆拾叁万捌仟肆佰肆拾肆元438444。\\n2、三方协商此套房的房款中的286150元用14#楼的发泡施工队叶占\\n文乙方的工程款进行抵顶52000 元用 14#楼的防水施工人员王国旗\\n丙方的人工费抵顶。剩余房款壹拾万元100000由乙方支付给甲方。\\n3、三方协商均同意丙方 52000 元工程款由乙方将该房产销售以后\\n按实际销售房款相关比例直接支付给丙方甲方不再参与不再负责\\n该房产备案至乙方指定人名下。\\n4、三方协商该房产对应的税金48229元其中20000元由乙丙双\\n方承担丙方承担3000元剩余28229 由甲方承担。\\n5、本协议签订的同时由乙方支付甲方房款定金四万元40000元,\\n到甲方指定的朱金成代收账户。\\n6、本协议签订后甲方与乙方、丙方所有债权债务结清由甲方从高\\n宏工程款中扣除相应抵顶款项乙方丙方不得再向高宏追偿。\\n印件与你件一放.由我本人#\\n\\u001b[0m\\n7、本协议签订后乙方丙方在销售该房产时所产生的盈余或亏损亏均\\n与甲方无任何关系。\\n8、在乙方找到购房客户甲方则配合乙方办理签订该房产的网签备\\n案手续网签备案前付清剩余房款及税金80000元给甲方其中税金\\n9、本协议签订以后乙丙双方可销售该房产,甲方配合办理相关手续。\\n10、本协议自双方签字盖章后生效任何一方不得违约否则按总房\\n款的日千分之一1承担违约责任。\\n(1)\\n1391453368802021年9月27日\\n丙方蕴\\n1779J343352021年9月27日\\n腹仰体与原件由成本人\\n201.\\n\\u001b[0m");
llmExtractDto.setPrompt("请根据属性定义从源文本中提取属性:\n" +
"\n" +
"示例文本:\n" +
"\"\n" +
"甲方:张三公司\n" +
"乙方:\n" +
"数量5000吨水泥\n" +
"合同金额8346元\n" +
"支付时间2022年11月30日\n" +
"履行期限2022年12月1日至2023年12月1日\n" +
"签订日期2022年11月23日\n" +
"\"\n" +
"\n" +
"示例结果:\n" +
"{\n" +
" \"甲方名称\": \"张三公司\",\n" +
" \"乙方名称\": \"\",\n" +
" \"数量\": \"5000吨水泥\",\n" +
" \"合同金额\": \"8346.00\",\n" +
" \"支付时间\": \"2022-11-30\",\n" +
" \"履行期限\": \"2022年12月1日至2023年12月1日\",\n" +
" \"签订日期\": \"2022-11-23\"\n" +
"}\n" +
"\n" +
"源文本:\n" +
"{ocr_txt}\n\n" +
"属性定义:\n" +
"{attr_define}\n" +
"\n" +
"### 注意事项:\n" +
"1. 将结果以JSON格式返回。不需要进行解释。\n" +
"2. 如果某字段提取不到,则返回\"\"。\n" +
"3. 日期格式为yyyy-MM-dd浮点型格式返回保留两位小数。\n" +
"4. 值为文本类型的数据,尽量使用原文中的文字。\n" +
"5. 只可以使用原文中的文字,不可以自行添加内容。\n" +
"\n" +
"回溯你输出的结果确保你的输出结果符合json格式。");
NotePromptExtractAttributesDto notePromptExtractAttributesDto = new NotePromptExtractAttributesDto();
notePromptExtractAttributesDto.setAttrName("甲方");
notePromptExtractAttributesDto.setAttrValueType("文本");
NotePromptExtractAttributesDto notePromptExtractAttributesDto2 = new NotePromptExtractAttributesDto();
notePromptExtractAttributesDto2.setAttrName("乙方");
notePromptExtractAttributesDto2.setAttrValueType("文本");
NotePromptExtractAttributesDto notePromptExtractAttributesDto3 = new NotePromptExtractAttributesDto();
notePromptExtractAttributesDto3.setAttrName("数量");
notePromptExtractAttributesDto3.setAttrValueType("文本");
NotePromptExtractAttributesDto notePromptExtractAttributesDto4 = new NotePromptExtractAttributesDto();
notePromptExtractAttributesDto4.setAttrName("合同金额");
notePromptExtractAttributesDto4.setAttrValueType("浮点");
NotePromptExtractAttributesDto notePromptExtractAttributesDto5 = new NotePromptExtractAttributesDto();
notePromptExtractAttributesDto5.setAttrName("支付时间");
notePromptExtractAttributesDto5.setAttrValueType("日期");
NotePromptExtractAttributesDto notePromptExtractAttributesDto6 = new NotePromptExtractAttributesDto();
notePromptExtractAttributesDto6.setAttrName("履行期限");
notePromptExtractAttributesDto6.setAttrValueType("文本");
NotePromptExtractAttributesDto notePromptExtractAttributesDto7 = new NotePromptExtractAttributesDto();
notePromptExtractAttributesDto7.setAttrName("签订日期");
notePromptExtractAttributesDto7.setAttrValueType("日期");
llmExtractDto.setExtractAttributes(List.of(notePromptExtractAttributesDto, notePromptExtractAttributesDto2, notePromptExtractAttributesDto3, notePromptExtractAttributesDto4, notePromptExtractAttributesDto5, notePromptExtractAttributesDto6, notePromptExtractAttributesDto7));
llmExtractService.extractAttribute(Collections.singletonList(llmExtractDto));
long end = System.currentTimeMillis();
log.info("耗时:{}", end - start);
}
@Test
public void test() {
for (int i = 0; i < 10; i++) {
xxlJobService.executeTaskByJobHandler("evidenceAnalysis", "1");
}
}
}

@ -1,82 +0,0 @@
package com.supervision.demo;
import com.supervision.police.dto.OcrExtractDto;
import com.supervision.police.service.OcrExtractService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@SpringBootTest
public class OcrExtractTest {
@Autowired
private OcrExtractService ocrExtractService;
@Test
public void testExtractTitle() {
List<OcrExtractDto> ocrExtractDtoList = new ArrayList<>();
OcrExtractDto ocrExtractDto = new OcrExtractDto();
ocrExtractDto.setId("1833322433007398913");
ocrExtractDto.setText("关于李社辉等人涉嫌合同诈骗罪的\n" +
"报案材料\n" +
"报案人许锋8。年\n" +
"一月\n" +
"/旦,汉族,\n" +
"号:-640/2119001012218\n" +
"电话1837571888。\n" +
"被报案人:\n" +
"李社辉年月1/日,汉族,住\n" +
"址西安市间良7x公园路7株号身份证号610114195505110513\n" +
"电话1810537777。\n" +
"宁夏博金特立体泊车设备有限公司,住所地:青铜峡市嘉宝\n" +
"工业园区7-8号。\n" +
"法定代表人:李社辉,该公司总经理。\n" +
"报案请求:\n" +
"因被报案人李社辉等人涉嫌合同诈骗罪,报案人现向贵局报\n" +
"案,请求立案侦查。\n" +
"事实与理由:\n" +
"一、背景事实\n" +
"2017年4月左右罗静给报案人打电话称其时任宁夏博金\n" +
"特立体泊车设备有限公司副总,公司项目的发拨、资金的发放均\n" +
"由他决定,将会有好的项目给报案人介绍。\n" +
"2017年5月10日罗静给报案人打电话说有一个很好的立\n" +
"体停车场的项目欲承包给报案人,让报案人准备二十万元保证金\n" +
"交到公司,并强调必须是现金。因此,当天下午报案人从银行卡\n" +
"里取出二十万元现金交至被报案人李社辉处,对方给报案人出具");
ocrExtractDtoList.add(ocrExtractDto);
OcrExtractDto ocrExtractDto2 = new OcrExtractDto();
ocrExtractDto2.setId("1833322459494428674");
ocrExtractDto2.setText("了《收据》一张,并与报案人签订了《协议书》一份,约定报案\n" +
"人同意向宁夏博金特立体泊车设备有限公司以现金方式进行担\n" +
"保,交纳质量及施工保证金,即人民币二十万元整。该保证金交\n" +
"至甲方账户后,宁夏博金特立体泊车设备有限公司须确保凯尔福\n" +
"邸项目由报案人完成。\n" +
"二、李社辉涉嫌合同诈骗罪的犯罪事实非常明确、证据确凿,\n" +
"应予认定\n" +
"在报案人与被报案人宁夏博金特立体泊车设备有限公司签订\n" +
"《协议书》后,报案人积极起草项目施工合同,期待与被报案人\n" +
"宁夏博金特立体泊车设备有限公司签订合同,完成合作,但对方\n" +
"总是以各种理由推脱。之后,报案人经多方打听,才知道被报案\n" +
"人宁夏博金特根本没有关于凯尔福邸的项目,报案人才知道上当\n" +
"受骗。报案人就开始向被报案人李社辉索要报案人交的二十万元\n" +
"保证金,被报案人李社辉等人以各种理由推,并且一直欺骗报\n" +
"案人说要给报案人介绍其他工程项目。但是这已经过去了两年,\n" +
"对方并没有给报案人退还保证金,也没有给报案人介绍其他项目。\n" +
"直到现在,被报案人李社辉等人不接听电话,也不出现与报案人\n" +
"处理,报案人深感受骗!\n" +
"李社辉等人骗取报案人钱财是合谋诈骗,是有预谋团伙作案,\n" +
"通过签订假协议的方式诈骗他人财物,涉案数额特别巨大,其行\n" +
"为严重扰乱了正常的市场经济秩序。\n" +
"三、李社辉等人行为已构成犯罪,符合立案标准。\n" +
"(一)立案标准明确\n" +
"《最高人民检察院公安部关于公安机关管辖的刑事案件立案\n" +
"2");
ocrExtractDtoList.add(ocrExtractDto2);
List<OcrExtractDto> result = ocrExtractService.extractTitle(ocrExtractDtoList);
log.info("result: {}", result);
}
}

@ -0,0 +1,45 @@
package com.supervision.demo;
import com.supervision.police.domain.XxlJobInfo;
import com.supervision.police.dto.LLMExtractDto;
import com.supervision.police.service.XxlJobService;
import com.supervision.utils.XxlJobUtil;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@Slf4j
@SpringBootTest
public class TaskTest {
@Autowired
private XxlJobUtil xxlJobUtil;
@Autowired
private XxlJobService xxlJobService;
@Autowired
private XxlJobSpringExecutor xxlJobSpringExecutor;
@Test
public void testTask() {
try {
// xxlJobService.login();
XxlJobInfo xxlJobInfo = new XxlJobInfo();
xxlJobInfo.setExecutorHandler("extractAttribute");
List<XxlJobInfo> xxlJobInfoList = xxlJobService.pageList(xxlJobInfo);
if(xxlJobInfoList!=null&&!xxlJobInfoList.isEmpty()){
xxlJobInfo = xxlJobInfoList.get(0);
log.info("xxlJobInfo:{}",xxlJobInfo);
xxlJobService.executeTaskById(String.valueOf(xxlJobInfo.getId()), null);
}
// xxlJobService.executeTask("testTask");
// Thread.sleep(2000);
// xxlJobUtil.executeTask("testTask");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Loading…
Cancel
Save