|
@@ -12,21 +12,29 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
|
|
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
|
|
|
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
|
|
|
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
|
|
|
+import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentSearchReqVO;
|
|
|
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
|
|
|
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
|
|
|
+import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
|
|
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
|
|
|
import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
|
|
|
+import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnum;
|
|
|
import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants;
|
|
|
+import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService;
|
|
|
import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
|
|
|
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
|
|
|
import jakarta.annotation.Resource;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.springframework.ai.chat.messages.*;
|
|
|
+import org.springframework.ai.chat.messages.Message;
|
|
|
+import org.springframework.ai.chat.messages.MessageType;
|
|
|
+import org.springframework.ai.chat.messages.SystemMessage;
|
|
|
+import org.springframework.ai.chat.messages.UserMessage;
|
|
|
import org.springframework.ai.chat.model.ChatModel;
|
|
|
import org.springframework.ai.chat.model.ChatResponse;
|
|
|
import org.springframework.ai.chat.model.StreamingChatModel;
|
|
|
import org.springframework.ai.chat.prompt.ChatOptions;
|
|
|
import org.springframework.ai.chat.prompt.Prompt;
|
|
|
+import org.springframework.ai.chat.prompt.PromptTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import reactor.core.publisher.Flux;
|
|
@@ -59,6 +67,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|
|
private AiChatModelService chatModalService;
|
|
|
@Resource
|
|
|
private AiApiKeyService apiKeyService;
|
|
|
+ @Resource
|
|
|
+ private AiKnowledgeSegmentService knowledgeSegmentService;
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public AiChatMessageSendRespVO sendMessage(AiChatMessageSendReqVO sendReqVO, Long userId) {
|
|
@@ -141,14 +151,27 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|
|
AiChatModelDO model, AiChatMessageSendReqVO sendReqVO) {
|
|
|
// 1. 构建 Prompt Message 列表
|
|
|
List<Message> chatMessages = new ArrayList<>();
|
|
|
- // 1.1 system context 角色设定
|
|
|
+
|
|
|
+ // 1.1 知识库召回
|
|
|
+ if (Objects.nonNull(conversation.getKnowledgeId())) {
|
|
|
+ List<AiKnowledgeSegmentDO> segmentList = knowledgeSegmentService.similaritySearch(new AiKnowledgeSegmentSearchReqVO().setKnowledgeId(conversation.getKnowledgeId()).setContent(sendReqVO.getContent()));
|
|
|
+ if (CollUtil.isNotEmpty(segmentList)) {
|
|
|
+ PromptTemplate promptTemplate = new PromptTemplate(AiChatRoleEnum.AI_KNOWLEDGE_ROLE.getSystemMessage());
|
|
|
+ StringBuilder infoBuilder = StrUtil.builder();
|
|
|
+ segmentList.forEach(segment -> infoBuilder.append(System.lineSeparator()).append(segment.getContent()));
|
|
|
+ Message message = promptTemplate.createMessage(Map.of("info", infoBuilder.toString()));
|
|
|
+ chatMessages.add(message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1.2 system context 角色设定
|
|
|
if (StrUtil.isNotBlank(conversation.getSystemMessage())) {
|
|
|
chatMessages.add(new SystemMessage(conversation.getSystemMessage()));
|
|
|
}
|
|
|
- // 1.2 history message 历史消息
|
|
|
+ // 1.3 history message 历史消息
|
|
|
List<AiChatMessageDO> contextMessages = filterContextMessages(messages, conversation, sendReqVO);
|
|
|
contextMessages.forEach(message -> chatMessages.add(AiUtils.buildMessage(message.getType(), message.getContent())));
|
|
|
- // 1.3 user message 新发送消息
|
|
|
+ // 1.4 user message 新发送消息
|
|
|
chatMessages.add(new UserMessage(sendReqVO.getContent()));
|
|
|
|
|
|
// 2. 构建 ChatOptions 对象
|
|
@@ -160,12 +183,12 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|
|
|
|
|
/**
|
|
|
* 从历史消息中,获得倒序的 n 组消息作为消息上下文
|
|
|
- *
|
|
|
+ * <p>
|
|
|
* n 组:指的是 user + assistant 形成一组
|
|
|
*
|
|
|
- * @param messages 消息列表
|
|
|
+ * @param messages 消息列表
|
|
|
* @param conversation 对话
|
|
|
- * @param sendReqVO 发送请求
|
|
|
+ * @param sendReqVO 发送请求
|
|
|
* @return 消息上下文
|
|
|
*/
|
|
|
private List<AiChatMessageDO> filterContextMessages(List<AiChatMessageDO> messages,
|
|
@@ -182,7 +205,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
|
|
|
}
|
|
|
AiChatMessageDO userMessage = CollUtil.get(messages, i - 1);
|
|
|
if (userMessage == null || ObjUtil.notEqual(assistantMessage.getReplyId(), userMessage.getId())
|
|
|
- || StrUtil.isEmpty(assistantMessage.getContent())) {
|
|
|
+ || StrUtil.isEmpty(assistantMessage.getContent())) {
|
|
|
continue;
|
|
|
}
|
|
|
// 由于后续要 reverse 反转,所以先添加 assistantMessage
|