42 changed files with 551 additions and 69 deletions
@ -1,7 +1,12 @@ |
|||||
package com.project.information.domain.dto; |
package com.project.information.domain.dto; |
||||
|
|
||||
|
import com.project.base.domain.dto.BaseDTO; |
||||
import lombok.Data; |
import lombok.Data; |
||||
|
|
||||
@Data |
@Data |
||||
public class KnowledgePointDTO { |
public class KnowledgePointDTO extends BaseDTO { |
||||
|
private Long id; |
||||
|
|
||||
|
private String content; |
||||
|
|
||||
} |
} |
||||
|
|||||
@ -0,0 +1,24 @@ |
|||||
|
package com.project.interaction.application; |
||||
|
|
||||
|
import com.project.information.domain.dto.KnowledgePointDTO; |
||||
|
import com.project.interaction.domain.dto.ClusterCallbackDTO; |
||||
|
import com.project.question.domain.dto.TaskKnowledgePointDTO; |
||||
|
import com.project.task.domain.enums.QuestionTypeEnum; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface AlgorithmApplicationService { |
||||
|
|
||||
|
/** |
||||
|
* 知识点分簇 |
||||
|
* @param taskId |
||||
|
* @param kpList |
||||
|
*/ |
||||
|
|
||||
|
void postToClustering(Long taskId, List<KnowledgePointDTO> kpList); |
||||
|
|
||||
|
|
||||
|
void generateQuestion(List<TaskKnowledgePointDTO> dtoList , QuestionTypeEnum questionType , int num); |
||||
|
|
||||
|
void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception; |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
package com.project.interaction.application.impl; |
||||
|
|
||||
|
import com.project.information.domain.dto.KnowledgePointDTO; |
||||
|
import com.project.interaction.application.AlgorithmApplicationService; |
||||
|
import com.project.interaction.domain.dto.ClusterCallbackDTO; |
||||
|
import com.project.interaction.domain.service.PostToClusteringDomainService; |
||||
|
import com.project.interaction.domain.service.SaveClusterDomainService; |
||||
|
import com.project.question.domain.dto.TaskKnowledgePointDTO; |
||||
|
import com.project.question.domain.enums.QuestionSourceTypeEnum; |
||||
|
import com.project.task.domain.enums.QuestionTypeEnum; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
@Service |
||||
|
public class AlgorithmApplicationServiceImpl implements AlgorithmApplicationService { |
||||
|
@Autowired |
||||
|
private PostToClusteringDomainService postToClusteringDomainService; |
||||
|
|
||||
|
@Autowired |
||||
|
private SaveClusterDomainService saveClusterDomainService; |
||||
|
@Override |
||||
|
public void postToClustering(Long taskId, List<KnowledgePointDTO> kpList) { |
||||
|
postToClusteringDomainService.postToClustering(taskId , kpList); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public void generateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num) { |
||||
|
System.out.println(String.format("<=======生成了%d道%s, 结合了知识点【%s】属于%s=======>" , |
||||
|
num , |
||||
|
questionType.getDescription() , |
||||
|
String.join("," , dtoList.stream().map(dto -> dto.getId().toString()).toList()) , |
||||
|
dtoList.size() > 1 ? QuestionSourceTypeEnum.Multi_Concept.getDesc() : QuestionSourceTypeEnum.Single_Concept.getDesc())); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception { |
||||
|
try { |
||||
|
saveClusterDomainService.saveCluster(taskId , clusters); |
||||
|
} catch (Exception e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
package com.project.interaction.controller; |
||||
|
|
||||
|
|
||||
|
|
||||
|
import com.project.base.domain.result.Result; |
||||
|
import com.project.interaction.application.AlgorithmApplicationService; |
||||
|
import com.project.interaction.domain.dto.ClusterCallbackDTO; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/api/interaction") |
||||
|
public class InteractionController { |
||||
|
|
||||
|
@Autowired |
||||
|
private AlgorithmApplicationService algorithmApplicationService; |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 手动触发同步接口 |
||||
|
* 强刷:/sync/all?force=true |
||||
|
*/ |
||||
|
@PostMapping("/saveCluster") |
||||
|
public Result<String> saveCluster(ClusterCallbackDTO dto) throws Exception{ |
||||
|
algorithmApplicationService.saveCluster(dto.getTaskId(), dto.getClusters()); |
||||
|
return Result.success("保存成功"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
package com.project.interaction.domain.dto; |
||||
|
|
||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
|
import com.fasterxml.jackson.core.type.TypeReference; |
||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
|
import com.project.base.domain.exception.BusinessErrorException; |
||||
|
import com.project.information.domain.param.FileCheckItem; |
||||
|
import lombok.Data; |
||||
|
import org.springframework.util.StringUtils; |
||||
|
|
||||
|
import java.util.Collections; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Data |
||||
|
public class ClusterCallbackDTO { |
||||
|
private Long taskId; |
||||
|
|
||||
|
private String clusters; |
||||
|
@Data |
||||
|
public static class ClusterItem { |
||||
|
private String topic; |
||||
|
private List<Long> atomIdList; |
||||
|
} |
||||
|
|
||||
|
// 手动解析为List的方法
|
||||
|
public List<ClusterItem> getClusters() { |
||||
|
if (StringUtils.isEmpty(clusters)) { |
||||
|
return Collections.emptyList(); |
||||
|
} |
||||
|
try { |
||||
|
return new ObjectMapper().readValue( |
||||
|
clusters, |
||||
|
new TypeReference<List<ClusterItem>>() {}); |
||||
|
} catch (JsonProcessingException e) { |
||||
|
// 处理解析异常
|
||||
|
throw new BusinessErrorException("Json解析失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -1,4 +1,4 @@ |
|||||
package com.project.interactor.domain.dto; |
package com.project.interaction.domain.dto; |
||||
|
|
||||
|
|
||||
import com.project.information.domain.dto.KnowledgePointDTO; |
import com.project.information.domain.dto.KnowledgePointDTO; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.project.interactor.domain.dto; |
package com.project.interaction.domain.dto; |
||||
|
|
||||
import lombok.Data; |
import lombok.Data; |
||||
|
|
||||
@ -1,4 +1,4 @@ |
|||||
package com.project.interactor.domain.service; |
package com.project.interaction.domain.service; |
||||
|
|
||||
import com.project.information.domain.dto.KnowledgePointDTO; |
import com.project.information.domain.dto.KnowledgePointDTO; |
||||
|
|
||||
@ -0,0 +1,9 @@ |
|||||
|
package com.project.interaction.domain.service; |
||||
|
|
||||
|
import com.project.interaction.domain.dto.ClusterCallbackDTO; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface SaveClusterDomainService { |
||||
|
void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception; |
||||
|
} |
||||
@ -1,9 +1,9 @@ |
|||||
package com.project.interactor.domain.service.impl; |
package com.project.interaction.domain.service.impl; |
||||
|
|
||||
import com.project.information.domain.dto.KnowledgePointDTO; |
import com.project.information.domain.dto.KnowledgePointDTO; |
||||
import com.project.interactor.domain.dto.ClusterQueryDTO; |
import com.project.interaction.domain.dto.ClusterQueryDTO; |
||||
import com.project.interactor.domain.dto.ClusterResultDTO; |
import com.project.interaction.domain.dto.ClusterResultDTO; |
||||
import com.project.interactor.domain.service.PostToClusteringDomainService; |
import com.project.interaction.domain.service.PostToClusteringDomainService; |
||||
import jakarta.annotation.Resource; |
import jakarta.annotation.Resource; |
||||
import lombok.extern.slf4j.Slf4j; |
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Value; |
import org.springframework.beans.factory.annotation.Value; |
||||
@ -0,0 +1,90 @@ |
|||||
|
package com.project.interaction.domain.service.impl; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
|
import com.project.information.domain.dto.KnowledgePointDTO; |
||||
|
import com.project.information.domain.entity.KnowledgePointEntity; |
||||
|
import com.project.information.domain.service.KnowledgePointBaseService; |
||||
|
import com.project.interaction.domain.dto.ClusterCallbackDTO; |
||||
|
import com.project.interaction.domain.service.SaveClusterDomainService; |
||||
|
import com.project.question.domain.entity.TaskKnowledgeClusterEntity; |
||||
|
import com.project.question.domain.entity.TaskKnowledgePointEntity; |
||||
|
import com.project.question.domain.enums.QuestionSourceTypeEnum; |
||||
|
import com.project.question.domain.service.GenerateQuestionDomainService; |
||||
|
import com.project.question.domain.service.TaskKnowledgeClusterBaseService; |
||||
|
import com.project.question.domain.service.TaskKnowledgePointBaseService; |
||||
|
import com.project.task.domain.entity.TaskEntity; |
||||
|
import com.project.task.domain.enums.QuestionTypeEnum; |
||||
|
import com.project.task.domain.service.TaskBaseService; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Objects; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
public class SaveClusterDomainServiceImpl implements SaveClusterDomainService { |
||||
|
@Autowired |
||||
|
private TaskBaseService taskBaseService; |
||||
|
|
||||
|
@Autowired |
||||
|
private TaskKnowledgeClusterBaseService taskKnowledgeClusterBaseService; |
||||
|
|
||||
|
@Autowired |
||||
|
private TaskKnowledgePointBaseService taskKnowledgePointBaseService; |
||||
|
|
||||
|
|
||||
|
@Autowired |
||||
|
private KnowledgePointBaseService knowledgePointBaseService; |
||||
|
|
||||
|
@Autowired |
||||
|
private GenerateQuestionDomainService generateQuestionDomainService; |
||||
|
|
||||
|
@Override |
||||
|
public void saveCluster(Long taskId, List<ClusterCallbackDTO.ClusterItem> clusters) throws Exception { |
||||
|
TaskEntity taskEntity = taskBaseService.getById(taskId); |
||||
|
int u = 0; |
||||
|
if (Objects.isNull(taskEntity) || Objects.isNull(taskEntity.getParticipantNum()) || taskEntity.getParticipantNum() <= 0) { |
||||
|
return; |
||||
|
} |
||||
|
u = taskEntity.getParticipantNum(); |
||||
|
log.info(">>> [回调处理] 开始持久化任务[{}]聚类结果,计划人数U={}", taskId, u); |
||||
|
for (ClusterCallbackDTO.ClusterItem cluster : clusters) { |
||||
|
// 1.保存任务知识点簇
|
||||
|
TaskKnowledgeClusterEntity clusterEntity = new TaskKnowledgeClusterEntity(); |
||||
|
clusterEntity.setTaskId(taskId); |
||||
|
clusterEntity.setClusterTopic(cluster.getTopic()); |
||||
|
clusterEntity.setClusterSize(cluster.getAtomIdList().size()); |
||||
|
taskKnowledgeClusterBaseService.save(clusterEntity); |
||||
|
// 2.提取该簇下的原子知识点,并保存任务知识点
|
||||
|
List<KnowledgePointDTO> kpList = knowledgePointBaseService.list(new LambdaQueryWrapper<KnowledgePointEntity>() |
||||
|
.in(KnowledgePointEntity::getId, cluster.getAtomIdList())) |
||||
|
.stream().map(entity -> entity.toDTO(KnowledgePointDTO::new)).toList(); |
||||
|
|
||||
|
List<TaskKnowledgePointEntity> taskKpList = kpList.stream().map(atomKp -> { |
||||
|
TaskKnowledgePointEntity taskKp = new TaskKnowledgePointEntity(); |
||||
|
taskKp.setTaskId(taskId); |
||||
|
taskKp.setClusterId(clusterEntity.getId()); |
||||
|
taskKp.setAtomId(atomKp.getId()); |
||||
|
taskKp.setContent(atomKp.getContent()); |
||||
|
return taskKp; |
||||
|
}).toList(); |
||||
|
// 批量插入
|
||||
|
taskKnowledgePointBaseService.saveBatch(taskKpList); |
||||
|
// 生成目标量
|
||||
|
int targetNum = (int) Math.ceil(1.2 * u); |
||||
|
for (TaskKnowledgePointEntity kp : taskKpList) { |
||||
|
// 调用题目生成方法
|
||||
|
for (QuestionTypeEnum value : QuestionTypeEnum.values()) { |
||||
|
generateQuestionDomainService.produce(kp.getId(), value , QuestionSourceTypeEnum.Single_Concept , targetNum); |
||||
|
} |
||||
|
} |
||||
|
if (clusterEntity.getClusterSize() > 1) { |
||||
|
// 簇生成目标量
|
||||
|
int clusterTargetNum = (int) Math.ceil(1.2 * u * clusterEntity.getClusterSize()); |
||||
|
generateQuestionDomainService.produce(clusterEntity.getId(), QuestionTypeEnum.MULTIPLE_CHOICE ,QuestionSourceTypeEnum.Multi_Concept , clusterTargetNum); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,10 +0,0 @@ |
|||||
package com.project.interactor.application; |
|
||||
|
|
||||
import com.project.information.domain.dto.KnowledgePointDTO; |
|
||||
|
|
||||
import java.util.List; |
|
||||
|
|
||||
public interface AlgorithmApplicationService { |
|
||||
|
|
||||
void postToClustering(Long taskId, List<KnowledgePointDTO> kpList); |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
package com.project.interactor.application.impl; |
|
||||
|
|
||||
import com.project.information.domain.dto.KnowledgePointDTO; |
|
||||
import com.project.interactor.application.AlgorithmApplicationService; |
|
||||
import com.project.interactor.domain.service.PostToClusteringDomainService; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
import java.util.List; |
|
||||
|
|
||||
@Service |
|
||||
public class AlgorithmApplicationServiceImpl implements AlgorithmApplicationService { |
|
||||
@Autowired |
|
||||
private PostToClusteringDomainService postToClusteringDomainService; |
|
||||
@Override |
|
||||
public void postToClustering(Long taskId, List<KnowledgePointDTO> kpList) { |
|
||||
postToClusteringDomainService.postToClustering(taskId , kpList); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,4 @@ |
|||||
|
package com.project.question.application; |
||||
|
|
||||
|
public interface QuestionApplicationService { |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
package com.project.question.application; |
||||
|
|
||||
|
public interface TaskKnowledgeClusterApplicationService { |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.project.question.application.impl; |
||||
|
|
||||
|
import com.project.question.application.QuestionApplicationService; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
@Service |
||||
|
public class QuestionApplicationServiceImpl implements QuestionApplicationService { |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.project.question.application.impl; |
||||
|
|
||||
|
import com.project.question.application.TaskKnowledgeClusterApplicationService; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
@Service |
||||
|
public class TaskKnowledgeClusterApplicationServiceImpl implements TaskKnowledgeClusterApplicationService { |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
package com.project.question.config; |
||||
|
|
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
||||
|
|
||||
|
import java.util.concurrent.Executor; |
||||
|
import java.util.concurrent.ThreadPoolExecutor; |
||||
|
|
||||
|
@Configuration |
||||
|
public class QuestionAsyncThreadPoolConfig { |
||||
|
|
||||
|
/** |
||||
|
* 题目生成池 (高并发、IO密集型) |
||||
|
* 核心:允许并行处理不同的知识点 |
||||
|
*/ |
||||
|
@Bean(name = "questionGenExecutor") |
||||
|
public Executor questionGenExecutor() { |
||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); |
||||
|
// 允许 5-10 个知识点同时进行 AI 出题
|
||||
|
executor.setCorePoolSize(5); |
||||
|
executor.setMaxPoolSize(10); |
||||
|
executor.setQueueCapacity(500); |
||||
|
executor.setThreadNamePrefix("question-gen-"); |
||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); |
||||
|
executor.initialize(); |
||||
|
return executor; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
package com.project.question.domain.dto; |
||||
|
|
||||
|
import com.project.base.domain.dto.BaseDTO; |
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class QuestionDTO extends BaseDTO { |
||||
|
private Long id; |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
package com.project.question.domain.dto; |
||||
|
|
||||
|
import com.project.base.domain.dto.BaseDTO; |
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class TaskKnowledgePointDTO extends BaseDTO { |
||||
|
private Long id; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
package com.project.question.domain.entity; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||
|
import com.baomidou.mybatisplus.annotation.TableField; |
||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||
|
import com.project.base.domain.entity.BaseEntity; |
||||
|
import jakarta.persistence.*; |
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
import org.hibernate.annotations.Comment; |
||||
|
|
||||
|
@Data |
||||
|
@Entity |
||||
|
@Table(name = "evaluator_question_kp_rel", indexes = { |
||||
|
@Index(name = "idx_kp_id", columnList = "kp_id"), |
||||
|
@Index(name = "idx_question_id", columnList = "question_id"), |
||||
|
@Index(name = "idx_task_id", columnList = "task_id") |
||||
|
}) |
||||
|
@TableName("evaluator_question_kp_rel") |
||||
|
@EqualsAndHashCode(callSuper = true) |
||||
|
public class QuestionKpRelEntity extends BaseEntity { |
||||
|
@TableId(type = IdType.ASSIGN_ID) |
||||
|
@Id |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "question_id") |
||||
|
@Comment("题目ID") |
||||
|
@TableField("question_id") |
||||
|
private Long questionId; |
||||
|
|
||||
|
@Column(name = "kp_id") |
||||
|
@Comment("考试任务知识点ID") |
||||
|
private Long kpId; |
||||
|
|
||||
|
@Column(name = "cluster_id") |
||||
|
@TableField("cluster_id") |
||||
|
@Comment("所属知识点簇ID") |
||||
|
private Long clusterId; |
||||
|
|
||||
|
@Column(name = "task_id") |
||||
|
@Comment("所属考试任务ID (冗余字段,方便清理及统计)") |
||||
|
@TableField("task_id") |
||||
|
private Long taskId; |
||||
|
|
||||
|
@Column(name = "question_type") |
||||
|
@TableField("question_type") |
||||
|
@Comment("题目类型") |
||||
|
private Integer questionType; |
||||
|
} |
||||
@ -1,4 +1,4 @@ |
|||||
package com.project.task.domain.entity; |
package com.project.question.domain.entity; |
||||
|
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
import com.baomidou.mybatisplus.annotation.TableField; |
||||
@ -1,4 +1,4 @@ |
|||||
package com.project.task.domain.entity; |
package com.project.question.domain.entity; |
||||
|
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
import com.baomidou.mybatisplus.annotation.TableField; |
||||
@ -0,0 +1,9 @@ |
|||||
|
package com.project.question.domain.service; |
||||
|
|
||||
|
import com.project.question.domain.enums.QuestionSourceTypeEnum; |
||||
|
import com.project.task.domain.enums.QuestionTypeEnum; |
||||
|
|
||||
|
public interface GenerateQuestionDomainService { |
||||
|
|
||||
|
void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount); |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
package com.project.question.domain.service; |
||||
|
|
||||
|
import com.project.question.domain.dto.TaskKnowledgePointDTO; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface SamplingStrategy { |
||||
|
|
||||
|
List<TaskKnowledgePointDTO> sample(Long clusterId); |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
package com.project.question.domain.service; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||
|
import com.project.question.domain.entity.TaskKnowledgeClusterEntity; |
||||
|
|
||||
|
public interface TaskKnowledgeClusterBaseService extends IService<TaskKnowledgeClusterEntity> { |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
package com.project.question.domain.service; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||
|
import com.project.question.domain.entity.TaskKnowledgePointEntity; |
||||
|
|
||||
|
public interface TaskKnowledgePointBaseService extends IService<TaskKnowledgePointEntity> { |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
package com.project.question.domain.service.impl; |
||||
|
|
||||
|
import com.project.question.domain.dto.TaskKnowledgePointDTO; |
||||
|
import com.project.question.domain.enums.QuestionSourceTypeEnum; |
||||
|
import com.project.question.domain.service.GenerateQuestionDomainService; |
||||
|
import com.project.question.domain.service.SamplingStrategy; |
||||
|
import com.project.question.domain.service.TaskKnowledgePointBaseService; |
||||
|
import com.project.task.domain.enums.QuestionTypeEnum; |
||||
|
import jakarta.annotation.Resource; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.Collections; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.CompletableFuture; |
||||
|
import java.util.concurrent.Executor; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
public class GenerateQuestionDomainServiceImpl implements GenerateQuestionDomainService { |
||||
|
|
||||
|
@Resource(name = "questionGenExecutor") |
||||
|
private Executor questionGenExecutor; |
||||
|
|
||||
|
@Autowired |
||||
|
private TaskKnowledgePointBaseService taskKnowledgePointBaseService; |
||||
|
|
||||
|
@Autowired |
||||
|
private SamplingStrategy samplingStrategy; |
||||
|
|
||||
|
@Override |
||||
|
public void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount) { |
||||
|
if (needCount <= 0) { |
||||
|
return; |
||||
|
} |
||||
|
CompletableFuture.runAsync(() -> { |
||||
|
log.info(">>> [题库预生成] 准备生产任务: SourceID={}, Type={}, Count={}", sourceId, sourceType, needCount); |
||||
|
|
||||
|
processBatch(sourceId,questionType , sourceType , needCount); |
||||
|
|
||||
|
}, questionGenExecutor); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private void processBatch(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int count) { |
||||
|
// 如果是簇复合题,执行随机采样 2-4 个知识点
|
||||
|
List<TaskKnowledgePointDTO> kpList; |
||||
|
if (QuestionSourceTypeEnum.Multi_Concept.equals(sourceType)) { |
||||
|
kpList = samplingStrategy.sample(sourceId); // 获取随机组合的 KPs
|
||||
|
} else { |
||||
|
// 单 KP 逻辑:直接查出对应 KP 的内容
|
||||
|
kpList = Collections.singletonList(taskKnowledgePointBaseService.getById(sourceId) |
||||
|
.toDTO(TaskKnowledgePointDTO::new)); |
||||
|
} |
||||
|
|
||||
|
// 2. 调用大模型并保存题目及其多对多关系 (QuestionPool & QuestionKpRel)
|
||||
|
//
|
||||
|
//aiLlmService.generateAndBatchSave(context, sourceType, count);
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
package com.project.question.domain.service.impl; |
||||
|
|
||||
|
import cn.hutool.core.collection.CollUtil; |
||||
|
import cn.hutool.core.util.RandomUtil; |
||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
|
import com.project.question.domain.dto.TaskKnowledgePointDTO; |
||||
|
import com.project.question.domain.entity.TaskKnowledgePointEntity; |
||||
|
import com.project.question.domain.service.SamplingStrategy; |
||||
|
import com.project.question.domain.service.TaskKnowledgePointBaseService; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.Collections; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Service |
||||
|
public class RandomSamplingStrategy implements SamplingStrategy { |
||||
|
@Autowired |
||||
|
private TaskKnowledgePointBaseService taskKnowledgePointBaseService; |
||||
|
|
||||
|
@Override |
||||
|
public List<TaskKnowledgePointDTO> sample(Long clusterId) { |
||||
|
List<TaskKnowledgePointDTO> dtoList = taskKnowledgePointBaseService.list(new LambdaQueryWrapper<TaskKnowledgePointEntity>() |
||||
|
.eq(TaskKnowledgePointEntity::getClusterId, clusterId)) |
||||
|
.stream().map(entity -> entity.toDTO(TaskKnowledgePointDTO::new)).toList(); |
||||
|
|
||||
|
if (CollUtil.isEmpty(dtoList)) { |
||||
|
return Collections.emptyList(); |
||||
|
} |
||||
|
// 确定采样数量:2 到 4 之间的随机数
|
||||
|
int totalSize = dtoList.size(); |
||||
|
int min = Math.min(totalSize, 2); |
||||
|
int max = Math.min(totalSize, 4); |
||||
|
int targetSampleSize = (min == max) ? min : RandomUtil.randomInt(min, max + 1); |
||||
|
Collections.shuffle(dtoList); |
||||
|
|
||||
|
return dtoList.subList(0 , targetSampleSize); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
package com.project.question.domain.service.impl; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
|
import com.project.question.domain.entity.TaskKnowledgeClusterEntity; |
||||
|
import com.project.question.domain.service.TaskKnowledgeClusterBaseService; |
||||
|
import com.project.question.mapper.TaskKnowledgeClusterMapper; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
|
||||
|
@Service |
||||
|
public class TaskKnowledgeClusterBaseServiceImpl extends ServiceImpl<TaskKnowledgeClusterMapper, TaskKnowledgeClusterEntity> implements TaskKnowledgeClusterBaseService { |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
package com.project.question.domain.service.impl; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
|
import com.project.question.domain.entity.TaskKnowledgePointEntity; |
||||
|
import com.project.question.domain.service.TaskKnowledgePointBaseService; |
||||
|
import com.project.question.mapper.TaskKnowledgePointMapper; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
|
||||
|
@Service |
||||
|
public class TaskKnowledgePointBaseServiceImpl extends ServiceImpl<TaskKnowledgePointMapper, TaskKnowledgePointEntity> implements TaskKnowledgePointBaseService { |
||||
|
} |
||||
@ -1,6 +1,6 @@ |
|||||
package com.project.task.mapper; |
package com.project.question.mapper; |
||||
|
|
||||
import com.project.task.domain.entity.TaskKnowledgeClusterEntity; |
import com.project.question.domain.entity.TaskKnowledgeClusterEntity; |
||||
import org.apache.ibatis.annotations.Mapper; |
import org.apache.ibatis.annotations.Mapper; |
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
|
|
||||
@ -1,7 +1,7 @@ |
|||||
package com.project.task.mapper; |
package com.project.question.mapper; |
||||
|
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import com.project.task.domain.entity.TaskKnowledgePointEntity; |
import com.project.question.domain.entity.TaskKnowledgePointEntity; |
||||
import org.apache.ibatis.annotations.Mapper; |
import org.apache.ibatis.annotations.Mapper; |
||||
|
|
||||
@Mapper |
@Mapper |
||||
Loading…
Reference in new issue