feat: 全局格式化代码

This commit is contained in:
evo
2025-12-06 14:38:41 +08:00
parent 96c53390aa
commit 7c7d5838cd
538 changed files with 21132 additions and 14160 deletions

View File

@@ -18,19 +18,20 @@
<img src="image/00.png" alt="RuoYi AI Logo" width="120" height="120">
### 企业级AI助手平台
*开箱即用的智能AI平台深度集成 FastGPT、扣子(Coze)、DIFY 等主流AI平台提供先进的RAG技术、知识图谱、数字人和AI流程编排能力*
**[🇺🇸 English](README_EN.md)** | **[📖 使用文档](https://doc.pandarobot.chat)** | **[🚀 在线体验](https://web.pandarobot.chat)** | **[🐛 问题反馈](https://github.com/ageerle/ruoyi-ai/issues)** | **[💡 功能建议](https://github.com/ageerle/ruoyi-ai/issues)**
**[🇺🇸 English](README_EN.md)** | **[📖 使用文档](https://doc.pandarobot.chat)** | *
*[🚀 在线体验](https://web.pandarobot.chat)** | **[🐛 问题反馈](https://github.com/ageerle/ruoyi-ai/issues)** | *
*[💡 功能建议](https://github.com/ageerle/ruoyi-ai/issues)**
</div>
## ✨ 核心亮点
### 智能AI引擎
- **多模型接入**:支持 OpenAI GPT-4、Azure、ChatGLM、通义千问、智谱AI 等主流模型
- **AI平台集成**:深度集成 **FastGPT**、**扣子(Coze)**、**DIFY** 等主流AI应用平台
- **Spring AI MCP 集成**基于模型上下文协议打造可扩展的AI工具生态系统
@@ -38,60 +39,64 @@
- **AI 编程助手**:内置智能代码分析和项目脚手架生成能力
### AI平台生态集成
- **FastGPT 深度集成**:原生支持 FastGPT API包括知识库检索、工作流编排和上下文管理
- **扣子(Coze) 官方SDK**集成字节跳动扣子平台官方SDK支持Bot对话和流式响应
- **DIFY 完整兼容**:使用 DIFY Java Client支持应用编排、工作流和知识库管理
- **统一聊天接口**:提供统一的聊天服务接口,支持多平台无缝切换和负载均衡
### 本地化RAG方案
- **私有知识库**:基于 Langchain4j 框架 + BGE-large-zh-v1.5 中文向量模型
- **多种向量库**:支持 Milvus、Weaviate、Qdrant 等主流向量数据库
- **数据安全可控**:支持完全本地部署,保护企业数据隐私
- **灵活模型部署**:兼容 Ollama、vLLM 等本地推理框架
### AI创作工具
- **AI 绘画创作**:深度集成 DALL·E-3、MidJourney、Stable Diffusion
- **智能PPT生成**:一键将文本内容转换为精美演示文稿
- **多模态理解**:支持文本、图片、文档等多种格式的智能处理
### 知识图谱与智能编排
- **知识图谱构建**:自动从文档和对话中提取实体关系,构建可视化知识网络
- **AI 流程编排**可视化工作流设计器支持复杂AI任务的编排和自动化执行
- **数字人交互**:集成数字人形象,提供更自然的人机交互体验
- **智能推理引擎**:基于知识图谱的智能推理和问答能力
## 🚀 快速体验
### 在线演示
- **用户端体验**[web.pandarobot.chat](https://web.pandarobot.chat) (账号admin 密码admin123)
- **管理后台**[admin.pandarobot.chat](https://admin.pandarobot.chat) (账号admin 密码admin123)
### 项目源码
| 项目模块 | GitHub 仓库 | Gitee 仓库 | GitCode 仓库 |
|---------|------------|-----------|-------------|
| 🔧 后端服务 | [ruoyi-ai](https://github.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitee.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitcode.com/ageerle/ruoyi-ai) |
| 🎨 用户前端 | [ruoyi-web](https://github.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitee.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitcode.com/ageerle/ruoyi-web) |
| 项目模块 | GitHub 仓库 | Gitee 仓库 | GitCode 仓库 |
|----------|-------------------------------------------------------|------------------------------------------------------|--------------------------------------------------------|
| 🔧 后端服务 | [ruoyi-ai](https://github.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitee.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitcode.com/ageerle/ruoyi-ai) |
| 🎨 用户前端 | [ruoyi-web](https://github.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitee.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitcode.com/ageerle/ruoyi-web) |
| 🛠️ 管理后台 | [ruoyi-admin](https://github.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitee.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitcode.com/ageerle/ruoyi-admin) |
### 合作项目
| 项目介绍 | GitHub 仓库 | Gitee 仓库 |
|:--------:|:----------:|:----------:|
| 项目介绍 | GitHub 仓库 | Gitee 仓库 |
|:-----:|:----------------------------------------------------------------------:|:----------------------------------------------------------------:|
| 前端简化版 | [ruoyi-element-ai](https://github.com/element-plus-x/ruoyi-element-ai) | [ruoyi-element-ai](https://gitee.com/he-jiayue/ruoyi-element-ai) |
## 🛠️ 技术架构
### 核心框架
- **后端架构**Spring Boot 3.4 + Spring AI + Langchain4j
- **数据存储**MySQL 8.0 + Redis + 向量数据库Milvus/Weaviate/Qdrant
- **前端技术**Vue 3 + Vben Admin + Naive UI
- **安全认证**Sa-Token + JWT 双重保障
### 系统组件
- **文档处理**PDF、Word、Excel 解析,图像智能分析
- **实时通信**WebSocket 实时通信SSE 流式响应
- **系统监控**:完善的日志体系、性能监控、服务健康检查
@@ -107,6 +112,7 @@
我们热烈欢迎社区贡献!无论您是资深开发者还是初学者,都可以为项目贡献力量 💪
### 贡献方式
1. **Fork** 项目到您的账户
2. **创建分支** (`git checkout -b feature/新功能名称`)
3. **提交代码** (`git commit -m '添加某某功能'`)
@@ -123,7 +129,8 @@
感谢以下优秀的开源项目为本项目提供支持:
- [Spring AI Alibaba Copilot](https://github.com/springaialibaba/spring-ai-alibaba-copilot) - 基于spring-ai-alibaba 的智能编码助手
- [Spring AI Alibaba Copilot](https://github.com/springaialibaba/spring-ai-alibaba-copilot) - 基于spring-ai-alibaba
的智能编码助手
- [Spring AI](https://spring.io/projects/spring-ai) - Spring 官方 AI 集成框架
- [Langchain4j](https://github.com/langchain4j/langchain4j) - 强大的 Java LLM 开发框架
- [RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus) - 成熟的企业级快速开发框架
@@ -132,7 +139,8 @@
## 🌐 生态伙伴
- [PPIO 派欧云](https://ppinfra.com/user/register?invited_by=P8QTUY&utm_source=github_ruoyi-ai) - 提供高性价比的 GPU 算力和模型 API 服务
- [PPIO 派欧云](https://ppinfra.com/user/register?invited_by=P8QTUY&utm_source=github_ruoyi-ai) - 提供高性价比的 GPU
算力和模型 API 服务
- [优云智算](https://www.compshare.cn/?ytag=GPU_YY-gh_ruoyi) - 万卡RTX40系GPU+海内外主流模型API服务秒级响应按量计费新客免费用。
- [胜算云](https://www.shengsuanyun.com/?from=CH_3WG71ZOS) - AI模型算力聚合超市云服务。
@@ -162,20 +170,32 @@
<div align="center">
**[⭐ 点个Star支持一下](https://github.com/ageerle/ruoyi-ai)** • **[🍴 Fork 开始贡献](https://github.com/ageerle/ruoyi-ai/fork)** • **[📚 English](README_EN.md)** • **[📖 查看完整文档](https://doc.pandarobot.chat)**
**[⭐ 点个Star支持一下](https://github.com/ageerle/ruoyi-ai)** • *
*[🍴 Fork 开始贡献](https://github.com/ageerle/ruoyi-ai/fork)** • **[📚 English](README_EN.md)** • *
*[📖 查看完整文档](https://doc.pandarobot.chat)**
*用 ❤️ 打造,由 RuoYi AI 开源社区维护*
</div>
<!-- Badge Links -->
[contributors-shield]: https://img.shields.io/github/contributors/ageerle/ruoyi-ai.svg?style=flat-square
[contributors-url]: https://github.com/ageerle/ruoyi-ai/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/ageerle/ruoyi-ai.svg?style=flat-square
[forks-url]: https://github.com/ageerle/ruoyi-ai/network/members
[stars-shield]: https://img.shields.io/github/stars/ageerle/ruoyi-ai.svg?style=flat-square
[stars-url]: https://github.com/ageerle/ruoyi-ai/stargazers
[issues-shield]: https://img.shields.io/github/issues/ageerle/ruoyi-ai.svg?style=flat-square
[issues-url]: https://github.com/ageerle/ruoyi-ai/issues
[license-shield]: https://img.shields.io/github/license/ageerle/ruoyi-ai.svg?style=flat-square
[license-url]: https://github.com/ageerle/ruoyi-ai/blob/main/LICENSE

View File

@@ -1,4 +1,3 @@
# RuoYi AI
<div align="center">
@@ -13,16 +12,19 @@
### Enterprise-Grade AI Assistant Platform
*Production-ready AI platform with deep integration of FastGPT, Coze, DIFY, featuring advanced RAG technology, knowledge graphs, digital humans, and AI workflow orchestration*
*Production-ready AI platform with deep integration of FastGPT, Coze, DIFY, featuring advanced RAG technology, knowledge
graphs, digital humans, and AI workflow orchestration*
**[📖 中文文档](README.md)** | **[📚 Documentation](https://doc.pandarobot.chat)** | **[🚀 Live Demo](https://web.pandarobot.chat)** | **[🐛 Report Bug](https://github.com/ageerle/ruoyi-ai/issues)** | **[💡 Request Feature](https://github.com/ageerle/ruoyi-ai/issues)**
**[📖 中文文档](README.md)** | **[📚 Documentation](https://doc.pandarobot.chat)** | *
*[🚀 Live Demo](https://web.pandarobot.chat)** | **[🐛 Report Bug](https://github.com/ageerle/ruoyi-ai/issues)** | *
*[💡 Request Feature](https://github.com/ageerle/ruoyi-ai/issues)**
</div>
## ✨ Key Features
### 🤖 Advanced AI Engine
- **Multi-Model Support**: OpenAI GPT-4, Azure, ChatGLM, Qwen, ZhipuAI
- **AI Platform Integration**: Deep integration with **FastGPT**, **Coze**, **DIFY** and other leading AI platforms
- **Spring AI MCP Integration**: Extensible tool ecosystem with Model Context Protocol
@@ -30,58 +32,69 @@
- **AI Copilot**: Intelligent code analysis and project scaffolding
### 🌟 AI Platform Ecosystem
- **FastGPT Deep Integration**: Native FastGPT API support with knowledge base retrieval, workflow orchestration and context management
- **Coze Official SDK**: Integration with ByteDance Coze platform official SDK, supporting Bot conversations and streaming responses
- **FastGPT Deep Integration**: Native FastGPT API support with knowledge base retrieval, workflow orchestration and
context management
- **Coze Official SDK**: Integration with ByteDance Coze platform official SDK, supporting Bot conversations and
streaming responses
- **DIFY Full Compatibility**: Using DIFY Java Client for app orchestration, workflows and knowledge base management
- **Unified Chat Interface**: Standardized chat service interface supporting seamless platform switching and load balancing
- **Unified Chat Interface**: Standardized chat service interface supporting seamless platform switching and load
balancing
### 🧠 Enterprise RAG Solution
- **Local Knowledge Base**: Langchain4j + BGE-large-zh-v1.5 embeddings
- **Vector Database Support**: Milvus, Weaviate, Qdrant
- **Privacy-First**: On-premise deployment with local LLM support
- **Ollama & vLLM Compatible**: Flexible model deployment options
### 🎨 Creative AI Tools
- **AI Art Generation**: DALL·E-3, MidJourney, Stable Diffusion integration
- **PPT Creation**: Automated slide generation from text input
- **Multi-Modal Processing**: Text, image, and document understanding
### 🧩 Knowledge Graph & Intelligent Orchestration
- **Knowledge Graph Construction**: Automatically extract entities and relationships from documents and conversations to build visual knowledge networks
- **AI Workflow Orchestration**: Visual workflow designer supporting complex AI task orchestration and automated execution
- **Knowledge Graph Construction**: Automatically extract entities and relationships from documents and conversations to
build visual knowledge networks
- **AI Workflow Orchestration**: Visual workflow designer supporting complex AI task orchestration and automated
execution
- **Digital Human Interaction**: Integrated digital human avatars for more natural human-computer interaction
- **Intelligent Reasoning Engine**: Knowledge graph-based intelligent reasoning and Q&A capabilities
## 🚀 Quick Start
### Live Demo
- **User Portal**: [web.pandarobot.chat](https://web.pandarobot.chat) (demo/demo123)
- **Admin Panel**: [admin.pandarobot.chat](https://admin.pandarobot.chat) (admin/admin123)
### Source Code
| Component | GitHub | Gitee | GitCode |
|-----------|--------|-------|---------|
| Backend API | [ruoyi-ai](https://github.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitee.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitcode.com/ageerle/ruoyi-ai) |
| User Frontend | [ruoyi-web](https://github.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitee.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitcode.com/ageerle/ruoyi-web) |
| Component | GitHub | Gitee | GitCode |
|----------------|-------------------------------------------------------|------------------------------------------------------|--------------------------------------------------------|
| Backend API | [ruoyi-ai](https://github.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitee.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitcode.com/ageerle/ruoyi-ai) |
| User Frontend | [ruoyi-web](https://github.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitee.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitcode.com/ageerle/ruoyi-web) |
| Admin Frontend | [ruoyi-admin](https://github.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitee.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitcode.com/ageerle/ruoyi-admin) |
### Collaborative Projects
| Project Description | GitHub Repository | Gitee Repository |
|:-------------------:|:-----------------:|:----------------:|
| Simplified Frontend | [ruoyi-element-ai](https://github.com/element-plus-x/ruoyi-element-ai) | [ruoyi-element-ai](https://gitee.com/he-jiayue/ruoyi-element-ai) |
| Project Description | GitHub Repository | Gitee Repository |
|:-------------------:|:----------------------------------------------------------------------:|:----------------------------------------------------------------:|
| Simplified Frontend | [ruoyi-element-ai](https://github.com/element-plus-x/ruoyi-element-ai) | [ruoyi-element-ai](https://gitee.com/he-jiayue/ruoyi-element-ai) |
## 🛠️ Tech Stack
### Core Framework
- **Backend**: Spring Boot 3.4, Spring AI, Langchain4j
- **Database**: MySQL 8.0, Redis, Vector Databases (Milvus/Weaviate/Qdrant)
- **Frontend**: Vue 3, Vben Admin, Naive UI
- **Authentication**: Sa-Token, JWT
### System Components
- **File Processing**: PDF, Word, Excel parsing, intelligent image analysis
- **Real-time Communication**: WebSocket real-time communication, SSE streaming
- **System Monitoring**: Comprehensive logging, performance monitoring, health checks
@@ -94,9 +107,11 @@ For detailed setup, configuration, and development guides, visit our comprehensi
## 🤝 Contributing
We welcome contributions from developers of all skill levels! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.
We welcome contributions from developers of all skill levels! Whether you're fixing bugs, adding features, or improving
documentation, your help is appreciated.
### How to Contribute
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
@@ -109,12 +124,12 @@ We welcome contributions from developers of all skill levels! Whether you're fix
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
Special thanks to these amazing open source projects:
- [Spring AI Alibaba Copilot](https://github.com/springaialibaba/spring-ai-alibaba-copilot) - Intelligent coding assistant based on spring-ai-alibaba with MCP protocol integration for project analysis and code generation
- [Spring AI Alibaba Copilot](https://github.com/springaialibaba/spring-ai-alibaba-copilot) - Intelligent coding
assistant based on spring-ai-alibaba with MCP protocol integration for project analysis and code generation
- [Spring AI](https://spring.io/projects/spring-ai) - Spring's AI integration framework
- [Langchain4j](https://github.com/langchain4j/langchain4j) - Java LLM framework
- [RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus) - Enterprise development framework
@@ -123,7 +138,8 @@ Special thanks to these amazing open source projects:
## 🌐 Ecosystem Partners
- [PPIO Cloud](https://ppinfra.com/user/register?invited_by=P8QTUY&utm_source=github_ruoyi-ai) - Cost-effective GPU containers and model APIs
- [PPIO Cloud](https://ppinfra.com/user/register?invited_by=P8QTUY&utm_source=github_ruoyi-ai) - Cost-effective GPU
containers and model APIs
## 💬 Community
@@ -150,22 +166,33 @@ Special thanks to these amazing open source projects:
<div align="center">
**[⭐ Star this repo](https://github.com/ageerle/ruoyi-ai)** • **[🍴 Fork it](https://github.com/ageerle/ruoyi-ai/fork)** • **[📖 中文文档](README.md)** • **[📚 Documentation](https://doc.pandarobot.chat)**
**[⭐ Star this repo](https://github.com/ageerle/ruoyi-ai)** • **[🍴 Fork it](https://github.com/ageerle/ruoyi-ai/fork)
****[📖 中文文档](README.md)** • **[📚 Documentation](https://doc.pandarobot.chat)**
*Built with ❤️ by the RuoYi AI community*
</div>
<!-- Badge Links -->
[contributors-shield]: https://img.shields.io/github/contributors/ageerle/ruoyi-ai.svg?style=flat-square
[contributors-url]: https://github.com/ageerle/ruoyi-ai/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/ageerle/ruoyi-ai.svg?style=flat-square
[forks-url]: https://github.com/ageerle/ruoyi-ai/network/members
[stars-shield]: https://img.shields.io/github/stars/ageerle/ruoyi-ai.svg?style=flat-square
[stars-url]: https://github.com/ageerle/ruoyi-ai/stargazers
[issues-shield]: https://img.shields.io/github/issues/ageerle/ruoyi-ai.svg?style=flat-square
[issues-url]: https://github.com/ageerle/ruoyi-ai/issues
[license-shield]: https://img.shields.io/github/license/ageerle/ruoyi-ai.svg?style=flat-square
[license-url]: https://github.com/ageerle/ruoyi-ai/blob/main/LICENSE

View File

@@ -78,7 +78,7 @@ mkdir logs minio minio-config mysql redis weaviate
- `Dockerfile`
> 📂 这些文件在项目目录 `/script/deploy/deploy` 下。
> 上传后请检查文件路径是否与上方目录结构一致。
> 上传后请检查文件路径是否与上方目录结构一致。
------
@@ -88,7 +88,7 @@ mkdir logs minio minio-config mysql redis weaviate
2. 选择 **Maven 构建配置**,勾选 `prod` 环境,取消 `dev` 环境
3. 点击 `package` 进行打包
4. **注意:** 在构建前请将 `application-prod.yml` 拖入
`ruoyi-admin/src/main/resources` 目录中
`ruoyi-admin/src/main/resources` 目录中
构建完成后会在:
@@ -103,7 +103,7 @@ ruoyi-admin/target/ruoyi-admin.jar
### 五、上传 Jar 包至服务器
将生成的 `ruoyi-admin.jar` 上传到服务器 `/ruoyi-ai/deploy` 目录下。
确保与 `Dockerfile` 同目录。
确保与 `Dockerfile` 同目录。
------
@@ -194,13 +194,13 @@ source /docker-entrypoint-initdb.d/ruoyi-ai.sql;
### 九、常用 Docker 命令
| 功能 | 命令 |
| ----------------- | --------------------------------- |
| 查看容器状态 | `docker ps -a` |
| 查看日志 | `docker logs -f <容器名>` |
| 停止服务 | `docker compose down` |
| 重启服务 | `docker compose restart` |
| 重新构建镜像 | `docker compose build --no-cache` |
| 功能 | 命令 |
|-----------|-----------------------------------|
| 查看容器状态 | `docker ps -a` |
| 查看日志 | `docker logs -f <容器名>` |
| 停止服务 | `docker compose down` |
| 重启服务 | `docker compose restart` |
| 重新构建镜像 | `docker compose build --no-cache` |
| 清理无用镜像/容器 | `docker system prune -a` |
------

View File

@@ -2,7 +2,8 @@
## 概述
Ruoyi-AI 工作流模块是一个基于 LangGraph4j 的智能工作流引擎支持可视化工作流设计、AI 模型集成、条件分支、人机交互等高级功能。该模块采用微服务架构,提供完整的 RESTful API 和流式响应支持。
Ruoyi-AI 工作流模块是一个基于 LangGraph4j 的智能工作流引擎支持可视化工作流设计、AI 模型集成、条件分支、人机交互等高级功能。该模块采用微服务架构,提供完整的
RESTful API 和流式响应支持。
## 模块架构
@@ -48,12 +49,14 @@ ruoyi-ai/
### 1. 工作流管理
#### 1.1 工作流定义
- **创建工作流**: 支持自定义标题、描述、公开性设置
- **编辑工作流**: 可视化节点编辑、连接线配置
- **版本控制**: 支持工作流的版本管理和回滚
- **权限管理**: 支持公开/私有工作流设置
#### 1.2 工作流执行
- **流式执行**: 基于 SSE 的实时流式响应
- **状态管理**: 完整的执行状态跟踪
- **错误处理**: 详细的错误信息和异常处理
@@ -62,26 +65,31 @@ ruoyi-ai/
### 2. 节点类型
#### 2.1 基础节点
- **Start**: 开始节点,定义工作流入口
- **End**: 结束节点,定义工作流出口
#### 2.2 AI 模型节点
- **Answer**: 大语言模型问答节点
- **Dalle3**: DALL-E 3 图像生成
- **Tongyiwanx**: 通义万相图像生成
- **Classifier**: 内容分类节点
#### 2.3 数据处理节点
- **DocumentExtractor**: 文档信息提取
- **KeywordExtractor**: 关键词提取
- **FaqExtractor**: 常见问题提取
- **KnowledgeRetrieval**: 知识库检索
#### 2.4 控制流节点
- **Switcher**: 条件分支节点
- **HumanFeedback**: 人机交互节点
#### 2.5 外部集成节点
- **Google**: Google 搜索集成
- **MailSend**: 邮件发送
- **HttpRequest**: HTTP 请求
@@ -90,6 +98,7 @@ ruoyi-ai/
### 3. 数据流管理
#### 3.1 输入输出定义
```java
// 节点输入输出数据结构
public class NodeIOData {
@@ -108,6 +117,7 @@ public enum WfIODataTypeEnum {
```
#### 3.2 参数引用
- **节点间引用**: 支持上游节点输出作为下游节点输入
- **参数映射**: 自动处理参数名称映射
- **类型转换**: 自动进行数据类型转换
@@ -117,6 +127,7 @@ public enum WfIODataTypeEnum {
### 1. 核心表结构
#### 1.1 工作流定义表 (t_workflow)
```sql
CREATE TABLE t_workflow (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
@@ -133,6 +144,7 @@ CREATE TABLE t_workflow (
```
#### 1.2 工作流节点表 (t_workflow_node)
```sql
CREATE TABLE t_workflow_node (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
@@ -153,6 +165,7 @@ CREATE TABLE t_workflow_node (
```
#### 1.3 工作流边表 (t_workflow_edge)
```sql
CREATE TABLE t_workflow_edge (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
@@ -168,6 +181,7 @@ CREATE TABLE t_workflow_edge (
```
#### 1.4 工作流运行时表 (t_workflow_runtime)
```sql
CREATE TABLE t_workflow_runtime (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
@@ -185,6 +199,7 @@ CREATE TABLE t_workflow_runtime (
```
#### 1.5 工作流组件表 (t_workflow_component)
```sql
CREATE TABLE t_workflow_component (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
@@ -205,6 +220,7 @@ CREATE TABLE t_workflow_component (
### 1. 工作流管理接口
#### 1.1 基础操作
```http
#
POST /workflow/add
@@ -232,6 +248,7 @@ POST /workflow/enable/{uuid}?enable=true
```
#### 1.2 搜索和查询
```http
#
GET /workflow/mine/search?keyword=&isPublic=true&currentPage=1&pageSize=10
@@ -246,6 +263,7 @@ GET /workflow/public/component/list
### 2. 工作流执行接口
#### 2.1 流式执行
```http
#
POST /workflow/run
@@ -266,6 +284,7 @@ Accept: text/event-stream
```
#### 2.2 运行时管理
```http
#
POST /workflow/runtime/resume/{runtimeUuid}
@@ -287,6 +306,7 @@ POST /workflow/runtime/clear?wfUuid=工作流UUID
### 3. 管理端接口
#### 3.1 工作流管理
```http
#
POST /admin/workflow/search
@@ -306,6 +326,7 @@ POST /admin/workflow/enable?uuid=工作流UUID&isEnable=true
### 1. 工作流引擎 (WorkflowEngine)
工作流引擎是整个模块的核心,负责:
- 工作流图的构建和编译
- 节点执行调度
- 状态管理和持久化
@@ -399,7 +420,6 @@ public class WorkflowGraphBuilder {
4. **状态更新**: 实时更新节点和工作流状态
5. **错误处理**: 捕获并处理执行过程中的错误
## 扩展开发
### 1. 自定义节点开发

View File

@@ -1,6 +1,6 @@
<?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"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

View File

@@ -1,6 +1,6 @@
<?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"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-ai</artifactId>

View File

@@ -81,6 +81,7 @@ public class AuthController {
/**
* 访客登录
*
* @param loginBody 登录信息
* @return token信息
*/
@@ -119,7 +120,7 @@ public class AuthController {
*/
@PostMapping("/register")
public R<Void> register(@Validated @RequestBody RegisterBody user, HttpServletRequest request) {
String domainName = request.getServerName();
String domainName = request.getServerName();
user.setDomainName(domainName);
registerService.register(user);
return R.ok();

View File

@@ -22,5 +22,4 @@ public class IndexController {
}
}

View File

@@ -1,4 +1,3 @@
--- # 数据源配置
spring:
datasource:
@@ -16,9 +15,9 @@ spring:
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: root
password: root
url: jdbc:mysql://47.112.190.27:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: ruoyi-ai
password: fc6jEZa77HHYZkw6
hikari:
# 最大连接池数量

View File

@@ -98,32 +98,32 @@
</appender>
<!-- 整合 skywalking 控制台输出 tid -->
<!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!-- 整合 skywalking 推送采集日志 -->
<!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!--系统操作日志-->
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="async_info" />
<appender-ref ref="async_error" />
<appender-ref ref="file_console" />
<!-- <appender-ref ref="sky_log"/>-->
<appender-ref ref="console"/>
<appender-ref ref="async_info"/>
<appender-ref ref="async_error"/>
<appender-ref ref="file_console"/>
<!-- <appender-ref ref="sky_log"/>-->
</root>
</configuration>

View File

@@ -1,6 +1,6 @@
<?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"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>

View File

@@ -1,6 +1,6 @@
<?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"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

View File

@@ -1,6 +1,6 @@
<?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"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.ruoyi</groupId>

View File

@@ -6,7 +6,6 @@ import cn.hutool.core.date.DateUnit;
import lombok.extern.slf4j.Slf4j;
/**
*
* @author https:www.unfbx.com
* @date 2023-03-10
*/
@@ -16,16 +15,14 @@ public class LocalCache {
* 缓存时长
*/
public static final long TIMEOUT = 30 * DateUnit.MINUTE.getMillis();
/**
* 清理间隔
*/
private static final long CLEAN_TIMEOUT = 30 * DateUnit.MINUTE.getMillis();
/**
* 缓存对象
*/
public static final TimedCache<String, Object> CACHE = CacheUtil.newTimedCache(TIMEOUT);
/**
* 清理间隔
*/
private static final long CLEAN_TIMEOUT = 30 * DateUnit.MINUTE.getMillis();
static {
//启动定时任务

View File

@@ -39,10 +39,10 @@ public class WebSocketConfig {
}
// 返回一个WebSocketConfigurer对象用于配置WebSocket
return registry -> registry
// 添加WebSocket处理程序和拦截器到指定路径设置允许的跨域来源
.addHandler(webSocketHandler, webSocketProperties.getPath())
.addInterceptors(handshakeInterceptor)
.setAllowedOrigins(webSocketProperties.getAllowedOrigins());
// 添加WebSocket处理程序和拦截器到指定路径设置允许的跨域来源
.addHandler(webSocketHandler, webSocketProperties.getPath())
.addInterceptors(handshakeInterceptor)
.setAllowedOrigins(webSocketProperties.getAllowedOrigins());
}
@Bean

View File

@@ -23,7 +23,7 @@ public class WebSocketProperties {
private String path;
/**
* 设置访问源地址
* 设置访问源地址
*/
private String allowedOrigins;
}

View File

@@ -1,9 +1,8 @@
package org.ruoyi.common.chat.constant;
/**
*
* @author https:www.unfbx.com
* @since 2023-03-06
* @since 2023-03-06
*/
public class OpenAIConst {

View File

@@ -7,7 +7,6 @@ import lombok.Data;
import java.math.BigDecimal;
/**
*
* @author https:www.unfbx.com
* @since 2023-03-18
*/

View File

@@ -7,7 +7,6 @@ import lombok.Data;
import java.util.List;
/**
*
* @author https:www.unfbx.com
* @since 2023-03-18
*/

View File

@@ -4,9 +4,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
*
* @author https:www.unfbx.com
* @since 2023-04-08
* @since 2023-04-08
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -7,7 +7,7 @@ import lombok.Data;
* 账户信息
*
* @author https:www.unfbx.com
* @since 2023-04-08
* @since 2023-04-08
*/
@Data
public class Subscription {

View File

@@ -12,7 +12,6 @@ import java.io.Serializable;
import java.util.List;
/**
*
* @author https:www.unfbx.com
* @since 1.1.2
* 2023-03-02
@@ -34,6 +33,7 @@ public class BaseMessage implements Serializable {
/**
* The tool calls generated by the model, such as function calls.
*
* @since 1.1.2
*/
@JsonProperty("tool_calls")

View File

@@ -7,7 +7,6 @@ import lombok.Data;
import java.io.Serializable;
/**
*
* @author https:www.unfbx.com
* @since 2023-03-02
*/

View File

@@ -11,7 +11,7 @@ import java.io.Serializable;
import java.util.List;
/**
* chat模型附带图片的参数
* chat模型附带图片的参数
*
* @author https:www.unfbx.com
* @since 1.1.2

View File

@@ -6,7 +6,6 @@ import lombok.*;
import lombok.extern.slf4j.Slf4j;
/**
*
* @author https://www.unfbx.com
* @since 1.1.2
* 2023-11-10

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FastGPTAnswerResponse {

View File

@@ -24,8 +24,9 @@ import java.io.Serializable;
* },
* }
* </pre>
*
* @author https:www.unfbx.com
* @since 2023-06-14
* @since 2023-06-14
*/
@Data
@Builder

View File

@@ -8,7 +8,6 @@ import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
*
* @author https://www.unfbx.com
* 2023-11-10
*/

View File

@@ -10,8 +10,6 @@ import java.io.Serializable;
import java.util.List;
/**
*
*
* @author https:www.unfbx.com
* @since 2023-03-02
*/
@@ -24,10 +22,6 @@ public class Message extends BaseMessage implements Serializable {
@JsonProperty("reasoning_content")
private String reasoningContent;
public static Builder builder() {
return new Builder();
}
/**
* 构造函数
*
@@ -57,6 +51,10 @@ public class Message extends BaseMessage implements Serializable {
super.setToolCallId(builder.toolCallId);
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private String role;
private String content;

View File

@@ -25,10 +25,6 @@ public class MessagePicture extends BaseMessage implements Serializable {
private List<Content> content;
public static Builder builder() {
return new Builder();
}
/**
* 构造函数
*
@@ -58,6 +54,10 @@ public class MessagePicture extends BaseMessage implements Serializable {
super.setToolCallId(builder.toolCallId);
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private String role;
private List<Content> content;

View File

@@ -5,8 +5,9 @@ import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 方法参数类扩展参数可以继承Parameters自己实现
* 方法参数类扩展参数可以继承Parameters自己实现
* 参考:
* <pre>
* {
@@ -21,8 +22,9 @@ import java.util.List;
* "required": ["location"]
* }
* </pre>
*
* @author https:www.unfbx.com
* @since 2023-06-14
* @since 2023-06-14
*/
@Data
@Builder

View File

@@ -7,9 +7,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -6,10 +6,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -5,11 +5,10 @@ import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -7,10 +7,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -10,7 +10,7 @@ import java.util.List;
import java.util.Map;
/**
* 问题类
* 问题类
*
* @author https:www.unfbx.com
* 2023-02-11
@@ -101,7 +101,8 @@ public class Completion implements Serializable {
/**
* 获取当前参数的tokens数
* @return token数量
*
* @return token数量
*/
// public long tokens() {
// if (StrUtil.isBlank(this.prompt) || StrUtil.isBlank(this.model)) {

View File

@@ -9,10 +9,10 @@ import org.ruoyi.common.chat.entity.common.Usage;
import java.io.Serializable;
/**
* 答案类
* 答案类
*
* @author https:www.unfbx.com
* 2023-02-11
* 2023-02-11
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -7,10 +7,8 @@ import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Getter
@Builder
@@ -35,7 +33,7 @@ public class Edit implements Serializable {
/**
* 使用什么取样温度0到2之间。较高的值(如0.8)将使输出更加随机,而较低的值(如0.2)将使输出更加集中和确定。
*
* <p>
* We generally recommend altering this or but not both.top_p
*/
@Builder.Default
@@ -43,7 +41,7 @@ public class Edit implements Serializable {
/**
* 使用温度采样的替代方法称为核心采样其中模型考虑具有top_p概率质量的令牌的结果。因此0.1 意味着只考虑包含前 10% 概率质量的代币。
*
* <p>
* 我们通常建议更改此设置但不要同时更改两者。temperature
*/
@JsonProperty("top_p")
@@ -90,6 +88,7 @@ public class Edit implements Serializable {
public void setInstruction(String instruction) {
this.instruction = instruction;
}
@Getter
@AllArgsConstructor
public enum Model {

View File

@@ -9,10 +9,8 @@ import org.ruoyi.common.chat.entity.common.Usage;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -9,10 +9,8 @@ import java.util.List;
import java.util.Objects;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Getter
@Slf4j

View File

@@ -8,10 +8,8 @@ import java.io.Serializable;
import java.util.List;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -6,10 +6,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -6,10 +6,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -6,10 +6,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -30,6 +30,7 @@ public class FineTune implements Serializable {
private String validationFile;
/**
* 参考
*
* @see Model
*/
private String model;
@@ -101,7 +102,7 @@ public class FineTune implements Serializable {
}
public void setSuffix(String suffix) {
if(Objects.nonNull(suffix) && !"".equals(suffix) && suffix.length() > 40){
if (Objects.nonNull(suffix) && !"".equals(suffix) && suffix.length() > 40) {
log.error("后缀长度不能大于40");
throw new BaseException(CommonError.PARAM_ERROR.msg());
}

View File

@@ -11,8 +11,6 @@ import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
*/

View File

@@ -11,10 +11,8 @@ import java.io.Serializable;
import java.util.Objects;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Getter
@Slf4j
@@ -48,11 +46,11 @@ public class ImageEdit implements Serializable {
private String user;
public ImageEdit setN(Integer n) {
if(n < 1){
if (n < 1) {
log.warn("n最小值1");
n = 1;
}
if(n > 10){
if (n > 10) {
log.warn("n最大值10");
n = 10;
}
@@ -61,11 +59,11 @@ public class ImageEdit implements Serializable {
}
public ImageEdit setPrompt(String prompt) {
if(Objects.isNull(prompt) || "".equals(prompt)){
if (Objects.isNull(prompt) || "".equals(prompt)) {
log.error("参数异常");
throw new BaseException(CommonError.PARAM_ERROR.msg());
}
if(prompt.length() > 1000){
if (prompt.length() > 1000) {
log.error("长度超过1000");
throw new BaseException(CommonError.PARAM_ERROR.msg());
}
@@ -74,7 +72,7 @@ public class ImageEdit implements Serializable {
}
public ImageEdit setSize(SizeEnum size) {
if(Objects.isNull(size)){
if (Objects.isNull(size)) {
size = SizeEnum.size_512;
}
this.size = size.getName();
@@ -82,7 +80,7 @@ public class ImageEdit implements Serializable {
}
public ImageEdit setResponseFormat(ResponseFormat responseFormat) {
if(Objects.isNull(responseFormat)){
if (Objects.isNull(responseFormat)) {
responseFormat = ResponseFormat.URL;
}
this.responseFormat = responseFormat.getName();

View File

@@ -7,10 +7,8 @@ import java.io.Serializable;
import java.util.List;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -12,10 +12,8 @@ import java.io.Serializable;
import java.util.Objects;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Getter
@Slf4j

View File

@@ -7,10 +7,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -6,10 +6,8 @@ import lombok.Getter;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@AllArgsConstructor
@Getter

View File

@@ -6,10 +6,8 @@ import lombok.Getter;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Getter
@AllArgsConstructor

View File

@@ -1,4 +1,5 @@
package org.ruoyi.common.chat.entity.models;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -13,8 +14,8 @@ public class LocalModelsSearchResponse {
private List<List<List<Double>>> topKEmbeddings; // 处理三层嵌套数组
// 默认构造函数
public LocalModelsSearchResponse() {}
public LocalModelsSearchResponse() {
}
}

View File

@@ -8,10 +8,8 @@ import java.io.Serializable;
import java.util.List;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -7,10 +7,8 @@ import java.io.Serializable;
import java.util.List;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -7,8 +7,6 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
*/

View File

@@ -7,10 +7,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -8,10 +8,8 @@ import java.io.Serializable;
import java.math.BigDecimal;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -10,10 +10,10 @@ import java.util.List;
import java.util.Objects;
/**
* 文本审核,敏感词鉴别
* 文本审核,敏感词鉴别
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Getter
@Builder

View File

@@ -7,10 +7,8 @@ import java.io.Serializable;
import java.util.List;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -7,10 +7,8 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-15
* 2023-02-15
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)

View File

@@ -7,7 +7,7 @@ import lombok.Getter;
import java.io.Serializable;
/**
* 语音转文字
* 语音转文字
*
* @author https:www.unfbx.com
* @since 2023-03-02

View File

@@ -6,8 +6,6 @@ import lombok.Data;
import java.io.Serializable;
/**
*
*
* @author https:www.unfbx.com
* @since 2023-03-02
*/

View File

@@ -47,7 +47,7 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
if (StrUtil.isNotBlank(messageContext)) {
messages = JSONUtil.toList(messageContext, Message.class);
// 上下文长度
int contextSize=10;
int contextSize = 10;
if (messages.size() >= contextSize) {
messages = messages.subList(1, contextSize);
}
@@ -58,13 +58,13 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
messages.add(currentMessage);
}
ChatCompletion chatCompletion = ChatCompletion
.builder()
.model("gpt-4o-mini")
.messages(messages)
.temperature(0.2)
.stream(true)
.build();
OpenAiStreamClient openAiStreamClient=(OpenAiStreamClient) SpringUtils.context().getBean("openAiStreamClient");
.builder()
.model("gpt-4o-mini")
.messages(messages)
.temperature(0.2)
.stream(true)
.build();
OpenAiStreamClient openAiStreamClient = (OpenAiStreamClient) SpringUtils.context().getBean("openAiStreamClient");
openAiStreamClient.streamChatCompletion(chatCompletion, eventSourceListener);
LocalCache.CACHE.put(session.getId(), JSONUtil.toJsonStr(messages), LocalCache.TIMEOUT);
}

View File

@@ -14,7 +14,7 @@ import org.springframework.web.socket.WebSocketSession;
import java.util.Objects;
/**
* OpenAI流式输出Socket接收
* OpenAI流式输出Socket接收
*
* @author https:www.unfbx.com
* @date 2023-03-23
@@ -22,12 +22,11 @@ import java.util.Objects;
@Slf4j
public class WebSocketEventListener extends EventSourceListener {
private WebSocketSession session;
/**
* 消息结束标识
*/
private final String msgEnd = "[DONE]";
private WebSocketSession session;
public WebSocketEventListener(WebSocketSession session) {
this.session = session;
@@ -59,8 +58,8 @@ public class WebSocketEventListener extends EventSourceListener {
String delta = "";
try {
delta = mapper.writeValueAsString(completionResponse.getChoices().get(0).getDelta());
}catch (Exception e){
log.error("转换失败{}",e.getMessage());
} catch (Exception e) {
log.error("转换失败{}", e.getMessage());
}
session.sendMessage(new TextMessage(delta));
}

View File

@@ -40,7 +40,7 @@ import java.time.LocalDate;
import java.util.Map;
/**
* open ai官方api接口
* open ai官方api接口
*
* @author https:www.unfbx.com
* 2023-02-15
@@ -58,7 +58,7 @@ public interface OpenAiApi {
/**
* models 返回的数据id
*
* @param id 模型主键
* @param id 模型主键
* @return Single Model
*/
@GET("v1/models/{id}")
@@ -317,7 +317,7 @@ public interface OpenAiApi {
/**
* 账户信息查询:里面包含总金额(美元)等信息
*
* @return 账户信息
* @return 账户信息
*/
@GET("v1/dashboard/billing/subscription")
Single<Subscription> subscription();

View File

@@ -56,7 +56,7 @@ import java.util.concurrent.TimeUnit;
/**
* open ai 客户端
* open ai 客户端
*
* @author https:www.unfbx.com
* @since 2023-02-11
@@ -100,15 +100,6 @@ public class OpenAiClient {
@Getter
private OpenAiAuthInterceptor authInterceptor;
/**
* 构造器
*
* @return OpenAiClient.Builder
*/
public static Builder builder() {
return new Builder();
}
/**
* 构造
*
@@ -156,6 +147,14 @@ public class OpenAiClient {
.build().create(OpenAiApi.class);
}
/**
* 构造器
*
* @return OpenAiClient.Builder
*/
public static Builder builder() {
return new Builder();
}
/**
* 创建默认OkHttpClient
@@ -681,7 +680,7 @@ public class OpenAiClient {
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("file", file.getName(), fileBody);
//自定义参数
Map<String, RequestBody> requestBodyMap = new HashMap<>(5,1L);
Map<String, RequestBody> requestBodyMap = new HashMap<>(5, 1L);
if (StrUtil.isNotBlank(translations.getModel())) {
requestBodyMap.put(Translations.Fields.model, RequestBody.create(MediaType.parse("multipart/form-data"), translations.getModel()));
@@ -812,6 +811,7 @@ public class OpenAiClient {
Single<Subscription> subscription = this.openAiApi.subscription();
return subscription.blockingGet();
}
/**
* 账户调用接口消耗金额信息查询
* 最多查询100天
@@ -833,7 +833,6 @@ public class OpenAiClient {
private @NotNull List<String> apiKey;
/**
* api请求地址结尾处有斜杠
*
*/
private String apiHost;
/**

View File

@@ -52,7 +52,7 @@ import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* open ai 客户端
* open ai 客户端
*
* @author https:www.unfbx.com
* 2023-02-28
@@ -63,31 +63,27 @@ import java.util.concurrent.TimeUnit;
@Setter
public class OpenAiStreamClient {
private static final String DONE_SIGNAL = "[DONE]";
@NotNull
private List<String> apiKey;
/**
* 自定义api host使用builder的方式构造client
*/
private String apiHost;
/**
* 自定义url 兼容多个平台
*/
private String apiUrl;
/**
* 自定义的okHttpClient
* 如果不自定义 就是用sdk默认的OkHttpClient实例
*/
private OkHttpClient okHttpClient;
/**
* api key的获取策略
*/
private KeyStrategyFunction<List<String>, String> keyStrategy;
private OpenAiApi openAiApi;
/**
* 自定义鉴权处理拦截器<br/>
* 可以不设置默认实现DefaultOpenAiAuthInterceptor <br/>
@@ -98,8 +94,6 @@ public class OpenAiStreamClient {
*/
private OpenAiAuthInterceptor authInterceptor;
private static final String DONE_SIGNAL = "[DONE]";
/**
* 构造实例对象
*
@@ -139,9 +133,9 @@ public class OpenAiStreamClient {
} else {
//自定义的okhttpClient 需要增加api keys
builder.okHttpClient = builder.okHttpClient
.newBuilder()
.addInterceptor(authInterceptor)
.build();
.newBuilder()
.addInterceptor(authInterceptor)
.build();
}
okHttpClient = builder.okHttpClient;
if (apiHost.endsWith("/")) {
@@ -155,6 +149,15 @@ public class OpenAiStreamClient {
}
/**
* 构造
*
* @return Builder
*/
public static Builder builder() {
return new Builder();
}
/**
* 创建默认的OkHttpClient
*/
@@ -165,16 +168,15 @@ public class OpenAiStreamClient {
this.authInterceptor.setApiKey(this.apiKey);
this.authInterceptor.setKeyStrategy(this.keyStrategy);
OkHttpClient okHttpClient = new OkHttpClient
.Builder()
.addInterceptor(this.authInterceptor)
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(50, TimeUnit.SECONDS)
.readTimeout(50, TimeUnit.SECONDS)
.build();
.Builder()
.addInterceptor(this.authInterceptor)
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(50, TimeUnit.SECONDS)
.readTimeout(50, TimeUnit.SECONDS)
.build();
return okHttpClient;
}
/**
* 流式输出最新版的GPT-3.5 chat completion 更加贴近官方网站的问答模型
*
@@ -191,9 +193,9 @@ public class OpenAiStreamClient {
ObjectMapper mapper = new ObjectMapper();
String requestBody = mapper.writeValueAsString(chatCompletion);
Request request = new Request.Builder()
.url(this.apiHost)
.post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody))
.build();
.url(this.apiHost)
.post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody))
.build();
factory.newEventSource(request, eventSourceListener);
} catch (Exception e) {
log.error("请求参数解析异常:{}", e.getMessage());
@@ -238,7 +240,6 @@ public class OpenAiStreamClient {
this.streamChatCompletion(chatCompletion, pluginEventSourceListener);
}
/**
* 插件问答简易版
* 默认取messages最后一个元素构建插件对话
@@ -255,7 +256,6 @@ public class OpenAiStreamClient {
this.streamChatCompletionWithPlugin(chatCompletion, eventSourceListener, pluginEventSourceListener, plugin);
}
/**
* 插件问答简易版
* 默认取messages最后一个元素构建插件对话
@@ -287,7 +287,6 @@ public class OpenAiStreamClient {
this.streamChatCompletionWithPlugin(chatCompletion, eventSourceListener, plugin);
}
/**
* 根据描述生成图片
*
@@ -457,6 +456,7 @@ public class OpenAiStreamClient {
Transcriptions transcriptions = Transcriptions.builder().build();
return this.speechToTextTranscriptions(file, transcriptions);
}
/**
* 文本转语音(异步)
*
@@ -475,12 +475,12 @@ public class OpenAiStreamClient {
* @param textToSpeech 参数
* @since 1.1.3
*/
public ResponseBody textToSpeech(TextToSpeech textToSpeech){
public ResponseBody textToSpeech(TextToSpeech textToSpeech) {
try {
Call<ResponseBody> responseBody = this.openAiApi.textToSpeech(textToSpeech);
return responseBody.execute().body();
} catch (IOException e) {
throw new BaseException("文本转语音(同步)失败: "+e.getMessage());
throw new BaseException("文本转语音(同步)失败: " + e.getMessage());
}
}
@@ -508,13 +508,13 @@ public class OpenAiStreamClient {
// 创建请求对象
Request request = new Request.Builder()
.url(url)
.build();
.url(url)
.build();
// 发送请求并处理响应
try {
return client.newCall(request).execute().body();
} catch (IOException e) {
throw new BaseException("语音克隆失败!{}",e.getMessage());
throw new BaseException("语音克隆失败!{}", e.getMessage());
}
}
@@ -602,16 +602,6 @@ public class OpenAiStreamClient {
return this.chatCompletionWithPlugin(chatCompletion, plugin);
}
/**
* 构造
*
* @return Builder
*/
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private @NotNull List<String> apiKey;
/**

View File

@@ -6,27 +6,27 @@ import java.io.IOException;
public class TestOpenAIAPI {
private final OkHttpClient client = new OkHttpClient();
private static final String API_KEY = "sk-Waea254YSRYVg4FZVCz2CDz73B22xRpmKpJ41kbczVgpPxvg";
private static final String URL = "https://api.gptgod.online/v1/chat/completions";
public void getChatGptResponse(String prompt) throws IOException {
RequestBody body = RequestBody.create(MediaType.get("application/json; charset=utf-8"),
"{\"model\": \"gpt-3.5-turbo\", \"messages\": [{\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, {\"role\": \"user\", \"content\": \"" + prompt + "\"}]}");
Request request = new Request.Builder()
.url(URL)
.post(body)
.addHeader("Authorization", "Bearer " + API_KEY)
.build();
try (Response response = client.newCall(request).execute()) {
}
}
private final OkHttpClient client = new OkHttpClient();
public static void main(String[] args) throws IOException {
TestOpenAIAPI api = new TestOpenAIAPI();
api.getChatGptResponse("Hello, how are you?");
}
public void getChatGptResponse(String prompt) throws IOException {
RequestBody body = RequestBody.create(MediaType.get("application/json; charset=utf-8"),
"{\"model\": \"gpt-3.5-turbo\", \"messages\": [{\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, {\"role\": \"user\", \"content\": \"" + prompt + "\"}]}");
Request request = new Request.Builder()
.url(URL)
.post(body)
.addHeader("Authorization", "Bearer " + API_KEY)
.build();
try (Response response = client.newCall(request).execute()) {
}
}
}

View File

@@ -1,10 +1,10 @@
package org.ruoyi.common.chat.openai.exception;
/**
* 错误
* 错误
*
* @author https:www.unfbx.com
* 2023-02-11
* 2023-02-11
*/
public enum CommonError implements IError {
MESSAGE_NOT_NUL(500, "Message 不能为空"),
@@ -15,7 +15,7 @@ public enum CommonError implements IError {
RETRY_ERROR(502, "请求异常,请重试~"),
//官方的错误码列表https://platform.openai.com/docs/guides/error-codes/api-errors
OPENAI_AUTHENTICATION_ERROR(401, "身份验证无效/提供的 API 密钥不正确/您必须是组织的成员才能使用 API"),
OPENAI_LIMIT_ERROR(429 , "达到请求的速率限制/您超出了当前配额,请检查您的计划和帐单详细信息/发动机当前过载,请稍后重试"),
OPENAI_LIMIT_ERROR(429, "达到请求的速率限制/您超出了当前配额,请检查您的计划和帐单详细信息/发动机当前过载,请稍后重试"),
OPENAI_SERVER_ERROR(500, "服务器在处理您的请求时出错"),
;

View File

@@ -1,9 +1,8 @@
package org.ruoyi.common.chat.openai.exception;
/**
*
*
* @author https:www.unfbx.com
* 2023-02-11
* 2023-02-11
*/
public interface IError {
String msg();

View File

@@ -5,7 +5,7 @@ import cn.hutool.core.util.RandomUtil;
import java.util.List;
/**
* 随机策略
* 随机策略
*
* @author https:www.unfbx.com
* @since 2023-04-03

View File

@@ -3,11 +3,11 @@ package org.ruoyi.common.chat.openai.function;
import java.util.function.Function;
/**
* key 的获取策略
* key 的获取策略
* jdk默认实现
* @see Function
*
* @author https:www.unfbx.com
* @see Function
* @since 2023-04-03
*/
@FunctionalInterface

View File

@@ -9,7 +9,7 @@ import java.util.List;
import java.util.Map;
/**
* 请求增加header apikey
* 请求增加header apikey
*
* @author https:www.unfbx.com
* @since 2023-03-23

View File

@@ -16,7 +16,7 @@ import java.util.Objects;
import java.util.stream.Collectors;
/**
* 动态处理key的鉴权拦截器
* 动态处理key的鉴权拦截器
*
* @author https:www.unfbx.com
* @since 2023-04-25
@@ -35,7 +35,6 @@ public class DynamicKeyOpenAiAuthInterceptor extends OpenAiAuthInterceptor {
/**
* 请求头处理
*
*/
public DynamicKeyOpenAiAuthInterceptor() {
this.setWarringConfig(null);

View File

@@ -4,7 +4,7 @@ import lombok.extern.slf4j.Slf4j;
import okhttp3.logging.HttpLoggingInterceptor;
/**
* 日志
* 日志
*
* @author https:www.unfbx.com
* 2023-02-28

View File

@@ -13,10 +13,10 @@ import java.io.IOException;
import java.util.Objects;
/**
* openai 返回值处理Interceptor
* openai 返回值处理Interceptor
*
* @author https:www.unfbx.com
* @since 2023-03-23
* @since 2023-03-23
*/
@Slf4j
public class OpenAiResponseInterceptor implements Interceptor {

View File

@@ -69,6 +69,10 @@ public abstract class PluginAbstract<R extends PluginParam, T> {
setParameters();
}
public abstract T func(R args);
public abstract String content(T t);
@Data
public static class Arg {
private String name;
@@ -81,8 +85,4 @@ public abstract class PluginAbstract<R extends PluginParam, T> {
@JsonIgnore
private boolean required;
}
public abstract T func(R args);
public abstract String content(T t);
}

View File

@@ -7,7 +7,7 @@ import org.ruoyi.common.chat.entity.chat.Message;
import java.util.List;
/**
* 对话请求对象
* 对话请求对象
*
* @author ageerle
* @sine 2023-04-08

View File

@@ -4,8 +4,6 @@ import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
/**
*
*
* @author https:www.unfbx.com
* @sine 2023-04-08
*/
@@ -18,15 +16,21 @@ public class Dall3Request {
@NotEmpty(message = "提示词不能为空")
private String prompt;
/** 图片大小 */
/**
* 图片大小
*/
@NotEmpty(message = "图片大小不能为空")
private String size ;
private String size;
/** 图片质量 */
/**
* 图片质量
*/
@NotEmpty(message = "图片质量不能为空")
private String quality;
/** 图片风格 */
/**
* 图片风格
*/
@NotEmpty(message = "图片风格不能为空")
private String style;

View File

@@ -10,7 +10,7 @@ import okhttp3.sse.EventSourceListener;
import java.util.Objects;
/**
* sse
* sse
*
* @author https:www.unfbx.com
* 2023-02-28
@@ -39,7 +39,7 @@ public class ConsoleEventSourceListener extends EventSourceListener {
@SneakyThrows
@Override
public void onFailure(EventSource eventSource, Throwable t, Response response) {
if(Objects.isNull(response)){
if (Objects.isNull(response)) {
log.error("OpenAI sse连接异常:{}", t);
eventSource.cancel();
return;

View File

@@ -7,7 +7,7 @@ import org.ruoyi.common.chat.openai.OpenAiStreamClient;
import org.ruoyi.common.chat.openai.plugin.PluginAbstract;
/**
* 插件开发返回信息收集sse监听器
* 插件开发返回信息收集sse监听器
*
* @author https:www.unfbx.com
* 2023-08-18

View File

@@ -19,7 +19,7 @@ import org.ruoyi.common.chat.openai.plugin.PluginParam;
import java.util.Objects;
/**
* 插件开发返回信息收集sse监听器
* 插件开发返回信息收集sse监听器
*
* @author https:www.unfbx.com
* 2023-08-18
@@ -30,21 +30,10 @@ public abstract class PluginListener<R extends PluginParam, T> extends EventSour
* openAi插件构建的参数
*/
private String arguments = "";
/**
* 获取openAi插件构建的参数
*
* @return arguments
*/
private String getArguments() {
return this.arguments;
}
private OpenAiStreamClient client;
private EventSourceListener eventSourceListener;
private PluginAbstract<R, T> plugin;
private ChatCompletion chatCompletion;
/**
* 构造方法必备四个元素
*
@@ -60,6 +49,15 @@ public abstract class PluginListener<R extends PluginParam, T> extends EventSour
this.chatCompletion = chatCompletion;
}
/**
* 获取openAi插件构建的参数
*
* @return arguments
*/
private String getArguments() {
return this.arguments;
}
/**
* sse关闭后处理第二次请求方法
*/

View File

@@ -15,7 +15,7 @@ import org.ruoyi.common.chat.entity.chat.Message;
import java.util.*;
/**
* token计算工具类
* token计算工具类
*
* @author https:www.unfbx.com
* @since 2023-04-04
@@ -152,7 +152,7 @@ public class TikTokensUtil {
}
Encoding enc = getEncoding(modelName);
if (Objects.isNull(enc)) {
log.warn("[{}]模型不存在或者暂不支持计算tokens直接返回tokens==0",modelName);
log.warn("[{}]模型不存在或者暂不支持计算tokens直接返回tokens==0", modelName);
return new ArrayList<>();
}
return enc.encode(text);
@@ -184,25 +184,25 @@ public class TikTokensUtil {
int tokensPerMessage = 0;
int tokensPerName = 0;
if (modelName.equals(ChatCompletion.Model.GPT_3_5_TURBO_0613.getName())
|| modelName.equals(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_0613.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_32K_0613.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName())
|| modelName.equals(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_0613.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_32K_0613.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_1106_PREVIEW.getName())
|| modelName.equals(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName())
) {
tokensPerMessage = 3;
tokensPerName = 1;
}else if(modelName.contains(ChatCompletion.Model.GPT_3_5_TURBO.getName())){
} else if (modelName.contains(ChatCompletion.Model.GPT_3_5_TURBO.getName())) {
//"gpt-3.5-turbo" in model:
log.warn("Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.");
tokensPerMessage = 3;
tokensPerName = 1;
}else if(modelName.contains(ChatCompletion.Model.GPT_4.getName())){
} else if (modelName.contains(ChatCompletion.Model.GPT_4.getName())) {
log.warn("Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.");
tokensPerMessage = 3;
tokensPerName = 1;
}else {
log.warn("不支持的model {} 按gpt4计算tokens",modelName);
} else {
log.warn("不支持的model {} 按gpt4计算tokens", modelName);
tokensPerMessage = 3;
tokensPerName = 1;
}

View File

@@ -70,7 +70,7 @@ public class WebSocketUtils {
broadcastMessage.setSessionKeys(unsentSessionKeys);
RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> {
log.info(" WebSocket发送主题订阅消息topic:{} session keys:{} message:{}",
WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage());
WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage());
});
}
}

View File

@@ -1,6 +1,6 @@
<?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"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.ruoyi</groupId>

View File

@@ -43,7 +43,7 @@ public class AsyncConfig implements AsyncConfigurer {
throwable.printStackTrace();
StringBuilder sb = new StringBuilder();
sb.append("Exception message - ").append(throwable.getMessage())
.append(", Method name - ").append(method.getName());
.append(", Method name - ").append(method.getName());
if (ArrayUtil.isNotEmpty(objects)) {
sb.append(", Parameter value - ").append(Arrays.toString(objects));
}

View File

@@ -16,31 +16,27 @@ import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "ruoyi")
public class RuoYiConfig {
/**
* 项目名称
*/
private String name;
/**
* 版本
*/
private String version;
/**
* 版权年份
*/
private String copyrightYear;
/**
* 实例演示开关
*/
private boolean demoEnabled;
/**
* 获取地址开关
*/
@Getter
private static boolean addressEnabled;
/**
* 项目名称
*/
private String name;
/**
* 版本
*/
private String version;
/**
* 版权年份
*/
private String copyrightYear;
/**
* 实例演示开关
*/
private boolean demoEnabled;
public void setAddressEnabled(boolean addressEnabled) {
RuoYiConfig.addressEnabled = addressEnabled;

View File

@@ -48,8 +48,8 @@ public class ThreadPoolConfig {
public ScheduledExecutorService scheduledExecutorService() {
log.info("====创建定时任务线程池====");
return new ScheduledThreadPoolExecutor(core,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
new ThreadPoolExecutor.CallerRunsPolicy()) {
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
new ThreadPoolExecutor.CallerRunsPolicy()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);

View File

@@ -16,19 +16,16 @@ import java.io.Serializable;
@NoArgsConstructor
public class R<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 成功
*/
public static final int SUCCESS = 200;
/**
* 失败
*/
public static final int FAIL = 500;
@Serial
private static final long serialVersionUID = 1L;
private int code;
private String msg;
@@ -84,7 +81,7 @@ public class R<T> implements Serializable {
/**
* 返回警告消息
*
* @param msg 返回内容
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/

View File

@@ -21,7 +21,7 @@ public class LoginBody {
* 用户名
*/
@NotBlank(message = "{user.username.not.blank}")
// @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
// @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
private String username;
/**

View File

@@ -3,7 +3,7 @@ package org.ruoyi.common.core.event;
import org.springframework.context.ApplicationEvent;
/**
* 定义一个事件类,用于通知配置变化
* 定义一个事件类,用于通知配置变化
*
* @author ageerle@163.com
* date 2024/5/19

View File

@@ -1,6 +1,6 @@
package org.ruoyi.common.core.exception;
public class AuthException extends RuntimeException{
public class AuthException extends RuntimeException {
private static final long serialVersionUID = 1L;

View File

@@ -46,22 +46,22 @@ public final class ServiceException extends RuntimeException {
return detailMessage;
}
public ServiceException setDetailMessage(String detailMessage) {
this.detailMessage = detailMessage;
return this;
}
@Override
public String getMessage() {
return message;
}
public Integer getCode() {
return code;
}
public ServiceException setMessage(String message) {
this.message = message;
return this;
}
public ServiceException setDetailMessage(String detailMessage) {
this.detailMessage = detailMessage;
return this;
public Integer getCode() {
return code;
}
}

View File

@@ -1,7 +1,6 @@
package org.ruoyi.common.core.manager;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.core.utils.Threads;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -7,19 +7,20 @@ package org.ruoyi.common.core.service;
public class BaseContext {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
/**
* @description: 获取值
* @author: yzm
**/
public static String getCurrentToken() {
return threadLocal.get();
}
/**
* @description: 设置值
* @author: yzm
* @param: [token] 线程token
**/
public static void setCurrentToken(String token){
public static void setCurrentToken(String token) {
threadLocal.set(token);
}
/**
* @description: 获取值
* @author: yzm
**/
public static String getCurrentToken(){
return threadLocal.get();
}
}

View File

@@ -13,8 +13,7 @@ public interface ConfigService {
* @param configKey
* @return
*/
String getConfigValue(String category,String configKey);
String getConfigValue(String category, String configKey);
}

View File

@@ -29,9 +29,9 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static final String[] PARSE_PATTERNS = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
/**
* 获取当前Date型日期

View File

@@ -17,7 +17,7 @@ public class ObjectUtils extends ObjectUtil {
/**
* 如果对象不为空,则获取对象中的某个字段 ObjectUtils.notNullGetter(user, User::getName);
*
* @param obj 对象
* @param obj 对象
* @param func 获取方法
* @return 对象字段
*/

View File

@@ -12,17 +12,16 @@ import java.util.concurrent.TimeUnit;
@Component
public class OkHttpUtil {
private final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(3000, TimeUnit.SECONDS)
.writeTimeout(3000, TimeUnit.SECONDS)
.readTimeout(3000, TimeUnit.SECONDS)
.build();
@Setter
private String apiHost;
@Setter
private String apiKey;
private final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(3000, TimeUnit.SECONDS)
.writeTimeout(3000, TimeUnit.SECONDS)
.readTimeout(3000, TimeUnit.SECONDS)
.build();
public String executeRequest(Request request) {
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
@@ -40,16 +39,16 @@ public class OkHttpUtil {
MediaType JSON = MediaType.get("application/json; charset=utf-8");
RequestBody body = RequestBody.create(json, JSON);
return new Request.Builder()
.url(apiHost + url)
.post(body)
.header("Authorization", apiKey)
.build();
.url(apiHost + url)
.post(body)
.header("Authorization", apiKey)
.build();
}
public Request createGetRequest(String url) {
return new Request.Builder()
.url(apiHost + url)
.header("Authorization", apiKey)
.build();
.url(apiHost + url)
.header("Authorization", apiKey)
.build();
}
}

Some files were not shown because too many files have changed in this diff Show More