mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2026-06-13 01:06:24 +00:00
add 新增 ruoyi-snailai-server 独立服务
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -56,7 +56,7 @@
|
||||
<easy-es.version>3.0.2</easy-es.version>
|
||||
<elasticsearch-client.version>7.17.28</elasticsearch-client.version>
|
||||
<!-- Spring AI 2.0 预览版,正式版发布后仅需调整此版本号 -->
|
||||
<spring-ai.version>2.0.0-M7</spring-ai.version>
|
||||
<spring-ai.version>2.0.0-M6</spring-ai.version>
|
||||
|
||||
<!-- 插件版本 -->
|
||||
<maven-jar-plugin.version>3.5.0</maven-jar-plugin.version>
|
||||
|
||||
@@ -44,7 +44,7 @@ snail-ai:
|
||||
# 应用 ID(在 Server「应用管理」页面创建后获取)
|
||||
app-id: 1
|
||||
# 认证令牌(在 Server「应用管理」页面创建时自动生成)
|
||||
token: SAI_ce6fbc820c50456baecc7cdcf2a14b1b
|
||||
token: SAI_7c557fc05a304b0482a65ca67afdb0b8
|
||||
port: 18889
|
||||
# Skill 文件临时目录
|
||||
skill-temp-dir: /tmp/snail-ai-agent/skills
|
||||
@@ -53,7 +53,7 @@ snail-ai:
|
||||
# 启用 OpenAPI Client
|
||||
enabled: true
|
||||
# Server HTTP 端口
|
||||
web-port: 8080
|
||||
web-port: 8900
|
||||
# 是否使用 HTTPS
|
||||
https: false
|
||||
# API 路径前缀
|
||||
|
||||
@@ -47,7 +47,7 @@ snail-ai:
|
||||
# 应用 ID(在 Server「应用管理」页面创建后获取)
|
||||
app-id: 1
|
||||
# 认证令牌(在 Server「应用管理」页面创建时自动生成)
|
||||
token: SAI_ce6fbc820c50456baecc7cdcf2a14b1b
|
||||
token: SAI_7c557fc05a304b0482a65ca67afdb0b8
|
||||
port: 18889
|
||||
# Skill 文件临时目录
|
||||
skill-temp-dir: /tmp/snail-ai-agent/skills
|
||||
@@ -56,7 +56,7 @@ snail-ai:
|
||||
# 启用 OpenAPI Client
|
||||
enabled: true
|
||||
# Server HTTP 端口
|
||||
web-port: 8080
|
||||
web-port: 8900
|
||||
# 是否使用 HTTPS
|
||||
https: false
|
||||
# API 路径前缀
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-monitor-admin</module>
|
||||
<module>ruoyi-snailai-server</module>
|
||||
<module>ruoyi-snailjob-server</module>
|
||||
</modules>
|
||||
|
||||
|
||||
22
ruoyi-extend/ruoyi-snailai-server/Dockerfile
Normal file
22
ruoyi-extend/ruoyi-snailai-server/Dockerfile
Normal file
@@ -0,0 +1,22 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-rocky:21.0.8-cds
|
||||
#FROM findepi/graalvm:java21-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
||||
RUN mkdir -p /ruoyi/snailai/logs
|
||||
|
||||
WORKDIR /ruoyi/snailai
|
||||
|
||||
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
|
||||
|
||||
EXPOSE 8900
|
||||
EXPOSE 18888
|
||||
|
||||
ADD ./target/ruoyi-snailai-server.jar ./app.jar
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \
|
||||
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
|
||||
-jar app.jar
|
||||
46
ruoyi-extend/ruoyi-snailai-server/pom.xml
Normal file
46
ruoyi-extend/ruoyi-snailai-server/pom.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-extend</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-snailai-server</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>snail-ai-starter</artifactId>
|
||||
<version>${snailai.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
<version>${spring-boot-admin.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.aizuda.snail.ai.starter.filter;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
public class ActuatorAuthFilter implements Filter {
|
||||
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
public ActuatorAuthFilter(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
if (authHeader == null || !authHeader.startsWith("Basic ")) {
|
||||
response.setHeader("WWW-Authenticate", "Basic realm=\"realm\"");
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
|
||||
String base64Credentials = authHeader.substring("Basic ".length());
|
||||
byte[] credDecoded = Base64.getDecoder().decode(base64Credentials);
|
||||
String credentials = new String(credDecoded, StandardCharsets.UTF_8);
|
||||
String[] split = credentials.split(":");
|
||||
if (split.length != 2) {
|
||||
response.setHeader("WWW-Authenticate", "Basic realm=\"realm\"");
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
if (!username.equals(split[0]) || !password.equals(split[1])) {
|
||||
response.setHeader("WWW-Authenticate", "Basic realm=\"realm\"");
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.aizuda.snail.ai.starter.filter;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 权限安全配置
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
|
||||
@Value("${spring.boot.admin.client.username}")
|
||||
private String username;
|
||||
@Value("${spring.boot.admin.client.password}")
|
||||
private String password;
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<ActuatorAuthFilter> actuatorFilterRegistrationBean() {
|
||||
FilterRegistrationBean<ActuatorAuthFilter> registrationBean = new FilterRegistrationBean<>();
|
||||
registrationBean.setFilter(new ActuatorAuthFilter(username, password));
|
||||
registrationBean.addUrlPatterns("/actuator", "/actuator/*");
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.dromara.snailai;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* Snail AI Server 启动程序
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class SnailAiServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
com.aizuda.snail.ai.starter.SnailAiSpringbootApplication.main(args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: root
|
||||
hikari:
|
||||
connection-timeout: 30000
|
||||
validation-timeout: 5000
|
||||
minimum-idle: 10
|
||||
maximum-pool-size: 20
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 900000
|
||||
keepaliveTime: 30000
|
||||
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
metadata:
|
||||
username: ${spring.boot.admin.client.username}
|
||||
userpassword: ${spring.boot.admin.client.password}
|
||||
username: @monitor.username@
|
||||
password: @monitor.password@
|
||||
@@ -0,0 +1,28 @@
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: root
|
||||
hikari:
|
||||
connection-timeout: 30000
|
||||
validation-timeout: 5000
|
||||
minimum-idle: 10
|
||||
maximum-pool-size: 20
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 900000
|
||||
keepaliveTime: 30000
|
||||
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
metadata:
|
||||
username: ${spring.boot.admin.client.username}
|
||||
userpassword: ${spring.boot.admin.client.password}
|
||||
username: @monitor.username@
|
||||
password: @monitor.password@
|
||||
@@ -0,0 +1,67 @@
|
||||
server:
|
||||
port: 8900
|
||||
servlet:
|
||||
context-path: /snail-ai
|
||||
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
enabled: true
|
||||
# 单个文件的最大限制 (根据 RAG 需求建议设为 50MB - 100MB)
|
||||
max-file-size: 50MB
|
||||
# 单次请求的总文件大小限制 (如果支持多文件并行上传,调大此项)
|
||||
max-request-size: 100MB
|
||||
web:
|
||||
resources:
|
||||
static-locations: classpath:admin/
|
||||
profiles:
|
||||
active: @profiles.active@
|
||||
snail-ai:
|
||||
server:
|
||||
grpc-port: 18888
|
||||
skill:
|
||||
upload-dir: ./upload/skills
|
||||
crypto:
|
||||
secret-key: ${SNAIL_AI_CRYPTO_KEY:0123456789abcdef0123456789abcdef}
|
||||
iv: ${SNAIL_AI_CRYPTO_IV:fedcba9876543210fedcba9876543210}
|
||||
resource:
|
||||
storage-type: LOCAL
|
||||
upload-dir: ./upload/resource
|
||||
minio:
|
||||
endpoint: http://localhost:9000
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
bucket: snail-ai
|
||||
# 短期记忆配置
|
||||
memory:
|
||||
short-term:
|
||||
# 存储类型选项: memory(内存) | db(数据库)
|
||||
# - memory: 适用于单机部署,高性能,重启后数据丢失
|
||||
# - db: 适用于分布式部署,数据持久化,性能较低
|
||||
store-type: db
|
||||
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath:/mapper/*.xml
|
||||
typeAliasesPackage: com.example.snail.job.po
|
||||
global-config:
|
||||
db-config:
|
||||
capital-mode: false
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
cache-enabled: true
|
||||
|
||||
logging:
|
||||
config: classpath:logback-plus.xml
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
endpoint:
|
||||
health:
|
||||
show-details: ALWAYS
|
||||
logfile:
|
||||
external-file: ./logs/ruoyi-snailai-server/console.log
|
||||
@@ -0,0 +1,9 @@
|
||||
Application Version: ${revision}
|
||||
Spring Boot Version: ${spring-boot.version}
|
||||
_ _ _
|
||||
(_) | (_)
|
||||
___ _ __ __ _ _| |______ __ _ _
|
||||
/ __| '_ \ / _` | | |______/ _` | |
|
||||
\__ \ | | | (_| | | | | (_| | |
|
||||
|___/_| |_|\__,_|_|_| \__,_|_|
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<property name="log.path" value="./logs/ruoyi-snailai-server" />
|
||||
<property name="console.log.pattern"
|
||||
value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/console.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/console.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大 1天 -->
|
||||
<maxHistory>1</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/info.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<MaxHistory>60</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/error.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log
|
||||
</FileNamePattern>
|
||||
<MaxHistory>60</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name ="async_info" class= "ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold >100</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref ="file_info"/>
|
||||
</appender>
|
||||
|
||||
<appender name ="async_error" class= "ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold >100</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref ="file_error"/>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出日志级别 -->
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file_console" />
|
||||
<appender-ref ref="async_info" />
|
||||
<appender-ref ref="async_error" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -346,7 +346,7 @@ insert into sys_menu values(1761400000000000001, '系统管理', 0, 1, 'system',
|
||||
insert into sys_menu values(1761400000000000002, '系统监控', 0, 3, 'monitor', null, '', 'N', 'Y', 'M', '0', '0', '', 'monitor', '', '', 1761000000000000103, 1761100000000000001, sysdate, null, null, '系统监控目录');
|
||||
insert into sys_menu values(1761400000000000003, '系统工具', 0, 4, 'tool', null, '', 'N', 'Y', 'M', '0', '0', '', 'tool', '', '', 1761000000000000103, 1761100000000000001, sysdate, null, null, '系统工具目录');
|
||||
insert into sys_menu values(1761400000000000005, '测试菜单', 0, 5, 'demo', null, '', 'N', 'Y', 'M', '0', '0', null, 'star', '', '', 1761000000000000103, 1761100000000000001, sysdate, null, null, '');
|
||||
insert into sys_menu values(1761400000000000006, 'AI会话', 0, 6, 'ai/chat', 'ai/chat/index', '', 'N', 'Y', 'C', '0', '0', '', 'checkbox', '', '', 1761000000000000103, 1761100000000000001, sysdate, null, null, 'AI聊天菜单');
|
||||
insert into sys_menu values(1761400000000000006, 'AI会话', 0, 8, 'ai/chat', 'ai/chat/index', '', 'N', 'Y', 'C', '0', '0', '', 'checkbox', '', '', 1761000000000000103, 1761100000000000001, sysdate, null, null, 'AI聊天菜单');
|
||||
insert into sys_menu values(1761400000000000004, 'PLUS官网', 0, 9, 'https://gitee.com/dromara/RuoYi-Vue-Plus', null, '', 'Y', 'Y', 'M', '0', '0', '', 'guide', '', '', 1761000000000000103, 1761100000000000001, sysdate, null, null, 'RuoYi-Vue-Plus官网地址');
|
||||
-- 二级菜单
|
||||
insert into sys_menu values(1761400000000000100, '用户管理', 1761400000000000001, 1, 'user', 'system/user/index', '', 'N', 'Y', 'C', '0', '0', 'system:user:list', 'user', '', '', 1761000000000000103, 1761100000000000001, sysdate, null, null, '用户管理菜单');
|
||||
|
||||
@@ -343,7 +343,7 @@ insert into sys_menu values(1761400000000000001, '系统管理', 0, 1, 'system',
|
||||
insert into sys_menu values(1761400000000000002, '系统监控', 0, 3, 'monitor', null, '', 'N', 'Y', 'M', '0', '0', '', 'monitor', '', '', 1761000000000000103, 1761100000000000001, now(), null, null, '系统监控目录');
|
||||
insert into sys_menu values(1761400000000000003, '系统工具', 0, 4, 'tool', null, '', 'N', 'Y', 'M', '0', '0', '', 'tool', '', '', 1761000000000000103, 1761100000000000001, now(), null, null, '系统工具目录');
|
||||
insert into sys_menu values(1761400000000000005, '测试菜单', 0, 5, 'demo', null, '', 'N', 'Y', 'M', '0', '0', null, 'star', '', '', 1761000000000000103, 1761100000000000001, now(), null, null, '测试菜单');
|
||||
insert into sys_menu values(1761400000000000006, 'AI会话', 0, 6, 'ai/chat', 'ai/chat/index', '', 'N', 'Y', 'C', '0', '0', '', 'checkbox', '', '', 1761000000000000103, 1761100000000000001, now(), null, null, 'AI聊天菜单');
|
||||
insert into sys_menu values(1761400000000000006, 'AI会话', 0, 8, 'ai/chat', 'ai/chat/index', '', 'N', 'Y', 'C', '0', '0', '', 'checkbox', '', '', 1761000000000000103, 1761100000000000001, now(), null, null, 'AI聊天菜单');
|
||||
insert into sys_menu values(1761400000000000004, 'PLUS官网', 0, 9, 'https://gitee.com/dromara/RuoYi-Vue-Plus', null, '', 'Y', 'Y', 'M', '0', '0', '', 'guide', '', '', 1761000000000000103, 1761100000000000001, now(), null, null, 'RuoYi-Vue-Plus官网地址');
|
||||
-- 二级菜单
|
||||
insert into sys_menu values(1761400000000000100, '用户管理', 1761400000000000001, 1, 'user', 'system/user/index', '', 'N', 'Y', 'C', '0', '0', 'system:user:list', 'user', '', '', 1761000000000000103, 1761100000000000001, now(), null, null, '用户管理菜单');
|
||||
|
||||
516
script/sql/ry_ai.sql
Normal file
516
script/sql/ry_ai.sql
Normal file
@@ -0,0 +1,516 @@
|
||||
-- ============================================================
|
||||
-- Snail AI MySQL 全量建表脚本(仅 CREATE,无 ALTER)
|
||||
-- 使用:mysql -u user -p database < snail_ai_schema.sql
|
||||
-- ============================================================
|
||||
|
||||
-- ============================================================
|
||||
-- Enterprise RAG Schema for MySQL
|
||||
-- ============================================================
|
||||
|
||||
-- Knowledge Base
|
||||
CREATE TABLE snail_ai_rag
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
icon VARCHAR(512),
|
||||
embedding_model_id BIGINT(128) NOT NULL,
|
||||
dimension_of_vector_model INT NOT NULL COMMENT '向量维度',
|
||||
rerank_model_id BIGINT(128),
|
||||
search_engine_instance_id BIGINT(128),
|
||||
vector_store_instance_id BIGINT(128),
|
||||
search_engine_enable TINYINT(1) DEFAULT 0,
|
||||
delimiter VARCHAR(32) DEFAULT '\n\n',
|
||||
rag_enhancement TEXT,
|
||||
config TEXT DEFAULT NULL COMMENT 'RAG检索和问答的页面配置参数',
|
||||
dedup_strategy TINYINT(1) NOT NULL DEFAULT 2 COMMENT '去重策略: 0=NONE 1=BY_NAME 2=BY_CONTENT 3=BY_NAME_OR_CONTENT',
|
||||
dedup_action TINYINT(1) NOT NULL DEFAULT 0 COMMENT '冲突动作: 0=REJECT 1=SKIP 2=OVERWRITE',
|
||||
upload_confirm TINYINT(1) NOT NULL DEFAULT 1 COMMENT '上传前二次确认: 0-关 1-开',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci;
|
||||
|
||||
-- RAG Documents
|
||||
CREATE TABLE snail_ai_rag_document
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
rag_id BIGINT NOT NULL,
|
||||
name VARCHAR(255),
|
||||
file_type VARCHAR(32),
|
||||
source_type VARCHAR(32),
|
||||
source_path VARCHAR(1024),
|
||||
storage_path VARCHAR(1024),
|
||||
storage_type VARCHAR(32) DEFAULT 'LOCAL',
|
||||
file_size BIGINT DEFAULT 0,
|
||||
content TEXT,
|
||||
status TINYINT(1) DEFAULT 0 COMMENT '状态: 0-待处理 1-解析中 2-处理中 3-处理完成 4-处理失败',
|
||||
error_msg TEXT,
|
||||
chunk_count INT DEFAULT 0,
|
||||
content_hash VARCHAR(64) DEFAULT NULL COMMENT '文件内容SHA-256哈希,用于去重',
|
||||
resource_id BIGINT DEFAULT NULL COMMENT '关联资源库 snail_ai_resource.id',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci;
|
||||
|
||||
CREATE INDEX idx_rag_doc_rag ON snail_ai_rag_document (rag_id);
|
||||
CREATE INDEX idx_rag_content_hash ON snail_ai_rag_document (rag_id, content_hash);
|
||||
CREATE INDEX idx_rag_name ON snail_ai_rag_document (rag_id, name);
|
||||
CREATE INDEX idx_rag_doc_resource ON snail_ai_rag_document (resource_id);
|
||||
|
||||
-- RAG Chunks
|
||||
CREATE TABLE snail_ai_rag_chunk
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
rag_id BIGINT NOT NULL,
|
||||
document_id BIGINT NOT NULL,
|
||||
paragraph_index INT,
|
||||
chunk_index INT,
|
||||
content TEXT,
|
||||
token_count INT,
|
||||
vector_id VARCHAR(128),
|
||||
content_hash VARCHAR(64) DEFAULT NULL COMMENT 'chunk内容SHA-256,用于向量去重',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci;
|
||||
|
||||
CREATE INDEX idx_rag_chunk_rag ON snail_ai_rag_chunk (rag_id);
|
||||
CREATE INDEX idx_rag_chunk_document ON snail_ai_rag_chunk (document_id);
|
||||
CREATE INDEX idx_chunk_rag_hash ON snail_ai_rag_chunk (rag_id, content_hash);
|
||||
|
||||
CREATE TABLE snail_ai_user
|
||||
(
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
role INT,
|
||||
totals INT,
|
||||
username VARCHAR(255),
|
||||
email VARCHAR(64),
|
||||
password VARCHAR(64) NOT NULL,
|
||||
create_dt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_username (username)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4;
|
||||
|
||||
INSERT INTO snail_ai_user (id, role, username, email, password, create_dt, update_dt)
|
||||
VALUES (1, 2, 'admin', '', '094c883e17947ff795de8b22279d81c2600dfe85e2dba3fbf562423e883b07ca',
|
||||
'2026-02-11 13:56:48.210429', '2026-02-11 13:56:48.210429');
|
||||
|
||||
-- ============================================
|
||||
-- 1. AI 模型提供商表
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_model_provider
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
provider_name VARCHAR(255) NOT NULL COMMENT '提供商名称',
|
||||
provider_key VARCHAR(50) NOT NULL COMMENT '提供商标识符',
|
||||
description TEXT COMMENT '提供商描述',
|
||||
icon_url VARCHAR(500) COMMENT 'LOGO图标URL',
|
||||
is_enabled TINYINT(1) DEFAULT 1 COMMENT '是否启用',
|
||||
created_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updated_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
UNIQUE KEY uk_provider_name (provider_name),
|
||||
UNIQUE KEY uk_provider_key (provider_key)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = 'AI模型提供商表';
|
||||
|
||||
CREATE INDEX idx_provider_key ON snail_ai_model_provider (provider_key);
|
||||
CREATE INDEX idx_is_enabled ON snail_ai_model_provider (is_enabled);
|
||||
|
||||
-- ============================================
|
||||
-- 2. AI模型配置表
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_model_config
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
provider_id BIGINT NOT NULL COMMENT '提供商ID',
|
||||
model_name VARCHAR(255) NOT NULL COMMENT '模型名称',
|
||||
model_key VARCHAR(100) NOT NULL COMMENT '模型标识符',
|
||||
model_type VARCHAR(50) NOT NULL COMMENT '模型类型(CHAT/EMBEDDING/RERANKER/IMAGE/SPEECH)',
|
||||
description VARCHAR(1000) COMMENT '模型描述',
|
||||
api_key VARCHAR(1000) COMMENT 'API密钥(加密存储)',
|
||||
api_endpoint VARCHAR(500) COMMENT 'API端点URL',
|
||||
config_json TEXT COMMENT '模型参数配置(JSON格式)',
|
||||
owner_id BIGINT COMMENT '所有者ID(NULL=全局,具体值=用户ID)',
|
||||
scope VARCHAR(20) NOT NULL DEFAULT 'GLOBAL' COMMENT '作用域(GLOBAL/PERSONAL)',
|
||||
is_default TINYINT(1) DEFAULT 0 COMMENT '是否为默认模型',
|
||||
is_enabled TINYINT(1) DEFAULT 1 COMMENT '是否启用',
|
||||
created_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updated_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
KEY fk_provider_id (provider_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = 'AI模型配置表';
|
||||
|
||||
CREATE INDEX idx_provider_model_type ON snail_ai_model_config (provider_id, model_type);
|
||||
CREATE INDEX idx_model_type_enabled ON snail_ai_model_config (model_type, is_enabled);
|
||||
CREATE INDEX idx_owner_id ON snail_ai_model_config (owner_id);
|
||||
CREATE INDEX idx_is_default ON snail_ai_model_config (is_default);
|
||||
CREATE INDEX idx_scope ON snail_ai_model_config (scope);
|
||||
CREATE INDEX idx_model_key ON snail_ai_model_config (model_key);
|
||||
|
||||
-- ============================================
|
||||
-- 3. 模型使用统计表
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_model_usage_stat
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
model_id BIGINT NOT NULL COMMENT '模型ID',
|
||||
user_id BIGINT NOT NULL COMMENT '用户ID',
|
||||
total_calls BIGINT DEFAULT 0 COMMENT '总调用次数',
|
||||
success_calls BIGINT DEFAULT 0 COMMENT '成功调用次数',
|
||||
failed_calls BIGINT DEFAULT 0 COMMENT '失败调用次数',
|
||||
total_tokens_used BIGINT DEFAULT 0 COMMENT '总Token使用量',
|
||||
total_cost DECIMAL(18, 8) DEFAULT 0 COMMENT '总费用',
|
||||
avg_response_time BIGINT DEFAULT 0 COMMENT '平均响应时间(毫秒)',
|
||||
last_used_dt TIMESTAMP NULL DEFAULT NULL COMMENT '最后使用时间',
|
||||
created_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updated_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
UNIQUE KEY unique_model_user (model_id, user_id),
|
||||
KEY fk_stat_model_id (model_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '模型使用统计表';
|
||||
|
||||
CREATE INDEX idx_model_id ON snail_ai_model_usage_stat (model_id);
|
||||
CREATE INDEX idx_user_id ON snail_ai_model_usage_stat (user_id);
|
||||
CREATE INDEX idx_last_used_dt ON snail_ai_model_usage_stat (last_used_dt);
|
||||
|
||||
-- ============================================
|
||||
-- 初始化数据 (可选)
|
||||
-- ============================================
|
||||
-- 插入常见的AI提供商(重复 provider_key 则忽略)
|
||||
INSERT IGNORE INTO snail_ai_model_provider (provider_name, provider_key, description, is_enabled)
|
||||
VALUES ('OpenAI', 'openai', 'OpenAI官方模型 (GPT-4, GPT-3.5等)', 1),
|
||||
('Claude', 'claude', 'Anthropic Claude模型', 1),
|
||||
('Ollama', 'ollama', '本地开源模型 (Llama, Mistral等)', 1),
|
||||
('Google Gemini', 'gemini', 'Google Gemini模型', 1);
|
||||
|
||||
-- ============================================
|
||||
-- 智能体相关表
|
||||
-- ============================================
|
||||
|
||||
-- 智能体主表
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_agent
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL COMMENT '智能体名称',
|
||||
description TEXT COMMENT '智能体描述',
|
||||
avatar VARCHAR(512) COMMENT '头像URL',
|
||||
instruction TEXT COMMENT '系统指令(System Prompt)',
|
||||
greeting TEXT COMMENT '欢迎语',
|
||||
preset_questions TEXT COMMENT '预设问题列表(JSON数组字符串)',
|
||||
chat_model_id BIGINT COMMENT '关联的对话模型ID',
|
||||
memory_enabled TINYINT(1) DEFAULT 0 COMMENT '是否启用记忆库',
|
||||
mcp_enabled TINYINT(1) DEFAULT 0 COMMENT '是否启用MCP',
|
||||
skill_enabled TINYINT(1) DEFAULT 0 COMMENT '是否启用Skill',
|
||||
web_search_enabled TINYINT(1) DEFAULT 0 COMMENT '是否启用联网搜索',
|
||||
rag_enabled TINYINT(1) DEFAULT 0 COMMENT '是否启用RAG',
|
||||
rag_id BIGINT NULL COMMENT '绑定的RAG ID',
|
||||
short_term_memory_size INT DEFAULT 20 COMMENT '短期记忆滑动窗口保留条数',
|
||||
creator_id BIGINT COMMENT '创建者用户ID',
|
||||
is_featured TINYINT(1) DEFAULT 0 COMMENT '是否精选',
|
||||
view_count INT DEFAULT 0 COMMENT '浏览次数',
|
||||
status TINYINT DEFAULT 1 COMMENT '状态: 1-活跃 2-非活跃 3-已废弃 4-已禁用',
|
||||
config TEXT COMMENT '扩展配置(预留)',
|
||||
app_id VARCHAR(128) NULL COMMENT '关联应用ID(NULL=本地执行)',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '智能体表';
|
||||
|
||||
CREATE INDEX idx_agent_creator ON snail_ai_agent (creator_id);
|
||||
CREATE INDEX idx_agent_featured ON snail_ai_agent (is_featured);
|
||||
|
||||
-- 智能体对话表
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_agent_conversation
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL COMMENT '智能体ID',
|
||||
user_id BIGINT NOT NULL COMMENT '用户ID',
|
||||
conversation_id VARCHAR(64) NOT NULL COMMENT '对话ID(UUID)',
|
||||
title VARCHAR(255) COMMENT '对话标题',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_conv_id (conversation_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '智能体对话表';
|
||||
|
||||
CREATE INDEX idx_agent_conv_agent ON snail_ai_agent_conversation (agent_id);
|
||||
CREATE INDEX idx_agent_conv_user ON snail_ai_agent_conversation (user_id);
|
||||
|
||||
-- 智能体对话消息记录表
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_agent_conversation_record
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL COMMENT '智能体ID',
|
||||
conversation_id VARCHAR(64) NOT NULL COMMENT '对话ID',
|
||||
user_id BIGINT NOT NULL COMMENT '用户ID',
|
||||
role VARCHAR(16) DEFAULT 'user' COMMENT 'user/assistant',
|
||||
content TEXT COMMENT '消息内容',
|
||||
thinking TEXT COMMENT '思考过程(仅assistant)',
|
||||
status INT DEFAULT 1 COMMENT '1=成功,2=失败,3=进行中',
|
||||
token_count INT DEFAULT 0 COMMENT 'Token数',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '智能体对话消息记录';
|
||||
|
||||
CREATE INDEX idx_agent_rec_conv ON snail_ai_agent_conversation_record (conversation_id);
|
||||
|
||||
-- 智能体使用统计表
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_agent_usage_stat
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL COMMENT '智能体ID',
|
||||
user_id BIGINT NOT NULL COMMENT '用户ID',
|
||||
user_name VARCHAR(255) COMMENT '用户名',
|
||||
department VARCHAR(255) DEFAULT '' COMMENT '部门',
|
||||
message_count INT DEFAULT 0 COMMENT '消息条数',
|
||||
conversation_count INT DEFAULT 0 COMMENT '对话轮次',
|
||||
stat_date DATE NOT NULL COMMENT '统计日期',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_agent_user_date (agent_id, user_id, stat_date)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '智能体使用统计';
|
||||
|
||||
CREATE INDEX idx_usage_agent ON snail_ai_agent_usage_stat (agent_id);
|
||||
CREATE INDEX idx_usage_date ON snail_ai_agent_usage_stat (stat_date);
|
||||
|
||||
-- ============================================
|
||||
-- MCP 服务管理
|
||||
-- ============================================
|
||||
|
||||
-- MCP 服务配置表
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_mcp_server
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL COMMENT 'MCP服务名称',
|
||||
description TEXT COMMENT 'MCP服务描述',
|
||||
transport_type TINYINT(1) DEFAULT 1 COMMENT '传输类型: 1-SSE 2-Streamable HTTP 3-Stdio',
|
||||
base_uri VARCHAR(1024) COMMENT '服务基础地址(SSE/Streamable HTTP时使用)',
|
||||
endpoint VARCHAR(1024) COMMENT '端点路径(SSE/Streamable HTTP时可选)',
|
||||
command VARCHAR(1024) COMMENT 'Stdio命令(Stdio时必填)',
|
||||
args TEXT COMMENT 'Stdio命令参数(JSON数组)',
|
||||
env_vars TEXT COMMENT 'Stdio环境变量(JSON对象)',
|
||||
version VARCHAR(32) DEFAULT '1.0.0' COMMENT '版本',
|
||||
auth_type TINYINT(1) DEFAULT 0 COMMENT '认证方式: 0-无需认证 1-API Key 2-OAuth 3-Basic Auth',
|
||||
auth_config TEXT COMMENT '认证配置(JSON)',
|
||||
status TINYINT(1) DEFAULT 0 COMMENT '状态: 0-未连接 1-已连接 2-异常',
|
||||
capabilities TEXT COMMENT '能力列表(JSON数组)',
|
||||
last_connect_dt TIMESTAMP NULL COMMENT '最后连接时间',
|
||||
creator_id BIGINT COMMENT '创建者用户ID',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP服务配置表';
|
||||
|
||||
CREATE INDEX idx_mcp_server_creator ON snail_ai_mcp_server (creator_id);
|
||||
CREATE INDEX idx_mcp_server_status ON snail_ai_mcp_server (status);
|
||||
|
||||
-- 智能体与MCP服务关联表(多对多)
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_agent_mcp_server
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL COMMENT '智能体ID',
|
||||
mcp_server_id BIGINT NOT NULL COMMENT 'MCP服务ID',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_agent_mcp (agent_id, mcp_server_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '智能体MCP服务关联表';
|
||||
|
||||
CREATE INDEX idx_agent_mcp_agent ON snail_ai_agent_mcp_server (agent_id);
|
||||
CREATE INDEX idx_agent_mcp_server ON snail_ai_agent_mcp_server (mcp_server_id);
|
||||
|
||||
-- 用户订阅的智能体(多对多)
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_user_agent
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL COMMENT '用户ID',
|
||||
agent_id BIGINT NOT NULL COMMENT '智能体ID',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_user_agent (user_id, agent_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '用户订阅的智能体';
|
||||
|
||||
CREATE INDEX idx_user_agent_user ON snail_ai_user_agent (user_id);
|
||||
|
||||
-- ============================================
|
||||
-- Skill 技能包管理
|
||||
-- ============================================
|
||||
|
||||
-- Skill 技能包表
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_skill
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL COMMENT 'Skill名称(从SKILL.md解析)',
|
||||
description TEXT COMMENT 'Skill描述(从SKILL.md解析)',
|
||||
file_name VARCHAR(255) COMMENT '上传的zip文件名',
|
||||
file_path VARCHAR(1024) COMMENT '解压后存储路径',
|
||||
file_size BIGINT DEFAULT 0 COMMENT '文件大小(字节)',
|
||||
skill_content LONGTEXT COMMENT 'SKILL.md正文内容(去除frontmatter)',
|
||||
storage_path VARCHAR(500) DEFAULT NULL COMMENT '对象存储相对路径前缀(如 skills/123/)',
|
||||
version BIGINT DEFAULT 0 COMMENT '版本号,文件变更时自增,用于缓存一致性校验',
|
||||
has_files TINYINT(1) DEFAULT 0 COMMENT '是否包含支撑文件(0=仅SKILL.md,1=有scripts/references等)',
|
||||
creator_id BIGINT COMMENT '创建者用户ID',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = 'Skill技能包表';
|
||||
|
||||
CREATE INDEX idx_skill_creator ON snail_ai_skill (creator_id);
|
||||
|
||||
-- Skill 支撑文件内容表
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_skill_file
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
skill_id BIGINT NOT NULL COMMENT 'Skill ID',
|
||||
file_path VARCHAR(255) NOT NULL COMMENT '文件相对路径',
|
||||
content LONGTEXT NOT NULL COMMENT '文件内容',
|
||||
file_size INT NOT NULL COMMENT '文件大小(字节)',
|
||||
encoding VARCHAR(50) DEFAULT 'utf-8' COMMENT '编码方式',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
UNIQUE KEY uk_skill_path (skill_id, file_path) COMMENT '同一Skill不能有重复的文件路径',
|
||||
KEY idx_skill_id (skill_id) COMMENT '技能ID索引'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = 'Skill支撑文件内容表';
|
||||
|
||||
-- 智能体与Skill关联表(多对多)
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_agent_skill
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL COMMENT '智能体ID',
|
||||
skill_id BIGINT NOT NULL COMMENT 'Skill ID',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_agent_skill (agent_id, skill_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '智能体Skill关联表';
|
||||
|
||||
CREATE INDEX idx_agent_skill_agent ON snail_ai_agent_skill (agent_id);
|
||||
CREATE INDEX idx_agent_skill_skill ON snail_ai_agent_skill (skill_id);
|
||||
|
||||
-- ============================================================
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_store_instance
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(128) NOT NULL COMMENT '实例名称',
|
||||
category TINYINT(1) NOT NULL COMMENT '分类: 1-向量库 2-搜索引擎',
|
||||
type TINYINT(1) NOT NULL COMMENT '类型: 1-PG_VECTOR 2-MILVUS 3-ELASTICSEARCH 4-PG_FULLTEXT',
|
||||
config TEXT DEFAULT NULL COMMENT '连接参数 JSON',
|
||||
status TINYINT(1) DEFAULT 1 COMMENT '状态: 0-停用 1-启用',
|
||||
is_default TINYINT(1) DEFAULT 0 COMMENT '是否为该 category 下默认实例',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '存储实例';
|
||||
|
||||
CREATE INDEX idx_store_instance_category ON snail_ai_store_instance (category);
|
||||
CREATE INDEX idx_store_instance_type ON snail_ai_store_instance (type);
|
||||
|
||||
-- ============================================================
|
||||
-- 记忆系统(配置 / 主表 / 历史 / 摘要 / 统计 / 提取进度)
|
||||
-- 依赖:snail_ai_store_instance(conversation_memory 外键)
|
||||
-- ============================================================
|
||||
|
||||
-- 客户端应用
|
||||
-- ----------------------------
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_app
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
app_id VARCHAR(128) NOT NULL COMMENT '应用唯一标识',
|
||||
app_name VARCHAR(255) NOT NULL COMMENT '应用名称',
|
||||
description VARCHAR(512) COMMENT '应用描述',
|
||||
token VARCHAR(128) NOT NULL COMMENT '通信认证令牌',
|
||||
route_strategy VARCHAR(32) DEFAULT 'LEAST_LOAD' COMMENT '路由策略',
|
||||
status TINYINT(1) DEFAULT 1 COMMENT '1=启用, 0=停用',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_app_id (app_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '客户端应用';
|
||||
|
||||
INSERT INTO snail_ai_app VALUES (1, '1', 'demo', '', 'SAI_7c557fc05a304b0482a65ca67afdb0b8', 'LEAST_LOAD', 1, '2026-05-26 12:31:17', '2026-05-26 12:31:17');
|
||||
|
||||
-- ----------------------------
|
||||
-- AI客户端实例节点
|
||||
-- ----------------------------
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_client_node
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
app_id VARCHAR(128) NOT NULL COMMENT '所属应用ID',
|
||||
host_id VARCHAR(128) NOT NULL COMMENT '客户端实例唯一标识',
|
||||
host_ip VARCHAR(64) NOT NULL COMMENT '客户端IP',
|
||||
grpc_port INT NOT NULL COMMENT '客户端gRPC端口',
|
||||
max_concurrent INT DEFAULT 10 COMMENT '最大并发对话数',
|
||||
active_chats INT DEFAULT 0 COMMENT '当前活跃对话数',
|
||||
supported_providers TEXT COMMENT '支持的模型提供商(JSON数组)',
|
||||
labels TEXT COMMENT '路由标签',
|
||||
expire_dt DATETIME NOT NULL COMMENT '过期时间(心跳更新)',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_client_node (app_id, host_id),
|
||||
INDEX idx_app_expire (app_id, expire_dt)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = 'AI客户端实例节点';
|
||||
|
||||
-- OpenAPI 外部用户映射表
|
||||
CREATE TABLE snail_ai_openapi_user
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
app_id VARCHAR(128) NOT NULL COMMENT '关联 snail_ai_app.app_id',
|
||||
open_id VARCHAR(64) NOT NULL COMMENT '平台分配的唯一标识(UUID)',
|
||||
platform_user_id BIGINT NOT NULL COMMENT '关联 snail_ai_user.id,注册时自动创建',
|
||||
external_id VARCHAR(256) DEFAULT NULL COMMENT '外部系统的用户标识(可选,幂等用)',
|
||||
nickname VARCHAR(128) DEFAULT NULL COMMENT '外部用户昵称',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_app_open (app_id, open_id),
|
||||
UNIQUE KEY uk_app_external (app_id, external_id),
|
||||
INDEX idx_open_id (open_id),
|
||||
INDEX idx_platform_user (platform_user_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
COMMENT='OpenAPI 外部用户映射表';
|
||||
|
||||
-- ----------------------------
|
||||
-- 通用资源存储
|
||||
-- ----------------------------
|
||||
CREATE TABLE IF NOT EXISTS snail_ai_resource
|
||||
(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
storage_key VARCHAR(512) NOT NULL COMMENT '存储键(相对路径或对象Key)',
|
||||
original_name VARCHAR(255) NOT NULL COMMENT '原始文件名',
|
||||
file_size BIGINT DEFAULT 0 COMMENT '文件大小(bytes)',
|
||||
mime_type VARCHAR(128) COMMENT 'MIME类型',
|
||||
storage_type VARCHAR(32) NOT NULL DEFAULT 'LOCAL' COMMENT '存储类型: LOCAL/MINIO',
|
||||
access_url VARCHAR(1024) COMMENT '访问URL',
|
||||
biz_type VARCHAR(64) NOT NULL DEFAULT 'GENERAL' COMMENT '业务类型: AVATAR/ATTACHMENT/DOCUMENT/GENERAL',
|
||||
biz_id BIGINT COMMENT '关联业务ID',
|
||||
creator_id BIGINT COMMENT '上传者ID',
|
||||
create_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_storage_key (storage_key),
|
||||
INDEX idx_biz (biz_type, biz_id),
|
||||
INDEX idx_creator (creator_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci COMMENT = '通用资源存储';
|
||||
@@ -212,7 +212,7 @@ insert into sys_menu values(1761400000000000001, '系统管理', 0, 1, 'system',
|
||||
insert into sys_menu values(1761400000000000002, '系统监控', 0, 3, 'monitor', null, '', 'N', 'Y', 'M', '0', '0', '', 'monitor', '', '', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '系统监控目录');
|
||||
insert into sys_menu values(1761400000000000003, '系统工具', 0, 4, 'tool', null, '', 'N', 'Y', 'M', '0', '0', '', 'tool', '', '', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '系统工具目录');
|
||||
insert into sys_menu values(1761400000000000005, '测试菜单', 0, 5, 'demo', null, '', 'N', 'Y', 'M', '0', '0', '', 'star', '', '', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '测试菜单');
|
||||
insert into sys_menu values(1761400000000000006, 'AI会话', 0, 6, 'ai/chat', 'ai/chat/index', '', 'N', 'Y', 'C', '0', '0', '', 'checkbox', '', '', 1761000000000000103, 1761100000000000001, sysdate(), null, null, 'AI聊天菜单');
|
||||
insert into sys_menu values(1761400000000000008, 'AI会话', 0, 8, 'ai/chat', 'ai/chat/index', '', 'N', 'Y', 'C', '0', '0', '', 'checkbox', '', '', 1761000000000000103, 1761100000000000001, sysdate(), null, null, 'AI聊天菜单');
|
||||
insert into sys_menu values(1761400000000000004, 'PLUS官网', 0, 9, 'https://gitee.com/dromara/RuoYi-Vue-Plus', null, '', 'Y', 'Y', 'M', '0', '0', '', 'guide', '', '', 1761000000000000103, 1761100000000000001, sysdate(), null, null, 'RuoYi-Vue-Plus官网地址');
|
||||
-- 二级菜单
|
||||
insert into sys_menu values(1761400000000000100, '用户管理', 1761400000000000001, 1, 'user', 'system/user/index', '', 'N', 'Y', 'C', '0', '0', 'system:user:list', 'user', '', '', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '用户管理菜单');
|
||||
|
||||
@@ -1378,7 +1378,7 @@ insert into sys_menu values(1761400000000000003, N'系统工具', 0, 4, N'tool',
|
||||
GO
|
||||
insert into sys_menu values(1761400000000000005, N'测试菜单', 0, 5, N'demo', NULL, N'', N'N', N'Y', N'M', N'0', N'0', NULL, N'star', N'', N'', 1761000000000000103, 1761100000000000001, getdate(), NULL, NULL, N'');
|
||||
GO
|
||||
insert into sys_menu values(1761400000000000006, N'AI会话', 0, 6, N'ai/chat', N'ai/chat/index', N'', N'N', N'Y', N'C', N'0', N'0', N'', N'checkbox', N'', N'', 1761000000000000103, 1761100000000000001, getdate(), NULL, NULL, N'AI聊天菜单');
|
||||
insert into sys_menu values(1761400000000000006, N'AI会话', 0, 8, N'ai/chat', N'ai/chat/index', N'', N'N', N'Y', N'C', N'0', N'0', N'', N'checkbox', N'', N'', 1761000000000000103, 1761100000000000001, getdate(), NULL, NULL, N'AI聊天菜单');
|
||||
GO
|
||||
insert into sys_menu values(1761400000000000004, N'PLUS官网', 0, 9, N'https://gitee.com/dromara/RuoYi-Vue-Plus', null, N'', N'Y', N'Y', N'M', N'0', N'0', N'', N'guide', N'', N'', 1761000000000000103, 1761100000000000001, getdate(), null, null, N'RuoYi-Vue-Plus官网地址');
|
||||
GO
|
||||
|
||||
Reference in New Issue
Block a user