Browse Source

对接数据服务

master
luoweijian 2 months ago
parent
commit
fa8c2c8015
  1. 79
      src/main/java/com/project/information/domain/service/impl/PostToDataExtractDomainServiceImpl.java
  2. 22
      src/main/java/com/project/interaction/controller/InteractionController.java
  3. 26
      src/main/java/com/project/milvus/application/impl/MilvusApplicationServiceImpl.java
  4. 3
      src/main/java/com/project/milvus/domain/dto/TitleVector.java
  5. 3
      src/main/resources/application-dev.yml

79
src/main/java/com/project/information/domain/service/impl/PostToDataExtractDomainServiceImpl.java

@ -3,6 +3,7 @@ package com.project.information.domain.service.impl;
import com.project.information.domain.entity.InformationFileEntity; import com.project.information.domain.entity.InformationFileEntity;
import com.project.information.domain.service.PostToDataExtractDomainService; import com.project.information.domain.service.PostToDataExtractDomainService;
import com.project.information.utils.MinIoUtils; import com.project.information.utils.MinIoUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -12,13 +13,14 @@ import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.io.InputStream; import java.io.InputStream;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
/** /**
* 发送子文件到数据服务解析 * 发送子文件到数据服务解析
@ -32,56 +34,55 @@ public class PostToDataExtractDomainServiceImpl implements PostToDataExtractDoma
@Autowired @Autowired
private MinIoUtils minIoUtils; private MinIoUtils minIoUtils;
private final RestTemplate restTemplate = new RestTemplate(); @Resource(name = "asycExecutor")
private Executor asycExecutor;
/** 数据服务地址(待确认) */
@Value("${dataExtract.host:http://172.16.204.50}")
private String dataExtractHost;
@Value("${dataExtract.port:8888}") private final RestTemplate restTemplate = new RestTemplate();
private String dataExtractPort;
@Value("${dataExtract.url:/word/parse}") @Value("${dataExtract.url:http://172.16.204.50/dataExtract/ai-check/api/documents-parse}")
private String dataExtractUrl; private String dataExtractUrl;
@Value("${dataExtract.callback-url:http://172.16.204.50/evaluator-api/api/interaction/dataExtractCallback}")
private String callbackUrl;
@Override @Override
@Async("asycExecutor")
public void postToDataExtract(InformationFileEntity file, Long informationId) { public void postToDataExtract(InformationFileEntity file, Long informationId) {
try { CompletableFuture.runAsync(() -> {
log.info(">>> [数据服务] 正在发送子文件解析请求, fileId={}, fileName={}", file.getId(), file.getFileName()); try {
log.info(">>> [数据服务] 正在发送子文件解析请求, fileId={}, fileName={}", file.getId(), file.getFileName());
// 从 MinIO 获取文件流 // 从 MinIO 获取文件流
try (InputStream inputStream = minIoUtils.getObject(file.getFilePath())) { try (InputStream inputStream = minIoUtils.getObject(file.getFilePath())) {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA); headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.setAccept(MediaType.parseMediaTypes("*/*")); headers.setAccept(MediaType.parseMediaTypes("*/*"));
// 将 InputStream 转换为字节数组 // 将 InputStream 转换为字节数组
byte[] bytes = IOUtils.toByteArray(inputStream); byte[] bytes = IOUtils.toByteArray(inputStream);
ByteArrayResource fileResource = new ByteArrayResource(bytes) { ByteArrayResource fileResource = new ByteArrayResource(bytes) {
@Override @Override
public String getFilename() { public String getFilename() {
return file.getFileName(); return file.getFileName();
} }
}; };
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", fileResource); body.add("file", fileResource);
body.add("fileId", file.getId()); body.add("fileId", file.getId());
body.add("informationId", informationId); body.add("informationId", informationId);
body.add("contentCategory", file.getContentCategory()); body.add("fileName", file.getFileName());
body.add("callbackUrl", callbackUrl);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers); HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
// 发送请求(同步,但整个方法在异步线程中执行) ResponseEntity<String> response = restTemplate.postForEntity(
ResponseEntity<String> response = restTemplate.postForEntity( dataExtractUrl, requestEntity, String.class);
dataExtractHost + ":" + dataExtractPort + dataExtractUrl,
requestEntity, String.class);
log.info(">>> [数据服务] 子文件 {} 解析请求已发送, response={}", file.getFileName(), response.getBody()); log.info(">>> [数据服务] 子文件 {} 解析请求已发送, response={}", file.getFileName(), response.getBody());
}
} catch (Exception e) {
log.error(">>> [数据服务] 子文件解析请求异常, fileId={}", file.getId(), e);
} }
} catch (Exception e) { }, asycExecutor);
log.error(">>> [数据服务] 子文件解析请求异常, fileId={}", file.getId(), e);
}
} }
} }

