Browse Source

文档上传就聚类

master
luoweijian 1 month ago
parent
commit
525120f651
  1. 1
      src/main/java/com/project/information/application/impl/KnowledgePointApplicationServiceImpl.java
  2. 3
      src/main/java/com/project/information/domain/dto/KnowledgePointDTO.java
  3. 10
      src/main/java/com/project/information/domain/entity/KnowledgePointEntity.java
  4. 8
      src/main/java/com/project/information/domain/service/KnowledgeClusterBaseService.java
  5. 11
      src/main/java/com/project/information/domain/service/impl/KnowledgeClusterBaseServiceImpl.java
  6. 24
      src/main/java/com/project/information/domain/service/impl/UploadInformationDomainServiceImpl.java
  7. 6
      src/main/java/com/project/interaction/application/AlgorithmApplicationService.java
  8. 9
      src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java
  9. 11
      src/main/java/com/project/interaction/controller/InteractionController.java
  10. 3
      src/main/java/com/project/interaction/domain/service/PostToClusteringDomainService.java
  11. 4
      src/main/java/com/project/interaction/domain/service/SaveClusterDomainService.java
  12. 39
      src/main/java/com/project/interaction/domain/service/impl/PostToClusteringDomainServiceImpl.java
  13. 37
      src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java
  14. 18
      src/main/java/com/project/task/domain/service/impl/InitTaskDomainServiceImpl.java

1
src/main/java/com/project/information/application/impl/KnowledgePointApplicationServiceImpl.java

