候选人AI面试分析
This commit is contained in:
@@ -182,4 +182,14 @@ public class HotakeAiCommonToolsController extends BaseController {
|
|||||||
return R.ok(hotakeAiCommonToolsService.getAiInterviewQuestions(rolesInfo));
|
return R.ok(hotakeAiCommonToolsService.getAiInterviewQuestions(rolesInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 候选人AI面试分析
|
||||||
|
*/
|
||||||
|
@ApiOperation("候选人AI面试分析")
|
||||||
|
@PostMapping(value = "/candidateAiInterviewAnalysis")
|
||||||
|
public R<?> candidateAiInterviewAnalysis(@RequestBody HotakeCandidateAiInterviewAnalysisVo analysisVo)
|
||||||
|
{
|
||||||
|
return R.ok(hotakeAiCommonToolsService.handleCandidateAiInterviewAnalysis(analysisVo));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.vetti.common.core.page.TableWebDataInfo;
|
|||||||
import com.vetti.common.enums.BusinessType;
|
import com.vetti.common.enums.BusinessType;
|
||||||
import com.vetti.common.utils.SecurityUtils;
|
import com.vetti.common.utils.SecurityUtils;
|
||||||
import com.vetti.hotake.domain.HotakeRolesApplyInfo;
|
import com.vetti.hotake.domain.HotakeRolesApplyInfo;
|
||||||
|
import com.vetti.hotake.domain.vo.HotakeRolesApplyStageVo;
|
||||||
import com.vetti.hotake.service.IHotakeRolesApplyInfoService;
|
import com.vetti.hotake.service.IHotakeRolesApplyInfoService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
@@ -96,4 +97,16 @@ public class HotakeRolesApplyInfoController extends BaseController
|
|||||||
{
|
{
|
||||||
return R.ok(hotakeRolesApplyInfoService.deleteHotakeRolesApplyInfoByIds(ids));
|
return R.ok(hotakeRolesApplyInfoService.deleteHotakeRolesApplyInfoByIds(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量修改候选人岗位申请信息所属阶段
|
||||||
|
*/
|
||||||
|
@ApiOperation("批量修改候选人岗位申请信息所属阶段")
|
||||||
|
@Log(title = "批量修改候选人岗位申请信息所属阶段", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/batchEditStage")
|
||||||
|
public R<?> batchEditStage(@RequestBody List<HotakeRolesApplyStageVo> stageVoList)
|
||||||
|
{
|
||||||
|
hotakeRolesApplyInfoService.updateBatchEditStage(stageVoList);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.vetti.web.entity.vo;
|
package com.vetti.web.entity.vo;
|
||||||
|
|
||||||
|
import com.vetti.hotake.domain.vo.HotakeAiInterviewQuestionRecordVo;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package com.vetti.web.service.impl;
|
package com.vetti.web.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.vetti.common.ai.gpt.ChatGPTClient;
|
import com.vetti.common.ai.gpt.ChatGPTClient;
|
||||||
import com.vetti.common.exception.ServiceException;
|
import com.vetti.common.exception.ServiceException;
|
||||||
@@ -11,14 +9,12 @@ import com.vetti.common.utils.spring.SpringUtils;
|
|||||||
import com.vetti.web.entity.dto.ConvAiTokenDto;
|
import com.vetti.web.entity.dto.ConvAiTokenDto;
|
||||||
import com.vetti.web.entity.dto.HotakeAiInterviewScoringDto;
|
import com.vetti.web.entity.dto.HotakeAiInterviewScoringDto;
|
||||||
import com.vetti.web.entity.vo.ConvAiTokenRequestVo;
|
import com.vetti.web.entity.vo.ConvAiTokenRequestVo;
|
||||||
import com.vetti.web.entity.vo.HotakeAiInterviewQuestionRecordVo;
|
|
||||||
import com.vetti.web.entity.vo.HotakeAiInterviewScoringVo;
|
import com.vetti.web.entity.vo.HotakeAiInterviewScoringVo;
|
||||||
import com.vetti.web.service.IElevenLabsConvAiTokenClientService;
|
import com.vetti.web.service.IElevenLabsConvAiTokenClientService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ chatGpt:
|
|||||||
modelPpg: gpt-4o-mini
|
modelPpg: gpt-4o-mini
|
||||||
modelRLinkAl: gpt-4o-mini
|
modelRLinkAl: gpt-4o-mini
|
||||||
modelRLinkAl_1: gpt-4o-mini
|
modelRLinkAl_1: gpt-4o-mini
|
||||||
|
modelAiIntPf: gpt-4o-mini
|
||||||
role: system
|
role: system
|
||||||
|
|
||||||
http:
|
http:
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ public class ChatGPTClient {
|
|||||||
@Value("${chatGpt.modelRLinkAl_1}")
|
@Value("${chatGpt.modelRLinkAl_1}")
|
||||||
private String modelRLinkAl_1;
|
private String modelRLinkAl_1;
|
||||||
|
|
||||||
|
@Value("${chatGpt.modelAiIntPf}")
|
||||||
|
private String modelAiIntPf;
|
||||||
|
|
||||||
@Value("${chatGpt.role}")
|
@Value("${chatGpt.role}")
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
@@ -140,6 +143,9 @@ public class ChatGPTClient {
|
|||||||
}else if("RLINKAL_1".equals(type)){
|
}else if("RLINKAL_1".equals(type)){
|
||||||
//招聘链接信息分析补全-第二阶段
|
//招聘链接信息分析补全-第二阶段
|
||||||
resultText = sendMessage(promptText, modelRLinkAl_1,objectMapper,client,role);
|
resultText = sendMessage(promptText, modelRLinkAl_1,objectMapper,client,role);
|
||||||
|
}else if("AIINTPF".equals(type)){
|
||||||
|
//候选人AI面试分析
|
||||||
|
resultText = sendMessage(promptText, modelAiIntPf,objectMapper,client,role);
|
||||||
}else {
|
}else {
|
||||||
resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role);
|
resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2077,4 +2077,204 @@ public class AiCommonPromptConstants {
|
|||||||
return promptStr;
|
return promptStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化AI生成问题提示词
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String initializationCandidateAiInterviewAnalysisPrompt(){
|
||||||
|
String promptStr = "# AI Interview Analysis Prompt\n" +
|
||||||
|
"\n" +
|
||||||
|
"## Role Definition\n" +
|
||||||
|
"You are a professional AI interview analyst specializing in multi-dimensional candidate assessment for traditional industries (construction, logistics, manufacturing, hospitality, mining).\n" +
|
||||||
|
"\n" +
|
||||||
|
"## Analysis Dimensions\n" +
|
||||||
|
"\n" +
|
||||||
|
"### 1. Technical Score (0-100 points)\n" +
|
||||||
|
"Assessment Criteria:\n" +
|
||||||
|
"- Professional knowledge depth and breadth\n" +
|
||||||
|
"- Practical work experience demonstration\n" +
|
||||||
|
"- Problem-solving ability\n" +
|
||||||
|
"- Safety awareness (critical for traditional industries)\n" +
|
||||||
|
"- Operational skill proficiency\n" +
|
||||||
|
"- Relevant certifications and qualifications\n" +
|
||||||
|
"\n" +
|
||||||
|
"Scoring Standards:\n" +
|
||||||
|
"- 90-100: Expert level, extensive experience, comprehensive skills\n" +
|
||||||
|
"- 80-89: Advanced, strong professional ability, sufficient experience\n" +
|
||||||
|
"- 70-79: Intermediate, basically competent, room for improvement\n" +
|
||||||
|
"- 60-69: Junior, requires training and guidance\n" +
|
||||||
|
"- 0-59: Unqualified, insufficient professional ability\n" +
|
||||||
|
"\n" +
|
||||||
|
"### 2. Communication Score (0-100 points)\n" +
|
||||||
|
"Assessment Criteria:\n" +
|
||||||
|
"- Clarity and accuracy of expression\n" +
|
||||||
|
"- Logical thinking and structured expression\n" +
|
||||||
|
"- Completeness and relevance of answers\n" +
|
||||||
|
"- Language organization ability\n" +
|
||||||
|
"- Listening and comprehension skills\n" +
|
||||||
|
"- Avoiding filler words (\"um\", \"uh\", etc.)\n" +
|
||||||
|
"\n" +
|
||||||
|
"Scoring Standards:\n" +
|
||||||
|
"- 90-100: Excellent expression, clear logic, efficient communication\n" +
|
||||||
|
"- 80-89: Good expression, basically clear, occasional redundancy\n" +
|
||||||
|
"- 70-79: Average expression, acceptable logic, needs improvement\n" +
|
||||||
|
"- 60-69: Poor expression, confused logic, communication difficulties\n" +
|
||||||
|
"- 0-59: Unclear expression, unable to communicate effectively\n" +
|
||||||
|
"\n" +
|
||||||
|
"### 3. Cultural Fit (0-100 points)\n" +
|
||||||
|
"Assessment Criteria:\n" +
|
||||||
|
"- Value alignment with company culture\n" +
|
||||||
|
"- Teamwork awareness and spirit\n" +
|
||||||
|
"- Work attitude and professional ethics\n" +
|
||||||
|
"- Sense of responsibility and dedication\n" +
|
||||||
|
"- Learning willingness and growth potential\n" +
|
||||||
|
"- Passion and identification with the industry\n" +
|
||||||
|
"\n" +
|
||||||
|
"Scoring Standards:\n" +
|
||||||
|
"- 90-100: Highly aligned, consistent values, strong team spirit\n" +
|
||||||
|
"- 80-89: Good alignment, basic recognition, strong adaptability\n" +
|
||||||
|
"- 70-79: Basic alignment, requires adaptation period\n" +
|
||||||
|
"- 60-69: Average alignment, possible cultural conflicts\n" +
|
||||||
|
"- 0-59: Misaligned, significant value differences\n" +
|
||||||
|
"\n" +
|
||||||
|
"## Output Format Requirements\n" +
|
||||||
|
"\n" +
|
||||||
|
"Must strictly return analysis results in the following JSON format:\n" +
|
||||||
|
"\n" +
|
||||||
|
"```json\n" +
|
||||||
|
"{\n" +
|
||||||
|
" \"scores\": {\n" +
|
||||||
|
" \"technical\": 85,\n" +
|
||||||
|
" \"communication\": 70,\n" +
|
||||||
|
" \"cultural\": 90\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"analysis\": {\n" +
|
||||||
|
" \"technical\": {\n" +
|
||||||
|
" \"strengths\": [\n" +
|
||||||
|
" \"Specific strength 1: e.g., '5 years of Maya and Blender experience'\",\n" +
|
||||||
|
" \"Specific strength 2: e.g., 'Proficient in animation toolset and VFX production'\"\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"improvements\": [\n" +
|
||||||
|
" \"Specific improvement 1: e.g., 'Recommend deepening knowledge of advanced shader techniques'\",\n" +
|
||||||
|
" \"Specific improvement 2: e.g., 'Could provide more project cases to demonstrate technical depth'\"\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"communication\": {\n" +
|
||||||
|
" \"strengths\": [\n" +
|
||||||
|
" \"Clear expression with strong logic\"\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"improvements\": [\n" +
|
||||||
|
" \"Avoid using filler words like 'um'\",\n" +
|
||||||
|
" \"Could organize answers more structurally\"\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"cultural\": {\n" +
|
||||||
|
" \"strengths\": [\n" +
|
||||||
|
" \"Values highly aligned with company culture\",\n" +
|
||||||
|
" \"Demonstrates strong teamwork awareness\"\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"improvements\": []\n" +
|
||||||
|
" }\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"notes\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"type\": \"critical\",\n" +
|
||||||
|
" \"content\": \"Answer touches on usability but misses important aspect: accessibility design\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"type\": \"warning\",\n" +
|
||||||
|
" \"content\": \"Noticed signs of AI-assisted answering\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"type\": \"recommendation\",\n" +
|
||||||
|
" \"content\": \"Recommend candidate prepare specific cases to demonstrate communication skills\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
"}\n" +
|
||||||
|
"```\n" +
|
||||||
|
"\n" +
|
||||||
|
"## Note Types\n" +
|
||||||
|
"\n" +
|
||||||
|
"### critical (Critical Issues) \uD83D\uDD34\n" +
|
||||||
|
"- Serious knowledge gaps or skill deficiencies\n" +
|
||||||
|
"- Obvious communication barriers\n" +
|
||||||
|
"- Severe value misalignment\n" +
|
||||||
|
"- Lack of safety awareness (critical for traditional industries)\n" +
|
||||||
|
"- Professional ethics issues\n" +
|
||||||
|
"\n" +
|
||||||
|
"### warning (Warning Items) ⚠\uFE0F\n" +
|
||||||
|
"- Issues requiring attention\n" +
|
||||||
|
"- Potential risk factors\n" +
|
||||||
|
"- Doubts requiring further confirmation\n" +
|
||||||
|
"- Signs of insufficient experience\n" +
|
||||||
|
"\n" +
|
||||||
|
"### recommendation (Improvement Suggestions) \uD83D\uDCA1\n" +
|
||||||
|
"- Specific improvement directions\n" +
|
||||||
|
"- Training and development suggestions\n" +
|
||||||
|
"- Interview technique improvements\n" +
|
||||||
|
"- Career development advice\n" +
|
||||||
|
"\n" +
|
||||||
|
"## Traditional Industry Focus Points\n" +
|
||||||
|
"\n" +
|
||||||
|
"### Construction Industry\n" +
|
||||||
|
"- Safety operation awareness\n" +
|
||||||
|
"- Site management experience\n" +
|
||||||
|
"- Quality control ability\n" +
|
||||||
|
"- Team coordination skills\n" +
|
||||||
|
"- Emergency handling capability\n" +
|
||||||
|
"\n" +
|
||||||
|
"### Logistics Industry\n" +
|
||||||
|
"- Time management awareness\n" +
|
||||||
|
"- Customer service attitude\n" +
|
||||||
|
"- Route planning ability\n" +
|
||||||
|
"- Responsibility and attention to detail\n" +
|
||||||
|
"- Physical fitness adaptability\n" +
|
||||||
|
"\n" +
|
||||||
|
"### Manufacturing Industry\n" +
|
||||||
|
"- Production efficiency awareness\n" +
|
||||||
|
"- Quality standard understanding\n" +
|
||||||
|
"- Equipment operation skills\n" +
|
||||||
|
"- Safety production awareness\n" +
|
||||||
|
"- Continuous improvement mindset\n" +
|
||||||
|
"\n" +
|
||||||
|
"### Hospitality Industry\n" +
|
||||||
|
"- Service awareness and attitude\n" +
|
||||||
|
"- Communication and expression skills\n" +
|
||||||
|
"- Adaptability and problem-solving\n" +
|
||||||
|
"- Professional appearance\n" +
|
||||||
|
"- Language abilities\n" +
|
||||||
|
"\n" +
|
||||||
|
"### Mining Industry\n" +
|
||||||
|
"- Safety operation awareness (most important)\n" +
|
||||||
|
"- Physical health condition\n" +
|
||||||
|
"- Emergency response capability\n" +
|
||||||
|
"- Environmental adaptability\n" +
|
||||||
|
"- Teamwork spirit\n" +
|
||||||
|
"\n" +
|
||||||
|
"## Scoring Principles\n" +
|
||||||
|
"\n" +
|
||||||
|
"1. **Objective and Fair**: Score based on actual candidate responses, avoid subjective bias\n" +
|
||||||
|
"2. **Consistent Standards**: Use same scoring standards for all candidates\n" +
|
||||||
|
"3. **Specific and Clear**: Strengths and improvements must be specific, avoid vagueness\n" +
|
||||||
|
"4. **Constructive**: Improvement suggestions should be actionable, help candidates grow\n" +
|
||||||
|
"5. **Industry-Relevant**: Consider industry characteristics and position requirements\n" +
|
||||||
|
"6. **Safety First**: Traditional industries particularly focus on safety awareness\n" +
|
||||||
|
"7. **Practice-Oriented**: Value practical experience and operational ability\n" +
|
||||||
|
"8. **Attitude Matters**: Work attitude and responsibility are fundamental\n" +
|
||||||
|
"\n" +
|
||||||
|
"## Important Notes\n" +
|
||||||
|
"\n" +
|
||||||
|
"1. Scores must be integers between 0-100\n" +
|
||||||
|
"2. List at least 1-3 strengths, maximum 5\n" +
|
||||||
|
"3. Improvements can be empty (when performance is excellent), maximum 3\n" +
|
||||||
|
"4. Notes are not mandatory, but critical issues must be recorded\n" +
|
||||||
|
"5. All descriptions should be specific and actionable, avoid vague statements\n" +
|
||||||
|
"6. For traditional industry candidates, don't overemphasize technical jargon\n" +
|
||||||
|
"7. Value practical operational ability and work experience over theoretical knowledge\n" +
|
||||||
|
"8. Safety awareness is a one-vote veto item for traditional industries\n";
|
||||||
|
|
||||||
|
return promptStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ package com.vetti.common.enums;
|
|||||||
*/
|
*/
|
||||||
public enum StageEnum {
|
public enum StageEnum {
|
||||||
|
|
||||||
APPLIED("Applied", "已申请"),
|
APPLIED("applied", "已申请"),
|
||||||
SHORTLISTED("Shortlisted", "入围"),
|
SHORTLISTED("shortlisted", "入围"),
|
||||||
INTERVIEW("Interview", "面试"),
|
INTERVIEW("interview", "面试"),
|
||||||
OFFER("Offer", "邀约"),
|
OFFER("offer", "邀约"),
|
||||||
HIRED("Hired", "受雇"),
|
HIRED("hired", "受雇"),
|
||||||
REFUSE_OFFER("refuseOffer", "拒绝邀约"),
|
REFUSE_OFFER("refuseOffer", "拒绝邀约"),
|
||||||
INTERVIEW_FAIL("InterviewFail", "面试失败"),
|
INTERVIEW_FAIL("interviewFail", "面试失败"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -74,11 +74,11 @@ public class HotakeRolesApplyInfo extends BaseEntity
|
|||||||
private String coverLetter;
|
private String coverLetter;
|
||||||
|
|
||||||
/** 候选人状态(Hot、Warm、Cold、Pending) */
|
/** 候选人状态(Hot、Warm、Cold、Pending) */
|
||||||
@ApiModelProperty("候选人状态(Hot、Warm、Cold、Pending)")
|
@ApiModelProperty("候选人状态(hot、warm、cold、pending)")
|
||||||
private String candidateStatus;
|
private String candidateStatus;
|
||||||
|
|
||||||
/** 当前阶段 */
|
/** 当前阶段 */
|
||||||
@ApiModelProperty("当前阶段(Applied:已申请,Shortlisted:入围,Interview:面试,Offer:邀约,Hired,受雇,refuseOffer:拒绝邀约,InterviewFail:面试失败)")
|
@ApiModelProperty("当前阶段(applied:已申请,shortlisted:入围,interview:面试,offer:邀约,hired,受雇,refuseOffer:拒绝邀约,interviewFail:面试失败)")
|
||||||
@Excel(name = "当前阶段")
|
@Excel(name = "当前阶段")
|
||||||
private String stage;
|
private String stage;
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ public class HotakeRolesApplyInfo extends BaseEntity
|
|||||||
private BigDecimal aiMatchScorePercentage;
|
private BigDecimal aiMatchScorePercentage;
|
||||||
|
|
||||||
/** 申请状态(pending:进行中,complete:已完成,Canceled:取消) */
|
/** 申请状态(pending:进行中,complete:已完成,Canceled:取消) */
|
||||||
@ApiModelProperty("申请状态(pending:进行中,complete:已完成,Canceled:取消)")
|
@ApiModelProperty("申请状态(pending:进行中,complete:已完成,canceled:取消)")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
@ApiModelProperty("岗位信息")
|
@ApiModelProperty("岗位信息")
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ public class HotakeRolesApplyOperRecord extends BaseEntity
|
|||||||
private Long roleApplyId;
|
private Long roleApplyId;
|
||||||
|
|
||||||
/** 当前阶段 */
|
/** 当前阶段 */
|
||||||
@ApiModelProperty("当前阶段")
|
@ApiModelProperty("阶段")
|
||||||
@Excel(name = "当前阶段")
|
@Excel(name = "阶段")
|
||||||
private String applyStage;
|
private String applyStage;
|
||||||
|
|
||||||
@ApiModelProperty("岗位申请Id数据集合")
|
@ApiModelProperty("岗位申请Id数据集合")
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.vetti.hotake.domain.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 候选人AI面试分析 返回对象
|
||||||
|
*
|
||||||
|
* @author ID
|
||||||
|
* @date 2025-09-06
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class HotakeCandidateAiInterviewAnalysisDto {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.vetti.web.entity.vo;
|
package com.vetti.hotake.domain.vo;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.vetti.hotake.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 候选人AI面试分析 请求对象
|
||||||
|
*
|
||||||
|
* @author ID
|
||||||
|
* @date 2025-09-06
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class HotakeCandidateAiInterviewAnalysisVo {
|
||||||
|
|
||||||
|
@ApiModelProperty("面试岗位")
|
||||||
|
private String position;
|
||||||
|
|
||||||
|
@ApiModelProperty("AI 面试问题记录 数据集合")
|
||||||
|
private List<HotakeAiInterviewQuestionRecordVo> aiInterviewQuestionRecordVoList;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
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 HotakeRolesApplyStageVo {
|
||||||
|
|
||||||
|
@ApiModelProperty("岗位申请Id")
|
||||||
|
private Long roleApplyId;
|
||||||
|
|
||||||
|
@ApiModelProperty("当前阶段")
|
||||||
|
private String stage;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -128,5 +128,11 @@ public interface IHotakeAiCommonToolsService {
|
|||||||
public String getAiInterviewQuestions(HotakeRolesInfo rolesInfo);
|
public String getAiInterviewQuestions(HotakeRolesInfo rolesInfo);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 候选人AI面试分析
|
||||||
|
* @param analysisVo 候选人AI面试分析信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String handleCandidateAiInterviewAnalysis(HotakeCandidateAiInterviewAnalysisVo analysisVo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.vetti.hotake.service;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.vetti.hotake.domain.HotakeRolesApplyInfo;
|
import com.vetti.hotake.domain.HotakeRolesApplyInfo;
|
||||||
|
import com.vetti.hotake.domain.vo.HotakeRolesApplyStageVo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 候选人岗位申请信息Service接口
|
* 候选人岗位申请信息Service接口
|
||||||
@@ -67,4 +68,13 @@ public interface IHotakeRolesApplyInfoService
|
|||||||
*/
|
*/
|
||||||
public int batchInsertHotakeRolesApplyInfo(List<HotakeRolesApplyInfo> hotakeRolesApplyInfoList);
|
public int batchInsertHotakeRolesApplyInfo(List<HotakeRolesApplyInfo> hotakeRolesApplyInfoList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改候选人岗位申请信息
|
||||||
|
*
|
||||||
|
* @param stageVoList 候选人岗位申请信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int updateBatchEditStage(List<HotakeRolesApplyStageVo> stageVoList);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -988,4 +988,52 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
|||||||
|
|
||||||
return resultJsonOne;
|
return resultJsonOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 候选人AI面试分析
|
||||||
|
* @param rolesInfo 候选人AI面试分析信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String handleCandidateAiInterviewAnalysis(HotakeCandidateAiInterviewAnalysisVo analysisVo) {
|
||||||
|
|
||||||
|
String prompt = AiCommonPromptConstants.initializationCandidateAiInterviewAnalysisPrompt();
|
||||||
|
|
||||||
|
String qa = "";
|
||||||
|
if(CollectionUtil.isNotEmpty(analysisVo.getAiInterviewQuestionRecordVoList())){
|
||||||
|
for(HotakeAiInterviewQuestionRecordVo recordVo : analysisVo.getAiInterviewQuestionRecordVoList()){
|
||||||
|
if("assistant".equals(recordVo.getUserType())){
|
||||||
|
qa = qa + "Question:"+recordVo.getContentText();
|
||||||
|
}
|
||||||
|
if("user".equals(recordVo.getUserType())){
|
||||||
|
qa = qa + "Answer:"+recordVo.getContentText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String userPrompt_1 = "Please conduct an interview analysis based on the questions answered by the following candidates:\n" +
|
||||||
|
"\n" +
|
||||||
|
"**Job Information**:\n" +
|
||||||
|
"Position:【"+analysisVo.getPosition()+"】\n" +
|
||||||
|
"Question And Answer:【"+qa+"】\n"+
|
||||||
|
"Please return the analysis results in the required JSON format.";
|
||||||
|
|
||||||
|
log.info("AI面试问题生成:{}",userPrompt_1);
|
||||||
|
//处理岗位信息补充
|
||||||
|
List<Map<String, String>> listOne = new LinkedList();
|
||||||
|
Map<String, String> mapEntityOne = new HashMap<>();
|
||||||
|
mapEntityOne.put("role", "system");
|
||||||
|
mapEntityOne.put("content",prompt);
|
||||||
|
listOne.add(mapEntityOne);
|
||||||
|
Map<String, String> mapUserEntityOne = new HashMap<>();
|
||||||
|
mapUserEntityOne.put("role", "user");
|
||||||
|
mapUserEntityOne.put("content",userPrompt_1);
|
||||||
|
listOne.add(mapUserEntityOne);
|
||||||
|
String promptJsonOne = JSONUtil.toJsonStr(listOne);
|
||||||
|
String resultStrOne = chatGPTClient.handleAiChat(promptJsonOne,"AIINTPF");
|
||||||
|
String resultJsonOne = resultStrOne.replaceAll("```json","").replaceAll("```","");
|
||||||
|
log.info("候选人AI面试分析结果:{}",resultJsonOne);
|
||||||
|
|
||||||
|
return resultJsonOne;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.vetti.hotake.domain.HotakeRolesApplyOperRecord;
|
|||||||
import com.vetti.hotake.domain.HotakeRolesInfo;
|
import com.vetti.hotake.domain.HotakeRolesInfo;
|
||||||
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
|
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
|
||||||
import com.vetti.hotake.domain.dto.VcDto.*;
|
import com.vetti.hotake.domain.dto.VcDto.*;
|
||||||
|
import com.vetti.hotake.domain.vo.HotakeRolesApplyStageVo;
|
||||||
import com.vetti.hotake.mapper.HotakeRolesApplyInfoMapper;
|
import com.vetti.hotake.mapper.HotakeRolesApplyInfoMapper;
|
||||||
import com.vetti.hotake.mapper.HotakeRolesInfoMapper;
|
import com.vetti.hotake.mapper.HotakeRolesInfoMapper;
|
||||||
import com.vetti.hotake.service.IHotakeRolesApplyInfoService;
|
import com.vetti.hotake.service.IHotakeRolesApplyInfoService;
|
||||||
@@ -334,4 +335,40 @@ public class HotakeRolesApplyInfoServiceImpl extends BaseServiceImpl implements
|
|||||||
return new HotakeCvInfoDto();
|
return new HotakeCvInfoDto();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改候选人岗位申请信息
|
||||||
|
*
|
||||||
|
* @param hotakeRolesApplyInfo 候选人岗位申请信息
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor=Exception.class)
|
||||||
|
@Override
|
||||||
|
public int updateBatchEditStage(List<HotakeRolesApplyStageVo> stageVoList)
|
||||||
|
{
|
||||||
|
int resultNum = 0;
|
||||||
|
if(CollectionUtil.isNotEmpty(stageVoList)){
|
||||||
|
for(HotakeRolesApplyStageVo stageVo : stageVoList){
|
||||||
|
HotakeRolesApplyInfo hotakeRolesApplyInfo = new HotakeRolesApplyInfo();
|
||||||
|
hotakeRolesApplyInfo.setId(stageVo.getRoleApplyId());
|
||||||
|
hotakeRolesApplyInfo.setStage(stageVo.getStage());
|
||||||
|
fill(FillTypeEnum.UPDATE.getCode(), hotakeRolesApplyInfo);
|
||||||
|
resultNum = hotakeRolesApplyInfoMapper.updateHotakeRolesApplyInfo(hotakeRolesApplyInfo);
|
||||||
|
HotakeRolesApplyOperRecord query = new HotakeRolesApplyOperRecord();
|
||||||
|
query.setRoleApplyId(hotakeRolesApplyInfo.getId()).setApplyStage(hotakeRolesApplyInfo.getStage());
|
||||||
|
List<HotakeRolesApplyOperRecord> applyOperRecords = rolesApplyOperRecordService.selectHotakeRolesApplyOperRecordList(query);
|
||||||
|
if(CollectionUtil.isEmpty(applyOperRecords)) {
|
||||||
|
StageEnum stageEnum = StageEnum.getByInfo(hotakeRolesApplyInfo.getStage());
|
||||||
|
if(stageEnum != null){
|
||||||
|
HotakeRolesApplyOperRecord hotakeRolesApplyOperRecord = new HotakeRolesApplyOperRecord();
|
||||||
|
hotakeRolesApplyOperRecord.setApplyStage(hotakeRolesApplyInfo.getStage());
|
||||||
|
hotakeRolesApplyOperRecord.setRoleApplyId(hotakeRolesApplyInfo.getId());
|
||||||
|
hotakeRolesApplyOperRecord.setRoleId(hotakeRolesApplyInfo.getRoleId());
|
||||||
|
rolesApplyOperRecordService.insertHotakeRolesApplyOperRecord(hotakeRolesApplyOperRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultNum;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user