AI 面试评分接口

This commit is contained in:
2026-01-18 08:39:50 +08:00
parent 8d0c1efd66
commit 27b7fcee7e
8 changed files with 145 additions and 26 deletions

View File

@@ -7,6 +7,7 @@ import com.vetti.hotake.domain.HotakeRolesInfo;
import com.vetti.hotake.domain.dto.*;
import com.vetti.hotake.domain.vo.*;
import com.vetti.hotake.service.IHotakeAiCommonToolsService;
import com.vetti.web.entity.vo.HotakeAiInterviewScoringVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -2,15 +2,15 @@ package com.vetti.web.controller.ai;
import com.vetti.common.core.controller.BaseController;
import com.vetti.common.core.domain.R;
import com.vetti.hotake.domain.dto.HotakeJobDescriptionGeneratorDto;
import com.vetti.hotake.domain.vo.HotakeJobDescriptionGeneratorVo;
import com.vetti.hotake.service.IHotakeAiCommonToolsService;
import com.vetti.web.entity.dto.ConvAiTokenDto;
import com.vetti.web.entity.dto.HotakeAiInterviewScoringDto;
import com.vetti.web.entity.vo.HotakeAiInterviewScoringVo;
import com.vetti.web.service.IElevenLabsConvAiTokenClientService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -39,4 +39,15 @@ public class HotakeElevenLabsConvAiTokenClientController extends BaseController
return R.ok(convAiTokenClientService.getConvAiToken());
}
/**
* AI语音面试结果评分处理
*/
@ApiOperation("AI语音面试结果评分处理")
@PostMapping(value = "/aiInterviewScoring")
public R<HotakeAiInterviewScoringDto> handleAiInterviewScoring(@RequestBody HotakeAiInterviewScoringVo scoringVo)
{
return R.ok(convAiTokenClientService.getAiInterviewScoring(scoringVo));
}
}

View File

@@ -0,0 +1,25 @@
package com.vetti.web.entity.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* AI 面试评分返回对象
*
* @author wangxiangshun
* @date 2025-11-02
*/
@Data
@Accessors(chain = true)
public class HotakeAiInterviewScoringDto {
@ApiModelProperty("分数")
private String score;
@ApiModelProperty("评价内容")
private String assessment;
@ApiModelProperty("内容")
private String content;
}

View File

@@ -0,0 +1,22 @@
package com.vetti.web.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* AI 面试问题记录 信息对象
*
* @author wangxiangshun
* @date 2026-01-17
*/
@Data
@Accessors(chain = true)
public class HotakeAiInterviewQuestionRecordVo {
@ApiModelProperty("用户类型(user:候选者,assistant:面试者AI)")
private String userType;
@ApiModelProperty("语音转义内容")
private String contentText;
}

View File

@@ -0,0 +1,21 @@
package com.vetti.web.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* AI 面试评分 信息对象
*
* @author wangxiangshun
* @date 2026-01-17
*/
@Data
@Accessors(chain = true)
public class HotakeAiInterviewScoringVo {
@ApiModelProperty("AI 面试问题记录 数据集合")
private List<HotakeAiInterviewQuestionRecordVo> aiInterviewQuestionRecordVoList;
}

View File

@@ -1,6 +1,9 @@
package com.vetti.web.service;
import com.vetti.web.entity.dto.ConvAiTokenDto;
import com.vetti.web.entity.dto.HotakeAiInterviewScoringDto;
import com.vetti.web.entity.vo.HotakeAiInterviewScoringVo;
/**
* ElevenLabs Agent 信息 服务类
*
@@ -14,4 +17,12 @@ public interface IElevenLabsConvAiTokenClientService {
* @return
*/
public ConvAiTokenDto getConvAiToken();
/**
* AI语音面试结果评分处理
* @param scoringVo 面试评分
* @return
*/
public HotakeAiInterviewScoringDto getAiInterviewScoring(HotakeAiInterviewScoringVo scoringVo);
}

View File

@@ -1,10 +1,18 @@
package com.vetti.web.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.vetti.common.ai.gpt.ChatGPTClient;
import com.vetti.common.exception.ServiceException;
import com.vetti.common.utils.SecurityUtils;
import com.vetti.common.utils.spring.SpringUtils;
import com.vetti.web.entity.dto.ConvAiTokenDto;
import com.vetti.web.entity.dto.HotakeAiInterviewScoringDto;
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.service.IElevenLabsConvAiTokenClientService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
@@ -15,7 +23,7 @@ import okhttp3.Response;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
@@ -88,28 +96,47 @@ public class ElevenLabsConvAiTokenClientServiceImpl implements IElevenLabsConvAi
}
/**
*
* @param scoringVo 岗位信息
* @return
*/
@Override
public HotakeAiInterviewScoringDto getAiInterviewScoring(HotakeAiInterviewScoringVo scoringVo) {
List<Map> list = new ArrayList<>();
//获取第一条数据记录
Map<String, String> mapEntity = new HashMap<>();
//更新问题记录
mapEntity.put("role", "system");
mapEntity.put("content", "You are a construction industry interview expert. Evaluate candidate responses and provide scores (1-5) and follow-up questions when needed. Always respond in JSON format.");
list.add(mapEntity);
if(CollectionUtil.isNotEmpty(scoringVo.getAiInterviewQuestionRecordVoList())){
for(HotakeAiInterviewQuestionRecordVo interviewQuestionRecordVo : scoringVo.getAiInterviewQuestionRecordVoList()){
Map<String, String> mapEntityUser = new HashMap<>();
//更新问题记录
mapEntityUser.put("role", interviewQuestionRecordVo.getUserType());
mapEntityUser.put("content", interviewQuestionRecordVo.getContentText());
list.add(mapEntityUser);
}
}
String promptJson = JSONUtil.toJsonStr(list);
ChatGPTClient gptClient = SpringUtils.getBean(ChatGPTClient.class);
String resultMsg = gptClient.handleAiChat(promptJson, "PF");
log.info("返回的结果为:{}",resultMsg);
//开始解析返回结果
Map mapResultData = JSONUtil.toBean(resultMsg,Map.class);
//获取评分
Object scoreStr = mapResultData.get("score");
Object assessment = mapResultData.get("assessment");
HotakeAiInterviewScoringDto scoringDto = new HotakeAiInterviewScoringDto();
scoringDto.setScore(scoreStr+"");
scoringDto.setAssessment(assessment+"");
scoringDto.setContent(scoreStr +"\n"+assessment);
return scoringDto;
}
// ===================== 测试主方法 =====================
// public static void main(String[] args) {
// ElevenLabsConvAiTokenClientServiceImpl client = new ElevenLabsConvAiTokenClientServiceImpl();
// try {
// // 获取Token传用户ID会话ID自动生成
// ConvAiTokenResponse response = client.getConvAiToken(null, "test_user_001");
//
// // 打印结果
// System.out.println("✅ 获取Token成功");
// System.out.println("Token" + response.getToken());
// System.out.println("会话ID" + response.getConversation_id());
// System.out.println("过期时间(时间戳):" + response.getExpires_at());
//
//
// // 后续使用拼接WebSocket地址
// String wsUrl = "wss://api.elevenlabs.io/v1/convai/ws?token=" + response.getToken();
// System.out.println("WebSocket连接地址" + wsUrl);
// } catch (IOException e) {
// System.err.println("❌ 获取Token失败" + e.getMessage());
// e.printStackTrace();
// }
// }
}