@ -79,7 +79,6 @@ public class KnowledgePointApplicationServiceImpl implements KnowledgePointAppli
} }
// 成功后更新状态 // 成功后更新状态
updateStatusInformation(null, InformationParseStatusEnum.InProgress.getValue(), id); updateStatusInformation(null, InformationParseStatusEnum.InProgress.getValue(), id);
// 聚类
} catch (Exception e) { } catch (Exception e) {
log.error("解析异常, ID:{}", id, e); log.error("解析异常, ID:{}", id, e);

3
src/main/java/com/project/information/domain/dto/KnowledgePointDTO.java

@ -24,6 +24,9 @@ public class KnowledgePointDTO extends BaseDTO {
private List<ExamFocusDTO> examFocusDTOList; private List<ExamFocusDTO> examFocusDTOList;
private Long clusterId;
@Data @Data
public static class ExamFocusDTO { public static class ExamFocusDTO {
/*考点底色*/ /*考点底色*/

10
src/main/java/com/project/information/domain/entity/KnowledgePointEntity.java

@ -24,7 +24,9 @@ import java.util.function.Supplier;
@Data @Data
@Table(name = "evaluator_knowledge_point" , @Table(name = "evaluator_knowledge_point" ,
indexes = {@Index(name = "Idx_informationId", columnList = "information_id")}) indexes = {@Index(name = "Idx_informationId", columnList = "information_id") ,
@Index(name = "Idx_clusterId", columnList = "cluster_id") ,
})
@Entity @Entity
@TableName(value = "evaluator_knowledge_point") @TableName(value = "evaluator_knowledge_point")
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -56,6 +58,12 @@ public class KnowledgePointEntity extends BaseEntity {
@Column(name = "exam_focus_list", columnDefinition = "json comment '考点集合'") @Column(name = "exam_focus_list", columnDefinition = "json comment '考点集合'")
private List<ExamFocus> examFocusList; private List<ExamFocus> examFocusList;
@Column(name = "cluster_id")
@TableField("cluster_id")
@Comment("所属知识点簇ID")
private Long clusterId;
@Data @Data
public static class ExamFocus { public static class ExamFocus {
/*考点底色*/ /*考点底色*/

8
src/main/java/com/project/information/domain/service/KnowledgeClusterBaseService.java

@ -0,0 +1,8 @@
package com.project.information.domain.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.project.information.domain.entity.KnowledgeClusterEntity;
import com.project.information.domain.entity.KnowledgePointEntity;
public interface KnowledgeClusterBaseService extends IService<KnowledgeClusterEntity> {
}

11
src/main/java/com/project/information/domain/service/impl/KnowledgeClusterBaseServiceImpl.java

@ -0,0 +1,11 @@
package com.project.information.domain.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.project.information.domain.entity.KnowledgeClusterEntity;
import com.project.information.domain.service.KnowledgeClusterBaseService;
import com.project.information.mapper.KnowledgeClusterMapper;
import org.springframework.stereotype.Service;
@Service
public class KnowledgeClusterBaseServiceImpl extends ServiceImpl<KnowledgeClusterMapper, KnowledgeClusterEntity> implements KnowledgeClusterBaseService {
}

24
src/main/java/com/project/information/domain/service/impl/UploadInformationDomainServiceImpl.java

@ -11,19 +11,24 @@ import com.project.base.domain.exception.BusinessErrorException;
import com.project.base.domain.result.Result; import com.project.base.domain.result.Result;
import com.project.information.application.KnowledgePointApplicationService; import com.project.information.application.KnowledgePointApplicationService;
import com.project.information.domain.dto.InformationDTO; import com.project.information.domain.dto.InformationDTO;
import com.project.information.domain.dto.KnowledgePointDTO;
import com.project.information.domain.entity.InformationEntity; import com.project.information.domain.entity.InformationEntity;
import com.project.information.domain.entity.KnowledgePointEntity;
import com.project.information.domain.entity.ProductLineEntity; import com.project.information.domain.entity.ProductLineEntity;
import com.project.information.domain.enums.InformationParseStatusEnum; import com.project.information.domain.enums.InformationParseStatusEnum;
import com.project.information.domain.param.FileCheckItem; import com.project.information.domain.param.FileCheckItem;
import com.project.information.domain.service.InformationBaseService; import com.project.information.domain.service.InformationBaseService;
import com.project.information.domain.service.KnowledgePointBaseService;
import com.project.information.domain.service.ProductLineBaseService; import com.project.information.domain.service.ProductLineBaseService;
import com.project.information.domain.service.UploadInformationDomainService; import com.project.information.domain.service.UploadInformationDomainService;
import com.project.information.utils.MinIoUtils; import com.project.information.utils.MinIoUtils;
import com.project.interaction.application.AlgorithmApplicationService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.*; import java.util.*;
@ -38,9 +43,15 @@ public class UploadInformationDomainServiceImpl implements UploadInformationDoma
private MinIoUtils minIoUtils; private MinIoUtils minIoUtils;
@Autowired @Autowired
private KnowledgePointApplicationService knowledgePointApplicationService; private KnowledgePointApplicationService knowledgePointApplicationService;
@Autowired
private KnowledgePointBaseService knowledgePointBaseService;
@Autowired @Autowired
private CustomIdGenerator customIdGenerator; private CustomIdGenerator customIdGenerator;
@Autowired
private AlgorithmApplicationService algorithmApplicationService;
private static final long MAX_SIZE = 50 * 1024 * 1024; // 50MB 限制 private static final long MAX_SIZE = 50 * 1024 * 1024; // 50MB 限制
@Override @Override
@ -135,6 +146,19 @@ public class UploadInformationDomainServiceImpl implements UploadInformationDoma
//发起解析文档知识点 //发起解析文档知识点
knowledgePointApplicationService.parse(fileMap); knowledgePointApplicationService.parse(fileMap);
// 聚类
for (Map.Entry<Long, String> entry : fileMap.entrySet()) {
Long informationId = entry.getKey();
List<KnowledgePointDTO> list = knowledgePointBaseService.lambdaQuery()
.eq(KnowledgePointEntity::getInformationId, informationId).list().stream()
.map(entity -> entity.toDTO(KnowledgePointDTO::new)).toList();
if (CollUtil.isNotEmpty(list)) {
algorithmApplicationService.postToClusteringByInformationId(informationId , list);
}
InformationEntity byId = informationBaseService.getById(informationId);
byId.setParseStatus(InformationParseStatusEnum.Success.getValue());
informationBaseService.updateById(byId);
}
return Result.success(String.format("上传成功:【%s】" , String.join("," , successFiles))); return Result.success(String.format("上传成功:【%s】" , String.join("," , successFiles)));
} }

6
src/main/java/com/project/interaction/application/AlgorithmApplicationService.java

@ -20,9 +20,15 @@ public interface AlgorithmApplicationService {
void postToClustering(Long taskId, List<KnowledgePointDTO> kpList); void postToClustering(Long taskId, List<KnowledgePointDTO> kpList);
void postToClusteringByInformationId(Long informationId, List<KnowledgePointDTO> kpList);
void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList , QuestionTypeEnum questionType , int num) throws Exception; void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList , QuestionTypeEnum questionType , int num) throws Exception;
void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception; void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception;
void saveClusterByInformationId(Long informationId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception;
Result<QuestionDTO> saveQuestion(QuestionDTO dto) throws Exception; Result<QuestionDTO> saveQuestion(QuestionDTO dto) throws Exception;
} }

9
src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java

@ -34,6 +34,10 @@ public class AlgorithmApplicationServiceImpl implements AlgorithmApplicationServ
postToClusteringDomainService.postToClustering(taskId , kpList); postToClusteringDomainService.postToClustering(taskId , kpList);
} }
@Override
public void postToClusteringByInformationId(Long informationId, List<KnowledgePointDTO> kpList) {
}
@Override @Override
public void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num) throws Exception { public void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num) throws Exception {
@ -46,6 +50,11 @@ public class AlgorithmApplicationServiceImpl implements AlgorithmApplicationServ
saveClusterDomainService.saveCluster(taskId , clusters); saveClusterDomainService.saveCluster(taskId , clusters);
} }
@Override
public void saveClusterByInformationId(Long informationId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception {
saveClusterDomainService.saveClusterByInformationId(informationId , clusters);
}
@Override @Override
public Result<QuestionDTO> saveQuestion(QuestionDTO dto) throws Exception { public Result<QuestionDTO> saveQuestion(QuestionDTO dto) throws Exception {
return saveQuestionDomainService.save(dto); return saveQuestionDomainService.save(dto);

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

@ -17,14 +17,15 @@ public class InteractionController {
private AlgorithmApplicationService algorithmApplicationService; private AlgorithmApplicationService algorithmApplicationService;
// @PostMapping("/saveCluster")
// public Result<String> saveCluster(ClusterCallbackDTO dto) throws Exception{
// algorithmApplicationService.saveCluster(dto.getTaskId(), dto.getClusters());
// return Result.success("保存成功");
// }
/**
* 手动触发同步接口
* 强刷/sync/all?force=true
*/
@PostMapping("/saveCluster") @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.saveClusterByInformationId(dto.getTaskId(), dto.getClusters());
return Result.success("保存成功"); return Result.success("保存成功");
} }

3
src/main/java/com/project/interaction/domain/service/PostToClusteringDomainService.java

@ -6,4 +6,7 @@ import java.util.List;
public interface PostToClusteringDomainService { public interface PostToClusteringDomainService {
void postToClustering(Long taskId, List<KnowledgePointDTO> kpList); void postToClustering(Long taskId, List<KnowledgePointDTO> kpList);
void postToClusteringByInformationId(Long informationId, List<KnowledgePointDTO> kpList);
} }

4
src/main/java/com/project/interaction/domain/service/SaveClusterDomainService.java

@ -6,4 +6,8 @@ import java.util.List;
public interface SaveClusterDomainService { public interface SaveClusterDomainService {
void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception; void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception;
void saveClusterByInformationId(Long informationId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception;
} }

39
src/main/java/com/project/interaction/domain/service/impl/PostToClusteringDomainServiceImpl.java

@ -65,4 +65,43 @@ public class PostToClusteringDomainServiceImpl implements PostToClusteringDomain
log.error(">>> [Interactor] 算法端通信异常", e); log.error(">>> [Interactor] 算法端通信异常", e);
} }
} }
@Override
public void postToClusteringByInformationId(Long informationId, List<KnowledgePointDTO> kpList) {
// 构建请求 DTO (AlgoRequestDTO)
Map<String, Object> requestBody = Collections.singletonMap("tasks",
Collections.singletonList(new ClusterQueryDTO(informationId, kpList)));
try {
log.info(">>> [Interactor] 正在向算法端发送请求, informationId: {}", informationId);
algorithmWebClient.post()
.uri(clusterUrl)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(String.class)
.flatMap(jsonStr -> Mono.fromCallable(() -> {
ObjectMapper mapper = new ObjectMapper();
// 第一次 readValue:去掉外层引号和转义符,把字符串变成正常的 JSON 格式
// 此时 unescapedJson 的值会变成 {"code": 200, "message": "请求成功!"}
String unescapedJson = mapper.readValue(jsonStr, String.class);
// 第二次 readValue:将标准的 JSON 字符串解析为 DTO
return mapper.readValue(unescapedJson, ClusterResultDTO.class);
}))
.doOnError(error -> log.error(">>> [Interactor] 算法端推送异常, informationId: {}, 原因: {}",
informationId, error.getMessage()))
// 结果处理(非阻塞订阅)
.subscribe(
result -> {
log.info(">>> [Interactor] 算法端已成功接收任务: {}", informationId);
},
error -> {
// 这里处理订阅过程中的报错,防止异常被丢弃
log.error(">>> [Interactor] 任务 {} 订阅执行失败", informationId, error);
}
);
} catch (Exception e) {
log.error(">>> [Interactor] 算法端通信异常", e);
}
}
} }