22
src/main/java/com/project/interaction/controller/InteractionController.java

@ -4,7 +4,6 @@ package com.project.interaction.controller;
import com.project.base.domain.exception.MissingParameterException; import com.project.base.domain.exception.MissingParameterException;
import com.project.base.domain.result.Result; import com.project.base.domain.result.Result;
import com.project.classicpaper.domain.service.ClassicPaperQuestionCallbackService;
import com.project.interaction.application.AiExtractCallbackApplicationService; import com.project.interaction.application.AiExtractCallbackApplicationService;
import com.project.interaction.application.AlgorithmApplicationService; import com.project.interaction.application.AlgorithmApplicationService;
import com.project.interaction.application.DataExtractCallbackApplicationService; import com.project.interaction.application.DataExtractCallbackApplicationService;
@ -41,11 +40,7 @@ public class InteractionController {
@Autowired @Autowired
private AiExtractCallbackApplicationService aiExtractCallbackApplicationService; private AiExtractCallbackApplicationService aiExtractCallbackApplicationService;
@Autowired // @PostMapping("/saveCluster")
private ClassicPaperQuestionCallbackService classicPaperQuestionCallbackService;
// @PostMapping("/saveCluster")
// public Result<String> saveCluster(ClusterCallbackDTO dto) throws Exception{ // public Result<String> saveCluster(ClusterCallbackDTO dto) throws Exception{
// algorithmApplicationService.saveCluster(dto.getTaskId(), dto.getClusters()); // algorithmApplicationService.saveCluster(dto.getTaskId(), dto.getClusters());
// return Result.success("保存成功"); // return Result.success("保存成功");
@ -57,20 +52,9 @@ public class InteractionController {
return Result.success("保存成功"); return Result.success("保存成功");
} }
/**
* 生题结果回调通用题库 + 经典套卷
* 通过 bizKey 区分业务场景
* - "PQ:paperQuestionId" 经典套卷生题
* 其他或 null 通用题库暂未实现静默忽略
*/
@PostMapping("/saveQuestion") @PostMapping("/saveQuestion")
public Result<String> saveQuestion(@RequestBody QuestionCallBackDTO dto) throws Exception { public Result<String> saveQuestion(QuestionCallBackDTO dto) throws Exception {
String bizKey = dto.getBizKey(); return null;
if (bizKey != null && bizKey.startsWith("PQ:")) {
classicPaperQuestionCallbackService.handleCallback(dto);
}
// 其他 bizKey 或 null → 暂不处理(兼容旧逻辑)
return Result.success("回调处理成功");
} }
/** /**

26
src/main/java/com/project/milvus/application/impl/MilvusApplicationServiceImpl.java

@ -2,6 +2,8 @@ package com.project.milvus.application.impl;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import com.project.base.domain.exception.MissingParameterException; import com.project.base.domain.exception.MissingParameterException;
import com.project.classicpaper.domain.service.ClassicPaperQuestionCallbackService;
import com.project.interaction.domain.dto.QuestionCallBackDTO;
import com.project.milvus.application.MilvusApplicationService; import com.project.milvus.application.MilvusApplicationService;
import com.project.milvus.domain.dto.TitleVector; import com.project.milvus.domain.dto.TitleVector;
import com.project.milvus.domain.service.CheckMilvusDomainService; import com.project.milvus.domain.service.CheckMilvusDomainService;
@ -32,6 +34,8 @@ public class MilvusApplicationServiceImpl implements MilvusApplicationService {
@Autowired @Autowired
private SaveQuestionDomainService saveQuestionDomainService; private SaveQuestionDomainService saveQuestionDomainService;
@Autowired
private ClassicPaperQuestionCallbackService classicPaperQuestionCallbackService;
//相似度阈值 //相似度阈值
private static final Float SIMILARITY_THRESHOLD = 0.8f; private static final Float SIMILARITY_THRESHOLD = 0.8f;
@ -40,6 +44,13 @@ public class MilvusApplicationServiceImpl implements MilvusApplicationService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void insertTitle(TitleVector title) { public void insertTitle(TitleVector title) {
// 经典套卷分支:走备用池 + 提拔,跳过 Milvus
if (title.getBizKey() != null && title.getBizKey().startsWith("PQ:")) {
log.info(">>> [回调处理] 经典套卷生题回调, bizKey={}", title.getBizKey());
handleClassicPaper(title);
return;
}
log.info(">>> [回调处理] 开始持久化题目{},知识点{},考试任务[{}]",title.QuestionDetailDTO,title.getTaskKpIdsList(), title.getTaskId()); log.info(">>> [回调处理] 开始持久化题目{},知识点{},考试任务[{}]",title.QuestionDetailDTO,title.getTaskKpIdsList(), title.getTaskId());
// 基础参数校验(在锁外,快速失败) // 基础参数校验(在锁外,快速失败)
@ -117,6 +128,21 @@ public class MilvusApplicationServiceImpl implements MilvusApplicationService {
return questionDTO; return questionDTO;
} }
/**
* 经典套卷回调构造 QuestionCallBackDTO 委托给 ClassicPaperQuestionCallbackService
*/
private void handleClassicPaper(TitleVector title) {
// 构造单题列表
QuestionDTO questionDTO = buildQuestionDTO(title);
List<QuestionDTO> questions = Collections.singletonList(questionDTO);
QuestionCallBackDTO callback = new QuestionCallBackDTO();
callback.setBizKey(title.getBizKey());
callback.setQuestions(questions);
classicPaperQuestionCallbackService.handleCallback(callback);
}
/** /**
* 构建锁的 key * 构建锁的 key
*/ */

