This commit is contained in:
2025-12-18 16:48:45 +08:00
parent b97f0da746
commit 41cbe2bd54
80 changed files with 5434 additions and 351 deletions

View File

@@ -0,0 +1,32 @@
package org.xyzh.api.ai.dto;
import java.io.Serializable;
import java.util.List;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "对话消息数据预处理对象")
public class ChatPrepareData implements Serializable {
private final static long serialVersionUID = 1L;
@Schema(description = "智能体Id")
private String agentId;
@Schema(description = "对话Id")
private String chatId;
@Schema(description = "用户问题")
private String query;
@Schema(description = "本次对话携带的dify文件对象")
private List<DifyFileInfo> files;
@Schema(description = "用户ID来客传wechatId员工传userId")
private String userId;
@Schema(description = "用户类型false=来客true=员工)")
private Boolean userType;
}

View File

@@ -29,6 +29,9 @@ public class TbAgent extends BaseDTO{
@Schema(description = "智能体APIKEY")
private String apiKey;
@Schema(description = "是否是对外智能体,未登录可用")
private Boolean outer;
@Schema(description = "引导词")
private String introduce;

View File

@@ -15,6 +15,9 @@ public class TbChatMessage extends BaseDTO{
@Schema(description = "消息ID")
private String messageId;
@Schema(description = "Dify消息ID")
private String difyMessageId;
@Schema(description = "对话ID")
private String chatId;

View File

@@ -61,7 +61,7 @@ public class TbKnowledge extends BaseDTO{
@Schema(description = "bidding所属项目ID")
private String projectId;
@Schema(description = "所属分类 workcase 内部知识库、外部知识库")
@Schema(description = "所属分类 workcase内部知识库、外部知识库其他服务default")
private String category;

View File

@@ -23,6 +23,6 @@ public class TbKnowledgeFile extends BaseDTO{
private String difyFileId;
@Schema(description = "文件版本")
private String version;
private Integer version;
}

View File

@@ -1,64 +1,62 @@
package org.xyzh.api.ai.service;
import java.io.File;
import java.util.List;
import java.util.Map;
import org.springframework.web.multipart.MultipartFile;
import org.xyzh.api.ai.dto.TbKnowledgeFile;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.core.page.PageParam;
/**
* @description AI文件上传服务只负责与Dify交互不处理minio和数据库
* @author yslg
* @since 2025-12-18
*/
public interface AIFileUploadService {
// ============================ 对话文件管理 ============================
/**
* 上传文件用于对话(图文多模态)
* @param file 上传的文件
* @param agentId 智能体ID
* @return Dify文件信息包含id、name、size等
*/
ResultDomain<Map<String, Object>> uploadFileForChat(
MultipartFile file,
String agentId
);
/**
* @description 上传文件用于对话(图文多模态)
* @param file 上传的文件
* @param agentId 智能体ID
* @return ResultDomain<Map<String, Object>> Dify文件信息
* @author yslg
* @since 2025-12-18
*/
ResultDomain<Map<String, Object>> uploadFileForChat(MultipartFile file, String agentId);
// ============================ 知识库文件管理 ============================
// ============================ 知识库Dify文档管理 ============================
/**
* 上传文件到知识库(同步到Dify
* @param knowledgeId 知识库ID
* @param file 上传的文件
* @param indexingTechnique 索引方式(可选)
* @return 上传结果
* @description 上传文件到Dify知识库(只负责Dify上传不处理minio和数据库
* @param difyDatasetId Dify知识库ID
* @param file 文件
* @param fileName 文件名
* @param indexingTechnique 索引方式
* @return ResultDomain<String> Dify文档ID
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledgeFile> uploadToKnowledge(
String knowledgeId,
MultipartFile file,
String indexingTechnique
);
ResultDomain<String> uploadFileToDify(String difyDatasetId, File file, String fileName, String indexingTechnique);
/**
* 批量上传文件到知识库
* @param knowledgeId 知识库ID
* @param files 上传的文件列表
* @param indexingTechnique 索引方式(可选)
* @return 上传结果列表
* @description 从Dify知识库删除文档
* @param difyDatasetId Dify知识库ID
* @param difyDocumentId Dify文档ID
* @return ResultDomain<Boolean> 删除结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledgeFile> batchUploadToKnowledge(
String knowledgeId,
List<MultipartFile> files,
String indexingTechnique
);
ResultDomain<Boolean> deleteFileFromDify(String difyDatasetId, String difyDocumentId);
/**
* 同时删除Dify中的文档
* @param fileId dify的文件ID
* @return 删除结果
* @description 批量从Dify知识库删除文档
* @param difyDatasetId Dify知识库ID
* @param difyDocumentIds Dify文档ID列表
* @return ResultDomain<Boolean> 删除结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<Boolean> deleteKnowledgeFile(String fileId);
ResultDomain<Boolean> batchDeleteFilesFromDify(String difyDatasetId, List<String> difyDocumentIds);
}

View File

@@ -1,9 +1,7 @@
package org.xyzh.api.ai.service;
import java.util.List;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.xyzh.api.ai.dto.DifyFileInfo;
import org.xyzh.api.ai.dto.ChatPrepareData;
import org.xyzh.api.ai.dto.TbChat;
import org.xyzh.api.ai.dto.TbChatMessage;
import org.xyzh.common.core.domain.ResultDomain;
@@ -17,7 +15,7 @@ public interface AgentChatService {
* @param title 会话标题(可选)
* @return 会话信息
*/
ResultDomain<TbChat> createChat(String agentId, String title);
ResultDomain<TbChat> createChat(TbChat chat);
/**
* 更新会话名称
@@ -26,7 +24,7 @@ public interface AgentChatService {
* @param title 会话标题(可选)
* @return 会话信息
*/
ResultDomain<TbChat> updateChat(String agentId, String chatId, String title);
ResultDomain<TbChat> updateChat(TbChat chat);
/**
* 删除会话
@@ -34,40 +32,31 @@ public interface AgentChatService {
* @param chatId 会话ID
* @return 会话信息
*/
ResultDomain<TbChat> deleteChat(String agentId, String chatId);
ResultDomain<TbChat> deleteChat(TbChat chat);
/**
* 获取会话列表
* @param agentId 智能体ID
* @return 会话列表
*/
ResultDomain<TbChat> getChatList(String agentId);
ResultDomain<TbChat> getChatList(TbChat filter);
// ====================== 智能体聊天管理 ======================
/**
* 获取会话消息列表
* @param agentId 智能体ID
* @param chatId 会话ID
* @param filter 会话过滤条件包含agentId, chatId, userId, userType
* @return 会话消息列表
*/
ResultDomain<TbChatMessage> getChatMessageList(String agentId, String chatId);
ResultDomain<TbChatMessage> getChatMessageList(TbChat filter);
/**
* 准备聊天数据POST传递复杂参数
* @param agentId 智能体ID
* @param chatId 会话ID可选为空则创建新会话
* @param query 用户问题
* @param filesData 上传的文件列表Dify文件信息
* @param prepareData 对话准备数据包含agentId, chatId, query, files, userId, userType
* @return ResultDomain<String> 返回sessionId
*/
ResultDomain<String> prepareChatMessageSession(
String agentId,
String chatId,
String query,
List<DifyFileInfo> filesData
);
ResultDomain<String> prepareChatMessageSession(ChatPrepareData prepareData);
/**
* 流式对话SSE- 使用sessionId建立SSE连接 产生chatMessage
@@ -78,21 +67,20 @@ public interface AgentChatService {
/**
* 停止对话生成通过Dify TaskID
* @param filter 会话过滤条件包含agentId, userId, userType
* @param taskId Dify任务ID
* @param agentId 智能体ID
* @return 停止结果
*/
ResultDomain<Boolean> stopChatMessageByTaskId(String taskId, String agentId);
ResultDomain<Boolean> stopChatMessageByTaskId(TbChat filter, String taskId);
/**
* 评价
* @param agentId 智能体ID
* @param chatId 会话ID
* @param filter 会话过滤条件包含agentId, chatId, userId, userType
* @param messageId 消息ID
* @param comment 评价
* @return 评价结果
*/
ResultDomain<Boolean> commentChatMessage(String agentId, String chatId, String messageId, String comment);
ResultDomain<Boolean> commentChatMessage(TbChat filter, String messageId, String comment);
}

View File

@@ -2,6 +2,7 @@ package org.xyzh.api.ai.service;
import org.xyzh.api.ai.dto.TbAgent;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageRequest;
/**
* Agent服务接口
@@ -12,6 +13,8 @@ public interface AgentService {
/**
* 添加Agent, 用户自己在dify搭建发布后在本服务进行接入
* @param tbAgent
* @author yslg
* @since 2025-12-17
* @return
*/
ResultDomain<TbAgent> addAgent(TbAgent tbAgent);
@@ -19,6 +22,8 @@ public interface AgentService {
/**
* 更新Agent
* @param tbAgent
* @author yslg
* @since 2025-12-17
* @return
*/
ResultDomain<TbAgent> updateAgent(TbAgent tbAgent);
@@ -26,7 +31,27 @@ public interface AgentService {
/**
* 删除Agent
* @param tbAgent
* @author yslg
* @since 2025-12-17
* @return
*/
ResultDomain<TbAgent> deleteAgent(TbAgent tbAgent);
ResultDomain<TbAgent> selectAgentById(String agentId);
/**
* @description 分页获取当前用户可用的agent智能体
* @param pageRequest
* @author yslg
* @since 2025-12-17
*/
ResultDomain<TbAgent> getAgentPage(PageRequest<TbAgent> pageRequest);
/**
* @description 获取当前用户所有可用智能体列表
* @param tbAgent
* @author yslg
* @since 2025-12-17
*/
ResultDomain<TbAgent> getAgentList(TbAgent tbAgent);
}

View File

@@ -3,6 +3,7 @@ package org.xyzh.api.ai.service;
import java.util.List;
import java.util.Map;
import org.springframework.web.multipart.MultipartFile;
import org.xyzh.api.ai.dto.TbKnowledge;
import org.xyzh.api.ai.dto.TbKnowledgeFile;
import org.xyzh.common.core.domain.ResultDomain;
@@ -11,13 +12,16 @@ import org.xyzh.common.core.page.PageParam;
public interface KnowledgeService {
// ================================= 知识库管理 =================================
/**
* 创建知识库同步到Dify
* @param knowledge 知识库信息
* @param permissionType 权限类型PUBLIC-公开DEPARTMENT-部门ROLE-角色PRIVATE-私有
* @param deptIds 部门ID列表DEPARTMENT类型需要
* @param roleIds 角色ID列表ROLE/PRIVATE类型需要
* @return 创建结果
* @description 创建知识库基础信息包含dify知识库各种参数的配置
* @param knowledge 知识库信息
* @param permissionType 权限类型PUBLIC-公开DEPARTMENT-部门ROLE-角色PRIVATE-私有
* @param deptIds 部门ID列表DEPARTMENT类型需要
* @param roleIds 角色ID列表ROLE/PRIVATE类型需要
* @return ResultDomain<TbKnowledge> 创建结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledge> createKnowledge(
TbKnowledge knowledge,
@@ -27,98 +31,138 @@ public interface KnowledgeService {
);
/**
* 更新知识库
* @param knowledge 知识库信息
* @return 更新结果
* @description 更新知识库包含dify知识库各种参数的配置
* @param knowledge 知识库信息
* @return ResultDomain<TbKnowledge> 更新结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledge> updateKnowledge(TbKnowledge knowledge);
/**
* 删除知识库同时删除Dify中的知识库
* @param knowledgeId 知识库ID
* @return 删除结果
* @description 删除知识库同时删除dify知识库
* @param knowledgeId 知识库ID
* @return ResultDomain<Boolean> 删除结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<Boolean> deleteKnowledge(String knowledgeId);
/**
* 根据ID查询知识库带权限校验
* @param knowledgeId 知识库ID
* @return 知识库信息
* @description 获取知识库详情包含dify知识库各种参数的配置
* @param knowledgeId 知识库ID
* @return ResultDomain<TbKnowledge> 知识库信息
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledge> getKnowledgeById(String knowledgeId);
/**
* 查询用户有权限的知识库列表
* @param filter 过滤条件
* @return 知识库列表
* @description 查询知识库列表
* @param filter 过滤条件
* @return ResultDomain<TbKnowledge> 知识库列表
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledge> listKnowledges(TbKnowledge filter);
/**
* 分页查询知识库
* @param filter 过滤条件
* @param pageParam 分页参数
* @return 分页结果
* @description 分页查询知识库
* @param filter 过滤条件
* @param pageParam 分页参数
* @return ResultDomain<TbKnowledge> 分页结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledge> pageKnowledges(TbKnowledge filter, PageParam pageParam);
/**
* 查询知识库的文档数量和分段数量从Dify同步
* @param knowledgeId 知识库ID
* @return 统计信息
* @description 获取知识库统计信息从Dify同步文档数量和分段数量)
* @param knowledgeId 知识库ID
* @return ResultDomain<TbKnowledge> 统计信息
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledge> getKnowledgeStats(String knowledgeId);
/**
* 获取可用的嵌入模型列表
* @return 嵌入模型列表
* @description 获取可用的嵌入模型列表
* @return ResultDomain<Map<String, Object>> 嵌入模型列表
* @author yslg
* @since 2025-12-18
*/
ResultDomain<Map<String, Object>> getAvailableEmbeddingModels();
/**
* 获取可用的Rerank模型列表
* @return Rerank模型列表
* @description 获取可用的Rerank模型列表
* @return ResultDomain<Map<String, Object>> Rerank模型列表
* @author yslg
* @since 2025-12-18
*/
ResultDomain<Map<String, Object>> getAvailableRerankModels();
// ================================= 文件管理 =================================
/**
* 获取Dify知识库文档列表
* @param knowledgeId 知识库ID
* @param page 页码从1开始
* @param limit 每页数量
* @return 文档列表
* @description 获取知识库文档列表从Dify获取
* @param knowledgeId 知识库ID
* @param page 页码从1开始
* @param limit 每页数量
* @return ResultDomain<Map<String, Object>> 文档列表
* @author yslg
* @since 2025-12-18
*/
ResultDomain<Map<String, Object>> getDocumentList(String knowledgeId, Integer page, Integer limit);
// ================================= 文件管理 =================================
/**
* 添加知识库文件
* @param knowledgeFile 文件信息
* @return 添加结果
*/
ResultDomain<TbKnowledgeFile> addKnowledgeFile(TbKnowledgeFile knowledgeFile);
/**
* 更新知识库文件, 产生一个新version 删除dify中旧版本的文件的document并上传新文件重新索引
* @param knowledgeFile 文件信息
* @return 更新结果
*/
ResultDomain<TbKnowledgeFile> updateKnowledgeFile(TbKnowledgeFile knowledgeFile);
/**
* 删除知识库文件
* @param knowledgeFile 文件信息
* @return 删除结果
*/
ResultDomain<TbKnowledgeFile> deleteKnowledgeFile(TbKnowledgeFile knowledgeFile);
/**
* @description 获取一个文件的所有历史版本
* @param fileId 文件ID
* @description 上传文件到知识库完整流程minio + Dify + 数据库)
* @param knowledgeId 知识库ID
* @param file 上传的文件
* @param indexingTechnique 索引方式
* @return ResultDomain<TbKnowledgeFile> 上传结果
* @author yslg
* @since 2025-12-15
* @since 2025-12-18
*/
ResultDomain<TbKnowledgeFile> getKnowledgeFileHistory(String fileId);
ResultDomain<TbKnowledgeFile> uploadKnowledgeFile(String knowledgeId, MultipartFile file, String indexingTechnique);
/**
* @description 批量上传文件到知识库
* @param knowledgeId 知识库ID
* @param files 文件列表
* @param indexingTechnique 索引方式
* @return ResultDomain<TbKnowledgeFile> 上传结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledgeFile> batchUploadKnowledgeFile(String knowledgeId, List<MultipartFile> files, String indexingTechnique);
/**
* @description 上传新版本文件fileRootId一致version递增
* @param knowledgeId 知识库ID
* @param file 新文件
* @param fileRootId 文件根ID
* @return ResultDomain<TbKnowledgeFile> 新版本文件信息
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledgeFile> updateKnowledgeFileVersion(String knowledgeId, MultipartFile file, String fileRootId);
/**
* @description 删除知识库文件根据fileRootId删除所有版本
* @param fileRootId 文件根ID
* @return ResultDomain<Boolean> 删除结果
* @author yslg
* @since 2025-12-18
*/
ResultDomain<Boolean> deleteKnowledgeFileById(String fileRootId);
/**
* @description 获取文件历史版本
* @param fileRootId 文件根ID
* @return ResultDomain<TbKnowledgeFile> 文件历史版本列表
* @author yslg
* @since 2025-12-18
*/
ResultDomain<TbKnowledgeFile> getKnowledgeFileHistory(String fileRootId);
}

View File

@@ -0,0 +1,50 @@
package org.xyzh.api.ai.vo;
import java.util.List;
import org.xyzh.api.ai.dto.PromptCard;
import org.xyzh.common.vo.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @description Agent视图
* @filename AgentVO.java
* @author yslg
* @copyright yslg
* @since 2025-11-05
*/
@Data
@Schema(description = "Agent视图")
public class AgentVO extends BaseVO{
private static final long serialVersionUID = 1L;
@Schema(description = "智能体ID")
private String agentId;
@Schema(description = "智能体名称")
private String name;
@Schema(description = "智能体描述")
private String description;
@Schema(description = "智能体url")
private String link;
@Schema(description = "智能体APIKEY")
private String apiKey;
@Schema(description = "是否是对外智能体,未登录可用")
private Boolean outer;
@Schema(description = "引导词")
private String introduce;
@Schema(description = "提示卡片数组")
private List<PromptCard> promptCards;
@Schema(description = "分类")
private String category;
}