37
src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java

@ -1,8 +1,11 @@
package com.project.interaction.domain.service.impl; package com.project.interaction.domain.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.project.information.domain.dto.KnowledgePointDTO; import com.project.information.domain.dto.KnowledgePointDTO;
import com.project.information.domain.entity.KnowledgeClusterEntity;
import com.project.information.domain.entity.KnowledgePointEntity; import com.project.information.domain.entity.KnowledgePointEntity;
import com.project.information.domain.service.KnowledgeClusterBaseService;
import com.project.information.domain.service.KnowledgePointBaseService; import com.project.information.domain.service.KnowledgePointBaseService;
import com.project.interaction.domain.dto.ClusterCallbackDTO; import com.project.interaction.domain.dto.ClusterCallbackDTO;
import com.project.interaction.domain.dto.ProduceDTO; import com.project.interaction.domain.dto.ProduceDTO;
@ -21,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
@Service @Service
@Slf4j @Slf4j
@ -34,6 +38,9 @@ public class SaveClusterDomainServiceImpl implements SaveClusterDomainService {
@Autowired @Autowired
private TaskKnowledgePointBaseService taskKnowledgePointBaseService; private TaskKnowledgePointBaseService taskKnowledgePointBaseService;
@Autowired
private KnowledgeClusterBaseService knowledgeClusterBaseService;
@Autowired @Autowired
private KnowledgePointBaseService knowledgePointBaseService; private KnowledgePointBaseService knowledgePointBaseService;
@ -43,6 +50,36 @@ public class SaveClusterDomainServiceImpl implements SaveClusterDomainService {
private final Integer ROUND_NUM = 2; private final Integer ROUND_NUM = 2;
@Override
public void saveClusterByInformationId(Long informationId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception {
// 原来有要删掉
List<KnowledgeClusterEntity> list = knowledgeClusterBaseService.lambdaQuery().eq(KnowledgeClusterEntity::getInformationId, informationId).list();
if (CollUtil.isNotEmpty(list)) {
knowledgeClusterBaseService.removeByIds(list.stream().map(KnowledgeClusterEntity::getId)
.collect(Collectors.toList()));
}
for (ClusterCallbackDTO.ClusterItem cluster : clusters) {
// 1.保存知识点簇
KnowledgeClusterEntity clusterEntity = new KnowledgeClusterEntity();
clusterEntity.setInformationId(informationId);
clusterEntity.setClusterTopic(cluster.getTopic());
clusterEntity.setClusterSize(cluster.getAtomIdList().size());
knowledgeClusterBaseService.save(clusterEntity);
// 2.提取该簇下的原子知识点,并保存任务知识点
List<KnowledgePointEntity> kpList = knowledgePointBaseService.list(new LambdaQueryWrapper<KnowledgePointEntity>()
.in(KnowledgePointEntity::getId, cluster.getAtomIdList()));
kpList.forEach(knowledgePointEntity -> knowledgePointEntity.setClusterId(clusterEntity.getId()));
// 批量插入
knowledgePointBaseService.updateBatchById(kpList);
}
}
@Override @Override
public void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) { public void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) {
TaskEntity taskEntity = taskBaseService.getById(taskId); TaskEntity taskEntity = taskBaseService.getById(taskId);

18
src/main/java/com/project/task/domain/service/impl/InitTaskDomainServiceImpl.java

@ -3,19 +3,23 @@ package com.project.task.domain.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.project.information.domain.dto.KnowledgePointDTO; import com.project.information.domain.dto.KnowledgePointDTO;
import com.project.information.domain.dto.ProductLineDTO;
import com.project.information.domain.entity.InformationEntity; import com.project.information.domain.entity.InformationEntity;
import com.project.information.domain.entity.KnowledgePointEntity; import com.project.information.domain.entity.KnowledgePointEntity;
import com.project.information.domain.enums.InformationParseStatusEnum; import com.project.information.domain.enums.InformationParseStatusEnum;
import com.project.information.domain.service.InformationBaseService; import com.project.information.domain.service.InformationBaseService;
import com.project.information.domain.service.KnowledgePointBaseService; import com.project.information.domain.service.KnowledgePointBaseService;
import com.project.interaction.application.AlgorithmApplicationService; import com.project.interaction.application.AlgorithmApplicationService;
import com.project.interaction.domain.dto.ClusterCallbackDTO;
import com.project.task.domain.service.InitTaskDomainService; import com.project.task.domain.service.InitTaskDomainService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -48,7 +52,7 @@ public class InitTaskDomainServiceImpl implements InitTaskDomainService {
}, taskInternalExecutor); }, taskInternalExecutor);
} }
public void handle(Long taskId, List<Long> docIds) { public void handle(Long taskId, List<Long> docIds) throws Exception {
boolean isReady = pollUntilDocsParsed(taskId, docIds); boolean isReady = pollUntilDocsParsed(taskId, docIds);
if (!isReady) { if (!isReady) {
@ -66,7 +70,17 @@ public class InitTaskDomainServiceImpl implements InitTaskDomainService {
return; return;
} }
if (CollUtil.isNotEmpty(kpList)) { if (CollUtil.isNotEmpty(kpList)) {
algorithmApplicationService.postToClustering(taskId , kpList); // algorithmApplicationService.postToClustering(taskId , kpList);
// 组装成任务知识点
Map<Long, List<KnowledgePointDTO>> collect = kpList.stream().collect(Collectors.groupingBy(KnowledgePointDTO::getClusterId));
List<ClusterCallbackDTO.ClusterItem> clusters = Lists.newArrayList();
collect.forEach((key, value) -> {
ClusterCallbackDTO.ClusterItem clusterItem = new ClusterCallbackDTO.ClusterItem();
clusterItem.setTopic(value.stream().map(KnowledgePointDTO::getId).map(String::valueOf).collect(Collectors.joining(",")));
clusterItem.setAtomIdList(value.stream().map(KnowledgePointDTO::getId).collect(Collectors.toList()));
clusters.add(clusterItem);
});
algorithmApplicationService.saveCluster(taskId , clusters);
log.info(">>> [任务初始化] 任务[{}]知识点已成功送往算法端,当前异步线程任务结束", taskId); log.info(">>> [任务初始化] 任务[{}]知识点已成功送往算法端,当前异步线程任务结束", taskId);
} else { } else {
log.info(">>> [任务初始化] 任务[{}]知识点集合为空", taskId); log.info(">>> [任务初始化] 任务[{}]知识点集合为空", taskId);

Loading…
Cancel
Save