3
src/main/java/com/project/milvus/domain/dto/TitleVector.java

@ -28,6 +28,9 @@ public class TitleVector {
//题目内容 //题目内容
public QuestionDTO.QuestionDetailDTO QuestionDetailDTO; public QuestionDTO.QuestionDetailDTO QuestionDetailDTO;
/** 业务标识:PQ:paperQuestionId(经典套卷),null 或不传为通用题库 */
private String bizKey;
public String getTaskKpIdsHash() { public String getTaskKpIdsHash() {
List<Long> sorted = new ArrayList<>(taskKpIds); List<Long> sorted = new ArrayList<>(taskKpIds);
Collections.sort(sorted); Collections.sort(sorted);

3
src/main/resources/application-dev.yml

@ -67,6 +67,9 @@ analysis:
host: http://172.16.204.50 host: http://172.16.204.50
port: 8888 port: 8888
url: /word/parse url: /word/parse
dataExtract:
url: http://172.16.204.50:8002/ai-check/api/documents-parse
callback-url: http://172.16.204.50:7088/api/interaction/dataExtractCallback
ding: ding:
appKey: dinggl2ktuhdhoczkg2o appKey: dinggl2ktuhdhoczkg2o
appSecret: nK104mgXPbkCWjX1I-EcYiubjM0FJAYcfqBKPkVcyvrBsLMF9XK1g9Qd_QVOndcK appSecret: nK104mgXPbkCWjX1I-EcYiubjM0FJAYcfqBKPkVcyvrBsLMF9XK1g9Qd_QVOndcK

Loading…
Cancel
Save