简历解析结构修改和字典逻辑修改

This commit is contained in:
2025-12-02 21:32:31 +08:00
parent 22c0f3d95d
commit 4eb473b77e
14 changed files with 246 additions and 41 deletions

View File

@@ -28,17 +28,17 @@ public class HotakeCvInfoDto {
@ApiModelProperty("地点")
private String location;
@ApiModelProperty("链接对象集合")
private List<VcLinksDto> linksList;
private List<VcLinksDto> links;
@ApiModelProperty("自我介绍")
private String about;
@ApiModelProperty("技能工具-许可证、注册/会员资格、认证")
private List<VcSkillsToolsDto> skillsToolsList;
private List<VcSkillsToolsDto> skillsTools;
@ApiModelProperty("语言")
private List<VcLanguagesDto> languagesList;
private List<VcLanguagesDto> languages;
@ApiModelProperty("工作经验集合")
private List<VcExperienceDto> experienceList;
private List<VcExperienceDto> experience;
@ApiModelProperty("教育经历")
private List<VcEducationDto> educationList;
private List<VcEducationDto> education;
}

View File

@@ -0,0 +1,29 @@
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 VcCertificateDto {
@ApiModelProperty("文件名称")
private String fileName;
@ApiModelProperty("文件后缀(doc/pdf)")
private String fileSuffix;
@ApiModelProperty("文件地址")
private String fileUrl;
@ApiModelProperty("文件大小")
private String fileSizeShow;
}

View File

@@ -22,4 +22,8 @@ public class VcEducationDto {
@ApiModelProperty("时间")
private String date;
@ApiModelProperty("证书附件")
private VcCertificateDto certificate;
}

View File

@@ -29,6 +29,6 @@ public class VcExperienceDto {
private String duration;
@ApiModelProperty("描述集合")
private List<VcExperienceDescriptionDto> descriptionList;
private List<VcExperienceDescriptionDto> description;
}

View File

@@ -16,7 +16,4 @@ public class VcSkillsToolsDto {
@ApiModelProperty("内容")
private String content;
@ApiModelProperty("证书附件URL")
private String fileUrl;
}

View File

