mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-18 17:38:48 +08:00
暂存修改
This commit is contained in:
parent
39d27a4249
commit
bb94a6b9a9
19
pom.xml
19
pom.xml
@ -33,6 +33,7 @@
|
|||||||
<lock4j.version>2.2.7</lock4j.version>
|
<lock4j.version>2.2.7</lock4j.version>
|
||||||
<dynamic-ds.version>4.5.0</dynamic-ds.version>
|
<dynamic-ds.version>4.5.0</dynamic-ds.version>
|
||||||
<snailjob.version>1.9.0</snailjob.version>
|
<snailjob.version>1.9.0</snailjob.version>
|
||||||
|
<snailai.version>0.0.1</snailai.version>
|
||||||
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
||||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||||
<lombok.version>1.18.42</lombok.version>
|
<lombok.version>1.18.42</lombok.version>
|
||||||
@ -278,6 +279,18 @@
|
|||||||
<version>${snailjob.version}</version>
|
<version>${snailjob.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aizuda</groupId>
|
||||||
|
<artifactId>snail-ai-agent-starter</artifactId>
|
||||||
|
<version>${snailai.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aizuda</groupId>
|
||||||
|
<artifactId>snail-ai-openapi-starter</artifactId>
|
||||||
|
<version>${snailai.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 加密包引入 -->
|
<!-- 加密包引入 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
@ -341,6 +354,12 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-ai</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara</groupId>
|
<groupId>org.dromara</groupId>
|
||||||
<artifactId>ruoyi-gen</artifactId>
|
<artifactId>ruoyi-gen</artifactId>
|
||||||
|
|||||||
@ -75,6 +75,10 @@
|
|||||||
<artifactId>ruoyi-job</artifactId>
|
<artifactId>ruoyi-job</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-ai</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- demo模块 -->
|
<!-- demo模块 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@ -13,7 +13,7 @@ spring.boot.admin.client:
|
|||||||
|
|
||||||
--- # snail-job 配置
|
--- # snail-job 配置
|
||||||
snail-job:
|
snail-job:
|
||||||
enabled: true
|
enabled: false
|
||||||
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
|
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
|
||||||
group: "ruoyi_group"
|
group: "ruoyi_group"
|
||||||
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
|
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
|
||||||
@ -28,6 +28,39 @@ snail-job:
|
|||||||
# 客户端ip指定
|
# 客户端ip指定
|
||||||
host:
|
host:
|
||||||
|
|
||||||
|
--- # snail-ai 配置
|
||||||
|
snail-ai:
|
||||||
|
# 启用客户端模式
|
||||||
|
enabled: true
|
||||||
|
# ==================== Server 连接 ====================
|
||||||
|
# Server 端 gRPC 地址(即 snail-ai-starter 的 snail-ai.server.grpc-port)
|
||||||
|
server:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 18888
|
||||||
|
# ==================== 客户端配置 ====================
|
||||||
|
# 本客户端 gRPC 端口(Server 通过此端口分发 Chat 请求)
|
||||||
|
# 应用 ID(在 Server「应用管理」页面创建后获取)
|
||||||
|
app-id: 1
|
||||||
|
# 认证令牌(在 Server「应用管理」页面创建时自动生成)
|
||||||
|
token: SAI_ce6fbc820c50456baecc7cdcf2a14b1b
|
||||||
|
port: 18889
|
||||||
|
# Skill 文件临时目录
|
||||||
|
skill-temp-dir: /tmp/snail-ai-agent/skills
|
||||||
|
# ==================== OpenAPI Client 配置 ====================
|
||||||
|
open-api:
|
||||||
|
# 启用 OpenAPI Client
|
||||||
|
enabled: true
|
||||||
|
# Server HTTP 端口
|
||||||
|
web-port: 18080
|
||||||
|
# 是否使用 HTTPS
|
||||||
|
https: false
|
||||||
|
# API 路径前缀
|
||||||
|
prefix: snail-ai
|
||||||
|
# 超时配置(毫秒)
|
||||||
|
connect-timeout-ms: 5000
|
||||||
|
read-timeout-ms: 60000
|
||||||
|
chat-timeout-ms: 300000
|
||||||
|
|
||||||
--- # 数据源配置
|
--- # 数据源配置
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
@ -47,9 +80,9 @@ spring:
|
|||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
url: jdbc:mysql://8.136.96.136:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: mysql_5NrZmE
|
||||||
# # 从库数据源
|
# # 从库数据源
|
||||||
# slave:
|
# slave:
|
||||||
# lazy: true
|
# lazy: true
|
||||||
@ -96,13 +129,13 @@ spring:
|
|||||||
spring.data:
|
spring.data:
|
||||||
redis:
|
redis:
|
||||||
# 地址
|
# 地址
|
||||||
host: localhost
|
host: 8.136.96.136
|
||||||
# 端口,默认为6379
|
# 端口,默认为6379
|
||||||
port: 6379
|
port: 6379
|
||||||
# 数据库索引
|
# 数据库索引
|
||||||
database: 0
|
database: 11
|
||||||
# redis 密码必须配置
|
# redis 密码必须配置
|
||||||
password: ruoyi123
|
password: redis_JsjKmr
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
# 是否开启ssl
|
# 是否开启ssl
|
||||||
|
|||||||
@ -224,7 +224,7 @@ message:
|
|||||||
--- # warm-flow工作流配置
|
--- # warm-flow工作流配置
|
||||||
warm-flow:
|
warm-flow:
|
||||||
# 是否开启工作流,默认true
|
# 是否开启工作流,默认true
|
||||||
enabled: true
|
enabled: false
|
||||||
# 是否开启设计器ui
|
# 是否开启设计器ui
|
||||||
ui: true
|
ui: true
|
||||||
# 是否显示流程图顶部文字
|
# 是否显示流程图顶部文字
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
<module>ruoyi-common-encrypt</module>
|
<module>ruoyi-common-encrypt</module>
|
||||||
<module>ruoyi-common-push</module>
|
<module>ruoyi-common-push</module>
|
||||||
<module>ruoyi-common-mqtt</module>
|
<module>ruoyi-common-mqtt</module>
|
||||||
|
<module>ruoyi-common-ai</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
41
ruoyi-common/ruoyi-common-ai/pom.xml
Normal file
41
ruoyi-common/ruoyi-common-ai/pom.xml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?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>
|
||||||
|
<artifactId>ruoyi-common</artifactId>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>ruoyi-common-ai</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
ruoyi-common-ai AI公共模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aizuda</groupId>
|
||||||
|
<artifactId>snail-ai-agent-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aizuda</groupId>
|
||||||
|
<artifactId>snail-ai-openapi-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-common-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package org.dromara.common.ai.config;
|
||||||
|
|
||||||
|
import com.aizuda.snail.ai.agent.starter.EnableSnailAiAgent;
|
||||||
|
import com.aizuda.snail.ai.openapi.client.starter.EnableSnailAiOpenApi;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Snail AI 自动配置
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
@ConditionalOnProperty(prefix = "snail-ai", name = "enabled", havingValue = "true")
|
||||||
|
@EnableSnailAiAgent
|
||||||
|
@EnableSnailAiOpenApi
|
||||||
|
public class SnailAiConfig {
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
org.dromara.common.ai.config.SnailAiConfig
|
||||||
@ -159,6 +159,13 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- ai模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-common-ai</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
<module>ruoyi-job</module>
|
<module>ruoyi-job</module>
|
||||||
<module>ruoyi-system</module>
|
<module>ruoyi-system</module>
|
||||||
<module>ruoyi-workflow</module>
|
<module>ruoyi-workflow</module>
|
||||||
|
<module>ruoyi-ai</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
31
ruoyi-modules/ruoyi-ai/pom.xml
Normal file
31
ruoyi-modules/ruoyi-ai/pom.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?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-modules</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<artifactId>ruoyi-ai</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
ai模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-common-ai</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-common-satoken</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
||||||
@ -0,0 +1,251 @@
|
|||||||
|
package org.dromara.ai.controller;
|
||||||
|
|
||||||
|
import com.aizuda.snail.ai.common.execption.SnailAiException;
|
||||||
|
import com.aizuda.snail.ai.common.model.PageResult;
|
||||||
|
import com.aizuda.snail.ai.common.model.Result;
|
||||||
|
import com.aizuda.snail.ai.common.openapi.dto.*;
|
||||||
|
import com.aizuda.snail.ai.openapi.client.core.api.OpenApiAgentClient;
|
||||||
|
import com.aizuda.snail.ai.openapi.client.core.api.OpenApiChatClient;
|
||||||
|
import com.aizuda.snail.ai.openapi.client.core.api.OpenApiConversationClient;
|
||||||
|
import com.aizuda.snail.ai.openapi.client.core.api.OpenApiUserClient;
|
||||||
|
import com.aizuda.snail.ai.openapi.client.core.listener.SseEventListener;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI 使用示例 Controller
|
||||||
|
* <p>
|
||||||
|
* 演示如何使用 OpenAPI Client 调用 Snail AI 服务端接口
|
||||||
|
*
|
||||||
|
* @author opensnail
|
||||||
|
* @date 2026-04-25
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/snail-ai")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Tag(name = "OpenAPI Demo", description = "OpenAPI 客户端使用示例")
|
||||||
|
public class OpenApiDemoController {
|
||||||
|
|
||||||
|
private final OpenApiAgentClient agentClient;
|
||||||
|
private final OpenApiChatClient chatClient;
|
||||||
|
private final OpenApiConversationClient conversationClient;
|
||||||
|
private final OpenApiUserClient userClient;
|
||||||
|
|
||||||
|
// ==================== User 相关接口 ====================
|
||||||
|
|
||||||
|
@PostMapping("/user/register")
|
||||||
|
@Operation(summary = "注册当前登录用户", description = "使用当前系统登录用户自动注册,返回 openId")
|
||||||
|
public Result<OpenApiUserVO> registerCurrentUser() {
|
||||||
|
OpenApiUserVO user = ensureOpenApiUser();
|
||||||
|
return Result.ok(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/user")
|
||||||
|
@Operation(summary = "获取当前登录用户的 OpenAPI 信息", description = "自动解析当前用户 openId 并查询详情")
|
||||||
|
public Result<OpenApiUserVO> getUser() {
|
||||||
|
String openId = ensureOpenId();
|
||||||
|
OpenApiUserQueryRequest request = new OpenApiUserQueryRequest();
|
||||||
|
request.setOpenId(openId);
|
||||||
|
return userClient.getUser(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Agent 相关接口 ====================
|
||||||
|
|
||||||
|
@GetMapping("/agents")
|
||||||
|
@Operation(summary = "获取所有 Agent 列表", description = "查询当前用户可访问的所有智能体")
|
||||||
|
public Result<List<OpenApiAgentVO>> listAgents() {
|
||||||
|
return agentClient.listAgents();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/agent/{agentId}")
|
||||||
|
@Operation(summary = "获取 Agent 详情", description = "根据 ID 查询智能体详细信息")
|
||||||
|
public Result<OpenApiAgentVO> getAgent(
|
||||||
|
@Parameter(description = "Agent ID", required = true, example = "1")
|
||||||
|
@PathVariable Long agentId) {
|
||||||
|
OpenApiAgentIdentityRequest request = new OpenApiAgentIdentityRequest();
|
||||||
|
request.setAgentId(agentId);
|
||||||
|
return agentClient.getAgent(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Conversation 相关接口 ====================
|
||||||
|
|
||||||
|
@PostMapping("/agent/{agentId}/conversation")
|
||||||
|
@Operation(summary = "创建会话", description = "为指定 Agent 创建一个新的对话会话")
|
||||||
|
public Result<OpenApiConversationVO> createConversation(
|
||||||
|
@Parameter(description = "Agent ID", required = true, example = "1")
|
||||||
|
@PathVariable Long agentId,
|
||||||
|
@Parameter(description = "创建会话请求")
|
||||||
|
@RequestBody OpenApiCreateConversationRequest request) {
|
||||||
|
request.setAgentId(agentId);
|
||||||
|
request.setOpenId(ensureOpenId());
|
||||||
|
return conversationClient.createConversation(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/agent/{agentId}/conversations")
|
||||||
|
@Operation(summary = "获取会话列表", description = "查询指定 Agent 的所有会话(分页)")
|
||||||
|
public PageResult<List<OpenApiConversationVO>> listConversations(
|
||||||
|
@Parameter(description = "Agent ID", required = true, example = "1")
|
||||||
|
@PathVariable Long agentId,
|
||||||
|
@Parameter(description = "页码", example = "1")
|
||||||
|
@RequestParam(defaultValue = "1") int page,
|
||||||
|
@Parameter(description = "每页数量", example = "10")
|
||||||
|
@RequestParam(defaultValue = "10") int size) {
|
||||||
|
OpenApiConversationQueryRequest request = new OpenApiConversationQueryRequest();
|
||||||
|
request.setAgentId(agentId);
|
||||||
|
request.setOpenId(ensureOpenId());
|
||||||
|
request.setPage(page);
|
||||||
|
request.setSize(size);
|
||||||
|
return conversationClient.listConversations(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/agent/{agentId}/conversation/{conversationId}/messages")
|
||||||
|
@Operation(summary = "获取会话消息", description = "查询指定会话的所有消息记录")
|
||||||
|
public Result<List<OpenApiMessageVO>> getMessages(
|
||||||
|
@Parameter(description = "Agent ID", required = true, example = "1")
|
||||||
|
@PathVariable Long agentId,
|
||||||
|
@Parameter(description = "会话 ID", required = true, example = "conv-123")
|
||||||
|
@PathVariable String conversationId) {
|
||||||
|
OpenApiConversationIdentityRequest request = new OpenApiConversationIdentityRequest();
|
||||||
|
request.setAgentId(agentId);
|
||||||
|
request.setConversationId(conversationId);
|
||||||
|
request.setOpenId(ensureOpenId());
|
||||||
|
return conversationClient.getMessages(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/agent/{agentId}/conversation/{conversationId}")
|
||||||
|
@Operation(summary = "删除会话", description = "删除指定的对话会话")
|
||||||
|
public Result<Void> deleteConversation(
|
||||||
|
@Parameter(description = "Agent ID", required = true, example = "1")
|
||||||
|
@PathVariable Long agentId,
|
||||||
|
@Parameter(description = "会话 ID", required = true, example = "conv-123")
|
||||||
|
@PathVariable String conversationId) {
|
||||||
|
OpenApiConversationIdentityRequest request = new OpenApiConversationIdentityRequest();
|
||||||
|
request.setAgentId(agentId);
|
||||||
|
request.setConversationId(conversationId);
|
||||||
|
request.setOpenId(ensureOpenId());
|
||||||
|
return conversationClient.deleteConversation(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Chat 相关接口 ====================
|
||||||
|
|
||||||
|
@PostMapping("/agent/{agentId}/chat/sync")
|
||||||
|
@Operation(summary = "同步对话", description = "发送消息并等待 AI 回复(非流式)")
|
||||||
|
public Result<OpenApiChatSyncResponse> chatSync(
|
||||||
|
@Parameter(description = "Agent ID", required = true, example = "1")
|
||||||
|
@PathVariable Long agentId,
|
||||||
|
@Parameter(description = "对话请求")
|
||||||
|
@RequestBody OpenApiChatRequest request) {
|
||||||
|
request.setAgentId(agentId);
|
||||||
|
request.setOpenId(ensureOpenId());
|
||||||
|
log.info("Sync chat request: agentId={}, content={}", agentId, request.getContent());
|
||||||
|
return chatClient.chatSync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/agent/{agentId}/chat/stream")
|
||||||
|
@Operation(summary = "流式对话", description = "发送消息并以 SSE 流式接收 AI 回复")
|
||||||
|
public SseEmitter chatStream(
|
||||||
|
@Parameter(description = "Agent ID", required = true, example = "1")
|
||||||
|
@PathVariable Long agentId,
|
||||||
|
@Parameter(description = "用户消息", required = true, example = "你好")
|
||||||
|
@RequestParam String content,
|
||||||
|
@Parameter(description = "会话 ID(可选)", example = "conv-123")
|
||||||
|
@RequestParam(required = false) String conversationId) {
|
||||||
|
|
||||||
|
SseEmitter emitter = new SseEmitter(300000L); // 5 分钟超时
|
||||||
|
|
||||||
|
OpenApiChatRequest request = new OpenApiChatRequest();
|
||||||
|
request.setAgentId(agentId);
|
||||||
|
request.setOpenId(ensureOpenId());
|
||||||
|
request.setContent(content);
|
||||||
|
request.setConversationId(conversationId);
|
||||||
|
|
||||||
|
log.info("Stream chat request: agentId={}, content={}", agentId, content);
|
||||||
|
try {
|
||||||
|
chatClient.chatStream(request, new SseEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onText(String text) {
|
||||||
|
try {
|
||||||
|
emitter.send(SseEmitter.event()
|
||||||
|
.name("text")
|
||||||
|
.data(text));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to send SSE text", e);
|
||||||
|
emitter.completeWithError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onThinking(String thinking) {
|
||||||
|
try {
|
||||||
|
emitter.send(SseEmitter.event()
|
||||||
|
.name("thinking")
|
||||||
|
.data(thinking));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to send SSE thinking", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete(String data) {
|
||||||
|
try {
|
||||||
|
emitter.send(SseEmitter.event()
|
||||||
|
.name("done")
|
||||||
|
.data(data));
|
||||||
|
emitter.complete();
|
||||||
|
log.info("Stream chat completed");
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to send SSE completion", e);
|
||||||
|
emitter.completeWithError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(String errorMessage) {
|
||||||
|
log.error("Stream chat error: {}", errorMessage);
|
||||||
|
try {
|
||||||
|
emitter.send(SseEmitter.event()
|
||||||
|
.name("error")
|
||||||
|
.data(errorMessage));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to send SSE error", e);
|
||||||
|
}
|
||||||
|
emitter.completeWithError(new SnailAiException(errorMessage));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Stream chat exception", e);
|
||||||
|
emitter.completeWithError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return emitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String ensureOpenId() {
|
||||||
|
return ensureOpenApiUser().getOpenId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpenApiUserVO ensureOpenApiUser() {
|
||||||
|
Long userId = LoginHelper.getUserId();
|
||||||
|
String username = LoginHelper.getLoginUser().getNickname();
|
||||||
|
|
||||||
|
OpenApiUserRegisterRequest registerRequest = new OpenApiUserRegisterRequest();
|
||||||
|
registerRequest.setExternalId(String.valueOf(userId));
|
||||||
|
registerRequest.setNickname(username);
|
||||||
|
Result<OpenApiUserVO> registerResult = userClient.register(registerRequest);
|
||||||
|
if (registerResult == null || registerResult.getData() == null) {
|
||||||
|
throw new SnailAiException("注册 OpenAPI 用户失败,返回为空");
|
||||||
|
}
|
||||||
|
OpenApiUserVO user = registerResult.getData();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
package org.dromara.ai;
|
||||||
Loading…
Reference in New Issue
Block a user