优化接口响应速度
This commit is contained in:
@@ -2,6 +2,7 @@ package org.jiayunet.service;
|
|||||||
|
|
||||||
import org.jiayunet.ai.AiChatAbility;
|
import org.jiayunet.ai.AiChatAbility;
|
||||||
import org.jiayunet.ai.AiResponseCleanTool;
|
import org.jiayunet.ai.AiResponseCleanTool;
|
||||||
|
import org.springframework.util.StopWatch;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -591,13 +592,17 @@ public class JobService {
|
|||||||
* <p>1. 查求职意向构造筛选条件(无意向则不设条件) 2. 排除已推荐的+已投递的 3. 取前35条候选 4. AI精筛返回8-10个</p>
|
* <p>1. 查求职意向构造筛选条件(无意向则不设条件) 2. 排除已推荐的+已投递的 3. 取前35条候选 4. AI精筛返回8-10个</p>
|
||||||
*/
|
*/
|
||||||
public JobAgentRecommendDto recommendJobs(JobAgentRecommendParam param, Long userId) {
|
public JobAgentRecommendDto recommendJobs(JobAgentRecommendParam param, Long userId) {
|
||||||
|
StopWatch sw = new StopWatch("recommendJobs");
|
||||||
|
|
||||||
// 1. 查求职意向
|
// 1. 查求职意向
|
||||||
|
sw.start("查求职意向");
|
||||||
UserJobIntention intention = userJobIntentionMapper.selectOne(new LambdaQueryWrapper<UserJobIntention>().eq(UserJobIntention::getUserId, userId));
|
UserJobIntention intention = userJobIntentionMapper.selectOne(new LambdaQueryWrapper<UserJobIntention>().eq(UserJobIntention::getUserId, userId));
|
||||||
|
sw.stop();
|
||||||
|
|
||||||
// 2. 构造查询参数
|
// 2. 构造查询参数
|
||||||
JobQueryParam queryParam = new JobQueryParam();
|
JobQueryParam queryParam = new JobQueryParam();
|
||||||
queryParam.setPageNum(1);
|
queryParam.setPageNum(1);
|
||||||
queryParam.setPageSize(35);
|
queryParam.setPageSize(60);
|
||||||
if (intention != null) {
|
if (intention != null) {
|
||||||
queryParam.setCategoryIds(intention.getCategoryIds());
|
queryParam.setCategoryIds(intention.getCategoryIds());
|
||||||
queryParam.setRegionCodes(intention.getRegionCodes());
|
queryParam.setRegionCodes(intention.getRegionCodes());
|
||||||
@@ -610,12 +615,16 @@ public class JobService {
|
|||||||
if (param.getExcludeJobIds() != null) {
|
if (param.getExcludeJobIds() != null) {
|
||||||
excludeIds.addAll(param.getExcludeJobIds());
|
excludeIds.addAll(param.getExcludeJobIds());
|
||||||
}
|
}
|
||||||
|
sw.start("查投递记录");
|
||||||
List<UserJobApplication> applications = userJobApplicationMapper.selectList(new LambdaQueryWrapper<UserJobApplication>().eq(UserJobApplication::getUserId, userId));
|
List<UserJobApplication> applications = userJobApplicationMapper.selectList(new LambdaQueryWrapper<UserJobApplication>().eq(UserJobApplication::getUserId, userId));
|
||||||
|
sw.stop();
|
||||||
applications.forEach(a -> excludeIds.add(a.getJobId()));
|
applications.forEach(a -> excludeIds.add(a.getJobId()));
|
||||||
queryParam.setExcludeJobIds(excludeIds);
|
queryParam.setExcludeJobIds(excludeIds);
|
||||||
|
|
||||||
// 4. 查询候选岗位(完整列表数据)
|
// 4. 查询候选岗位(完整列表数据)
|
||||||
|
sw.start("查候选岗位");
|
||||||
PageResult<JobDto> candidates = listJobs(queryParam, userId);
|
PageResult<JobDto> candidates = listJobs(queryParam, userId);
|
||||||
|
sw.stop();
|
||||||
if (candidates.getList().isEmpty()) {
|
if (candidates.getList().isEmpty()) {
|
||||||
JobAgentRecommendDto dto = new JobAgentRecommendDto();
|
JobAgentRecommendDto dto = new JobAgentRecommendDto();
|
||||||
dto.setSummary("暂无合适的岗位推荐");
|
dto.setSummary("暂无合适的岗位推荐");
|
||||||
@@ -624,18 +633,28 @@ public class JobService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. 批量查岗位详情(title + description + requirement)
|
// 5. 批量查岗位详情(title + description + requirement)
|
||||||
|
sw.start("查岗位详情");
|
||||||
List<Long> candidateJobIds = candidates.getList().stream().map(JobDto::getId).collect(Collectors.toList());
|
List<Long> candidateJobIds = candidates.getList().stream().map(JobDto::getId).collect(Collectors.toList());
|
||||||
List<Job> jobDetails = jobMapper.selectList(new LambdaQueryWrapper<Job>().in(Job::getId, candidateJobIds).select(Job::getId, Job::getTitle, Job::getDescription, Job::getRequirement));
|
List<Job> jobDetails = jobMapper.selectList(new LambdaQueryWrapper<Job>().in(Job::getId, candidateJobIds).select(Job::getId, Job::getTitle, Job::getDescription, Job::getRequirement));
|
||||||
Map<Long, Job> jobDetailMap = jobDetails.stream().collect(Collectors.toMap(Job::getId, j -> j));
|
Map<Long, Job> jobDetailMap = jobDetails.stream().collect(Collectors.toMap(Job::getId, j -> j));
|
||||||
|
sw.stop();
|
||||||
|
|
||||||
// 6. 构造候选岗位映射(供AI返回后过滤使用)
|
// 6. 构造别名映射(短序号 → 真实ID)和候选岗位映射
|
||||||
Map<Long, JobDto> candidateMap = candidates.getList().stream().collect(Collectors.toMap(JobDto::getId, d -> d));
|
Map<Integer, Long> aliasToRealId = new HashMap<>();
|
||||||
|
Map<Long, JobDto> candidateMap = new HashMap<>();
|
||||||
|
int seq = 1;
|
||||||
|
for (JobDto dto : candidates.getList()) {
|
||||||
|
aliasToRealId.put(seq, dto.getId());
|
||||||
|
candidateMap.put(dto.getId(), dto);
|
||||||
|
seq++;
|
||||||
|
}
|
||||||
|
|
||||||
// 7. 构造AI输入
|
// 7. 构造AI输入(用短序号替代19位雪花ID,减少token消耗)
|
||||||
StringBuilder jobInfo = new StringBuilder();
|
StringBuilder jobInfo = new StringBuilder();
|
||||||
|
seq = 1;
|
||||||
for (JobDto dto : candidates.getList()) {
|
for (JobDto dto : candidates.getList()) {
|
||||||
Job detail = jobDetailMap.get(dto.getId());
|
Job detail = jobDetailMap.get(dto.getId());
|
||||||
jobInfo.append("ID:").append(dto.getId())
|
jobInfo.append("ID:").append(seq++)
|
||||||
.append("\n标题:").append(dto.getTitle())
|
.append("\n标题:").append(dto.getTitle())
|
||||||
.append("\n公司:").append(dto.getCompanyName())
|
.append("\n公司:").append(dto.getCompanyName())
|
||||||
.append("\n岗位职责:").append(detail != null ? detail.getDescription() : "")
|
.append("\n岗位职责:").append(detail != null ? detail.getDescription() : "")
|
||||||
@@ -646,25 +665,29 @@ public class JobService {
|
|||||||
String preferenceInfo = param.getPreference() != null ? param.getPreference() : "无特殊偏好";
|
String preferenceInfo = param.getPreference() != null ? param.getPreference() : "无特殊偏好";
|
||||||
|
|
||||||
String systemPrompt = "你是一个求职推荐助手。根据用户的偏好,从候选岗位中选出8-10个最合适的岗位。" +
|
String systemPrompt = "你是一个求职推荐助手。根据用户的偏好,从候选岗位中选出8-10个最合适的岗位。" +
|
||||||
"返回JSON格式:{\"summary\":\"推荐说明(20字以内)\",\"jobIds\":[岗位ID列表]}。" +
|
"返回JSON格式:{\"summary\":\"推荐说明(14字以内)\",\"jobIds\":[岗位ID列表]}。" +
|
||||||
"只返回JSON,不要其他内容。";
|
"只返回JSON,不要其他内容。";
|
||||||
String userMessage = "【用户偏好】\n" + preferenceInfo + "\n\n【候选岗位】\n" + jobInfo;
|
String userMessage = "【用户偏好】\n" + preferenceInfo + "\n\n【候选岗位】\n" + jobInfo;
|
||||||
|
|
||||||
// 8. 调用AI
|
// 8. 调用AI
|
||||||
|
sw.start("AI调用");
|
||||||
String aiResponse = aiChatAbility.chat("job-recommend", systemPrompt, userMessage);
|
String aiResponse = aiChatAbility.chat("job-recommend", systemPrompt, userMessage);
|
||||||
String json = AiResponseCleanTool.clean(aiResponse);
|
String json = AiResponseCleanTool.clean(aiResponse);
|
||||||
|
sw.stop();
|
||||||
|
|
||||||
// 9. 解析AI返回,过滤出选中的岗位
|
log.info("recommendJobs耗时统计:\n{}", sw.prettyPrint());
|
||||||
|
|
||||||
|
// 9. 解析AI返回,别名映射回真实ID,过滤出选中的岗位
|
||||||
try {
|
try {
|
||||||
JsonNode root = HttpTool.objectMapper.readTree(json);
|
JsonNode root = HttpTool.objectMapper.readTree(json);
|
||||||
String summary = root.path("summary").asText("为你精选了合适的岗位");
|
String summary = root.path("summary").asText("为你精选了合适的岗位");
|
||||||
List<Long> selectedIds = new ArrayList<>();
|
List<Long> selectedRealIds = new ArrayList<>();
|
||||||
root.path("jobIds").forEach(node -> selectedIds.add(node.asLong()));
|
root.path("jobIds").forEach(node -> {
|
||||||
|
Long realId = aliasToRealId.get(node.asInt());
|
||||||
|
if (realId != null) selectedRealIds.add(realId);
|
||||||
|
});
|
||||||
|
|
||||||
List<JobDto> selectedJobs = selectedIds.stream()
|
List<JobDto> selectedJobs = selectedRealIds.stream().map(candidateMap::get).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
.map(candidateMap::get)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
JobAgentRecommendDto result = new JobAgentRecommendDto();
|
JobAgentRecommendDto result = new JobAgentRecommendDto();
|
||||||
result.setSummary(summary);
|
result.setSummary(summary);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ app:
|
|||||||
job-recommend:
|
job-recommend:
|
||||||
base-url: ${AI_BASE_URL:https://ark.cn-beijing.volces.com/api/v3}
|
base-url: ${AI_BASE_URL:https://ark.cn-beijing.volces.com/api/v3}
|
||||||
api-key: ${AI_API_KEY:fd065993-bee2-4f31-8bf2-56d5d3012c02}
|
api-key: ${AI_API_KEY:fd065993-bee2-4f31-8bf2-56d5d3012c02}
|
||||||
model: ${AI_MODEL:doubao-1-5-pro-32k-250115}
|
model: ${AI_MODEL:doubao-1-5-lite-32k-250115}
|
||||||
|
|
||||||
|
|
||||||
# 岗位清洗配置
|
# 岗位清洗配置
|
||||||
|
|||||||
Reference in New Issue
Block a user