|
|
@ -18,6 +18,7 @@ import com.cloud.kicc.system.mapper.ImContentMapper; |
|
|
|
import com.cloud.kicc.system.service.FileService; |
|
|
|
import com.cloud.kicc.system.service.FileService; |
|
|
|
import com.cloud.kicc.system.service.IImContentService; |
|
|
|
import com.cloud.kicc.system.service.IImContentService; |
|
|
|
import com.cloud.kicc.system.util.AiUtil; |
|
|
|
import com.cloud.kicc.system.util.AiUtil; |
|
|
|
|
|
|
|
import com.knuddels.jtokkit.api.ModelType; |
|
|
|
import com.pig4cloud.plugin.oss.OssProperties; |
|
|
|
import com.pig4cloud.plugin.oss.OssProperties; |
|
|
|
import com.pig4cloud.plugin.oss.service.OssTemplate; |
|
|
|
import com.pig4cloud.plugin.oss.service.OssTemplate; |
|
|
|
import com.theokanning.openai.audio.CreateSpeechRequest; |
|
|
|
import com.theokanning.openai.audio.CreateSpeechRequest; |
|
|
@ -28,6 +29,7 @@ import com.theokanning.openai.completion.chat.ChatCompletionResult; |
|
|
|
import com.theokanning.openai.completion.chat.ChatMessage; |
|
|
|
import com.theokanning.openai.completion.chat.ChatMessage; |
|
|
|
import com.theokanning.openai.completion.chat.ChatMessageRole; |
|
|
|
import com.theokanning.openai.completion.chat.ChatMessageRole; |
|
|
|
import com.theokanning.openai.service.OpenAiService; |
|
|
|
import com.theokanning.openai.service.OpenAiService; |
|
|
|
|
|
|
|
import com.theokanning.openai.utils.TikTokensUtil; |
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
import lombok.SneakyThrows; |
|
|
|
import lombok.SneakyThrows; |
|
|
|
import okhttp3.ResponseBody; |
|
|
|
import okhttp3.ResponseBody; |
|
|
@ -40,7 +42,6 @@ import org.springframework.web.multipart.MultipartFile; |
|
|
|
import java.io.File; |
|
|
|
import java.io.File; |
|
|
|
import java.time.Duration; |
|
|
|
import java.time.Duration; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.time.format.DateTimeFormatter; |
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Objects; |
|
|
|
import java.util.Objects; |
|
|
@ -92,7 +93,8 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent |
|
|
|
).or(i -> |
|
|
|
).or(i -> |
|
|
|
i.eq(ImContent::getSendUserId, imContent.getReceiveUserId()) |
|
|
|
i.eq(ImContent::getSendUserId, imContent.getReceiveUserId()) |
|
|
|
.eq(ImContent::getReceiveUserId, imContent.getSendUserId()) |
|
|
|
.eq(ImContent::getReceiveUserId, imContent.getSendUserId()) |
|
|
|
) .orderByAsc(ImContent::getSendTime)); |
|
|
|
).last(String.format("LIMIT %s", openAiConfigProperties.getContextMessageMaxCount())) |
|
|
|
|
|
|
|
.orderByAsc(ImContent::getSendTime)); |
|
|
|
|
|
|
|
|
|
|
|
// 历史上下文消息
|
|
|
|
// 历史上下文消息
|
|
|
|
List<ChatMessage> historyMessages = imContents.stream().map(item -> { |
|
|
|
List<ChatMessage> historyMessages = imContents.stream().map(item -> { |
|
|
@ -101,6 +103,8 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent |
|
|
|
chatMessage.setContent(item.getContent()); |
|
|
|
chatMessage.setContent(item.getContent()); |
|
|
|
return chatMessage; |
|
|
|
return chatMessage; |
|
|
|
}).collect(Collectors.toList()); |
|
|
|
}).collect(Collectors.toList()); |
|
|
|
|
|
|
|
// 截断支持的上下文消息列表到令牌限制
|
|
|
|
|
|
|
|
truncateToTokenLimit(openAiConfigProperties.getModel(), historyMessages); |
|
|
|
|
|
|
|
|
|
|
|
// Completion消息
|
|
|
|
// Completion消息
|
|
|
|
ChatMessage completionMessage = new ChatMessage(ChatMessageRole.USER.value(), imContent.getContent()); |
|
|
|
ChatMessage completionMessage = new ChatMessage(ChatMessageRole.USER.value(), imContent.getContent()); |
|
|
@ -261,4 +265,23 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent |
|
|
|
return String.format("请过 %s小时%s分钟%s秒 之后在试!",hours,minutes,seconds); |
|
|
|
return String.format("请过 %s小时%s分钟%s秒 之后在试!",hours,minutes,seconds); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 截断支持的上下文消息列表到令牌限制 |
|
|
|
|
|
|
|
* @param messages 上下文消息列表 |
|
|
|
|
|
|
|
* @param modelName 指定模型 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private void truncateToTokenLimit(String modelName, List<ChatMessage> messages) { |
|
|
|
|
|
|
|
ModelType modelType = ModelType.fromName(modelName) |
|
|
|
|
|
|
|
.orElseThrow(() -> new CheckedException(String.format("找不到指定的:%s模型请检查配置!", modelName)));; |
|
|
|
|
|
|
|
int sumTokens = TikTokensUtil.tokens(modelName, messages); |
|
|
|
|
|
|
|
// 从前向后遍历消息,直到总 token 数在限制之内
|
|
|
|
|
|
|
|
while (!messages.isEmpty() && sumTokens > modelType.getMaxContextLength()) { |
|
|
|
|
|
|
|
// 移除列表中的第一个消息
|
|
|
|
|
|
|
|
messages.remove(0); |
|
|
|
|
|
|
|
// 重新计算总 token 数
|
|
|
|
|
|
|
|
sumTokens = TikTokensUtil.tokens(modelName, messages); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|