Эх сурвалжийг харах

feat(ai): 添加 Dify聊天功能支持

zrd 3 долоо хоног өмнө
parent
commit
9d45862ef9

+ 4 - 0
yudao-module-ai/yudao-module-ai-biz/pom.xml

@@ -60,5 +60,9 @@
             <groupId>cn.iocoder.boot</groupId>
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-test</artifactId>
             <artifactId>yudao-spring-boot-starter-test</artifactId>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-excel</artifactId>
+        </dependency>
     </dependencies>
     </dependencies>
 </project>
 </project>

+ 5 - 2
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java

@@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.format.annotation.DateTimeFormat;
 
 
+import java.io.Serial;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -12,7 +13,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Schema(description = "管理后台 - AI 聊天消息的分页 Request VO")
 @Schema(description = "管理后台 - AI 聊天消息的分页 Request VO")
 @Data
 @Data
 public class AiChatMessagePageReqVO extends PageParam {
 public class AiChatMessagePageReqVO extends PageParam {
-
+    
+    @Serial
+    private static final long serialVersionUID = 83042160850734267L;
     @Schema(description = "对话编号", example = "2048")
     @Schema(description = "对话编号", example = "2048")
     private Long conversationId;
     private Long conversationId;
 
 
@@ -21,7 +24,7 @@ public class AiChatMessagePageReqVO extends PageParam {
 
 
     @Schema(description = "消息内容", example = "你好")
     @Schema(description = "消息内容", example = "你好")
     private String content;
     private String content;
-
+    private String contentType;
     @Schema(description = "创建时间")
     @Schema(description = "创建时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
     private LocalDateTime[] createTime;

+ 1 - 1
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java

@@ -18,7 +18,7 @@ public class AiChatMessageRespVO {
 
 
     @Schema(description = "回复消息编号", example = "1024")
     @Schema(description = "回复消息编号", example = "1024")
     private Long replyId;
     private Long replyId;
-
+    private String contentType;
     @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role")
     @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role")
     private String type; // 参见 MessageType 枚举类
     private String type; // 参见 MessageType 枚举类
 
 

+ 1 - 1
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java

@@ -26,7 +26,7 @@ public class AiChatMessageSendReqVO {
     private String content;
     private String content;
     @Schema(description = "令牌")
     @Schema(description = "令牌")
     private String token;
     private String token;
-
+    private String contentType;
     @Schema(description = "是否携带上下文", example = "true")
     @Schema(description = "是否携带上下文", example = "true")
     private Boolean useContext;
     private Boolean useContext;
     
     

+ 1 - 1
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java

@@ -25,7 +25,7 @@ public class AiChatMessageSendRespVO {
 
 
         @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role")
         @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role")
         private String type; // 参见 MessageType 枚举类
         private String type; // 参见 MessageType 枚举类
-
+        private String contentType;
         @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊")
         @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊")
         private String content;
         private String content;
         private String event;
         private String event;

+ 9 - 2
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java

@@ -9,9 +9,13 @@ import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 import org.springframework.ai.chat.messages.MessageType;
 import org.springframework.ai.chat.messages.MessageType;
 
 
+import java.io.Serial;
 import java.util.List;
 import java.util.List;
 
 
 /**
 /**
@@ -27,7 +31,9 @@ import java.util.List;
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
 public class AiChatMessageDO extends BaseDO {
 public class AiChatMessageDO extends BaseDO {
-
+    
+    @Serial
+    private static final long serialVersionUID = 8754536560987460356L;
     /**
     /**
      * 编号,作为每条聊天记录的唯一标识符
      * 编号,作为每条聊天记录的唯一标识符
      */
      */
@@ -87,6 +93,7 @@ public class AiChatMessageDO extends BaseDO {
      * 聊天内容
      * 聊天内容
      */
      */
     private String content;
     private String content;
+    private String contentType;
 
 
     /**
     /**
      * 是否携带上下文
      * 是否携带上下文

+ 9 - 7
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java

@@ -118,12 +118,12 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
         // 3. 插入 user 发送消息
         // 3. 插入 user 发送消息
         AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
         AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
                 userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
                 userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
-                null);
+                null, sendReqVO.getContentType());
 
 
         // 3.1 插入 assistant 接收消息
         // 3.1 插入 assistant 接收消息
         AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
         AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
                 userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
                 userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
-                knowledgeSegments);
+                knowledgeSegments, sendReqVO.getContentType());
 
 
         // 3.2 创建 chat 需要的 Prompt
         // 3.2 创建 chat 需要的 Prompt
         Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, model, sendReqVO);
         Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, model, sendReqVO);
@@ -167,12 +167,12 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
         // 3. 插入 user 发送消息
         // 3. 插入 user 发送消息
         AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
         AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
                 userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
                 userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
-                null);
+                null, sendReqVO.getContentType());
 
 
         // 4.1 插入 assistant 接收消息
         // 4.1 插入 assistant 接收消息
         AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
         AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
                 userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
                 userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
-                knowledgeSegments);
+                knowledgeSegments, sendReqVO.getContentType());
 
 
         // 4.2 构建 Prompt,并进行调用
         // 4.2 构建 Prompt,并进行调用
         Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, model, sendReqVO);
         Prompt prompt = buildPrompt(conversation, historyMessages, knowledgeSegments, model, sendReqVO);
@@ -229,7 +229,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
         // 3. 插入 user 发送消息
         // 3. 插入 user 发送消息
         AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
         AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
                 userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
                 userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext(),
-                null);
+                null, sendReqVO.getContentType());
         String apiKey = DictFrameworkUtils.parseDictDataValue("ai_key", "多轮对话");
         String apiKey = DictFrameworkUtils.parseDictDataValue("ai_key", "多轮对话");
         JSONObject requestBody = new JSONObject();
         JSONObject requestBody = new JSONObject();
         if (StrUtil.isNotBlank(conversation.getDifyConversationId())) {
         if (StrUtil.isNotBlank(conversation.getDifyConversationId())) {
@@ -291,7 +291,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
         StringBuffer difyId = new StringBuffer();
         StringBuffer difyId = new StringBuffer();
         AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
         AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
                 userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
                 userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext(),
-                knowledgeSegments);
+                knowledgeSegments, sendReqVO.getContentType());
         return flux.map(chunk -> {
         return flux.map(chunk -> {
             String newContent = chunk.getContent();
             String newContent = chunk.getContent();
             contentBuffer.append(newContent);
             contentBuffer.append(newContent);
@@ -494,12 +494,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
     private AiChatMessageDO createChatMessage(Long conversationId, Long replyId,
     private AiChatMessageDO createChatMessage(Long conversationId, Long replyId,
             AiModelDO model, Long userId, Long roleId,
             AiModelDO model, Long userId, Long roleId,
             MessageType messageType, String content, Boolean useContext,
             MessageType messageType, String content, Boolean useContext,
-            List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments) {
+                                              List<AiKnowledgeSegmentSearchRespBO> knowledgeSegments,
+                                              String contentType) {
         AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId)
         AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId)
                 .setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId)
                 .setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId)
                 .setType(messageType.getValue()).setContent(content).setUseContext(useContext)
                 .setType(messageType.getValue()).setContent(content).setUseContext(useContext)
                 .setSegmentIds(convertList(knowledgeSegments, AiKnowledgeSegmentSearchRespBO::getId));
                 .setSegmentIds(convertList(knowledgeSegments, AiKnowledgeSegmentSearchRespBO::getId));
         message.setCreateTime(LocalDateTime.now());
         message.setCreateTime(LocalDateTime.now());
+        message.setContentType(contentType);
         chatMessageMapper.insert(message);
         chatMessageMapper.insert(message);
         return message;
         return message;
     }
     }