AI 提问追问环境demo 添加
This commit is contained in:
@@ -8,6 +8,7 @@ import com.vetti.common.ai.gpt.OpenAiStreamClient;
|
||||
import com.vetti.common.ai.gpt.service.OpenAiStreamListenerService;
|
||||
import com.vetti.common.ai.whisper.WhisperClient;
|
||||
import com.vetti.common.config.RuoYiConfig;
|
||||
import com.vetti.common.core.redis.RedisCache;
|
||||
import com.vetti.common.utils.spring.SpringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
@@ -24,6 +25,7 @@ import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* 语音面试 web处理器
|
||||
@@ -60,6 +62,16 @@ public class ChatWebSocketHandler {
|
||||
*/
|
||||
private final Map<String,String> cacheReplyFlag = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 缓存客户端,面试回答信息
|
||||
*/
|
||||
private final Map<String,String> cacheMsgMapData = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 缓存客户端,AI提问的问题结果信息
|
||||
*/
|
||||
private final Map<String,String> cacheQuestionResult = new ConcurrentHashMap<>();
|
||||
|
||||
// 语音文件保存目录
|
||||
private static final String VOICE_STORAGE_DIR = "/voice_files/";
|
||||
|
||||
@@ -92,6 +104,10 @@ public class ChatWebSocketHandler {
|
||||
createWhisperRealtimeSocket(session.getId());
|
||||
//是初次自我介绍后的问答环节
|
||||
cacheReplyFlag.put(session.getId(),"YES");
|
||||
//初始化面试回答数据记录
|
||||
cacheMsgMapData.put(session.getId(),"");
|
||||
//初始化面试问题
|
||||
cacheQuestionResult.put(session.getId(),"");
|
||||
//发送初始化面试官语音流
|
||||
String openingPathUrl = RuoYiConfig.getProfile() + VOICE_SYSTEM_DIR + "opening.wav";
|
||||
try {
|
||||
@@ -128,10 +144,11 @@ public class ChatWebSocketHandler {
|
||||
String startFlag = cacheReplyFlag.get(session.getId());
|
||||
//语音结束,开始进行回答解析
|
||||
String cacheResultText = cacheClientTts.get(clientId);
|
||||
log.info("返回的结果为:{}", cacheResultText);
|
||||
log.info("面试者回答信息为:{}", cacheResultText);
|
||||
if (StrUtil.isEmpty(cacheResultText)) {
|
||||
cacheResultText = "Hi.";
|
||||
}
|
||||
String promptJson = "";
|
||||
if("YES".equals(startFlag)) {
|
||||
//自我介绍结束后马上返回一个Good
|
||||
//发送初始化面试官语音流
|
||||
@@ -146,7 +163,37 @@ public class ChatWebSocketHandler {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
cacheResultText = "你是面试官,根据Construction Labourer候选人回答生成追问。只要一个问题";
|
||||
Map<String,String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role","system");
|
||||
mapEntity.put("content","你是面试官,根据Construction Labourer候选人回答生成追问。只要一个问题,问题不要重复");
|
||||
List<Map<String,String>> list = new LinkedList();
|
||||
list.add(mapEntity);
|
||||
promptJson = JSONUtil.toJsonStr(list);
|
||||
//记录缓存中
|
||||
cacheMsgMapData.put(session.getId(),promptJson);
|
||||
}else{
|
||||
//开始根据面试者回答的问题,进行追问回答
|
||||
// {
|
||||
// role: "system",
|
||||
// content: "你是面试官,根据Construction Labourer候选人回答生成追问。"
|
||||
// },
|
||||
// {
|
||||
// role: "user",
|
||||
// content: `问题:${question}\n候选人回答:${answer}`
|
||||
// }
|
||||
//获取面试者回答信息
|
||||
//获取缓存记录
|
||||
String msgMapData = cacheMsgMapData.get(session.getId());
|
||||
if(StrUtil.isNotEmpty(msgMapData)){
|
||||
List<Map> list = JSONUtil.toList(msgMapData, Map.class);
|
||||
//获取最后一条数据记录
|
||||
Map<String,String> mapEntity = list.get(list.size()-1);
|
||||
//更新问题记录
|
||||
String content = mapEntity.get("content");
|
||||
mapEntity.put("content", StrUtil.format(content, cacheResultText));
|
||||
promptJson = JSONUtil.toJsonStr(list);
|
||||
cacheMsgMapData.put(session.getId(),promptJson);
|
||||
}
|
||||
}
|
||||
//获取完问答数据,直接清空缓存数据
|
||||
cacheClientTts.put(clientId,"");
|
||||
@@ -154,10 +201,18 @@ public class ChatWebSocketHandler {
|
||||
log.info("1、开始进行AI回答时间:{}", System.currentTimeMillis() / 1000);
|
||||
//把提问的文字发送给CPT(流式处理)
|
||||
OpenAiStreamClient aiStreamClient = SpringUtils.getBean(OpenAiStreamClient.class);
|
||||
aiStreamClient.streamChat(cacheResultText, new OpenAiStreamListenerService() {
|
||||
log.info("AI提示词为:{}",promptJson);
|
||||
aiStreamClient.streamChat(promptJson, new OpenAiStreamListenerService() {
|
||||
@Override
|
||||
public void onMessage(String content) {
|
||||
log.info("返回AI结果:{}", content);
|
||||
String questionResult = cacheQuestionResult.get(session.getId());
|
||||
if(StrUtil.isEmpty(questionResult)){
|
||||
questionResult = content;
|
||||
}else{
|
||||
questionResult = questionResult + content;
|
||||
}
|
||||
cacheQuestionResult.put(session.getId(),questionResult);
|
||||
// 实时输出内容
|
||||
//开始进行语音输出-流式持续输出
|
||||
log.info("2、开始进行AI回答时间:{}", System.currentTimeMillis() / 1000);
|
||||
@@ -185,6 +240,21 @@ public class ChatWebSocketHandler {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
try {
|
||||
//开始往缓存中记录提问的问题
|
||||
String questionResult = cacheQuestionResult.get(session.getId());
|
||||
//获取缓存记录
|
||||
String msgMapData = cacheMsgMapData.get(session.getId());
|
||||
if(StrUtil.isNotEmpty(msgMapData)){
|
||||
List<Map> list = JSONUtil.toList(msgMapData, Map.class);
|
||||
Map<String,String> mapEntity = new HashMap<>();
|
||||
mapEntity.put("role","system");
|
||||
mapEntity.put("content","问题:"+questionResult+"\\n候选人回答:{}");
|
||||
list.add(mapEntity);
|
||||
cacheMsgMapData.put(session.getId(),JSONUtil.toJsonStr(list));
|
||||
}
|
||||
//清空问题
|
||||
cacheQuestionResult.put(session.getId(),"");
|
||||
|
||||
Map<String, String> resultEntity = new HashMap<>();
|
||||
resultEntity.put("msg", "done");
|
||||
//发送通知告诉客户端已经回答结束了
|
||||
@@ -454,6 +524,5 @@ public class ChatWebSocketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -37,10 +38,10 @@ public class OpenAiStreamClient {
|
||||
/**
|
||||
* 发送流式请求
|
||||
*
|
||||
* @param prompt 提示词
|
||||
* @param promptJson 提示词json数据集合
|
||||
* @param listener 流式响应监听器
|
||||
*/
|
||||
public void streamChat(String prompt, OpenAiStreamListenerService listener) {
|
||||
public void streamChat(String promptJson, OpenAiStreamListenerService listener) {
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
@@ -53,13 +54,18 @@ public class OpenAiStreamClient {
|
||||
Map<String, Object> requestBody = new HashMap<>();
|
||||
requestBody.put("model", model);
|
||||
requestBody.put("stream", true);
|
||||
|
||||
// 构建消息
|
||||
Map<String, String> message = new HashMap<>();
|
||||
message.put("role", role);
|
||||
message.put("content", prompt);
|
||||
requestBody.put("messages", new Object[]{message});
|
||||
|
||||
if(StrUtil.isNotEmpty(promptJson)) {
|
||||
List<Map> promptList = JSONUtil.toList(promptJson, Map.class);
|
||||
Object[] objects = new Object[promptList.size()];
|
||||
for (int i = 0; i < promptList.size(); i++) {
|
||||
objects[i] = promptList.get(i);
|
||||
}
|
||||
//获取到的提示
|
||||
requestBody.put("messages", objects);
|
||||
}
|
||||
//开始给AI发送请求数据
|
||||
System.out.println("请求AI数据参数为:"+JSONUtil.toJsonStr(requestBody));
|
||||
// 创建请求
|
||||
Request request = new Request.Builder()
|
||||
.url(apiUrl)
|
||||
|
||||
Reference in New Issue
Block a user