756 lines
21 KiB
Markdown
756 lines
21 KiB
Markdown
|
|
# pigx-dify 模块架构设计
|
|||
|
|
|
|||
|
|
## 1. 模块概述
|
|||
|
|
|
|||
|
|
### 1.1 定位
|
|||
|
|
pigx-dify 是 pigx 平台的 AI 服务模块,专门用于集成 Dify AI 平台,提供智能体管理、知识库管理和 AI 对话功能。
|
|||
|
|
|
|||
|
|
### 1.2 核心功能
|
|||
|
|
- 智能体(Agent)管理
|
|||
|
|
- 知识库(Knowledge)管理
|
|||
|
|
- AI 对话(Chat)功能
|
|||
|
|
- Dify API 集成
|
|||
|
|
- 流式响应支持(SSE)
|
|||
|
|
|
|||
|
|
### 1.3 技术栈
|
|||
|
|
- Spring Boot 3.5.8
|
|||
|
|
- Spring Cloud 2025.0.0
|
|||
|
|
- MyBatis-Plus 3.5.14
|
|||
|
|
- MySQL 8.0
|
|||
|
|
- Dify API Client
|
|||
|
|
- SSE (Server-Sent Events)
|
|||
|
|
|
|||
|
|
## 2. 模块结构
|
|||
|
|
|
|||
|
|
### 2.1 Maven 项目结构
|
|||
|
|
|
|||
|
|
```xml
|
|||
|
|
<!-- pigx-dify/pom.xml -->
|
|||
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|||
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|||
|
|
<modelVersion>4.0.0</modelVersion>
|
|||
|
|
<parent>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx</artifactId>
|
|||
|
|
<version>6.4.0</version>
|
|||
|
|
</parent>
|
|||
|
|
|
|||
|
|
<artifactId>pigx-dify</artifactId>
|
|||
|
|
<packaging>pom</packaging>
|
|||
|
|
<description>Dify AI integration module</description>
|
|||
|
|
|
|||
|
|
<modules>
|
|||
|
|
<module>pigx-dify-api</module>
|
|||
|
|
<module>pigx-dify-biz</module>
|
|||
|
|
</modules>
|
|||
|
|
</project>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 pigx-dify-api 结构
|
|||
|
|
|
|||
|
|
```xml
|
|||
|
|
<!-- pigx-dify-api/pom.xml -->
|
|||
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|||
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|||
|
|
<parent>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-dify</artifactId>
|
|||
|
|
<version>6.4.0</version>
|
|||
|
|
</parent>
|
|||
|
|
|
|||
|
|
<artifactId>pigx-dify-api</artifactId>
|
|||
|
|
<description>Dify API interfaces and entities</description>
|
|||
|
|
|
|||
|
|
<dependencies>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-common-core</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.baomidou</groupId>
|
|||
|
|
<artifactId>mybatis-plus-annotation</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>org.springdoc</groupId>
|
|||
|
|
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
</dependencies>
|
|||
|
|
</project>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.3 pigx-dify-biz 结构
|
|||
|
|
|
|||
|
|
```xml
|
|||
|
|
<!-- pigx-dify-biz/pom.xml -->
|
|||
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|||
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|||
|
|
<parent>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-dify</artifactId>
|
|||
|
|
<version>6.4.0</version>
|
|||
|
|
</parent>
|
|||
|
|
|
|||
|
|
<artifactId>pigx-dify-biz</artifactId>
|
|||
|
|
<description>Dify business implementation</description>
|
|||
|
|
|
|||
|
|
<dependencies>
|
|||
|
|
<!-- pigx dependencies -->
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-dify-api</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-common-security</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-common-log</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-common-mybatis</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.pig4cloud</groupId>
|
|||
|
|
<artifactId>pigx-common-swagger</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
|
|||
|
|
<!-- Spring Boot -->
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>org.springframework.boot</groupId>
|
|||
|
|
<artifactId>spring-boot-starter-web</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>org.springframework.boot</groupId>
|
|||
|
|
<artifactId>spring-boot-starter-undertow</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
|
|||
|
|
<!-- Spring Cloud -->
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.alibaba.cloud</groupId>
|
|||
|
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>com.alibaba.cloud</groupId>
|
|||
|
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
|
|||
|
|
<!-- HTTP Client for Dify API -->
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>org.apache.httpcomponents.client5</groupId>
|
|||
|
|
<artifactId>httpclient5</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>org.springframework</groupId>
|
|||
|
|
<artifactId>spring-webflux</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
|
|||
|
|
<!-- SSE Support -->
|
|||
|
|
<dependency>
|
|||
|
|
<groupId>org.springframework.boot</groupId>
|
|||
|
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
|||
|
|
</dependency>
|
|||
|
|
</dependencies>
|
|||
|
|
|
|||
|
|
<build>
|
|||
|
|
<plugins>
|
|||
|
|
<plugin>
|
|||
|
|
<groupId>org.springframework.boot</groupId>
|
|||
|
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
|||
|
|
</plugin>
|
|||
|
|
</plugins>
|
|||
|
|
</build>
|
|||
|
|
</project>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 3. 包结构设计
|
|||
|
|
|
|||
|
|
### 3.1 pigx-dify-api 包结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
pigx-dify-api/
|
|||
|
|
└── src/main/java/com/pig4cloud/pigx/dify/api/
|
|||
|
|
├── entity/ # 实体类
|
|||
|
|
│ ├── TbAgent.java # 智能体
|
|||
|
|
│ ├── TbChat.java # 聊天会话
|
|||
|
|
│ ├── TbChatMessage.java # 聊天消息
|
|||
|
|
│ └── TbKnowledge.java # 知识库
|
|||
|
|
├── dto/ # 数据传输对象
|
|||
|
|
│ ├── AgentDTO.java
|
|||
|
|
│ ├── ChatDTO.java
|
|||
|
|
│ ├── ChatMessageDTO.java
|
|||
|
|
│ └── KnowledgeDTO.java
|
|||
|
|
├── vo/ # 视图对象
|
|||
|
|
│ ├── AgentVO.java
|
|||
|
|
│ ├── ChatVO.java
|
|||
|
|
│ └── KnowledgeVO.java
|
|||
|
|
├── feign/ # Feign接口
|
|||
|
|
│ └── RemoteDifyService.java
|
|||
|
|
└── constant/ # 常量定义
|
|||
|
|
└── DifyConstant.java
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 pigx-dify-biz 包结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
pigx-dify-biz/
|
|||
|
|
└── src/main/java/com/pig4cloud/pigx/dify/
|
|||
|
|
├── DifyApplication.java # 启动类
|
|||
|
|
├── config/ # 配置类
|
|||
|
|
│ ├── DifyConfig.java # Dify配置
|
|||
|
|
│ ├── WebConfig.java # Web配置
|
|||
|
|
│ └── AsyncConfig.java # 异步配置
|
|||
|
|
├── controller/ # 控制器
|
|||
|
|
│ ├── AgentController.java # 智能体管理
|
|||
|
|
│ ├── ChatController.java # 对话管理
|
|||
|
|
│ └── KnowledgeController.java # 知识库管理
|
|||
|
|
├── service/ # 服务层
|
|||
|
|
│ ├── AgentService.java
|
|||
|
|
│ ├── ChatService.java
|
|||
|
|
│ ├── KnowledgeService.java
|
|||
|
|
│ └── impl/
|
|||
|
|
│ ├── AgentServiceImpl.java
|
|||
|
|
│ ├── ChatServiceImpl.java
|
|||
|
|
│ └── KnowledgeServiceImpl.java
|
|||
|
|
├── mapper/ # 数据访问层
|
|||
|
|
│ ├── AgentMapper.java
|
|||
|
|
│ ├── ChatMapper.java
|
|||
|
|
│ ├── ChatMessageMapper.java
|
|||
|
|
│ └── KnowledgeMapper.java
|
|||
|
|
├── client/ # 外部API客户端
|
|||
|
|
│ ├── DifyApiClient.java # Dify API客户端
|
|||
|
|
│ ├── dto/ # Dify API DTO
|
|||
|
|
│ │ ├── DifyRequest.java
|
|||
|
|
│ │ └── DifyResponse.java
|
|||
|
|
│ └── callback/
|
|||
|
|
│ └── StreamCallback.java # 流式回调
|
|||
|
|
└── handler/ # 处理器
|
|||
|
|
├── SseHandler.java # SSE处理
|
|||
|
|
└── GlobalExceptionHandler.java # 全局异常处理
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 4. 核心代码设计
|
|||
|
|
|
|||
|
|
### 4.1 启动类
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
package com.pig4cloud.pigx.dify;
|
|||
|
|
|
|||
|
|
import com.pig4cloud.pigx.common.feign.annotation.EnablePigxFeignClients;
|
|||
|
|
import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer;
|
|||
|
|
import com.pig4cloud.pigx.common.swagger.annotation.EnablePigxDoc;
|
|||
|
|
import org.springframework.boot.SpringApplication;
|
|||
|
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
|
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
|||
|
|
|
|||
|
|
@EnablePigxDoc
|
|||
|
|
@EnablePigxResourceServer
|
|||
|
|
@EnablePigxFeignClients
|
|||
|
|
@EnableDiscoveryClient
|
|||
|
|
@SpringBootApplication
|
|||
|
|
public class DifyApplication {
|
|||
|
|
public static void main(String[] args) {
|
|||
|
|
SpringApplication.run(DifyApplication.class, args);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 配置类
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
package com.pig4cloud.pigx.dify.config;
|
|||
|
|
|
|||
|
|
import lombok.Data;
|
|||
|
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
|
|
import org.springframework.context.annotation.Configuration;
|
|||
|
|
|
|||
|
|
@Data
|
|||
|
|
@Configuration
|
|||
|
|
@ConfigurationProperties(prefix = "dify")
|
|||
|
|
public class DifyConfig {
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Dify API基础URL
|
|||
|
|
*/
|
|||
|
|
private String apiBaseUrl = "https://api.dify.ai/v1";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 默认API Key(可被智能体配置覆盖)
|
|||
|
|
*/
|
|||
|
|
private String defaultApiKey;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 连接超时(毫秒)
|
|||
|
|
*/
|
|||
|
|
private Integer connectTimeout = 10000;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 读取超时(毫秒)
|
|||
|
|
*/
|
|||
|
|
private Integer readTimeout = 30000;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 流式响应超时(毫秒)
|
|||
|
|
*/
|
|||
|
|
private Integer streamTimeout = 60000;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 是否启用调试日志
|
|||
|
|
*/
|
|||
|
|
private Boolean debug = false;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.3 实体设计
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
package com.pig4cloud.pigx.dify.api.entity;
|
|||
|
|
|
|||
|
|
import com.baomidou.mybatisplus.annotation.*;
|
|||
|
|
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
|||
|
|
import lombok.Data;
|
|||
|
|
import lombok.EqualsAndHashCode;
|
|||
|
|
|
|||
|
|
import java.time.LocalDateTime;
|
|||
|
|
|
|||
|
|
@Data
|
|||
|
|
@TableName("tb_agent")
|
|||
|
|
@EqualsAndHashCode(callSuper = true)
|
|||
|
|
public class TbAgent extends Model<TbAgent> {
|
|||
|
|
|
|||
|
|
@TableId(type = IdType.ASSIGN_UUID)
|
|||
|
|
private String agentId;
|
|||
|
|
|
|||
|
|
private String name;
|
|||
|
|
|
|||
|
|
private String description;
|
|||
|
|
|
|||
|
|
private String difyApiKey;
|
|||
|
|
|
|||
|
|
private String difyAgentId;
|
|||
|
|
|
|||
|
|
private String config; // JSON配置
|
|||
|
|
|
|||
|
|
private String icon;
|
|||
|
|
|
|||
|
|
private Integer status; // 0:禁用 1:启用
|
|||
|
|
|
|||
|
|
@TableField(fill = FieldFill.INSERT)
|
|||
|
|
private Long tenantId;
|
|||
|
|
|
|||
|
|
@TableField(fill = FieldFill.INSERT)
|
|||
|
|
private String createBy;
|
|||
|
|
|
|||
|
|
@TableField(fill = FieldFill.INSERT)
|
|||
|
|
private LocalDateTime createTime;
|
|||
|
|
|
|||
|
|
@TableField(fill = FieldFill.UPDATE)
|
|||
|
|
private String updateBy;
|
|||
|
|
|
|||
|
|
@TableField(fill = FieldFill.UPDATE)
|
|||
|
|
private LocalDateTime updateTime;
|
|||
|
|
|
|||
|
|
@TableLogic
|
|||
|
|
private Integer delFlag;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.4 Controller设计
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
package com.pig4cloud.pigx.dify.controller;
|
|||
|
|
|
|||
|
|
import com.pig4cloud.pigx.common.core.util.R;
|
|||
|
|
import com.pig4cloud.pigx.common.security.annotation.Inner;
|
|||
|
|
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
|
|||
|
|
import com.pig4cloud.pigx.dify.api.dto.ChatDTO;
|
|||
|
|
import com.pig4cloud.pigx.dify.service.ChatService;
|
|||
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|||
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|||
|
|
import lombok.RequiredArgsConstructor;
|
|||
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|||
|
|
import org.springframework.web.bind.annotation.*;
|
|||
|
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
|||
|
|
|
|||
|
|
@RestController
|
|||
|
|
@RequiredArgsConstructor
|
|||
|
|
@RequestMapping("/chat")
|
|||
|
|
@Tag(name = "对话管理")
|
|||
|
|
public class ChatController {
|
|||
|
|
|
|||
|
|
private final ChatService chatService;
|
|||
|
|
|
|||
|
|
@Operation(summary = "创建对话")
|
|||
|
|
@PostMapping
|
|||
|
|
@PreAuthorize("@pms.hasPermission('dify_chat_add')")
|
|||
|
|
public R<ChatDTO> createChat(@RequestBody ChatDTO chatDTO) {
|
|||
|
|
chatDTO.setUserId(SecurityUtils.getUser().getId());
|
|||
|
|
chatDTO.setTenantId(SecurityUtils.getUser().getTenantId());
|
|||
|
|
return R.ok(chatService.createChat(chatDTO));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Operation(summary = "流式对话")
|
|||
|
|
@PostMapping("/stream/{chatId}")
|
|||
|
|
@PreAuthorize("@pms.hasPermission('dify_chat_message')")
|
|||
|
|
public SseEmitter streamChat(@PathVariable String chatId,
|
|||
|
|
@RequestBody String message) {
|
|||
|
|
return chatService.streamChat(chatId, message, SecurityUtils.getUser());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Operation(summary = "获取对话历史")
|
|||
|
|
@GetMapping("/{chatId}/messages")
|
|||
|
|
@PreAuthorize("@pms.hasPermission('dify_chat_view')")
|
|||
|
|
public R<?> getChatMessages(@PathVariable String chatId) {
|
|||
|
|
return R.ok(chatService.getChatMessages(chatId));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 5. 数据库设计
|
|||
|
|
|
|||
|
|
### 5.1 数据表DDL
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 智能体表
|
|||
|
|
CREATE TABLE `tb_agent` (
|
|||
|
|
`agent_id` varchar(36) NOT NULL COMMENT '智能体ID',
|
|||
|
|
`name` varchar(100) NOT NULL COMMENT '名称',
|
|||
|
|
`description` varchar(500) DEFAULT NULL COMMENT '描述',
|
|||
|
|
`dify_api_key` varchar(255) DEFAULT NULL COMMENT 'Dify API Key',
|
|||
|
|
`dify_agent_id` varchar(100) DEFAULT NULL COMMENT 'Dify Agent ID',
|
|||
|
|
`config` text COMMENT '配置信息(JSON)',
|
|||
|
|
`icon` varchar(255) DEFAULT NULL COMMENT '图标',
|
|||
|
|
`status` tinyint DEFAULT '1' COMMENT '状态 0:禁用 1:启用',
|
|||
|
|
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
|
|||
|
|
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
|
|||
|
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
|
|||
|
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|||
|
|
`del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
|
|||
|
|
PRIMARY KEY (`agent_id`),
|
|||
|
|
KEY `idx_tenant_id` (`tenant_id`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='智能体表';
|
|||
|
|
|
|||
|
|
-- 聊天会话表
|
|||
|
|
CREATE TABLE `tb_chat` (
|
|||
|
|
`chat_id` varchar(36) NOT NULL COMMENT '会话ID',
|
|||
|
|
`agent_id` varchar(36) NOT NULL COMMENT '智能体ID',
|
|||
|
|
`user_id` bigint NOT NULL COMMENT '用户ID',
|
|||
|
|
`title` varchar(200) DEFAULT NULL COMMENT '会话标题',
|
|||
|
|
`conversation_id` varchar(100) DEFAULT NULL COMMENT 'Dify会话ID',
|
|||
|
|
`status` tinyint DEFAULT '1' COMMENT '状态 0:关闭 1:活跃',
|
|||
|
|
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
|
|||
|
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|||
|
|
`del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
|
|||
|
|
PRIMARY KEY (`chat_id`),
|
|||
|
|
KEY `idx_user_id` (`user_id`),
|
|||
|
|
KEY `idx_agent_id` (`agent_id`),
|
|||
|
|
KEY `idx_tenant_id` (`tenant_id`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='聊天会话表';
|
|||
|
|
|
|||
|
|
-- 聊天消息表
|
|||
|
|
CREATE TABLE `tb_chat_message` (
|
|||
|
|
`message_id` varchar(36) NOT NULL COMMENT '消息ID',
|
|||
|
|
`chat_id` varchar(36) NOT NULL COMMENT '会话ID',
|
|||
|
|
`content` text NOT NULL COMMENT '消息内容',
|
|||
|
|
`role` varchar(20) NOT NULL COMMENT '角色(user/ai/system)',
|
|||
|
|
`dify_message_id` varchar(100) DEFAULT NULL COMMENT 'Dify消息ID',
|
|||
|
|
`parent_message_id` varchar(36) DEFAULT NULL COMMENT '父消息ID',
|
|||
|
|
`metadata` text COMMENT '元数据(JSON)',
|
|||
|
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
PRIMARY KEY (`message_id`),
|
|||
|
|
KEY `idx_chat_id` (`chat_id`),
|
|||
|
|
KEY `idx_create_time` (`create_time`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='聊天消息表';
|
|||
|
|
|
|||
|
|
-- 知识库表
|
|||
|
|
CREATE TABLE `tb_knowledge` (
|
|||
|
|
`knowledge_id` varchar(36) NOT NULL COMMENT '知识库ID',
|
|||
|
|
`title` varchar(200) NOT NULL COMMENT '标题',
|
|||
|
|
`description` text COMMENT '描述',
|
|||
|
|
`dify_dataset_id` varchar(100) DEFAULT NULL COMMENT 'Dify数据集ID',
|
|||
|
|
`status` tinyint DEFAULT '1' COMMENT '状态 0:禁用 1:启用',
|
|||
|
|
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
|
|||
|
|
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
|
|||
|
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|||
|
|
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
|
|||
|
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|||
|
|
`del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
|
|||
|
|
PRIMARY KEY (`knowledge_id`),
|
|||
|
|
KEY `idx_tenant_id` (`tenant_id`)
|
|||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='知识库表';
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 6. 配置文件
|
|||
|
|
|
|||
|
|
### 6.1 bootstrap.yml
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
server:
|
|||
|
|
port: 9500
|
|||
|
|
|
|||
|
|
spring:
|
|||
|
|
application:
|
|||
|
|
name: @project.artifactId@
|
|||
|
|
profiles:
|
|||
|
|
active: @profiles.active@
|
|||
|
|
cloud:
|
|||
|
|
nacos:
|
|||
|
|
discovery:
|
|||
|
|
server-addr: ${NACOS_HOST:pigx-register}:${NACOS_PORT:8848}
|
|||
|
|
config:
|
|||
|
|
server-addr: ${spring.cloud.nacos.discovery.server-addr}
|
|||
|
|
file-extension: yml
|
|||
|
|
shared-configs:
|
|||
|
|
- data-id: common.yml
|
|||
|
|
refresh: true
|
|||
|
|
- data-id: db.yml
|
|||
|
|
refresh: true
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 application.yml
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# Dify配置
|
|||
|
|
dify:
|
|||
|
|
api-base-url: ${DIFY_API_BASE_URL:https://api.dify.ai/v1}
|
|||
|
|
default-api-key: ${DIFY_DEFAULT_API_KEY:}
|
|||
|
|
connect-timeout: 10000
|
|||
|
|
read-timeout: 30000
|
|||
|
|
stream-timeout: 60000
|
|||
|
|
debug: false
|
|||
|
|
|
|||
|
|
# MyBatis-Plus配置
|
|||
|
|
mybatis-plus:
|
|||
|
|
mapper-locations: classpath:/mapper/*.xml
|
|||
|
|
type-aliases-package: com.pig4cloud.pigx.dify.api.entity
|
|||
|
|
configuration:
|
|||
|
|
map-underscore-to-camel-case: true
|
|||
|
|
|
|||
|
|
# 安全配置
|
|||
|
|
security:
|
|||
|
|
oauth2:
|
|||
|
|
resource:
|
|||
|
|
ignore-urls:
|
|||
|
|
- /actuator/**
|
|||
|
|
- /v3/api-docs/**
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 7. 服务注册
|
|||
|
|
|
|||
|
|
### 7.1 路由配置
|
|||
|
|
|
|||
|
|
在 pigx-gateway 中添加路由:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
spring:
|
|||
|
|
cloud:
|
|||
|
|
gateway:
|
|||
|
|
routes:
|
|||
|
|
- id: pigx-dify
|
|||
|
|
uri: lb://pigx-dify
|
|||
|
|
predicates:
|
|||
|
|
- Path=/dify/**
|
|||
|
|
filters:
|
|||
|
|
- StripPrefix=1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 Feign配置
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
package com.pig4cloud.pigx.dify.api.feign;
|
|||
|
|
|
|||
|
|
import com.pig4cloud.pigx.common.core.constant.ServiceNameConstants;
|
|||
|
|
import com.pig4cloud.pigx.common.core.util.R;
|
|||
|
|
import com.pig4cloud.pigx.dify.api.dto.ChatDTO;
|
|||
|
|
import org.springframework.cloud.openfeign.FeignClient;
|
|||
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|||
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|||
|
|
|
|||
|
|
@FeignClient(contextId = "remoteDifyService",
|
|||
|
|
value = ServiceNameConstants.DIFY_SERVICE)
|
|||
|
|
public interface RemoteDifyService {
|
|||
|
|
|
|||
|
|
@GetMapping("/chat/{chatId}")
|
|||
|
|
R<ChatDTO> getChatInfo(@PathVariable("chatId") String chatId);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 8. 部署配置
|
|||
|
|
|
|||
|
|
### 8.1 Docker配置
|
|||
|
|
|
|||
|
|
```dockerfile
|
|||
|
|
FROM pig4cloud/java:8-jre
|
|||
|
|
|
|||
|
|
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
|||
|
|
|
|||
|
|
COPY target/pigx-dify-biz.jar /app.jar
|
|||
|
|
|
|||
|
|
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.2 K8s部署
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
apiVersion: apps/v1
|
|||
|
|
kind: Deployment
|
|||
|
|
metadata:
|
|||
|
|
name: pigx-dify
|
|||
|
|
namespace: pigx
|
|||
|
|
spec:
|
|||
|
|
replicas: 1
|
|||
|
|
selector:
|
|||
|
|
matchLabels:
|
|||
|
|
app: pigx-dify
|
|||
|
|
template:
|
|||
|
|
metadata:
|
|||
|
|
labels:
|
|||
|
|
app: pigx-dify
|
|||
|
|
spec:
|
|||
|
|
containers:
|
|||
|
|
- name: pigx-dify
|
|||
|
|
image: pigx/pigx-dify:latest
|
|||
|
|
ports:
|
|||
|
|
- containerPort: 9500
|
|||
|
|
env:
|
|||
|
|
- name: NACOS_HOST
|
|||
|
|
value: "pigx-register"
|
|||
|
|
- name: DIFY_API_BASE_URL
|
|||
|
|
value: "https://api.dify.ai/v1"
|
|||
|
|
- name: DIFY_DEFAULT_API_KEY
|
|||
|
|
valueFrom:
|
|||
|
|
secretKeyRef:
|
|||
|
|
name: dify-secret
|
|||
|
|
key: api-key
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9. 集成测试
|
|||
|
|
|
|||
|
|
### 9.1 单元测试
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@SpringBootTest
|
|||
|
|
class ChatServiceTest {
|
|||
|
|
|
|||
|
|
@Autowired
|
|||
|
|
private ChatService chatService;
|
|||
|
|
|
|||
|
|
@MockBean
|
|||
|
|
private DifyApiClient difyApiClient;
|
|||
|
|
|
|||
|
|
@Test
|
|||
|
|
void testCreateChat() {
|
|||
|
|
// 测试创建对话
|
|||
|
|
ChatDTO chatDTO = new ChatDTO();
|
|||
|
|
chatDTO.setAgentId("test-agent");
|
|||
|
|
chatDTO.setUserId(1L);
|
|||
|
|
|
|||
|
|
ChatDTO result = chatService.createChat(chatDTO);
|
|||
|
|
assertNotNull(result.getChatId());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 9.2 API测试
|
|||
|
|
|
|||
|
|
```http
|
|||
|
|
### 创建对话
|
|||
|
|
POST http://localhost:9999/dify/chat
|
|||
|
|
Authorization: Bearer {{token}}
|
|||
|
|
Content-Type: application/json
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
"agentId": "agent-001",
|
|||
|
|
"title": "测试对话"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
### 发送消息(流式)
|
|||
|
|
POST http://localhost:9999/dify/chat/stream/{{chatId}}
|
|||
|
|
Authorization: Bearer {{token}}
|
|||
|
|
Content-Type: text/plain
|
|||
|
|
|
|||
|
|
你好,请介绍一下自己
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 10. 监控告警
|
|||
|
|
|
|||
|
|
### 10.1 健康检查
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Component
|
|||
|
|
public class DifyHealthIndicator implements HealthIndicator {
|
|||
|
|
|
|||
|
|
@Autowired
|
|||
|
|
private DifyApiClient difyApiClient;
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public Health health() {
|
|||
|
|
try {
|
|||
|
|
// 检查Dify API连通性
|
|||
|
|
boolean isHealthy = difyApiClient.checkHealth();
|
|||
|
|
if (isHealthy) {
|
|||
|
|
return Health.up()
|
|||
|
|
.withDetail("dify", "Available")
|
|||
|
|
.build();
|
|||
|
|
}
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
return Health.down()
|
|||
|
|
.withDetail("dify", "Unavailable")
|
|||
|
|
.withException(e)
|
|||
|
|
.build();
|
|||
|
|
}
|
|||
|
|
return Health.down().build();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 10.2 日志配置
|
|||
|
|
|
|||
|
|
```xml
|
|||
|
|
<!-- logback-spring.xml -->
|
|||
|
|
<configuration>
|
|||
|
|
<logger name="com.pig4cloud.pigx.dify" level="INFO"/>
|
|||
|
|
<logger name="com.pig4cloud.pigx.dify.client" level="DEBUG"/>
|
|||
|
|
</configuration>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 11. 安全考虑
|
|||
|
|
|
|||
|
|
### 11.1 API Key管理
|
|||
|
|
- API Key 加密存储
|
|||
|
|
- 支持多租户隔离
|
|||
|
|
- 定期轮换机制
|
|||
|
|
|
|||
|
|
### 11.2 数据隔离
|
|||
|
|
- 租户级别数据隔离
|
|||
|
|
- 用户权限验证
|
|||
|
|
- 敏感信息脱敏
|
|||
|
|
|
|||
|
|
### 11.3 限流配置
|
|||
|
|
```java
|
|||
|
|
@Configuration
|
|||
|
|
public class RateLimitConfig {
|
|||
|
|
|
|||
|
|
@Bean
|
|||
|
|
public RedisRateLimiter redisRateLimiter() {
|
|||
|
|
return new RedisRateLimiter(10, 20); // 10 requests per second
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 12. 迁移清单
|
|||
|
|
|
|||
|
|
- [ ] 创建 Maven 模块结构
|
|||
|
|
- [ ] 迁移实体类和 Mapper
|
|||
|
|
- [ ] 迁移 Service 层业务逻辑
|
|||
|
|
- [ ] 迁移 Controller 层接口
|
|||
|
|
- [ ] 适配权限注解
|
|||
|
|
- [ ] 迁移 DifyApiClient
|
|||
|
|
- [ ] 配置服务注册和发现
|
|||
|
|
- [ ] 数据库表结构迁移
|
|||
|
|
- [ ] 前端页面迁移
|
|||
|
|
- [ ] 集成测试
|
|||
|
|
- [ ] 部署配置
|