AI接入逻辑完善
This commit is contained in:
@@ -84,6 +84,9 @@ public class HotakeCvInfo extends BaseEntity
|
||||
@ApiModelProperty("简历分析结果数据存储")
|
||||
private String cvOptimizeJson;
|
||||
|
||||
@ApiModelProperty("分析附件结果Json")
|
||||
private String analyzedAttachmentJson;
|
||||
|
||||
@ApiModelProperty("文本修正的数量")
|
||||
private Integer textCorrectionsNums;
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.vetti.hotake.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 网站信息提取 请求对象
|
||||
*
|
||||
* @author ID
|
||||
* @date 2025-09-06
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class HotakeWebInfoExtractVo {
|
||||
|
||||
@ApiModelProperty("网站地址")
|
||||
private String webUrl;
|
||||
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.vetti.hotake.domain.dto.HotakeJobDescriptionGeneratorDto;
|
||||
import com.vetti.hotake.domain.vo.HotakeInitialQuestionEliminationScoreVo;
|
||||
import com.vetti.hotake.domain.vo.HotakeInitialScreeningQuestionsVo;
|
||||
import com.vetti.hotake.domain.vo.HotakeResumeJobMatchingScoreVo;
|
||||
import com.vetti.hotake.domain.vo.HotakeWebInfoExtractVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,14 +26,11 @@ public interface IHotakeAiCommonToolsService {
|
||||
**/
|
||||
public HotakeJobDescriptionGeneratorDto getJobDescriptionGenerator(Long roleId);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 初筛问题生成
|
||||
**/
|
||||
public List<HotakeInitialScreeningQuestionsInfo> getInitialScreeningQuestionsGenerator(HotakeInitialScreeningQuestionsVo questionsVo);
|
||||
|
||||
|
||||
/**
|
||||
* 简历岗位匹配度评分
|
||||
**/
|
||||
@@ -43,10 +41,57 @@ public interface IHotakeAiCommonToolsService {
|
||||
**/
|
||||
public HotakeCvOptimizeDto getResumeAnalysisOptimizer(String cvConnect);
|
||||
|
||||
|
||||
/**
|
||||
* 初步筛选问题淘汰评分
|
||||
**/
|
||||
public HotakeInitialQuestionEliminationScoreDto getInitialQuestionEliminationScore(HotakeInitialQuestionEliminationScoreVo questionEliminationScoreVo);
|
||||
|
||||
/**
|
||||
* 处理分析附件结果
|
||||
* @param connect
|
||||
* @return
|
||||
*/
|
||||
public String handleAnalyzedAttachment(String connect);
|
||||
|
||||
|
||||
/**
|
||||
* 处理附件分析结果合并信息
|
||||
* @param basicInformation 基础信息
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
public String handleAttachmentResultMerging(String basicInformation,String attachmentContent);
|
||||
|
||||
|
||||
/**
|
||||
* 生成最终的Markdown格式简历
|
||||
* @param markdown
|
||||
* @return
|
||||
*/
|
||||
public String handleGenerateMarkdown(String markdown);
|
||||
|
||||
/**
|
||||
* 网站内容抓取
|
||||
* @param webUrl
|
||||
* @return
|
||||
*/
|
||||
public String handleWebContentScraping(String webUrl);
|
||||
|
||||
/**
|
||||
* 网站AI信息提取(使用提示词)
|
||||
* @param webInfoExtractVo 网站提取对象
|
||||
* @return
|
||||
*/
|
||||
public String handleWebInfoExtract(HotakeWebInfoExtractVo webInfoExtractVo);
|
||||
|
||||
/**
|
||||
* 网站信息增强处理
|
||||
* @param webContent 网站内容
|
||||
* @return
|
||||
*/
|
||||
public String handleWebInfoEnhancedProcessing(String webContent);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -87,4 +87,13 @@ public interface IHotakeCvInfoService
|
||||
public HotakeCvInfo handleCvAnalysis(HotakeCvInfo hotakeCvInfo);
|
||||
|
||||
|
||||
/**
|
||||
* 根据其他的附件信息生成个人简历
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public HotakeCvInfo getGenerateResume();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@ package com.vetti.hotake.service.impl;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.vetti.common.ai.gpt.ChatGPTClient;
|
||||
import com.vetti.common.constant.AiCommonPromptConstants;
|
||||
import com.vetti.common.core.domain.entity.SysUser;
|
||||
import com.vetti.common.core.service.BaseServiceImpl;
|
||||
import com.vetti.common.utils.SecurityUtils;
|
||||
import com.vetti.common.utils.html.ReadHtmlByOkHttp;
|
||||
import com.vetti.hotake.domain.HotakeInitScreQuestionsReplyRecordInfo;
|
||||
import com.vetti.hotake.domain.HotakeInitialScreeningQuestionsInfo;
|
||||
import com.vetti.hotake.domain.HotakeRolesInfo;
|
||||
@@ -18,14 +22,18 @@ import com.vetti.hotake.domain.dto.roleDto.ResponsibilitiesDto;
|
||||
import com.vetti.hotake.domain.vo.HotakeInitialQuestionEliminationScoreVo;
|
||||
import com.vetti.hotake.domain.vo.HotakeInitialScreeningQuestionsVo;
|
||||
import com.vetti.hotake.domain.vo.HotakeResumeJobMatchingScoreVo;
|
||||
import com.vetti.hotake.domain.vo.HotakeWebInfoExtractVo;
|
||||
import com.vetti.hotake.mapper.HotakeInitialScreeningQuestionsInfoMapper;
|
||||
import com.vetti.hotake.mapper.HotakeRolesApplyInfoMapper;
|
||||
import com.vetti.hotake.mapper.HotakeRolesInfoMapper;
|
||||
import com.vetti.hotake.service.IHotakeAiCommonToolsService;
|
||||
import com.vetti.system.mapper.SysUserMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.catalina.security.SecurityUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -52,6 +60,9 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
@Autowired
|
||||
private ChatGPTClient chatGPTClient;
|
||||
|
||||
@Autowired
|
||||
private SysUserMapper userMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 职位描述生成器
|
||||
@@ -65,7 +76,7 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
HotakeJobDescriptionGeneratorDto generatorDto = new HotakeJobDescriptionGeneratorDto();
|
||||
//根据岗位ID查询岗位基本信息
|
||||
HotakeRolesInfo rolesInfo = hotakeRolesInfoMapper.selectHotakeRolesInfoById(roleId);
|
||||
String prompt = initializationJobDescriptionPrompt(rolesInfo.getRoleName(),rolesInfo.getRoleType(),
|
||||
String prompt = AiCommonPromptConstants.initializationJobDescriptionPrompt(rolesInfo.getRoleName(),rolesInfo.getRoleType(),
|
||||
rolesInfo.getRequiredSkillsJson());
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
@@ -133,7 +144,7 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
List<HotakeInitialScreeningQuestionsInfo> questionsInfoList = new ArrayList<>();
|
||||
//根据岗位ID查询岗位基本信息
|
||||
HotakeRolesInfo rolesInfo = hotakeRolesInfoMapper.selectHotakeRolesInfoById(questionsVo.getRoleId());
|
||||
String prompt = initializationInitialScreeningQuestionsPrompt(rolesInfo.getRoleName(),rolesInfo.getAboutRole(),
|
||||
String prompt = AiCommonPromptConstants.initializationInitialScreeningQuestionsPrompt(rolesInfo.getRoleName(),rolesInfo.getAboutRole(),
|
||||
rolesInfo.getResponsibilities());
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
@@ -180,7 +191,7 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
@Override
|
||||
public String getResumeJobMatchingScore(HotakeResumeJobMatchingScoreVo scoreVo) {
|
||||
//查询岗位信息
|
||||
String prompt = initializationResumeJobMatchingScorePrompt(scoreVo.getJobTitle(),scoreVo.getJobDescription(),
|
||||
String prompt = AiCommonPromptConstants.initializationResumeJobMatchingScorePrompt(scoreVo.getJobTitle(),scoreVo.getJobDescription(),
|
||||
scoreVo.getKeyResponsibilities(),scoreVo.getJobRequirements(),scoreVo.getPersonalInformation(),
|
||||
scoreVo.getWorkHistory(),scoreVo.getProjectExperience(),scoreVo.getSkillsList(),
|
||||
scoreVo.getEducationalBackground(),scoreVo.getOtherRelevantInformation());
|
||||
@@ -205,7 +216,7 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
@Override
|
||||
public HotakeCvOptimizeDto getResumeAnalysisOptimizer(String cvConnect) {
|
||||
//传输简历内容,返回简历分析结果
|
||||
String prompt = initializationResumeAnalysisOptimizerPrompt();
|
||||
String prompt = AiCommonPromptConstants.initializationResumeAnalysisOptimizerPrompt();
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role", "system");
|
||||
@@ -435,7 +446,7 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
List<HotakeInitialScreeningQuestionsInfo> screeningQuestionsInfoList = hotakeInitialScreeningQuestionsInfoMapper.selectHotakeInitialScreeningQuestionsInfoList(queryQuestionsInfo);
|
||||
|
||||
//提示词处理
|
||||
String prompt = initializationQuestionEliminationScorePrompt(questionEliminationScoreVo.getRoleName());
|
||||
String prompt = AiCommonPromptConstants.initializationQuestionEliminationScorePrompt(questionEliminationScoreVo.getRoleName());
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role", "system");
|
||||
@@ -467,680 +478,171 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
return dto;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化职位描述生成器提示词
|
||||
* @param jobTitle Specific position 岗位
|
||||
* @param industry Industry sector 行业领域
|
||||
* @param coreRequirements Key skills or experience requirements 所需技能或经验
|
||||
* 处理分析附件结果
|
||||
* @param connect
|
||||
* @return
|
||||
*/
|
||||
private String initializationJobDescriptionPrompt(String jobTitle,String industry,String coreRequirements){
|
||||
String prompt = "You are a senior HR expert and recruitment copywriter specializing in optimizing and generating attractive job descriptions.\n" +
|
||||
"\n" +
|
||||
"Core Task:\n" +
|
||||
"Generate standardized, professional, and candidate-attractive job description copy based on user-provided \"job title, industry, and core requirements.\"\n" +
|
||||
"\n" +
|
||||
"Input Format:\n" +
|
||||
"- Job Title: ["+jobTitle+"]\n" +
|
||||
"- Industry: ["+industry+"]\n" +
|
||||
"- Core Requirements: ["+coreRequirements+"]\n" +
|
||||
"\n" +
|
||||
"Output Structure:\n" +
|
||||
"1. Job Description\n" +
|
||||
"2. Key Responsibilities\n" +
|
||||
"3. Requirements\n" +
|
||||
"\n" +
|
||||
"Writing Principles:\n" +
|
||||
"1. Professional yet approachable language, avoiding overly formal or rigid tone\n" +
|
||||
"2. Highlight career development prospects and value\n" +
|
||||
"3. Specific and clear requirements, avoiding vague statements\n" +
|
||||
"4. Reflect company culture and team atmosphere\n" +
|
||||
"5. Use industry-standard terminology to ensure professionalism\n" +
|
||||
"\n" +
|
||||
"Job Description Guidelines:\n" +
|
||||
"- Concisely summarize the core value and significance of the position\n" +
|
||||
"- Highlight the position's importance within the company/team\n" +
|
||||
"- Emphasize career development opportunities\n" +
|
||||
"- Keep length between 100-150 words\n" +
|
||||
"\n" +
|
||||
"Key Responsibilities Guidelines:\n" +
|
||||
"- List 5-8 specific responsibilities\n" +
|
||||
"- Arrange by importance\n" +
|
||||
"- Start with action verbs, be specific\n" +
|
||||
"- Reflect work challenges and growth opportunities\n" +
|
||||
"\n" +
|
||||
"Requirements Guidelines:\n" +
|
||||
"- Separate into essential requirements and preferred qualifications\n" +
|
||||
"- Include four dimensions: education, experience, skills, and qualities\n" +
|
||||
"- Reasonable requirements, avoid excessive barriers\n" +
|
||||
"- Reflect position-specific needs\n" +
|
||||
"\n" +
|
||||
"Target Industry Adaptation:\n" +
|
||||
"\n" +
|
||||
"### Construction Industry\n" +
|
||||
"- Core Keywords: Safety first, quality control, project management, teamwork\n" +
|
||||
"- Key Requirements: Safety awareness, field experience, technical qualifications, stress resistance\n" +
|
||||
"- Development Path: Technical specialization, project management, safety management, quality control\n" +
|
||||
"\n" +
|
||||
"### Logistics Industry\n" +
|
||||
"- Core Keywords: Efficiency optimization, cost control, supply chain management, customer service\n" +
|
||||
"- Key Requirements: Time management, communication coordination, problem solving, strong responsibility\n" +
|
||||
"- Development Path: Operations optimization, management advancement, professional certification, cross-departmental development\n" +
|
||||
"\n" +
|
||||
"### Manufacturing Industry\n" +
|
||||
"- Core Keywords: Production efficiency, quality standards, safe operations, continuous improvement\n" +
|
||||
"- Key Requirements: Technical skills, safety awareness, teamwork, learning ability\n" +
|
||||
"- Development Path: Skill enhancement, team leader, supervisor, professional technical route\n" +
|
||||
"\n" +
|
||||
"### Hospitality Industry\n" +
|
||||
"- Core Keywords: Customer service, teamwork, flexibility, professional image\n" +
|
||||
"- Key Requirements: Service mindset, communication skills, stress resistance, language abilities\n" +
|
||||
"- Development Path: Service specialization, management training, department supervisor, hotel management\n" +
|
||||
"\n" +
|
||||
"### Mining Industry\n" +
|
||||
"- Core Keywords: Safe operations, environmental protection, technical standards, teamwork\n" +
|
||||
"- Key Requirements: Safety awareness, physical requirements, technical qualifications, emergency response\n" +
|
||||
"- Development Path: Technical certification, safety management, equipment expertise, field management\n" +
|
||||
"\n" +
|
||||
"Language Style:\n" +
|
||||
"- Practical and down-to-earth, close to frontline work\n" +
|
||||
"- Emphasize the importance of safety and quality\n" +
|
||||
"- Highlight career development and skill enhancement opportunities\n" +
|
||||
"- Emphasize teamwork and responsibility\n" +
|
||||
"- Avoid overly technical expressions, use clear and understandable language\n" +
|
||||
"\n" +
|
||||
"Output Format Requirements:\n" +
|
||||
"Must return standard JSON format with the following structure:\n" +
|
||||
"\n" +
|
||||
"```json\n" +
|
||||
"{\n" +
|
||||
" \"job_description\": {\n" +
|
||||
" \"overview\": \"Concise description of position value and significance\",\n" +
|
||||
" \"development_prospects\": \"Career development prospects description\"\n" +
|
||||
" },\n" +
|
||||
" \"key_responsibilities\": [\n" +
|
||||
" {\n" +
|
||||
" \"id\": 1,\n" +
|
||||
" \"responsibility\": \"Specific responsibility description\",\n" +
|
||||
" \"priority\": \"high|medium|low\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"requirements\": {\n" +
|
||||
" \"essential\": [\n" +
|
||||
" {\n" +
|
||||
" \"category\": \"education|experience|skills|qualities\",\n" +
|
||||
" \"requirement\": \"Specific requirement description\",\n" +
|
||||
" \"details\": \"Detailed explanation\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"preferred\": [\n" +
|
||||
" {\n" +
|
||||
" \"category\": \"education|experience|skills|qualities\", \n" +
|
||||
" \"requirement\": \"Preferred condition description\",\n" +
|
||||
" \"details\": \"Detailed explanation\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"company_culture\": \"Company culture and team atmosphere description\",\n" +
|
||||
" \"industry_focus\": \"Industry characteristics and focus\",\n" +
|
||||
" \"total_responsibilities\": 6,\n" +
|
||||
" \"total_essential_requirements\": 4,\n" +
|
||||
" \"total_preferred_requirements\": 3\n" +
|
||||
"}\n" +
|
||||
"```\n" +
|
||||
"\n" +
|
||||
"Important Notes:\n" +
|
||||
"- Ensure content complies with labor laws\n" +
|
||||
"- Avoid discriminatory language\n" +
|
||||
"- Maintain content timeliness and accuracy\n" +
|
||||
"- Adjust requirement difficulty based on different levels";
|
||||
|
||||
|
||||
return prompt;
|
||||
@Override
|
||||
public String handleAnalyzedAttachment(String connect) {
|
||||
//处理提示词数据
|
||||
String prompt = AiCommonPromptConstants.initializationAnalyzedAttachmentPrompt();
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role", "system");
|
||||
mapEntity.put("content",prompt);
|
||||
list.add(mapEntity);
|
||||
Map<String, String> mapUserEntity = new HashMap<>();
|
||||
mapUserEntity.put("role", "user");
|
||||
mapUserEntity.put("content",connect);
|
||||
list.add(mapUserEntity);
|
||||
String promptJson = JSONUtil.toJsonStr(list);
|
||||
String resultStr = chatGPTClient.handleAiChat(promptJson,"AAFX");
|
||||
String resultJson = resultStr.replaceAll("```json","").replaceAll("```","");
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化初筛问题生成提示词
|
||||
* @param jobTitle 岗位
|
||||
* @param jobRequirements 职位要求
|
||||
* @param screeningFocus 筛选重点
|
||||
* 处理附件分析结果合并信息
|
||||
* @param basicInformation 基础信息
|
||||
* @param attachmentContent 所有附件信息
|
||||
* @return
|
||||
*/
|
||||
private String initializationInitialScreeningQuestionsPrompt(String jobTitle,String jobRequirements,
|
||||
String screeningFocus){
|
||||
String prompt = "You are an experienced recruitment expert specializing in designing effective screening questions to quickly identify suitable candidates.\n" +
|
||||
"\n" +
|
||||
"Core Task:\n" +
|
||||
"Generate targeted and easily assessable screening questions based on job requirements and specified question types to help HR quickly filter candidates.\n" +
|
||||
"\n" +
|
||||
"Input Information:\n" +
|
||||
"- Job Title: ["+jobTitle+"]\n" +
|
||||
"- Job Requirements: ["+jobRequirements+"]\n" +
|
||||
"- Screening Focus: ["+screeningFocus+"]\n" +
|
||||
"- Question Type: [Specified question type to generate]\n" +
|
||||
"\n" +
|
||||
"Supported Question Types:\n" +
|
||||
"\n" +
|
||||
"### 1. Single Choice (Radio) - Single Selection\n" +
|
||||
"- Use Cases: Years of experience, education level, work status, etc.\n" +
|
||||
"- Features: Only one option can be selected, convenient for quick screening\n" +
|
||||
"- Examples: Work experience years, highest education, current work status\n" +
|
||||
"\n" +
|
||||
"### 2. Multiple Choices (Checkbox) - Multiple Selection\n" +
|
||||
"- Use Cases: Skills mastery, tool usage, certifications, etc.\n" +
|
||||
"- Features: Multiple options can be selected, comprehensive understanding of candidate abilities\n" +
|
||||
"- Examples: Programming languages mastered, tools used, certifications held\n" +
|
||||
"\n" +
|
||||
"### 3. Rating Scale (1-5) - Rating Questions\n" +
|
||||
"- Use Cases: Skill proficiency, experience richness, self-assessment, etc.\n" +
|
||||
"- Features: 1-5 point scale, convenient for quantitative comparison\n" +
|
||||
"- Examples: Skill proficiency level, project experience richness, communication ability self-assessment\n" +
|
||||
"\n" +
|
||||
"### 4. Short Text Answer - Open-ended Questions\n" +
|
||||
"- Use Cases: Project experience description, career planning, reasons for leaving, etc.\n" +
|
||||
"- Features: Requires text description, in-depth understanding of candidate situation\n" +
|
||||
"- Examples: Project experience description, career development planning, work motivation\n" +
|
||||
"\n" +
|
||||
"Question Design Principles:\n" +
|
||||
"1. Generate questions in the specified format according to the designated question type\n" +
|
||||
"2. Questions should be specific and clear, avoiding vague statements\n" +
|
||||
"3. Easy to quantify and compare for assessment\n" +
|
||||
"4. Quickly identify candidates who don't meet basic requirements\n" +
|
||||
"5. Cover key dimensions: skills, experience, attitude, etc.\n" +
|
||||
"6. Limit to 5-8 questions to avoid excessive length\n" +
|
||||
"\n" +
|
||||
"Question Type Selection Guidelines:\n" +
|
||||
"- Basic qualification screening: Prioritize Single Choice\n" +
|
||||
"- Skills and abilities assessment: Use Multiple Choices or Rating Scale\n" +
|
||||
"- In-depth experience understanding: Use Short Text Answer\n" +
|
||||
"- Degree assessment: Use Rating Scale\n" +
|
||||
"\n" +
|
||||
"Industry-Specific Questions:\n" +
|
||||
"\n" +
|
||||
"### Technology Industry\n" +
|
||||
"- Data sensitivity, user thinking, rapid learning ability\n" +
|
||||
"- Attention to and learning capability for new technologies\n" +
|
||||
"\n" +
|
||||
"### Sales Positions\n" +
|
||||
"- Sales performance, client maintenance, stress resistance\n" +
|
||||
"- Communication skills and negotiation experience\n" +
|
||||
"\n" +
|
||||
"### Technical Positions\n" +
|
||||
"- Programming languages, project experience, technical depth\n" +
|
||||
"- Ability and methods for learning new technologies\n" +
|
||||
"\n" +
|
||||
"### Operations Positions\n" +
|
||||
"- Data analysis capability, event planning experience\n" +
|
||||
"- Understanding of user growth and retention\n" +
|
||||
"\n" +
|
||||
"Output Format Requirements:\n" +
|
||||
"Must return standard JSON format with the following structure:\n" +
|
||||
"\n" +
|
||||
"```json\n" +
|
||||
"{\n" +
|
||||
" \"questions\": [\n" +
|
||||
" {\n" +
|
||||
" \"id\": 1,\n" +
|
||||
" \"type\": \"single_choice|multiple_choices|rating_scale|short_text\",\n" +
|
||||
" \"question\": \"Question content\",\n" +
|
||||
" \"options\": [\"Option 1\", \"Option 2\", \"Option 3\"], // Only for single_choice and multiple_choices\n" +
|
||||
" \"scale\": {\n" +
|
||||
" \"min\": 1,\n" +
|
||||
" \"max\": 5,\n" +
|
||||
" \"labels\": {\n" +
|
||||
" \"1\": \"Not familiar at all\",\n" +
|
||||
" \"2\": \"Slightly familiar\", \n" +
|
||||
" \"3\": \"Moderately familiar\",\n" +
|
||||
" \"4\": \"Quite familiar\",\n" +
|
||||
" \"5\": \"Very familiar\"\n" +
|
||||
" }\n" +
|
||||
" }, // Only for rating_scale\n" +
|
||||
" \"placeholder\": \"Please briefly describe...\", // Only for short_text\n" +
|
||||
" \"required\": true,\n" +
|
||||
" \"category\": \"basic_qualification|skills_assessment|experience_verification|motivation_attitude|practical_conditions\",\n" +
|
||||
" \"scoring_criteria\": \"Scoring criteria description\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"screening_guidelines\": {\n" +
|
||||
" \"must_meet_conditions\": [\"Must-meet condition 1\", \"Must-meet condition 2\"],\n" +
|
||||
" \"bonus_points\": [\"Bonus point 1\", \"Bonus point 2\"],\n" +
|
||||
" \"red_flags\": [\"Red flag 1\", \"Red flag 2\"]\n" +
|
||||
" },\n" +
|
||||
" \"total_questions\": 5\n" +
|
||||
"}\n" +
|
||||
"```\n" +
|
||||
"\n" +
|
||||
"Important Notes:\n" +
|
||||
"1. Questions must be legal and compliant, avoiding personal privacy\n" +
|
||||
"2. Avoid discriminatory questions (age, gender, marital status, etc.)\n" +
|
||||
"3. Questions should be directly related to the position\n" +
|
||||
"4. Maintain objectivity and fairness in questions\n" +
|
||||
"5. Consider candidate response time, avoid overly complex questions\n" +
|
||||
"\n" +
|
||||
"Quality Checklist:\n" +
|
||||
"□ Are questions directly related to job requirements?\n" +
|
||||
"□ Can they effectively distinguish suitable from unsuitable candidates?\n" +
|
||||
"□ Are question statements clear and understandable?\n" +
|
||||
"□ Have discriminatory contents been avoided?\n" +
|
||||
"□ Are assessment criteria clear?";
|
||||
|
||||
|
||||
return prompt;
|
||||
@Override
|
||||
public String handleAttachmentResultMerging(String basicInformation, String attachmentContent) {
|
||||
//处理提示词数据
|
||||
String prompt = AiCommonPromptConstants.initializationAttachmentResultMergingPrompt(basicInformation,attachmentContent);
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role", "system");
|
||||
mapEntity.put("content",prompt);
|
||||
list.add(mapEntity);
|
||||
Map<String, String> mapUserEntity = new HashMap<>();
|
||||
mapUserEntity.put("role", "user");
|
||||
mapUserEntity.put("content","基本信息:"+basicInformation+"\\n分析结果:"+attachmentContent);
|
||||
list.add(mapUserEntity);
|
||||
String promptJson = JSONUtil.toJsonStr(list);
|
||||
String resultStr = chatGPTClient.handleAiChat(promptJson,"AAHB");
|
||||
String resultJson = resultStr.replaceAll("```json","").replaceAll("```","");
|
||||
log.info("处理附件分析结果合并信息:{}",resultJson);
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化简历岗位匹配度评分提示词
|
||||
*
|
||||
* @param jobTitle 岗位
|
||||
* @param jobDescription 岗位描述
|
||||
* @param keyResponsibilities 主要职责
|
||||
* @param jobRequirements 任职要求
|
||||
* @param personalInformation 个人信息
|
||||
* @param workHistory 工作经历
|
||||
* @param projectExperience 项目经验
|
||||
* @param skillsList 技能清单
|
||||
* @param educationalBackground 教育背景
|
||||
* @param otherRelevantInformation 其他相关信息
|
||||
* 生成最终的Markdown格式简历
|
||||
* @param markdown
|
||||
* @return
|
||||
*/
|
||||
private String initializationResumeJobMatchingScorePrompt(String jobTitle,String jobDescription,
|
||||
String keyResponsibilities,String jobRequirements,
|
||||
String personalInformation,String workHistory,
|
||||
String projectExperience,String skillsList,
|
||||
String educationalBackground,String otherRelevantInformation){
|
||||
String prompt = "You are a professional resume analysis expert and recruitment consultant, specializing in evaluating the match between candidate resumes and specific job positions.\n" +
|
||||
"\n" +
|
||||
"Core Task:\n" +
|
||||
"Comprehensively analyze candidate resumes and target job requirements to provide objective and accurate job fit scoring and detailed analysis reports.\n" +
|
||||
"\n" +
|
||||
"Input Information:\n" +
|
||||
"1. Job Information:\n" +
|
||||
" - Job Title:["+jobTitle+"]\n" +
|
||||
" - Job Description:["+jobDescription+"]\n" +
|
||||
" - Key Responsibilities:["+keyResponsibilities+"]\n" +
|
||||
" - Requirements (essential and preferred qualifications):["+jobRequirements+"]\n" +
|
||||
"\n" +
|
||||
"2. Candidate Resume:\n" +
|
||||
" - Personal information (work experience, educational background, etc.):["+personalInformation+"]\n" +
|
||||
" - Work History:["+workHistory+"]\n" +
|
||||
" - Project Experience:["+projectExperience+"]\n" +
|
||||
" - Skills List:["+skillsList+"]\n" +
|
||||
" - Educational Background:["+educationalBackground+"]\n" +
|
||||
" - Other relevant information:["+otherRelevantInformation+"]\n" +
|
||||
"\n" +
|
||||
"Scoring Dimensions (Total 100 points):\n" +
|
||||
"\n" +
|
||||
"### 1. Work Experience Match (30 points)\n" +
|
||||
"- Relevant industry experience: 10 points\n" +
|
||||
"- Similar position experience: 15 points\n" +
|
||||
"- Work years alignment: 5 points\n" +
|
||||
"\n" +
|
||||
"Scoring Standards:\n" +
|
||||
"- Perfect match: Full points\n" +
|
||||
"- Highly relevant: 80-90%\n" +
|
||||
"- Partially relevant: 60-79%\n" +
|
||||
"- Slightly relevant: 40-59%\n" +
|
||||
"- Not relevant: 0-39%\n" +
|
||||
"\n" +
|
||||
"### 2. Skills and Abilities Match (25 points)\n" +
|
||||
"- Professional skills: 15 points\n" +
|
||||
"- Soft skills: 10 points\n" +
|
||||
"\n" +
|
||||
"Scoring Focus:\n" +
|
||||
"- Mastery level of essential skills\n" +
|
||||
"- Coverage of preferred skills\n" +
|
||||
"- Skill depth and breadth\n" +
|
||||
"- Demonstration of learning ability\n" +
|
||||
"\n" +
|
||||
"### 3. Educational Background Match (15 points)\n" +
|
||||
"- Education level: 8 points\n" +
|
||||
"- Major relevance: 7 points\n" +
|
||||
"\n" +
|
||||
"Considerations:\n" +
|
||||
"- Whether education level meets requirements\n" +
|
||||
"- Degree of major background relevance\n" +
|
||||
"- Continuous learning and professional development\n" +
|
||||
"\n" +
|
||||
"### 4. Project Experience Match (20 points)\n" +
|
||||
"- Project scale and complexity: 10 points\n" +
|
||||
"- Project outcomes and impact: 10 points\n" +
|
||||
"\n" +
|
||||
"Assessment Points:\n" +
|
||||
"- Relevance of projects to target position\n" +
|
||||
"- Role and responsibilities in projects\n" +
|
||||
"- Quantified project achievements\n" +
|
||||
"- Demonstration of problem-solving abilities\n" +
|
||||
"\n" +
|
||||
"### 5. Overall Quality Assessment (10 points)\n" +
|
||||
"- Career development trajectory: 5 points\n" +
|
||||
"- Stability and growth potential: 5 points\n" +
|
||||
"\n" +
|
||||
"Considerations:\n" +
|
||||
"- Logic and coherence of career development\n" +
|
||||
"- Work stability (job-hopping frequency and reasons)\n" +
|
||||
"- Growth potential and learning ability\n" +
|
||||
"- Clarity of career planning\n" +
|
||||
"\n" +
|
||||
"Output Format Requirements:\n" +
|
||||
"Must return standard JSON format with the following structure:\n" +
|
||||
"\n" +
|
||||
"```json\n" +
|
||||
"{\n" +
|
||||
" \"overall_score\": {\n" +
|
||||
" \"total_score\": 85,\n" +
|
||||
" \"max_score\": 100,\n" +
|
||||
" \"match_level\": \"excellent|good|average|poor\",\n" +
|
||||
" \"recommendation\": \"strongly_recommend|recommend|consider_carefully|not_recommend\"\n" +
|
||||
" },\n" +
|
||||
" \"detailed_scores\": {\n" +
|
||||
" \"work_experience\": {\n" +
|
||||
" \"total\": 25,\n" +
|
||||
" \"max\": 30,\n" +
|
||||
" \"breakdown\": {\n" +
|
||||
" \"industry_experience\": {\"score\": 8, \"max\": 10, \"analysis\": \"Analysis explanation\"},\n" +
|
||||
" \"similar_position\": {\"score\": 12, \"max\": 15, \"analysis\": \"Analysis explanation\"},\n" +
|
||||
" \"work_years\": {\"score\": 5, \"max\": 5, \"analysis\": \"Analysis explanation\"}\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"skills_abilities\": {\n" +
|
||||
" \"total\": 20,\n" +
|
||||
" \"max\": 25,\n" +
|
||||
" \"breakdown\": {\n" +
|
||||
" \"professional_skills\": {\"score\": 12, \"max\": 15, \"matching_skills\": [\"Skill 1\", \"Skill 2\"], \"missing_skills\": [\"Missing skill 1\"]},\n" +
|
||||
" \"soft_skills\": {\"score\": 8, \"max\": 10, \"analysis\": \"Analysis explanation\"}\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"education\": {\n" +
|
||||
" \"total\": 12,\n" +
|
||||
" \"max\": 15,\n" +
|
||||
" \"breakdown\": {\n" +
|
||||
" \"education_level\": {\"score\": 6, \"max\": 8, \"analysis\": \"Analysis explanation\"},\n" +
|
||||
" \"major_relevance\": {\"score\": 6, \"max\": 7, \"analysis\": \"Analysis explanation\"}\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"project_experience\": {\n" +
|
||||
" \"total\": 18,\n" +
|
||||
" \"max\": 20,\n" +
|
||||
" \"relevant_projects\": [\"Project 1\", \"Project 2\"],\n" +
|
||||
" \"achievement_highlights\": [\"Achievement 1\", \"Achievement 2\"],\n" +
|
||||
" \"analysis\": \"Project experience analysis\"\n" +
|
||||
" },\n" +
|
||||
" \"overall_quality\": {\n" +
|
||||
" \"total\": 8,\n" +
|
||||
" \"max\": 10,\n" +
|
||||
" \"breakdown\": {\n" +
|
||||
" \"career_trajectory\": {\"score\": 4, \"max\": 5, \"analysis\": \"Analysis explanation\"},\n" +
|
||||
" \"stability_growth\": {\"score\": 4, \"max\": 5, \"analysis\": \"Analysis explanation\"}\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"match_highlights\": [\n" +
|
||||
" \"Outstanding matching advantage 1\",\n" +
|
||||
" \"Outstanding matching advantage 2\",\n" +
|
||||
" \"Outstanding matching advantage 3\"\n" +
|
||||
" ],\n" +
|
||||
" \"risk_points\": [\n" +
|
||||
" \"Issue requiring attention 1\",\n" +
|
||||
" \"Issue requiring attention 2\"\n" +
|
||||
" ],\n" +
|
||||
" \"interview_recommendations\": {\n" +
|
||||
" \"key_assessment_areas\": [\"Key assessment area 1\", \"Key assessment area 2\"],\n" +
|
||||
" \"critical_questions\": [\"Suggested interview question 1\", \"Suggested interview question 2\"],\n" +
|
||||
" \"skill_verification\": [\"Skill to verify 1\", \"Skill to verify 2\"]\n" +
|
||||
" },\n" +
|
||||
" \"hiring_recommendation\": {\n" +
|
||||
" \"level\": \"strongly_recommend|recommend|consider_carefully|not_recommend\",\n" +
|
||||
" \"reasoning\": \"Brief explanation of recommendation\"\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
"```\n" +
|
||||
"\n" +
|
||||
"Scoring Level Descriptions:\n" +
|
||||
"- 90-100 points: Excellent match, strongly recommend\n" +
|
||||
"- 80-89 points: Good match, recommend for interview\n" +
|
||||
"- 70-79 points: Average match, consider for interview\n" +
|
||||
"- 60-69 points: Low match, consider carefully\n" +
|
||||
"- Below 60 points: Poor match, not recommended\n" +
|
||||
"\n" +
|
||||
"Important Notes:\n" +
|
||||
"1. Maintain objectivity and fairness, base assessment on facts\n" +
|
||||
"2. Avoid personal bias and discrimination\n" +
|
||||
"3. Consider candidate's growth potential\n" +
|
||||
"4. Combine company culture and team needs\n" +
|
||||
"5. Provide constructive analysis and recommendations\n" +
|
||||
"\n" +
|
||||
"Quality Check:\n" +
|
||||
"□ Is the scoring well-supported by evidence?\n" +
|
||||
"□ Is the analysis objective and comprehensive?\n" +
|
||||
"□ Are all key dimensions considered?\n" +
|
||||
"□ Are recommendations actionable?\n" +
|
||||
"□ Have discriminatory evaluations been avoided?";
|
||||
|
||||
|
||||
return prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化简历优化分析器提示词
|
||||
* @return
|
||||
*/
|
||||
private String initializationResumeAnalysisOptimizerPrompt(){
|
||||
String prompt = "You are a professional resume analysis and optimization expert, specializing in providing resume improvement recommendations for traditional industries including construction, logistics, manufacturing, hospitality, and mining.\n" +
|
||||
"\n" +
|
||||
"## Core Mission\n" +
|
||||
"Analyze uploaded resumes, identify issues, and provide optimization recommendations to help candidates improve resume quality and job search success rates.\n" +
|
||||
"\n" +
|
||||
"## Analysis Dimensions\n" +
|
||||
"\n" +
|
||||
"### 1. Text Correction Analysis\n" +
|
||||
"Check for the following issues:\n" +
|
||||
"- **Spelling Errors**: Identify word spelling mistakes\n" +
|
||||
"- **Grammar Errors**: Sentence structure, tense, and grammatical issues\n" +
|
||||
"- **Punctuation**: Improper or missing punctuation usage\n" +
|
||||
"- **Format Consistency**: Date formats, capitalization, abbreviation uniformity\n" +
|
||||
"- **Professional Terminology**: Accuracy of industry-specific terms\n" +
|
||||
"\n" +
|
||||
"### 2. Logic Correction Analysis\n" +
|
||||
"Check for the following issues:\n" +
|
||||
"- **Timeline Conflicts**: Overlapping or illogical dates in work/education history\n" +
|
||||
"- **Career Progression Logic**: Whether promotion paths are reasonable\n" +
|
||||
"- **Skill Matching**: Whether claimed skills match work experience\n" +
|
||||
"- **Experience Consistency**: Whether descriptions across sections are consistent\n" +
|
||||
"- **Gap Explanations**: Whether employment gaps need clarification\n" +
|
||||
"\n" +
|
||||
"### 3. Content Optimization Recommendations\n" +
|
||||
"Provide the following optimization suggestions:\n" +
|
||||
"- **Personal Summary Optimization**: Highlight core strengths and value proposition\n" +
|
||||
"- **Work Experience Optimization**: Use quantified data and specific achievements\n" +
|
||||
"- **Skills Display Optimization**: Organize by importance and relevance\n" +
|
||||
"- **Keyword Optimization**: Add industry-relevant keywords\n" +
|
||||
"- **Structure Optimization**: Improve resume layout and information hierarchy\n" +
|
||||
"\n" +
|
||||
"## Traditional Industry Focus\n" +
|
||||
"\n" +
|
||||
"### Construction Industry Priorities\n" +
|
||||
"- Safety qualifications and certifications\n" +
|
||||
"- Project scale and complexity\n" +
|
||||
"- Site management experience\n" +
|
||||
"- Quality control capabilities\n" +
|
||||
"\n" +
|
||||
"### Logistics Industry Priorities\n" +
|
||||
"- Transportation efficiency optimization\n" +
|
||||
"- Inventory management experience\n" +
|
||||
"- Customer service capabilities\n" +
|
||||
"- Cost control achievements\n" +
|
||||
"\n" +
|
||||
"### Manufacturing Industry Priorities\n" +
|
||||
"- Production efficiency improvements\n" +
|
||||
"- Quality management systems\n" +
|
||||
"- Equipment operation skills\n" +
|
||||
"- Safety operation records\n" +
|
||||
"\n" +
|
||||
"### Hospitality Industry Priorities\n" +
|
||||
"- Customer service experience\n" +
|
||||
"- Multilingual capabilities\n" +
|
||||
"- Team collaboration skills\n" +
|
||||
"- Sales performance\n" +
|
||||
"\n" +
|
||||
"### Mining Industry Priorities\n" +
|
||||
"- Safety operation qualifications\n" +
|
||||
"- Equipment operation experience\n" +
|
||||
"- Environmental adaptability\n" +
|
||||
"- Technical compliance adherence\n" +
|
||||
"\n" +
|
||||
"## Output Format\n" +
|
||||
"\n" +
|
||||
"Please strictly follow this JSON format for analysis results:\n" +
|
||||
"\n" +
|
||||
"```json\n" +
|
||||
"{\n" +
|
||||
" \"analysis_summary\": {\n" +
|
||||
" \"overall_score\": 85,\n" +
|
||||
" \"main_strengths\": [\"Specific strength 1\", \"Specific strength 2\"],\n" +
|
||||
" \"critical_issues\": [\"Critical issue 1\", \"Critical issue 2\"],\n" +
|
||||
" \"improvement_potential\": \"high|medium|low\"\n" +
|
||||
" },\n" +
|
||||
" \"text_corrections\": {\n" +
|
||||
" \"spelling_errors\": [\n" +
|
||||
" {\n" +
|
||||
" \"original\": \"Incorrect text\",\n" +
|
||||
" \"corrected\": \"Correct text\",\n" +
|
||||
" \"location\": \"Personal summary line 2\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"grammar_errors\": [\n" +
|
||||
" {\n" +
|
||||
" \"original\": \"Grammatically incorrect sentence\",\n" +
|
||||
" \"corrected\": \"Corrected sentence\",\n" +
|
||||
" \"location\": \"Work experience item 1\",\n" +
|
||||
" \"explanation\": \"Tense inconsistency\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"formatting_issues\": [\n" +
|
||||
" {\n" +
|
||||
" \"issue\": \"Inconsistent date format\",\n" +
|
||||
" \"suggestion\": \"Use consistent MM/YYYY format\",\n" +
|
||||
" \"locations\": [\"Work Experience\", \"Education\"]\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"logic_corrections\": {\n" +
|
||||
" \"timeline_conflicts\": [\n" +
|
||||
" {\n" +
|
||||
" \"conflict\": \"Overlapping work periods\",\n" +
|
||||
" \"details\": \"2020-2022 at Company A, 2021-2023 at Company B\",\n" +
|
||||
" \"suggestion\": \"Verify and correct timeline, or explain part-time situation\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"career_progression\": [\n" +
|
||||
" {\n" +
|
||||
" \"issue\": \"Position regression\",\n" +
|
||||
" \"details\": \"From Manager to Assistant\",\n" +
|
||||
" \"suggestion\": \"Explain reason for position change or adjust description\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"skill_experience_mismatch\": [\n" +
|
||||
" {\n" +
|
||||
" \"skill\": \"Project Management\",\n" +
|
||||
" \"issue\": \"Claims 5 years experience but work history shows only 2 years\",\n" +
|
||||
" \"suggestion\": \"Adjust skill description or add relevant experience\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"optimization_suggestions\": {\n" +
|
||||
" \"personal_summary\": {\n" +
|
||||
" \"current_issues\": [\"Too generic\", \"Lacks quantified data\"],\n" +
|
||||
" \"optimized_version\": \"Experienced construction project manager with 8 years in residential and commercial projects, successfully managing projects worth over $5M, specializing in cost control and quality management, certified PMP with White Card qualification.\",\n" +
|
||||
" \"key_improvements\": [\"Add specific numbers\", \"Highlight core qualifications\", \"Emphasize industry experience\"]\n" +
|
||||
" },\n" +
|
||||
" \"work_experience\": [\n" +
|
||||
" {\n" +
|
||||
" \"position\": \"Project Manager - ABC Construction\",\n" +
|
||||
" \"current_description\": \"Responsible for project management work\",\n" +
|
||||
" \"optimized_description\": \"• Managed 3 concurrent residential projects worth $2.8M, achieving 100% on-time, on-budget completion rate\\n• Coordinated 15-person team including engineers, contractors, and suppliers\\n• Implemented quality control processes, reducing rework by 25%\",\n" +
|
||||
" \"improvements\": [\"Quantify achievements\", \"Specific responsibilities\", \"Highlight accomplishments\"]\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"skills_section\": {\n" +
|
||||
" \"current_issues\": [\"Poor skill ordering\", \"Missing industry keywords\"],\n" +
|
||||
" \"suggested_structure\": {\n" +
|
||||
" \"core_skills\": [\"Project Management\", \"Quality Control\", \"Cost Management\", \"Team Leadership\"],\n" +
|
||||
" \"technical_skills\": [\"AutoCAD\", \"MS Project\", \"Building Codes\", \"Safety Management\"],\n" +
|
||||
" \"certifications\": [\"PMP\", \"White Card\", \"First Aid\", \"WHS Certificate\"]\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"keyword_optimization\": {\n" +
|
||||
" \"missing_keywords\": [\"Construction Management\", \"Site Supervision\", \"Safety Compliance\", \"Budget Control\"],\n" +
|
||||
" \"industry_terms\": [\"Residential Construction\", \"Commercial Projects\", \"Subcontractor Management\", \"Quality Assurance\"],\n" +
|
||||
" \"ats_keywords\": [\"Project Delivery\", \"Cost Effectiveness\", \"Team Collaboration\", \"Customer Satisfaction\"]\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"action_plan\": {\n" +
|
||||
" \"immediate_fixes\": [\n" +
|
||||
" \"Correct all spelling and grammar errors\",\n" +
|
||||
" \"Standardize dates and formatting\",\n" +
|
||||
" \"Resolve timeline conflicts\"\n" +
|
||||
" ],\n" +
|
||||
" \"content_improvements\": [\n" +
|
||||
" \"Rewrite personal summary to highlight core value\",\n" +
|
||||
" \"Add quantified achievements to each work experience\",\n" +
|
||||
" \"Reorganize skills section\"\n" +
|
||||
" ],\n" +
|
||||
" \"strategic_enhancements\": [\n" +
|
||||
" \"Add industry-relevant keywords\",\n" +
|
||||
" \"Highlight safety and compliance experience\",\n" +
|
||||
" \"Emphasize project management achievements\"\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"estimated_improvement\": {\n" +
|
||||
" \"current_ats_score\": 65,\n" +
|
||||
" \"potential_ats_score\": 85,\n" +
|
||||
" \"recruiter_appeal\": \"Significantly improved\",\n" +
|
||||
" \"interview_probability\": \"+40%\"\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
"```\n" +
|
||||
"\n" +
|
||||
"## Analysis Principles\n" +
|
||||
"\n" +
|
||||
"1. **Constructive**: All suggestions should be actionable improvement recommendations\n" +
|
||||
"2. **Specific**: Provide concrete modification examples, not just general advice\n" +
|
||||
"3. **Industry-Relevant**: Offer targeted suggestions based on target industry characteristics\n" +
|
||||
"4. **Balanced**: Point out issues while also acknowledging strengths\n" +
|
||||
"5. **Practical**: Consider actual needs of ATS systems and recruiters\n" +
|
||||
"\n" +
|
||||
"## Important Notes\n" +
|
||||
"\n" +
|
||||
"- Maintain professional and encouraging tone\n" +
|
||||
"- Avoid overly harsh criticism\n" +
|
||||
"- Provide feasible solutions\n" +
|
||||
"- Consider candidates of different experience levels\n" +
|
||||
"- Respect personal privacy, don't request sensitive information";
|
||||
|
||||
return prompt;
|
||||
@Override
|
||||
public String handleGenerateMarkdown(String markdown) {
|
||||
String prompt = AiCommonPromptConstants.initializationGenerateMarkdownPrompt();
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role", "system");
|
||||
mapEntity.put("content",prompt);
|
||||
list.add(mapEntity);
|
||||
Map<String, String> mapUserEntity = new HashMap<>();
|
||||
mapUserEntity.put("role", "user");
|
||||
mapUserEntity.put("content",markdown);
|
||||
list.add(mapUserEntity);
|
||||
String promptJson = JSONUtil.toJsonStr(list);
|
||||
String resultStr = chatGPTClient.handleAiChat(promptJson,"MARKDOWN");
|
||||
String resultJson = resultStr.replaceAll("```json","").replaceAll("```","");
|
||||
log.info("处理附件分析结果合并信息:{}",resultJson);
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化初步筛选问题淘汰评分提示词
|
||||
* 网站内容抓取
|
||||
* @param webUrl 网站链接地址
|
||||
* @return
|
||||
*/
|
||||
private String initializationQuestionEliminationScorePrompt(String roleName){
|
||||
|
||||
String prompt = "你是资深的面试专家和职业顾问,专注于为建筑、物流、制造、酒店、矿业等传统行业的求职者初步筛选面试回答进行打分,分数区间为0到100分。\n" +
|
||||
"\n" +
|
||||
"##核心任务\n" +
|
||||
"根据所提供的问题与答案,结合所申请的岗位,进行最终的打分与评价说明.\n" +
|
||||
"\n" +
|
||||
"##输入项参数\n" +
|
||||
"岗位:[]\n" +
|
||||
"\n" +
|
||||
"##返回的结构\n" +
|
||||
"\n" +
|
||||
"{ \\\"score\\\": \\\"\\\", \\\"evaluate\\\": \\\"\\\"}。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息,score为分数,evaluate为评价说明(返回英文)";
|
||||
|
||||
return prompt;
|
||||
@Override
|
||||
public String handleWebContentScraping(String webUrl) {
|
||||
//网站内容抓取
|
||||
try {
|
||||
String htmlContent = ReadHtmlByOkHttp.getHtmlContentByOkHttp(webUrl);
|
||||
String resultStr = ReadHtmlByOkHttp.removeHtmlTagAndAttrByJsoup(htmlContent);
|
||||
String resultData = ReadHtmlByOkHttp.removeBlankLineAndSpace(resultStr);
|
||||
return resultData;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 网站AI信息提取(使用提示词)
|
||||
* @param webInfoExtractVo 网站提取对象
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String handleWebInfoExtract(HotakeWebInfoExtractVo webInfoExtractVo) {
|
||||
//获取
|
||||
String webContent = handleWebContentScraping(webInfoExtractVo.getWebUrl());
|
||||
|
||||
String prompt = AiCommonPromptConstants.initializationWebInfoExtractPrompt();
|
||||
String userPrompt = "Please analyze the following company website:\n" +
|
||||
"\n" +
|
||||
"URL: "+webInfoExtractVo.getWebUrl()+"\n" +
|
||||
"\n" +
|
||||
"Content:\n" +
|
||||
webContent;
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role", "system");
|
||||
mapEntity.put("content",prompt);
|
||||
list.add(mapEntity);
|
||||
Map<String, String> mapUserEntity = new HashMap<>();
|
||||
mapUserEntity.put("role", "user");
|
||||
mapUserEntity.put("content",userPrompt);
|
||||
list.add(mapUserEntity);
|
||||
String promptJson = JSONUtil.toJsonStr(list);
|
||||
String resultStr = chatGPTClient.handleAiChat(promptJson,"WEBAITQ");
|
||||
String resultJson = resultStr.replaceAll("```json","").replaceAll("```","");
|
||||
log.info("网站AI信息提取:{}",resultJson);
|
||||
//直接更新个人信息中的企业名和地址
|
||||
Map dataMap = JSONUtil.toBean(resultJson,Map.class);
|
||||
Map companyOverviewMap = (Map)dataMap.get("company_overview");
|
||||
String companyName = companyOverviewMap.get("company_name").toString();
|
||||
Map contactInfoMap = (Map)companyOverviewMap.get("contact_info");
|
||||
String location = contactInfoMap.get("address").toString();
|
||||
|
||||
SysUser user = userMapper.selectUserById(SecurityUtils.getUserId());
|
||||
user.setCompanyName(companyName);
|
||||
user.setLocation(location);
|
||||
userMapper.updateUser(user);
|
||||
// String resultData = handleWebInfoEnhancedProcessing(resultJson);
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 网站信息增强处理
|
||||
* @param webUlr
|
||||
* @param webContent 网站内容
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String handleWebInfoEnhancedProcessing(String webContent) {
|
||||
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role", "system");
|
||||
mapEntity.put("content","You are a professional HR consultant...\n" +
|
||||
"Please enhance and structure the company information...");
|
||||
list.add(mapEntity);
|
||||
Map<String, String> mapUserEntity = new HashMap<>();
|
||||
mapUserEntity.put("role", "user");
|
||||
mapUserEntity.put("content","Please enhance the following company information:\n" +webContent);
|
||||
list.add(mapUserEntity);
|
||||
String promptJson = JSONUtil.toJsonStr(list);
|
||||
String resultStr = chatGPTClient.handleAiChat(promptJson,"WEBAITQ");
|
||||
String resultJson = resultStr.replaceAll("```json","").replaceAll("```","");
|
||||
log.info("网站信息增强处理:{}",resultJson);
|
||||
|
||||
return resultJson;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,33 +6,39 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.vetti.common.ai.gpt.ChatGPTClient;
|
||||
import com.vetti.common.config.RuoYiConfig;
|
||||
import com.vetti.common.core.service.BaseServiceImpl;
|
||||
import com.vetti.common.enums.FillTypeEnum;
|
||||
import com.vetti.common.enums.MinioBucketNameEnum;
|
||||
import com.vetti.common.utils.HtmlToPdfUtil;
|
||||
import com.vetti.common.utils.MarkdownUtil;
|
||||
import com.vetti.common.utils.MultipartFileUtil;
|
||||
import com.vetti.common.utils.SecurityUtils;
|
||||
import com.vetti.common.utils.readFile.FileContentUtil;
|
||||
import com.vetti.hotake.domain.HotakeCvInfo;
|
||||
import com.vetti.hotake.domain.HotakeProblemBaseInfo;
|
||||
import com.vetti.hotake.domain.HotakeSysFile;
|
||||
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
|
||||
import com.vetti.hotake.domain.dto.HotakeCvOptimizeDto;
|
||||
import com.vetti.hotake.domain.dto.VcDto.*;
|
||||
import com.vetti.hotake.domain.vo.HotakeSysFileVo;
|
||||
import com.vetti.hotake.mapper.HotakeCvInfoMapper;
|
||||
import com.vetti.hotake.service.IHotakeAiCommonToolsService;
|
||||
import com.vetti.hotake.service.IHotakeCvInfoService;
|
||||
import com.vetti.hotake.service.IHotakeProblemBaseInfoService;
|
||||
import com.vetti.hotake.service.IHotakeSysFileService;
|
||||
import io.minio.GetObjectArgs;
|
||||
import io.minio.MinioClient;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 简历信息Service业务层处理
|
||||
@@ -45,6 +51,9 @@ import java.util.Map;
|
||||
@Service
|
||||
public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeCvInfoService {
|
||||
|
||||
// 系统目录
|
||||
private static final String SYSTEM_DIR = "/system_files/";
|
||||
|
||||
/**
|
||||
* 问题前缀
|
||||
*/
|
||||
@@ -65,6 +74,9 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
||||
@Autowired
|
||||
private IHotakeAiCommonToolsService aiCommonToolsService;
|
||||
|
||||
@Autowired
|
||||
private IHotakeSysFileService sysFileService;
|
||||
|
||||
/**
|
||||
* 查询简历信息
|
||||
*
|
||||
@@ -134,14 +146,21 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public HotakeCvInfo insertHotakeCvInfo(HotakeCvInfo hotakeCvInfo) {
|
||||
//删除原先的CV简历信息
|
||||
hotakeCvInfoMapper.deleteHotakeCvInfoByUserIdAndType(SecurityUtils.getUserId(),"cv");
|
||||
if("cv".equals(hotakeCvInfo.getCvFileType())){
|
||||
//删除原先的CV简历信息
|
||||
hotakeCvInfoMapper.deleteHotakeCvInfoByUserIdAndType(SecurityUtils.getUserId(),"cv");
|
||||
}
|
||||
fill(FillTypeEnum.INSERT.getCode(), hotakeCvInfo);
|
||||
String fileSuffix = FileUtil.getSuffix(hotakeCvInfo.getCvUrl());
|
||||
if (StrUtil.isNotEmpty(fileSuffix)) {
|
||||
fileSuffix = fileSuffix.toLowerCase();
|
||||
}
|
||||
hotakeCvInfo.setCvFileSuffix(fileSuffix);
|
||||
if(!"cv".equals(hotakeCvInfo.getCvFileType())){
|
||||
//对附件进行基础数据的解析
|
||||
String resultStr = handleAnalyzedAttachment(hotakeCvInfo.getCvUrl(),fileSuffix);
|
||||
hotakeCvInfo.setAnalyzedAttachmentJson(resultStr);
|
||||
}
|
||||
hotakeCvInfoMapper.insertHotakeCvInfo(hotakeCvInfo);
|
||||
return hotakeCvInfo;
|
||||
}
|
||||
@@ -331,6 +350,168 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
||||
return cvInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据其他的附件信息生成个人简历
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public HotakeCvInfo getGenerateResume() {
|
||||
//根据候选人登陆信息查询所有的附件信息
|
||||
HotakeCvInfo queryCv = new HotakeCvInfo();
|
||||
queryCv.setUserId(SecurityUtils.getUserId());
|
||||
List<HotakeCvInfo> cvInfoList = hotakeCvInfoMapper.selectHotakeCvInfoList(queryCv);
|
||||
|
||||
//基础数据信息,从推荐信中过去
|
||||
String basicInformation = "";
|
||||
//其他的附件信息集合
|
||||
String attachmentContent = "";
|
||||
if(CollectionUtil.isNotEmpty(cvInfoList)){
|
||||
List<HotakeCvInfo> cvInfos = cvInfoList.stream().filter(e->"letter".equals(e.getCvFileType())).toList();
|
||||
if(CollectionUtil.isNotEmpty(cvInfos)){
|
||||
basicInformation = cvInfos.get(0).getAnalyzedAttachmentJson();
|
||||
}
|
||||
List<HotakeCvInfo> cvInfoOnes = cvInfoList.stream().filter(e->!"letter".equals(e.getCvFileType())
|
||||
&& "cv".equals(e.getCvFileType())).toList();
|
||||
if(CollectionUtil.isNotEmpty(cvInfoOnes)){
|
||||
List<Map> attachmentContentList = new ArrayList<>();
|
||||
for (HotakeCvInfo hotakeCvInfo : cvInfoOnes) {
|
||||
if(StrUtil.isNotEmpty(hotakeCvInfo.getAnalyzedAttachmentJson())){
|
||||
Map map = JSONUtil.toBean(hotakeCvInfo.getAnalyzedAttachmentJson(), Map.class);
|
||||
attachmentContentList.add(map);
|
||||
}
|
||||
}
|
||||
if(CollectionUtil.isNotEmpty(attachmentContentList)){
|
||||
attachmentContent = JSONUtil.toJsonStr(attachmentContentList);
|
||||
}
|
||||
}
|
||||
}
|
||||
String cvData = aiCommonToolsService.handleAttachmentResultMerging(basicInformation,attachmentContent);
|
||||
//进行简历数据组合
|
||||
Map dataMap = JSONUtil.toBean(cvData, Map.class);
|
||||
HotakeCvInfoDto cvInfoDto = new HotakeCvInfoDto();
|
||||
//个人基本信息
|
||||
Map personalInfoMap = (Map)dataMap.get("personal_info");
|
||||
cvInfoDto.setName(personalInfoMap.get("name").toString());
|
||||
Map contactDetailsMap = (Map)personalInfoMap.get("contact_details");
|
||||
cvInfoDto.setPhone(contactDetailsMap.get("phone").toString());
|
||||
cvInfoDto.setEmail(contactDetailsMap.get("email").toString());
|
||||
cvInfoDto.setLocation(contactDetailsMap.get("address").toString());
|
||||
//个人介绍
|
||||
cvInfoDto.setAbout(dataMap.get("professional_summary").toString());
|
||||
|
||||
//技能工具
|
||||
Map skillsCertificatesMap = (Map)dataMap.get("skills_certificates");
|
||||
List<String> skillsList = (List<String>)skillsCertificatesMap.get("skills");
|
||||
//技能工具
|
||||
List<VcSkillsToolsDto> skillsTools = new ArrayList<>();
|
||||
if(CollectionUtil.isNotEmpty(skillsList)){
|
||||
for (String skill : skillsList) {
|
||||
VcSkillsToolsDto toolsDto = new VcSkillsToolsDto();
|
||||
toolsDto.setContent(skill);
|
||||
skillsTools.add(toolsDto);
|
||||
}
|
||||
}
|
||||
cvInfoDto.setSkillsTools(skillsTools);
|
||||
//工作经验集合
|
||||
List<VcExperienceDto> experience = new ArrayList<>();
|
||||
List<Map> workExperienceMapList = (List<Map>)dataMap.get("work_experience");
|
||||
if (CollectionUtil.isNotEmpty(workExperienceMapList)) {
|
||||
for (Map map : workExperienceMapList) {
|
||||
VcExperienceDto experienceDto = new VcExperienceDto();
|
||||
|
||||
experienceDto.setCompany(map.get("company").toString());
|
||||
experienceDto.setTitle(map.get("position").toString());
|
||||
String time_period = map.get("time_period").toString();
|
||||
if(StrUtil.isNotEmpty(time_period)){
|
||||
String[] times = time_period.split("–");
|
||||
experienceDto.setDurationStart(times[0]);
|
||||
if(times.length > 1){
|
||||
experienceDto.setDurationEnd(times[1]);
|
||||
}
|
||||
}
|
||||
List<VcExperienceDescriptionDto> description = new ArrayList<>();
|
||||
List<String> responsibilitiesList = (List<String>)map.get("responsibilities");
|
||||
if(CollectionUtil.isNotEmpty(responsibilitiesList)){
|
||||
for (String responsibility : responsibilitiesList) {
|
||||
VcExperienceDescriptionDto descriptionDto = new VcExperienceDescriptionDto();
|
||||
descriptionDto.setContent(responsibility);
|
||||
description.add(descriptionDto);
|
||||
}
|
||||
experienceDto.setDescription(description);
|
||||
}
|
||||
experience.add(experienceDto);
|
||||
}
|
||||
cvInfoDto.setExperience(experience);
|
||||
}
|
||||
//教育经历
|
||||
List<VcEducationDto> educationList = new ArrayList<>();
|
||||
List<Map> educationMapList = (List<Map>)dataMap.get("education");
|
||||
if(CollectionUtil.isNotEmpty(educationMapList)){
|
||||
for(Map map : educationMapList){
|
||||
VcEducationDto educationDto = new VcEducationDto();
|
||||
educationDto.setDegree(map.get("degree").toString());
|
||||
educationDto.setInstitution(map.get("school").toString());
|
||||
String time_period = map.get("time_period").toString();
|
||||
if(StrUtil.isNotEmpty(time_period)){
|
||||
String[] times = time_period.split("–");
|
||||
educationDto.setDurationStart(times[0]);
|
||||
if(times.length > 1){
|
||||
educationDto.setDurationEnd(times[1]);
|
||||
}
|
||||
}
|
||||
educationList.add(educationDto);
|
||||
}
|
||||
}
|
||||
cvInfoDto.setEducation(educationList);
|
||||
//创建简历信息
|
||||
HotakeCvInfo cvInfo = new HotakeCvInfo();
|
||||
cvInfo.setUserId(SecurityUtils.getUserId());
|
||||
cvInfo.setCvInfoDto(cvInfoDto);
|
||||
cvInfo.setCvTemplateJson(JSONUtil.toJsonStr(cvInfoDto));
|
||||
cvInfo.setCvFileType("cv");
|
||||
cvInfo.setCvFileSuffix("pdf");
|
||||
cvInfo.setStatus("1");
|
||||
//生成简历PDF数据
|
||||
String markdown = aiCommonToolsService.handleGenerateMarkdown(cvData);
|
||||
markdown = markdown.replaceAll("markdown","");
|
||||
try {
|
||||
String html = MarkdownUtil.markdownToHtml(markdown);
|
||||
// 可注入 CSS
|
||||
html = """
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body { font-family: SimSun; }
|
||||
h1 { color: #2c3e50; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
""" + html + """
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
//生成PDF文件
|
||||
String resultFileName = SecurityUtils.getUsername() + "_" + System.currentTimeMillis() + ".pdf";
|
||||
cvInfo.setCvName(resultFileName);
|
||||
String resultPathUrl = RuoYiConfig.getProfile() + SYSTEM_DIR + resultFileName;
|
||||
HtmlToPdfUtil.htmlToPdf(html, resultPathUrl);
|
||||
//上传到minio中
|
||||
File pdf = new File(resultPathUrl);
|
||||
MultipartFile multipartFile =
|
||||
MultipartFileUtil.fileToMultipartFile(pdf);
|
||||
HotakeSysFileVo fileVo = new HotakeSysFileVo();
|
||||
fileVo.setMinioBucketName("cv-fs");
|
||||
HotakeSysFile sysFile = sysFileService.insertHotakeSysFile(multipartFile,fileVo);
|
||||
cvInfo.setFileSizeShow(sysFile.getFileSizeShow());
|
||||
cvInfo.setCvUrl(sysFile.getStoragePath());
|
||||
//创建简历对象数据
|
||||
insertHotakeCvInfo(cvInfo);
|
||||
//保存简历PDF附件数据
|
||||
// log.info("Markdown数据为:{}",markdown);
|
||||
}catch (Exception e){}
|
||||
return cvInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 简历解析数据
|
||||
@@ -509,6 +690,28 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
||||
System.out.println(strs[0].replaceAll("Score:","").trim().split("/")[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理分析附件返回对应的json 内容
|
||||
* @return
|
||||
*/
|
||||
private String handleAnalyzedAttachment(String fileUrl,String fileSuffix){
|
||||
log.info("开始处理附件,对附件进行解析");
|
||||
try {
|
||||
InputStream inputStream = minioClient.getObject(
|
||||
GetObjectArgs.builder()
|
||||
.bucket(MinioBucketNameEnum.CV.getCode())
|
||||
.object(fileUrl)
|
||||
.build());
|
||||
String contents = FileContentUtil.readFileContent(inputStream, fileSuffix);
|
||||
String resultStr = aiCommonToolsService.handleAnalyzedAttachment(contents);
|
||||
log.info("返回的分析附件结果数据为:{}",resultStr);
|
||||
return resultStr;
|
||||
}catch (Exception e){}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user