21 KiB
21 KiB
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 项目结构
<!-- 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 结构
<!-- 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 结构
<!-- 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 启动类
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 配置类
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 实体设计
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设计
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
-- 智能体表
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
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
# 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 中添加路由:
spring:
cloud:
gateway:
routes:
- id: pigx-dify
uri: lb://pigx-dify
predicates:
- Path=/dify/**
filters:
- StripPrefix=1
7.2 Feign配置
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配置
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部署
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 单元测试
@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测试
### 创建对话
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 健康检查
@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 日志配置
<!-- 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 限流配置
@Configuration
public class RateLimitConfig {
@Bean
public RedisRateLimiter redisRateLimiter() {
return new RedisRateLimiter(10, 20); // 10 requests per second
}
}
12. 迁移清单
- 创建 Maven 模块结构
- 迁移实体类和 Mapper
- 迁移 Service 层业务逻辑
- 迁移 Controller 层接口
- 适配权限注解
- 迁移 DifyApiClient
- 配置服务注册和发现
- 数据库表结构迁移
- 前端页面迁移
- 集成测试
- 部署配置