@@ -13,6 +13,7 @@ import com.vetti.common.utils.readFile.FileContentUtil;
import com.vetti.hotake.domain.HotakeCvInfo;
import com.vetti.hotake.domain.HotakeProblemBaseInfo;
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
import com.vetti.hotake.domain.dto.VcDto.*;
import com.vetti.hotake.mapper.HotakeCvInfoMapper;
import com.vetti.hotake.service.IHotakeCvInfoService;
import com.vetti.hotake.service.IHotakeProblemBaseInfoService;
@@ -67,8 +68,11 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
@Override
public HotakeCvInfo selectHotakeCvInfoById(Long id) {
HotakeCvInfo cvInfo = hotakeCvInfoMapper.selectHotakeCvInfoById(id);
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(cvInfo.getCvTemplateJson(),HotakeCvInfoDto.class);
cvInfo.setCvInfoDto(cvInfoDto);
if(StrUtil.isNotEmpty(cvInfo.getCvTemplateJson())){
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(cvInfo.getCvTemplateJson(),HotakeCvInfoDto.class);
cvInfo.setCvInfoDto(cvInfoDto);
}
HotakeProblemBaseInfo query = new HotakeProblemBaseInfo();
query.setCvId(id);
List<HotakeProblemBaseInfo> problemBaseInfoList = hotakeProblemBaseInfoService.selectHotakeProblemBaseInfoList(query);
@@ -138,8 +142,8 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
mapEntityOne.put("role", "user");
mapEntityOne.put("content", "Position: Construction Labourer" +
"\\nCandidate: " + cvInfoDto.getName() +
"\\nKey Skills: " + JSONUtil.toJsonStr(cvInfoDto.getSkillsToolsList()) +
"\\nExperience: " + JSONUtil.toJsonStr(cvInfoDto.getExperienceList()) +
"\\nKey Skills: " + JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()) +
"\\nExperience: " + JSONUtil.toJsonStr(cvInfoDto.getExperience()) +
"\\nStrengths: Professional certifications, Relevant experience" +
"\\nConcerns: " + JSONUtil.toJsonStr(cvInfoDto.getAbout()));
list.add(mapEntityOne);
@@ -180,7 +184,12 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
fill(FillTypeEnum.UPDATE.getCode(), hotakeCvInfo);
hotakeCvInfo.setCvTemplateJson(JSONUtil.toJsonStr(hotakeCvInfo.getCvInfoDto()));
//修改的时候重新生成问题和评分
hotakeCvInfoMapper.updateHotakeCvInfo(hotakeCvInfo);
return hotakeCvInfo;
}
@@ -269,12 +278,109 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
List<Map<String,String>> list = new LinkedList();
Map<String,String> entity = new HashMap<>();
entity.put("role","user");
entity.put("content","从下面提供的文本中提取所有能识别到的简历信息只提取原文中存在的内容不要补充、不推测、不总结。需要提取的字段包括name姓名、phone电话号码、email电子邮件地址、position岗位、location地点、links所有链接地址、about关于我/自我介绍、skills_tools关键资格许可证、注册/会员资格、认证、languages语言能力、experience工作经历(除了title、company、location、duration其他的都放到描述里面)、education教育经历。请将提取结果以结构化 JSON 格式返回,格式如下:{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"links\\\": [{\\\"content\\\":\\\"\\\"}], \\\"about\\\": \\\"\\\", \\\"skillsTools\\\": [{\\\"content\\\":\\\"\\\"}], \\\"languages\\\": [{\\\"content\\\":\\\"\\\"}], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"duration\\\": \\\"\\\",\\\"description\\\": [{\\\"content\\\":\\\"\\\"}]}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"date\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息不要解释说明不要改写内容。以下为待处理文本"+contents);
entity.put("content","从下面提供的文本中提取所有能识别到的简历信息只提取原文中存在的内容不要补充、不推测、不总结。需要提取的字段包括name姓名、phone电话号码、email电子邮件地址、position岗位、location地点、links所有链接地址、about关于我/自我介绍、skills_tools关键资格许可证、注册/会员资格、认证、languages语言能力、experience工作经历(除了title、company、location、duration,其他的都放到description里面,并且description里面要根据换行符分成不同的content)、education教育经历。请将提取结果以结构化 JSON 格式返回,格式如下:{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"links\\\": [{\\\"content\\\":\\\"\\\"}], \\\"about\\\": \\\"\\\", \\\"skillsTools\\\": [{\\\"content\\\":\\\"\\\"}], \\\"languages\\\": [{\\\"content\\\":\\\"\\\"}], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"duration\\\": \\\"\\\",\\\"description\\\": [{\\\"content\\\":\\\"\\\"}]}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"date\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息不要解释说明不要改写内容。以下为待处理文本"+contents);
//根据AI做
list.add(entity);
String resultCv = chatGPTClient.handleAiChat(JSONUtil.toJsonStr(list), "JX");
log.info("开始返回简历解析结果:{}", resultCv);
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(resultCv, HotakeCvInfoDto.class);
//数据添加默认值
if(cvInfoDto != null){
if(StrUtil.isEmpty(cvInfoDto.getName())){
cvInfoDto.setName("-");
}
if(StrUtil.isEmpty(cvInfoDto.getPhone())){
cvInfoDto.setPhone("-");
}
if(StrUtil.isEmpty(cvInfoDto.getEmail())){
cvInfoDto.setEmail("-");
}
if(StrUtil.isEmpty(cvInfoDto.getPosition())){
cvInfoDto.setPosition("-");
}
if(StrUtil.isEmpty(cvInfoDto.getLocation())){
cvInfoDto.setLocation("-");
}
if(StrUtil.isEmpty(cvInfoDto.getAbout())){
cvInfoDto.setAbout("-");
}
if(CollectionUtil.isNotEmpty(cvInfoDto.getSkillsTools())){
for (VcSkillsToolsDto toolsDto :cvInfoDto.getSkillsTools()) {
if(StrUtil.isEmpty(toolsDto.getContent())){
toolsDto.setContent("-");
}
}
}
if(CollectionUtil.isNotEmpty(cvInfoDto.getLinks())){
for (VcLinksDto linksDto :cvInfoDto.getLinks()) {
if(StrUtil.isEmpty(linksDto.getContent())){
linksDto.setContent("-");
}
}
}
if(CollectionUtil.isNotEmpty(cvInfoDto.getLanguages())){
for (VcLanguagesDto languagesDto :cvInfoDto.getLanguages()) {
if(StrUtil.isEmpty(languagesDto.getContent())){
languagesDto.setContent("-");
}
}
}
if(CollectionUtil.isNotEmpty(cvInfoDto.getExperience())){
for (VcExperienceDto experienceDto :cvInfoDto.getExperience()) {
if (StrUtil.isEmpty(experienceDto.getTitle())){
experienceDto.setTitle("-");
}
if(StrUtil.isEmpty(experienceDto.getCompany())){
experienceDto.setCompany("-");
}
if(StrUtil.isEmpty(experienceDto.getLocation())){
experienceDto.setLocation("-");
}
if(StrUtil.isEmpty(experienceDto.getDuration())){
experienceDto.setDuration("-");
}
if (CollectionUtil.isNotEmpty(experienceDto.getDescription())){
for(VcExperienceDescriptionDto descriptionDto :experienceDto.getDescription()){
if(StrUtil.isEmpty(descriptionDto.getContent())){
descriptionDto.setContent("-");
}
}
}
}
}
if(CollectionUtil.isNotEmpty(cvInfoDto.getEducation())){
for (VcEducationDto educationDto :cvInfoDto.getEducation()) {
if (StrUtil.isEmpty(educationDto.getDegree())){
educationDto.setDegree("-");
}
if(StrUtil.isEmpty(educationDto.getInstitution())){
educationDto.setInstitution("-");
}
if(StrUtil.isEmpty(educationDto.getDate())){
educationDto.setDate("-");
}
if(educationDto.getCertificate() != null){
if(StrUtil.isEmpty(educationDto.getCertificate().getFileName())){
educationDto.getCertificate().setFileName("-");
}
if (StrUtil.isEmpty(educationDto.getCertificate().getFileSuffix())){
educationDto.getCertificate().setFileSuffix("-");
}
if (StrUtil.isEmpty(educationDto.getCertificate().getFileUrl())){
educationDto.getCertificate().setFileUrl("-");
}
if (StrUtil.isEmpty(educationDto.getCertificate().getFileSizeShow())){
educationDto.getCertificate().setFileSizeShow("-");
}
}
}
}
}
return cvInfoDto;
} catch (Exception e) {
e.printStackTrace();
@@ -303,10 +409,10 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
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()));
"\\nSkills: " + JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()) +
"\\nExperience: " + JSONUtil.toJsonStr(cvInfoDto.getExperience()) +
"\\nEducation: " + JSONUtil.toJsonStr(cvInfoDto.getEducation()) +
"\\nCertifications: " + JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()));
list.add(mapEntityOne);
String promptText = JSONUtil.toJsonStr(list);
resultMsg = chatGPTClient.handleAiChat(promptText, "CV");