简历解析业务逻辑处理
This commit is contained in:
@@ -186,7 +186,8 @@ public class ChatWebSocketMultipleHandler {
|
|||||||
mapEntity.put("content", StrUtil.format(content, cacheResultText));
|
mapEntity.put("content", StrUtil.format(content, cacheResultText));
|
||||||
cacheMsgMapData1.put(session.getId(), JSONUtil.toJsonStr(list));
|
cacheMsgMapData1.put(session.getId(), JSONUtil.toJsonStr(list));
|
||||||
}
|
}
|
||||||
|
Long replyNums = cacheQuestionNum.get(session.getId());
|
||||||
|
cacheQuestionNum.put(session.getId(), replyNums+1);
|
||||||
//验证是否结速
|
//验证是否结速
|
||||||
Boolean isEndFlag = checkIsEnd(session);
|
Boolean isEndFlag = checkIsEnd(session);
|
||||||
if(isEndFlag){
|
if(isEndFlag){
|
||||||
@@ -633,6 +634,7 @@ public class ChatWebSocketMultipleHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证面试是否结束
|
* 验证面试是否结束
|
||||||
|
* 记录回答问题的次数
|
||||||
* @param session
|
* @param session
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -640,7 +642,8 @@ public class ChatWebSocketMultipleHandler {
|
|||||||
Long replyNums = cacheQuestionNum.get(session.getId());
|
Long replyNums = cacheQuestionNum.get(session.getId());
|
||||||
//回答次数大于等于5就直接结束面试
|
//回答次数大于等于5就直接结束面试
|
||||||
Boolean flag = true;
|
Boolean flag = true;
|
||||||
if(replyNums >= 5){
|
if(replyNums.longValue() >= 5L){
|
||||||
|
flag = false;
|
||||||
//获取问答评分记录
|
//获取问答评分记录
|
||||||
String promptJson = cacheMsgMapData1.get(session.getId());
|
String promptJson = cacheMsgMapData1.get(session.getId());
|
||||||
//根据模型获取评分
|
//根据模型获取评分
|
||||||
@@ -668,9 +671,6 @@ public class ChatWebSocketMultipleHandler {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flag = false;
|
|
||||||
}else{
|
|
||||||
cacheQuestionNum.put(session.getId(), replyNums+1);
|
|
||||||
}
|
}
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -172,6 +172,7 @@ chatGpt:
|
|||||||
model: ft:gpt-3.5-turbo-0125:vetti:interview-unified:CaGyCXOr
|
model: ft:gpt-3.5-turbo-0125:vetti:interview-unified:CaGyCXOr
|
||||||
modelQuestion: gpt-4o-mini
|
modelQuestion: gpt-4o-mini
|
||||||
modelCV: ft:gpt-3.5-turbo-0125:vetti:vetti-resume-full:CYT0C8JG
|
modelCV: ft:gpt-3.5-turbo-0125:vetti:vetti-resume-full:CYT0C8JG
|
||||||
|
modelJxCv: gpt-4o-mini
|
||||||
role: system
|
role: system
|
||||||
|
|
||||||
http:
|
http:
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ chatGpt:
|
|||||||
model: ft:gpt-3.5-turbo-0125:vetti:interview-unified:CaGyCXOr
|
model: ft:gpt-3.5-turbo-0125:vetti:interview-unified:CaGyCXOr
|
||||||
modelQuestion: gpt-4o-mini
|
modelQuestion: gpt-4o-mini
|
||||||
modelCV: ft:gpt-3.5-turbo-0125:vetti:vetti-resume-full:CYT0C8JG
|
modelCV: ft:gpt-3.5-turbo-0125:vetti:vetti-resume-full:CYT0C8JG
|
||||||
|
modelJxCv: gpt-4o-mini
|
||||||
role: system
|
role: system
|
||||||
|
|
||||||
http:
|
http:
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ public class ElevenLabsStreamClient {
|
|||||||
ByteArrayOutputStream smallChunkBuffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream smallChunkBuffer = new ByteArrayOutputStream();
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
|
log.info("开始发送语音流:{}",System.currentTimeMillis()/1000);
|
||||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
try{
|
try{
|
||||||
// 如果上一包还在发送 → 阻塞等待
|
// 如果上一包还在发送 → 阻塞等待
|
||||||
@@ -80,10 +81,10 @@ public class ElevenLabsStreamClient {
|
|||||||
}
|
}
|
||||||
}catch (Exception e){}
|
}catch (Exception e){}
|
||||||
//语音流合并到2KB左右进行发送
|
//语音流合并到2KB左右进行发送
|
||||||
if(smallChunkBuffer.size() >= 3072){
|
if(smallChunkBuffer.size() >= 4096){
|
||||||
// 🔥开始发送 → 上锁
|
// 🔥开始发送 → 上锁
|
||||||
sending[0] = true;
|
sending[0] = true;
|
||||||
log.info("语音流大于"+smallChunkBuffer.size()+"啦,发送完成!!!");
|
// log.info("语音流大于"+smallChunkBuffer.size()+"啦,发送完成!!!");
|
||||||
byte[] merged = smallChunkBuffer.toByteArray();
|
byte[] merged = smallChunkBuffer.toByteArray();
|
||||||
smallChunkBuffer.reset();
|
smallChunkBuffer.reset();
|
||||||
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged), result -> {
|
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged), result -> {
|
||||||
@@ -99,16 +100,19 @@ public class ElevenLabsStreamClient {
|
|||||||
}
|
}
|
||||||
//都加完缓冲区,最最后一次发送
|
//都加完缓冲区,最最后一次发送
|
||||||
if(smallChunkBuffer.size() > 2){
|
if(smallChunkBuffer.size() > 2){
|
||||||
|
try {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}catch (Exception e){}
|
||||||
// 如果上一包还在发送 → 阻塞等待
|
// 如果上一包还在发送 → 阻塞等待
|
||||||
byte[] merged = smallChunkBuffer.toByteArray();
|
byte[] merged = smallChunkBuffer.toByteArray();
|
||||||
smallChunkBuffer.reset();
|
smallChunkBuffer.reset();
|
||||||
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged), result -> {
|
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged), result -> {
|
||||||
log.info("最后一次发送,语音流大于"+smallChunkBuffer.size()+"啦,发送完成!!!");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
log.info("结束发送语音流:{}",System.currentTimeMillis()/1000);
|
||||||
//返回结束点
|
//返回结束点
|
||||||
try {
|
try {
|
||||||
Thread.sleep(20);
|
Thread.sleep(50);
|
||||||
}catch (Exception e){}
|
}catch (Exception e){}
|
||||||
Map<String,String> dataText = new HashMap<>();
|
Map<String,String> dataText = new HashMap<>();
|
||||||
dataText.put("type","voiceEnd");
|
dataText.put("type","voiceEnd");
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ public class ChatGPTClient {
|
|||||||
@Value("${chatGpt.modelCV}")
|
@Value("${chatGpt.modelCV}")
|
||||||
private String modelCV;
|
private String modelCV;
|
||||||
|
|
||||||
|
@Value("${chatGpt.modelJxCv}")
|
||||||
|
private String modelJxCv;
|
||||||
|
|
||||||
@Value("${chatGpt.role}")
|
@Value("${chatGpt.role}")
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
@@ -66,6 +69,8 @@ public class ChatGPTClient {
|
|||||||
resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role);
|
resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role);
|
||||||
} else if("PF".equals(type)){
|
} else if("PF".equals(type)){
|
||||||
resultText = sendMessage(promptText, model,objectMapper,client,role);
|
resultText = sendMessage(promptText, model,objectMapper,client,role);
|
||||||
|
}else if("JX".equals(type)){
|
||||||
|
resultText = sendMessage(promptText, modelJxCv,objectMapper,client,role);
|
||||||
}else {
|
}else {
|
||||||
resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role);
|
resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.vetti.hotake.domain;
|
package com.vetti.hotake.domain;
|
||||||
|
|
||||||
|
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
@@ -52,4 +53,13 @@ public class HotakeCvInfo extends BaseEntity
|
|||||||
@Excel(name = "状态", readConverterExp = "0=,禁=用,1,启=用")
|
@Excel(name = "状态", readConverterExp = "0=,禁=用,1,启=用")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
|
@ApiModelProperty("简历详细信息-固定模版")
|
||||||
|
private HotakeCvInfoDto cvInfoDto;
|
||||||
|
|
||||||
|
@ApiModelProperty("简历预设问题记录")
|
||||||
|
private HotakeProblemBaseInfo problemBaseInfo;
|
||||||
|
|
||||||
|
@ApiModelProperty("简历评分")
|
||||||
|
private String score;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ public class HotakeProblemBaseInfo extends BaseEntity
|
|||||||
@Excel(name = "问题")
|
@Excel(name = "问题")
|
||||||
private String contents;
|
private String contents;
|
||||||
|
|
||||||
|
@ApiModelProperty("问题数量")
|
||||||
|
private Integer questionNums;
|
||||||
|
|
||||||
/** 状态(0 禁用,1 启用) */
|
/** 状态(0 禁用,1 启用) */
|
||||||
@ApiModelProperty("状态(0 禁用,1 启用)")
|
@ApiModelProperty("状态(0 禁用,1 启用)")
|
||||||
@Excel(name = "状态", readConverterExp = "0=,禁=用,1,启=用")
|
@Excel(name = "状态", readConverterExp = "0=,禁=用,1,启=用")
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.vetti.hotake.domain.dto;
|
||||||
|
|
||||||
|
import com.vetti.hotake.domain.dto.VcDto.*;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历结构化信息对象 hotake_cv_info
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class HotakeCvInfoDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("姓名")
|
||||||
|
private String name;
|
||||||
|
@ApiModelProperty("电话")
|
||||||
|
private String phone;
|
||||||
|
@ApiModelProperty("邮箱")
|
||||||
|
private String email;
|
||||||
|
@ApiModelProperty("链接对象集合")
|
||||||
|
private List<VcLinksDto> linksList;
|
||||||
|
@ApiModelProperty("自我介绍")
|
||||||
|
private String about;
|
||||||
|
@ApiModelProperty("技能工具-许可证、注册/会员资格、认证")
|
||||||
|
private List<VcSkillsToolsDto> skillsToolsList;
|
||||||
|
@ApiModelProperty("语言")
|
||||||
|
private List<VcLanguagesDto> languagesList;
|
||||||
|
@ApiModelProperty("工作经验集合")
|
||||||
|
private List<VcExperienceDto> experienceList;
|
||||||
|
@ApiModelProperty("教育经历")
|
||||||
|
private List<VcEducationDto> educationList;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.vetti.hotake.domain.dto.VcDto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历-教育经历-信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class VcEducationDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("学位")
|
||||||
|
private String degree;
|
||||||
|
|
||||||
|
@ApiModelProperty("学校名")
|
||||||
|
private String institution;
|
||||||
|
|
||||||
|
@ApiModelProperty("时间")
|
||||||
|
private String date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.vetti.hotake.domain.dto.VcDto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历-工作经验-描述-信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class VcExperienceDescriptionDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("内容")
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.vetti.hotake.domain.dto.VcDto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历-工作经验-信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class VcExperienceDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("标题")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@ApiModelProperty("公司")
|
||||||
|
private String company;
|
||||||
|
|
||||||
|
@ApiModelProperty("地点")
|
||||||
|
private String location;
|
||||||
|
|
||||||
|
@ApiModelProperty("时间")
|
||||||
|
private String duration;
|
||||||
|
|
||||||
|
@ApiModelProperty("描述集合")
|
||||||
|
private List<VcExperienceDescriptionDto> descriptionList;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.vetti.hotake.domain.dto.VcDto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历-语言-信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class VcLanguagesDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("内容")
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.vetti.hotake.domain.dto.VcDto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历链接-信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class VcLinksDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("内容")
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.vetti.hotake.domain.dto.VcDto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历 技能工具-许可证、注册/会员资格、认证-信息对象
|
||||||
|
*
|
||||||
|
* @author wangxiangshun
|
||||||
|
* @date 2025-11-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class VcSkillsToolsDto {
|
||||||
|
|
||||||
|
@ApiModelProperty("内容")
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package com.vetti.hotake.service;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.vetti.hotake.domain.HotakeCvInfo;
|
import com.vetti.hotake.domain.HotakeCvInfo;
|
||||||
|
import com.vetti.hotake.domain.HotakeProblemBaseInfo;
|
||||||
|
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 简历信息Service接口
|
* 简历信息Service接口
|
||||||
@@ -38,10 +40,10 @@ public interface IHotakeCvInfoService
|
|||||||
/**
|
/**
|
||||||
* 处理简历信息
|
* 处理简历信息
|
||||||
*
|
*
|
||||||
* @param hotakeCvInfo 简历信息
|
* @param cvInfoDto 简历信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public void handleHotakeCvInfo(HotakeCvInfo hotakeCvInfo);
|
public HotakeProblemBaseInfo handleHotakeCvInfo(HotakeCvInfoDto cvInfoDto);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
package com.vetti.hotake.service.impl;
|
package com.vetti.hotake.service.impl;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
@@ -17,11 +9,12 @@ import com.vetti.common.enums.FillTypeEnum;
|
|||||||
import com.vetti.common.enums.MinioBucketNameEnum;
|
import com.vetti.common.enums.MinioBucketNameEnum;
|
||||||
import com.vetti.common.utils.DateUtils;
|
import com.vetti.common.utils.DateUtils;
|
||||||
import com.vetti.common.utils.SecurityUtils;
|
import com.vetti.common.utils.SecurityUtils;
|
||||||
import com.vetti.common.utils.file.MinioUtil;
|
|
||||||
import com.vetti.common.utils.readFile.FileContentUtil;
|
import com.vetti.common.utils.readFile.FileContentUtil;
|
||||||
import com.vetti.common.utils.readText.ResumeTextExtractor;
|
import com.vetti.hotake.domain.HotakeCvInfo;
|
||||||
import com.vetti.common.utils.readText.vo.ResumeData;
|
|
||||||
import com.vetti.hotake.domain.HotakeProblemBaseInfo;
|
import com.vetti.hotake.domain.HotakeProblemBaseInfo;
|
||||||
|
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
|
||||||
|
import com.vetti.hotake.mapper.HotakeCvInfoMapper;
|
||||||
|
import com.vetti.hotake.service.IHotakeCvInfoService;
|
||||||
import com.vetti.hotake.service.IHotakeProblemBaseInfoService;
|
import com.vetti.hotake.service.IHotakeProblemBaseInfoService;
|
||||||
import io.minio.GetObjectArgs;
|
import io.minio.GetObjectArgs;
|
||||||
import io.minio.MinioClient;
|
import io.minio.MinioClient;
|
||||||
@@ -30,11 +23,11 @@ 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 com.vetti.hotake.mapper.HotakeCvInfoMapper;
|
import java.io.InputStream;
|
||||||
import com.vetti.hotake.domain.HotakeCvInfo;
|
import java.util.HashMap;
|
||||||
import com.vetti.hotake.service.IHotakeCvInfoService;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import javax.annotation.Resource;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 简历信息Service业务层处理
|
* 简历信息Service业务层处理
|
||||||
@@ -113,8 +106,23 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
|||||||
}
|
}
|
||||||
hotakeCvInfo.setCvFileSuffix(fileSuffix);
|
hotakeCvInfo.setCvFileSuffix(fileSuffix);
|
||||||
if("cv".equals(hotakeCvInfo.getCvFileType())){
|
if("cv".equals(hotakeCvInfo.getCvFileType())){
|
||||||
|
try{
|
||||||
|
InputStream inputStream = minioClient.getObject(
|
||||||
|
GetObjectArgs.builder()
|
||||||
|
.bucket(MinioBucketNameEnum.CV.getCode())
|
||||||
|
.object(hotakeCvInfo.getCvUrl())
|
||||||
|
.build());
|
||||||
|
String contents = FileContentUtil.readFileContent(inputStream,hotakeCvInfo.getCvFileSuffix());
|
||||||
|
//生成简历模版数据信息
|
||||||
|
HotakeCvInfoDto cvInfoDto = handleAnalysisCvInfo(contents);
|
||||||
|
hotakeCvInfo.setCvInfoDto(cvInfoDto);
|
||||||
//对简历数据进行处理生成相应的题库数据
|
//对简历数据进行处理生成相应的题库数据
|
||||||
handleHotakeCvInfo(hotakeCvInfo);
|
HotakeProblemBaseInfo problemBaseInfo = handleHotakeCvInfo(cvInfoDto);
|
||||||
|
hotakeCvInfo.setProblemBaseInfo(problemBaseInfo);
|
||||||
|
//生成对应的简历评分
|
||||||
|
handleHotakeCvInfoScore(cvInfoDto);
|
||||||
|
}catch (Exception e){
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return hotakeCvInfo;
|
return hotakeCvInfo;
|
||||||
}
|
}
|
||||||
@@ -125,19 +133,9 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void handleHotakeCvInfo(HotakeCvInfo hotakeCvInfo) {
|
public HotakeProblemBaseInfo handleHotakeCvInfo(HotakeCvInfoDto cvInfoDto) {
|
||||||
|
HotakeProblemBaseInfo problemBaseInfo = new HotakeProblemBaseInfo();
|
||||||
try{
|
try{
|
||||||
InputStream inputStream = minioClient.getObject(
|
|
||||||
GetObjectArgs.builder()
|
|
||||||
.bucket(MinioBucketNameEnum.CV.getCode())
|
|
||||||
.object(hotakeCvInfo.getCvUrl())
|
|
||||||
.build());
|
|
||||||
|
|
||||||
String contents = FileContentUtil.readFileContent(inputStream,hotakeCvInfo.getCvFileSuffix());
|
|
||||||
//进行简历数据提取
|
|
||||||
ResumeTextExtractor extractor = new ResumeTextExtractor();
|
|
||||||
ResumeData resumeData = extractor.extractResumeData(contents,"");
|
|
||||||
log.info("返回简历基本内容:{}", resumeData);
|
|
||||||
//调用AI大模型
|
//调用AI大模型
|
||||||
List<Map<String,String>> list = new LinkedList();
|
List<Map<String,String>> list = new LinkedList();
|
||||||
Map<String,String> mapEntity = new HashMap<>();
|
Map<String,String> mapEntity = new HashMap<>();
|
||||||
@@ -147,35 +145,33 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
|||||||
Map<String,String> mapEntityOne = new HashMap<>();
|
Map<String,String> mapEntityOne = new HashMap<>();
|
||||||
mapEntityOne.put("role","user");
|
mapEntityOne.put("role","user");
|
||||||
mapEntityOne.put("content","Position: Construction Labourer"+
|
mapEntityOne.put("content","Position: Construction Labourer"+
|
||||||
"\\nCandidate: "+resumeData.getPersonalInfo().getName()+
|
"\\nCandidate: "+cvInfoDto.getName()+
|
||||||
"\\nKey Skills: "+JSONUtil.toJsonStr(resumeData.getSkills())+
|
"\\nKey Skills: "+JSONUtil.toJsonStr(cvInfoDto.getSkillsToolsList())+
|
||||||
"\\nExperience: "+resumeData.getPersonalInfo().getExperienceYears()+"years"+
|
"\\nExperience: "+JSONUtil.toJsonStr(cvInfoDto.getExperienceList())+
|
||||||
"\\nStrengths: Professional certifications, Relevant experience"+
|
"\\nStrengths: Professional certifications, Relevant experience"+
|
||||||
"\\nConcerns: "+JSONUtil.toJsonStr(resumeData.getSummary()));
|
"\\nConcerns: "+JSONUtil.toJsonStr(cvInfoDto.getAbout()));
|
||||||
list.add(mapEntityOne);
|
list.add(mapEntityOne);
|
||||||
String promptText = JSONUtil.toJsonStr(list);
|
String promptText = JSONUtil.toJsonStr(list);
|
||||||
String resultMsg = chatGPTClient.handleAiChat(promptText,"CV");
|
String resultMsg = chatGPTClient.handleAiChat(promptText,"CV");
|
||||||
|
log.info("返回简历问题数据:{}",resultMsg);
|
||||||
resultMsg = resultMsg.replaceAll("\n","#AA#");
|
resultMsg = resultMsg.replaceAll("\n","#AA#");
|
||||||
String question = "";
|
String question = "";
|
||||||
|
Integer questionNums = 0;
|
||||||
if(StrUtil.isNotEmpty(resultMsg)){
|
if(StrUtil.isNotEmpty(resultMsg)){
|
||||||
String[] results = resultMsg.split("#AA#");
|
resultMsg = resultMsg.replaceAll(QUESTION_PREFIX,"");
|
||||||
question = results[0].replaceAll(QUESTION_PREFIX,"");
|
questionNums = resultMsg.split("#AA#").length;
|
||||||
if(StrUtil.isEmpty(question)){
|
|
||||||
//设置一个默认值
|
|
||||||
question = "Your professional certifications is impressive. Can you give me a specific example of how this benefited a project?";
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
log.info("返回初始化问题:{}",resultMsg);
|
|
||||||
//生成预设问题记录
|
//生成预设问题记录
|
||||||
//先删除该用户的预设问题
|
//先删除该用户的预设问题
|
||||||
hotakeProblemBaseInfoService.deleteHotakeProblemBaseInfoByUserId(SecurityUtils.getUserId());
|
hotakeProblemBaseInfoService.deleteHotakeProblemBaseInfoByUserId(SecurityUtils.getUserId());
|
||||||
HotakeProblemBaseInfo problemBaseInfo = new HotakeProblemBaseInfo();
|
|
||||||
problemBaseInfo.setUserId(SecurityUtils.getUserId());
|
problemBaseInfo.setUserId(SecurityUtils.getUserId());
|
||||||
problemBaseInfo.setContents(question);
|
problemBaseInfo.setContents(resultMsg);
|
||||||
|
problemBaseInfo.setQuestionNums(questionNums);
|
||||||
hotakeProblemBaseInfoService.insertHotakeProblemBaseInfo(problemBaseInfo);
|
hotakeProblemBaseInfoService.insertHotakeProblemBaseInfo(problemBaseInfo);
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return problemBaseInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -230,4 +226,63 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
|||||||
public int batchInsertHotakeCvInfo(List<HotakeCvInfo> hotakeCvInfoList){
|
public int batchInsertHotakeCvInfo(List<HotakeCvInfo> hotakeCvInfoList){
|
||||||
return hotakeCvInfoMapper.batchInsertHotakeCvInfo(hotakeCvInfoList);
|
return hotakeCvInfoMapper.batchInsertHotakeCvInfo(hotakeCvInfoList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简历解析数据
|
||||||
|
* @param contents
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private HotakeCvInfoDto handleAnalysisCvInfo(String contents){
|
||||||
|
//根据AI做
|
||||||
|
String pom = "[\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"role\": \"user\",\n" +
|
||||||
|
" \"content\": \"从下面提供的文本中提取所有能识别到的简历信息,只提取原文中存在的内容,不要补充、不推测、不总结。需要提取的字段包括:name(姓名)、phone(电话号码)、email(电子邮件地址)、links(所有链接地址)、about(关于我/自我介绍)、skills_tools(关键资格(许可证、注册/会员资格、认证))、languages(语言能力)、experience(工作经历(除了title、company、location、duration其他的都放到描述里面))、education(教育经历)。请将提取结果以结构化 JSON 格式返回,格式如下:{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"links\\\": [], \\\"about\\\": \\\"\\\", \\\"skills_tools\\\": [], \\\"languages\\\": [], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"duration\\\": \\\"\\\",\\\"description\\\": []}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"date\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息,不要解释说明,不要改写内容。以下为待处理文本:" + contents +
|
||||||
|
" }\n" +
|
||||||
|
"]";
|
||||||
|
String resultCv = chatGPTClient.handleAiChat(pom,"JX");
|
||||||
|
try{
|
||||||
|
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(resultCv,HotakeCvInfoDto.class);
|
||||||
|
return cvInfoDto;
|
||||||
|
}catch (Exception e){
|
||||||
|
}
|
||||||
|
return new HotakeCvInfoDto();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理简历信息
|
||||||
|
* @param hotakeCvInfo 简历信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private HotakeProblemBaseInfo handleHotakeCvInfoScore(HotakeCvInfoDto cvInfoDto) {
|
||||||
|
HotakeProblemBaseInfo problemBaseInfo = new HotakeProblemBaseInfo();
|
||||||
|
try{
|
||||||
|
//调用AI大模型
|
||||||
|
List<Map<String,String>> list = new LinkedList();
|
||||||
|
Map<String,String> mapEntity = new HashMap<>();
|
||||||
|
mapEntity.put("role","system");
|
||||||
|
mapEntity.put("content","You are a construction industry HR expert. Evaluate resumes and provide scores and recommendations for construction management positions.");
|
||||||
|
list.add(mapEntity);
|
||||||
|
Map<String,String> mapEntityOne = new HashMap<>();
|
||||||
|
mapEntityOne.put("role","user");
|
||||||
|
mapEntityOne.put("content","Position: Construction Labourer"+
|
||||||
|
"\\nCandidate: "+cvInfoDto.getName()+
|
||||||
|
"\\nResume Summary: "+JSONUtil.toJsonStr(cvInfoDto.getAbout())+
|
||||||
|
"\\nSkills: "+JSONUtil.toJsonStr(cvInfoDto.getSkillsToolsList())+
|
||||||
|
"\\nExperience: "+JSONUtil.toJsonStr(cvInfoDto.getExperienceList())+
|
||||||
|
"\\nEducation: "+JSONUtil.toJsonStr(cvInfoDto.getEducationList())+
|
||||||
|
"\\nCertifications: "+JSONUtil.toJsonStr(cvInfoDto.getSkillsToolsList()));
|
||||||
|
list.add(mapEntityOne);
|
||||||
|
String promptText = JSONUtil.toJsonStr(list);
|
||||||
|
String resultMsg = chatGPTClient.handleAiChat(promptText,"CV");
|
||||||
|
log.info("返回简历评分数据:{}",resultMsg);
|
||||||
|
|
||||||
|
}catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return problemBaseInfo;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user