需求分析:
场景:调用三方chatGPT服务,通过传递历史聊天记录来获得联系上下文的回答
需要解决的问题:传递的历史聊天记录有限制,所以每次就需要去判断是否超出限制,如果超出限制就要淘汰掉一些最早的聊天记录去传值。
数据结构(简化):定义一个集合,集合中的对象有两个属性,一个是聊天内容,一个是聊天内容的字数
分析:如果传递的数据>设定的最大值,这个时候我们把两者的差计算出来定义为A,然后去聊天记录的集合的开始去判断A是否小于集合中第一个元素设定的字数,如果小于那把这个元素从集合中移除就行了,如果不小于,那就需要拿到集合的前两个元素设定的字数加起来,再和A去判断,以此类推
使用递归算法获取淘汰集合的临界坐标:
温馨提示:注释都放到代码里了哦~
/**
* 淘汰老的聊天记录
* @param num 是集合总字数和设定限制的差值
* @param s 是最后要返回的临界值,也就是s前面的坐标都要被淘汰
*/
int weedOut(int num, int s, List<ChatMessage> chatMessageList) {
int sum = 0; // 集合聊天记录最前面部分tokens相加
for (int i = 0; i < s; i++) {
ChatMessage chatMessages = chatMessageList.get(i);
// 计算要淘汰的元素的字数
sum += chatMessages.getTokens();
}
// 判断要淘汰的元素的字数,如果不符合条件 下标继续下移 s + 1
if (sum > num) {
return s; // 最后要这个集合下标为s后面的
} else {
return weedOut(num, s + 1, chatMessageList);
}
}
结合业务的完整代码供大家交流:
/**
* @author : jiagang
* @date : Created in 2023/7/12 10:48
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ChatTest {
@Autowired
private ChatMessageService chatMessageService;
@Test
public void test1(){
List<ChatMessage> chatMessageList = chatMessageService.chatMessageList(ChatMessage.builder().sessionId("f3667fec-ff71-f1e9-108a-658f527378a3").build());
JSONArray jsonArray = new JSONArray(); // 最终结果
if (!CollectionUtils.isEmpty(chatMessageList)) {
// 计算聊天信息tokens
int sum = chatMessageList.stream().mapToInt(ChatMessage::getTokens).sum(); // 301 个 99 202
if (sum > VoiceChatConstant.TOKENS) {
// 获取淘汰集合坐标的临界点
int index = weedOut(sum - VoiceChatConstant.TOKENS, 1, chatMessageList);
System.out.println("获取到的临界点下标---->" + index);
for (int i = index; i < chatMessageList.size();i ++){
ChatMessage chatMessage = chatMessageList.get(i);
JSONObject jsonObject = new JSONObject();
//jsonObject.put("id",chatMessage.getId());
jsonObject.put("role",chatMessage.getSenderCode().equals(VoiceChatConstant.CHAT_CODE) ? VoiceChatConstant.CHAT_CODE : VoiceChatConstant.USER_CODE);
jsonObject.put("content",chatMessage.getMessage());
jsonArray.add(jsonObject);
}
} else {
chatMessageList.forEach(c ->{
JSONObject jsonObject = new JSONObject();
jsonObject.put("role", c.getSenderCode().equals(VoiceChatConstant.CHAT_CODE) ? VoiceChatConstant.CHAT_CODE : VoiceChatConstant.USER_CODE);
jsonObject.put("content", c.getMessage());
jsonArray.add(jsonObject);
});
}
}
System.out.println(jsonArray);
}
/**
* 淘汰老的聊天记录
* @param num 是集合总字数和设定限制的差值
* @param s 是最后要返回的临界值,也就是s前面的坐标都要被淘汰
*/
int weedOut(int num, int s, List<ChatMessage> chatMessageList) {
int sum = 0; // 集合聊天记录最前面部分tokens相加
for (int i = 0; i < s; i++) {
ChatMessage chatMessages = chatMessageList.get(i);
// 计算要淘汰的元素的字数
sum += chatMessages.getTokens();
}
// 判断要淘汰的元素的字数,如果不符合条件 下标继续下移 s + 1
if (sum > num) {
return s; // 最后要这个集合下标为s后面的
} else {
return weedOut(num, s + 1, chatMessageList);
}
}
}
分割线-----------------------------------------------------------------------------------------------------------------------------------------------------------
创作不易,三连支持一下吧
最后的最后送大家一句话
白驹过隙,沧海桑田