diff --git a/README.md b/README.md index b0d141db6..57df75e2b 100644 --- a/README.md +++ b/README.md @@ -1,400 +1,143 @@ -

- Coverage Status - Downloads - Downloads - Downloads -

+# YuDao Asset Cloud - 资产管理系统 + +基于 YuDao Cloud 重构的资产管理系统。 + +## 技术栈 + +- **后端**: Spring Boot 3.5 + Spring Cloud 2024 + JDK 17 +- **数据库**: MySQL 8.0 + Redis 7.0 +- **注册中心**: Nacos 2.3 +- **工作流**: Flowable +- **定时任务**: XXL-Job 2.4 +- **前端**: Vue3 + Vben Admin + +## 项目结构 + +``` +yudao-asset-cloud/ +├── yudao-dependencies/ # 依赖管理 +├── yudao-framework/ # 框架核心 +├── yudao-gateway/ # 网关 +├── yudao-server/ # 单体启动(开发用) +├── yudao-module-system/ # 系统管理模块 +├── yudao-module-infra/ # 基础设施模块 +├── yudao-module-bpm/ # 工作流模块 +├── yudao-module-asset/ # 资产管理模块 ⭐ +│ ├── yudao-module-asset-api/ # API 接口 +│ └── yudao-module-asset-biz/ # 业务实现 +├── sql/ # 数据库脚本 +└── docker-compose.yml # Docker 编排 +``` + +## 核心功能 + +### 第一阶段(已规划) +1. **基础数据**: 车辆、客户、停车场 +2. **备车管理**: 车辆整备、检查项配置 +3. **合同管理**: 合同创建、审批流 +4. **交车管理**: 任务派发、交车作业 +5. **还车管理**: 还车作业、费用结算 +6. **替换车管理**: 临时/永久替换 + +## 快速开始 + +### 1. 启动基础环境 + +```bash +# 启动 MySQL + Redis + Nacos + XXL-Job +docker-compose up -d + +# 查看服务状态 +docker-compose ps +``` + +### 2. 初始化数据库 + +```bash +# 导入 YuDao 基础表 +mysql -h127.0.0.1 -uroot -p123456 ruoyi-vue-pro < sql/mysql/ruoyi-vue-pro.sql + +# 导入资产管理表 +mysql -h127.0.0.1 -uroot -p123456 ruoyi-vue-pro < sql/asset-schema.sql +``` + +### 3. 启动后端服务 + +```bash +# 方式一:IDEA 启动(推荐开发) +# 运行 AssetServerApplication.java + +# 方式二:Maven 启动 +cd yudao-module-asset/yudao-module-asset-biz +mvn spring-boot:run +``` + +### 4. 访问地址 + +- **Nacos 控制台**: http://localhost:8848/nacos (nacos/nacos) +- **XXL-Job 控制台**: http://localhost:9090/xxl-job-admin (admin/123456) +- **后端 API**: http://localhost:48083 +- **测试接口**: http://localhost:48083/admin-api/asset/truck/test + +## 开发规范 + +### 数据库表命名 +- 统一前缀: `asset_` +- 示例: `asset_truck`, `asset_contract` + +### 包结构 +``` +cn.iocoder.yudao.module.asset/ +├── controller/admin/ # 管理后台控制器 +├── controller/app/ # 移动端控制器(可选) +├── service/ # 服务层 +├── dal/ +│ ├── dataobject/ # DO 实体 +│ ├── mysql/ # Mapper +│ └── redis/ # Redis 操作 +├── convert/ # 对象转换 +└── enums/ # 枚举 +``` + +### 代码生成 +使用 YuDao 代码生成器快速生成 CRUD 代码。 + +## 部署 + +### 开发环境 +- **服务器**: 47.103.115.36 (Ubuntu 24.04) +- **部署方式**: Docker Compose + +```bash +# 上传项目到服务器 +scp -r yudao-asset-cloud root@47.103.115.36:/opt/ + +# SSH 登录服务器 +ssh root@47.103.115.36 + +# 启动服务 +cd /opt/yudao-asset-cloud +docker-compose up -d +``` + +## 项目进度 + +- [x] 项目初始化 +- [x] 模块结构搭建 +- [x] 数据库设计 +- [x] Docker 环境配置 +- [ ] 车辆管理 CRUD +- [ ] 备车功能 +- [ ] 合同管理 +- [ ] 交车功能 +- [ ] 还车功能 +- [ ] 替换车功能 -**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!!** +## 文档 -**「我喜欢写代码,乐此不疲」** -**「我喜欢做开源,以此为乐」** +- [YuDao Cloud 官方文档](https://cloud.iocoder.cn) +- [项目需求文档](../memory/2026-03-11-资产管理系统重构.md) -我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。 +## 联系方式 -如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。 - -可参考 [《迁移文档》](https://cloud.iocoder.cn/migrate-module/) ,只需要 5-10 分钟,即可将【完整版】按需迁移到【精简版】 - -## 🐶 新手必读 - -* 演示地址【Vue3 + element-plus】: -* 演示地址【Vue3 + vben(ant-design-vue)】: -* 演示地址【Vue2 + element-ui】: -* 启动文档: -* 视频教程: - -## 🐰 版本说明 - -| 版本 | JDK 8 + Spring Boot 2.7 | JDK 17/21 + Spring Boot 3.2 | -|-----------------------------------------------------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------------------| -| 【完整版】[yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [`master`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master-jdk17/) 分支 | -| 【精简版】[yudao-cloud-mini](https://gitee.com/yudaocode/yudao-cloud-mini) | [`master`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master-jdk17/) 分支 | - -* 【完整版】:包括系统功能、基础设施、会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP 等功能 -* 【精简版】:只包括系统功能、基础设施功能,不包括会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP 等功能 - -可参考 [《迁移文档》](https://cloud.iocoder.cn/migrate-module/) ,只需要 5-10 分钟,即可将【完整版】按需迁移到【精简版】 - -## 🐯 平台简介 - -**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。 - -> 有任何问题,或者想要的功能,可以在 _Issues_ 中提给艿艿。 -> -> 😜 给项目点点 Star 吧,这对我们真的很重要! - -![架构图](/.image/common/yudao-cloud-architecture.png) - -* Java 后端:`master` 分支为 JDK 8 + Spring Boot 2.7,`master-jdk17` 分支为 JDK 17/21 + Spring Boot 3.2 -* 管理后台的电脑端:Vue3 提供 [element-plus](https://gitee.com/yudaocode/yudao-ui-admin-vue3)、[vben(ant-design-vue)](https://gitee.com/yudaocode/yudao-ui-admin-vben) 两个版本,Vue2 提供 [element-ui](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) 版本 -* 管理后台的移动端:采用 [uni-app](https://github.com/dcloudio/uni-app) 方案,一份代码多终端适配,同时支持 APP、小程序、H5! -* 后端采用 Spring Cloud Alibaba 微服务架构,注册中心 + 配置中心 Nacos,定时任务 XXL-Job,服务保障 Sentinel,服务网关 Gateway,分布式事务 Seata -* 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等,基于 MyBatis Plus、Redis + Redisson 操作 -* 消息队列可使用 Event、Redis、RabbitMQ、Kafka、RocketMQ 等 -* 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录 -* 支持加载动态权限菜单,按钮级别权限控制,Redis 缓存提升性能 -* 支持 SaaS 多租户,可自定义每个租户的权限,提供透明化的多租户底层封装 -* 工作流使用 Flowable,支持动态表单、在线设计流程、会签 / 或签、多种任务分配方式 -* 高效率开发,使用代码生成器可以一键生成 Java、Vue 前后端代码、SQL 脚本、接口文档,支持单表、树表、主子表 -* 实时通信,采用 Spring WebSocket 实现,内置 Token 身份校验,支持 WebSocket 集群 -* 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款 -* 集成阿里云、腾讯云等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务 -* 集成报表设计器、大屏设计器,通过拖拽即可生成酷炫的报表与大屏 - -## 🐳 项目关系 - -![架构演进](/.image/common/yudao-roadmap.png) - -三个项目的功能对比,可见社区共同整理的 [国产开源项目对比](https://www.yuque.com/xiatian-bsgny/lm0ec1/wqf8mn) 表格。 - -### 后端项目 - -| 项目 | Star | 简介 | -|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------| -| [ruoyi-vue-pro](https://gitee.com/zhijiantianya/ruoyi-vue-pro) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro) | 基于 Spring Boot 多模块架构 | -| [yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [![Gitee star](https://gitee.com/zhijiantianya/yudao-cloud/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/yudao-cloud) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/yudao-cloud.svg?style=social&label=Stars)](https://github.com/YunaiV/yudao-cloud) | 基于 Spring Cloud 微服务架构 | -| [Spring-Boot-Labs](https://gitee.com/yudaocode/SpringBoot-Labs) | [![Gitee star](https://gitee.com/yudaocode/SpringBoot-Labs/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/yudao-cloud) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/SpringBoot-Labs.svg?style=social&label=Stars)](https://github.com/yudaocode/SpringBoot-Labs) | 系统学习 Spring Boot & Cloud 专栏 | - -### 前端项目 - -| 项目 | Star | 简介 | -|----------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------| -| [yudao-ui-admin-vue3](https://gitee.com/yudaocode/yudao-ui-admin-vue3) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vue3/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vue3) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vue3.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vue3) | 基于 Vue3 + element-plus 实现的管理后台 | -| [yudao-ui-admin-vben](https://gitee.com/yudaocode/yudao-ui-admin-vben) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vben/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vben) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vben.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vben) | 基于 Vue3 + vben(ant-design-vue) 实现的管理后台 | -| [yudao-mall-uniapp](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 | -| [yudao-ui-admin-vue2](https://gitee.com/yudaocode/yudao-ui-admin-vue2) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vue2/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vue2) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vue2.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vue2) | 基于 Vue2 + element-ui 实现的管理后台 | -| [yudao-ui-admin-uniapp](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-uniapp) | 基于 Vue2 + element-ui 实现的管理后台 | -| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 | - -## 😎 开源协议 - -**为什么推荐使用本项目?** - -① 本项目采用比 Apache 2.0 更宽松的 [MIT License](https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/LICENSE) 开源协议,个人与企业可 100% 免费使用,不用保留类作者、Copyright 信息。 - -② 代码全部开源,不会像其他项目一样,只开源部分代码,让你无法了解整个项目的架构设计。[国产开源项目对比](https://www.yuque.com/xiatian-bsgny/lm0ec1/wqf8mn) - -![开源项目对比](/.image/common/project-vs.png) - -③ 代码整洁、架构整洁,遵循《阿里巴巴 Java 开发手册》规范,代码注释详细,113770 行 Java 代码,42462 行代码注释。 - -## 🤝 项目外包 - -我们也是接外包滴,如果你有项目想要外包,可以微信联系【**Aix9975**】。 - -团队包含专业的项目经理、架构师、前端工程师、后端工程师、测试工程师、运维工程师,可以提供全流程的外包服务。 - -项目可以是商城、SCRM 系统、OA 系统、物流系统、ERP 系统、CMS 系统、HIS 系统、支付系统、IM 聊天、微信公众号、微信小程序等等。 - -## 🐼 内置功能 - -系统内置多种多种业务功能,可以用于快速你的业务系统: - -![功能分层](/.image/common/ruoyi-vue-pro-biz.png) - -* 通用模块(必选):系统功能、基础设施 -* 通用模块(可选):工作流程、支付系统、数据报表、会员中心 -* 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号、AI 大模型 - -> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。 -> -> * 额外新增的功能,我们使用 🚀 标记。 -> * 重新实现的功能,我们使用 ⭐️ 标记。 - -🙂 所有功能,都通过 **单元测试** 保证高质量。 - -### 系统功能 - -| | 功能 | 描述 | -|-----|-------|---------------------------------| -| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 | -| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 | -| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | -| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 | -| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | -| | 岗位管理 | 配置系统用户所属担任职务 | -| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 | -| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 | -| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | -| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 | -| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 | -| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 | -| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | -| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 | -| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | -| | 通知公告 | 系统通知公告信息发布维护 | -| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 | -| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 | -| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 | - -![功能图](/.image/common/system-feature.png) - -### 工作流程 - -![功能图](/.image/common/bpm-feature.png) - -基于 Flowable 构建,可支持信创(国产)数据库,满足中国特色流程操作: - -| BPMN 设计器 | 钉钉/飞书设计器 | -|------------------------------|--------------------------------| -| ![](/.image/工作流设计器-bpmn.jpg) | ![](/.image/工作流设计器-simple.jpg) | - -> 历经头部企业生产验证,工作流引擎须标配仿钉钉/飞书 + BPMN 双设计器!!! -> -> 前者支持轻量配置简单流程,后者实现复杂场景深度编排 - -| 功能列表 | 功能描述 | 是否完成 | -|------------|-------------------------------------------------------------------------------------|------| -| SIMPLE 设计器 | 仿钉钉/飞书设计器,支持拖拽搭建表单流程,10 分钟快速完成审批流程配置 | ✅ | -| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ | -| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ | -| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ | -| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批,A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ | -| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ | -| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ | -| 转办 | A 转给其 B 审批,B 审批后,进入下一节点 | ✅ | -| 委派 | A 转给其 B 审批,B 审批后,转给 A,A 继续审批后进入下一节点 | ✅ | -| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ | -| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ | -| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ | -| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ | -| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ | -| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ | -| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ | -| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ | -| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ | -| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ | -| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ | -| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ | -| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ | -| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ | -| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ | - -### 支付系统 - -| | 功能 | 描述 | -|-----|------|---------------------------| -| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 | -| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 | -| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 | -| 🚀 | 回调通知 | 查看支付回调业务的【支付】【退款】的通知结果 | -| 🚀 | 接入示例 | 提供接入支付系统的【支付】【退款】的功能实战 | - -### 基础设施 - -| | 功能 | 描述 | -|-----|-----------|----------------------------------------------| -| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 | -| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 | -| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 | -| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 | -| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 | -| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 | -| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 | -| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 | -| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 | -| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | -| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | -| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 | -| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 | -| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 | -| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 | -| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 | -| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 | -| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 | - -![功能图](/.image/common/infra-feature.png) - -### 数据报表 - -| | 功能 | 描述 | -|-----|-------|--------------------| -| 🚀 | 报表设计器 | 支持数据报表、图形报表、打印设计等 | -| 🚀 | 大屏设计器 | 拖拽生成数据大屏,内置几十种图表组件 | - -### 微信公众号 - -| | 功能 | 描述 | -|----|--------|-------------------------------| -| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 | -| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 | -| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 | -| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 | -| 🚀 | 模版消息 | 配置和发送模版消息,用于向粉丝推送通知类消息 | -| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 | -| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 | -| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 | -| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 | -| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 | -| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 | - -### 商城系统 - -演示地址: - -![功能图](/.image/common/mall-feature.png) - -![功能图](/.image/common/mall-preview.png) - -### 会员中心 - -| | 功能 | 描述 | -|-----|------|----------------------------------| -| 🚀 | 会员管理 | 会员是 C 端的消费者,该功能用于会员的搜索与管理 | -| 🚀 | 会员标签 | 对会员的标签进行创建、查询、修改、删除等操作 | -| 🚀 | 会员等级 | 对会员的等级、成长值进行管理,可用于订单折扣等会员权益 | -| 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 | -| 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 | - -### ERP 系统 - -演示地址: - -![功能图](/.image/common/erp-feature.png) - -### CRM 系统 - -演示地址: - -![功能图](/.image/common/crm-feature.png) - -### AI 大模型 - -演示地址: - -![功能图](/.image/common/ai-feature.png) - -![功能图](/.image/common/ai-preview.gif) - -## 🐨 技术栈 - -### 微服务 - -| 项目 | 说明 | -|-----------------------|--------------------| -| `yudao-dependencies` | Maven 依赖版本管理 | -| `yudao-framework` | Java 框架拓展 | -| `yudao-server` | 管理后台 + 用户 APP 的服务端 | -| `yudao-module-system` | 系统功能的 Module 模块 | -| `yudao-module-member` | 会员中心的 Module 模块 | -| `yudao-module-infra` | 基础设施的 Module 模块 | -| `yudao-module-bpm` | 工作流程的 Module 模块 | -| `yudao-module-pay` | 支付系统的 Module 模块 | -| `yudao-module-mall` | 商城系统的 Module 模块 | -| `yudao-module-erp` | ERP 系统的 Module 模块 | -| `yudao-module-crm` | CRM 系统的 Module 模块 | -| `yudao-module-ai` | AI 大模型的 Module 模块 | -| `yudao-module-mp` | 微信公众号的 Module 模块 | -| `yudao-module-report` | 大屏报表 Module 模块 | - -### 框架 - -| 框架 | 说明 | 版本 | 学习指南 | -|---------------------------------------------------------------------------------------------|------------------|------------|---------------------------------------------------------------------| -| [Spring Cloud Alibaba](https://github.com/alibaba/spring-cloud-alibaba) | 微服务框架 | 2023.0.1 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | -| [Nacos](https://github.com/alibaba/nacos) | 配置中心 & 注册中心 | 2.3.2 | [文档](https://www.iocoder.cn/categories/Nacos/?yudao) | -| [RocketMQ](https://github.com/apache/rocketmq) | 消息队列 | 5.2.0 | [文档](https://www.iocoder.cn/categories/RocketMQ/?yudao) | -| [Sentinel](https://github.com/alibaba/sentinel) | 服务保障 | 1.8.6 | [文档](https://www.iocoder.cn/categories/Sentinel/?yudao) | -| [XXL Job](https://github.com/xuxueli/xxl-job) | 定时任务 | 2.4.0 | [文档](https://www.iocoder.cn/XXL-JOB/good-collection/?yudao) | -| [Spring Cloud Gateway](https://github.com/spring-cloud/spring-cloud-gateway) | 服务网关 | 4.1.0 | [文档](https://www.iocoder.cn/categories/Spring-Cloud-Gateway/?yudao) | -| [Seata](https://github.com/seata/seata) | 分布式事务 | 1.6.1 | [文档](https://www.iocoder.cn/categories/Seata/?yudao) | -| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | | -| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.23 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | -| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.7 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | -| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 4.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | -| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | | -| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.32.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | -| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 6.1.10 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | -| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 6.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | -| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 8.0.1 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | -| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 7.0.0 | [文档](https://doc.iocoder.cn/bpm/) | -| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | -| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 9.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | -| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | -| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.17.1 | | -| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.6.3 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) | -| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.34 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | -| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.10.1 | - | -| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 5.7.0 | - | - -## 🐷 演示图 - -### 系统功能 - -| 模块 | biu | biu | biu | -|----------|-----------------------------|---------------------------|--------------------------| -| 登录 & 首页 | ![登录](/.image/登录.jpg) | ![首页](/.image/首页.jpg) | ![个人中心](/.image/个人中心.jpg) | -| 用户 & 应用 | ![用户管理](/.image/用户管理.jpg) | ![令牌管理](/.image/令牌管理.jpg) | ![应用管理](/.image/应用管理.jpg) | -| 租户 & 套餐 | ![租户管理](/.image/租户管理.jpg) | ![租户套餐](/.image/租户套餐.png) | - | -| 部门 & 岗位 | ![部门管理](/.image/部门管理.jpg) | ![岗位管理](/.image/岗位管理.jpg) | - | -| 菜单 & 角色 | ![菜单管理](/.image/菜单管理.jpg) | ![角色管理](/.image/角色管理.jpg) | - | -| 审计日志 | ![操作日志](/.image/操作日志.jpg) | ![登录日志](/.image/登录日志.jpg) | - | -| 短信 | ![短信渠道](/.image/短信渠道.jpg) | ![短信模板](/.image/短信模板.jpg) | ![短信日志](/.image/短信日志.jpg) | -| 字典 & 敏感词 | ![字典类型](/.image/字典类型.jpg) | ![字典数据](/.image/字典数据.jpg) | ![敏感词](/.image/敏感词.jpg) | -| 错误码 & 通知 | ![错误码管理](/.image/错误码管理.jpg) | ![通知公告](/.image/通知公告.jpg) | - | - -### 工作流程 - -| 模块 | biu | biu | biu | -|---------|---------------------------------|---------------------------------|---------------------------------| -| 流程模型 | ![流程模型-列表](/.image/流程模型-列表.jpg) | ![流程模型-设计](/.image/流程模型-设计.jpg) | ![流程模型-定义](/.image/流程模型-定义.jpg) | -| 表单 & 分组 | ![流程表单](/.image/流程表单.jpg) | ![用户分组](/.image/用户分组.jpg) | - | -| 我的流程 | ![我的流程-列表](/.image/我的流程-列表.jpg) | ![我的流程-发起](/.image/我的流程-发起.jpg) | ![我的流程-详情](/.image/我的流程-详情.jpg) | -| 待办 & 已办 | ![任务列表-审批](/.image/任务列表-审批.jpg) | ![任务列表-待办](/.image/任务列表-待办.jpg) | ![任务列表-已办](/.image/任务列表-已办.jpg) | -| OA 请假 | ![OA请假-列表](/.image/OA请假-列表.jpg) | ![OA请假-发起](/.image/OA请假-发起.jpg) | ![OA请假-详情](/.image/OA请假-详情.jpg) | - -### 基础设施 - -| 模块 | biu | biu | biu | -|---------------|-------------------------------|-----------------------------|---------------------------| -| 代码生成 | ![代码生成](/.image/代码生成.jpg) | ![生成效果](/.image/生成效果.jpg) | - | -| 文档 | ![系统接口](/.image/系统接口.jpg) | ![数据库文档](/.image/数据库文档.jpg) | - | -| 文件 & 配置 | ![文件配置](/.image/文件配置.jpg) | ![文件管理](/.image/文件管理2.jpg) | ![配置管理](/.image/配置管理.jpg) | -| 定时任务 | ![定时任务](/.image/定时任务.jpg) | ![任务日志](/.image/任务日志.jpg) | - | -| API 日志 | ![访问日志](/.image/访问日志.jpg) | ![错误日志](/.image/错误日志.jpg) | - | -| MySQL & Redis | ![MySQL](/.image/MySQL.jpg) | ![Redis](/.image/Redis.jpg) | - | -| 监控平台 | ![Java监控](/.image/Java监控.jpg) | ![链路追踪](/.image/链路追踪.jpg) | ![日志中心](/.image/日志中心.jpg) | - -### 支付系统 - -| 模块 | biu | biu | biu | -|---------|---------------------------|---------------------------------|---------------------------------| -| 商家 & 应用 | ![商户信息](/.image/商户信息.jpg) | ![应用信息-列表](/.image/应用信息-列表.jpg) | ![应用信息-编辑](/.image/应用信息-编辑.jpg) | -| 支付 & 退款 | ![支付订单](/.image/支付订单.jpg) | ![退款订单](/.image/退款订单.jpg) | --- | -### 数据报表 - -| 模块 | biu | biu | biu | -|-------|---------------------------------|---------------------------------|---------------------------------------| -| 报表设计器 | ![数据报表](/.image/报表设计器-数据报表.jpg) | ![图形报表](/.image/报表设计器-图形报表.jpg) | ![报表设计器-打印设计](/.image/报表设计器-打印设计.jpg) | -| 大屏设计器 | ![大屏列表](/.image/大屏设计器-列表.jpg) | ![大屏预览](/.image/大屏设计器-预览.jpg) | ![大屏编辑](/.image/大屏设计器-编辑.jpg) | - -### 移动端(管理后台) - -| biu | biu | biu | -|----------------------------------|----------------------------------|----------------------------------| -| ![](/.image/admin-uniapp/01.png) | ![](/.image/admin-uniapp/02.png) | ![](/.image/admin-uniapp/03.png) | -| ![](/.image/admin-uniapp/04.png) | ![](/.image/admin-uniapp/05.png) | ![](/.image/admin-uniapp/06.png) | -| ![](/.image/admin-uniapp/07.png) | ![](/.image/admin-uniapp/08.png) | ![](/.image/admin-uniapp/09.png) | - -目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。 +- 项目负责人: 亮哥(初如) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..59a28a914 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,101 @@ +version: '3.8' + +services: + # MySQL 8.0 + mysql: + image: mysql:8.0 + container_name: asset-mysql + restart: always + environment: + MYSQL_ROOT_PASSWORD: 123456 + MYSQL_DATABASE: ruoyi-vue-pro + TZ: Asia/Shanghai + ports: + - "3306:3306" + volumes: + - ./data/mysql:/var/lib/mysql + - ./sql:/docker-entrypoint-initdb.d + command: + - --default-authentication-plugin=mysql_native_password + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + networks: + - asset-network + + # Redis 7.0 + redis: + image: redis:7.0-alpine + container_name: asset-redis + restart: always + ports: + - "6379:6379" + volumes: + - ./data/redis:/data + command: redis-server --appendonly yes + networks: + - asset-network + + # Nacos 2.3 + nacos: + image: nacos/nacos-server:v2.3.0 + container_name: asset-nacos + restart: always + environment: + MODE: standalone + SPRING_DATASOURCE_PLATFORM: mysql + MYSQL_SERVICE_HOST: mysql + MYSQL_SERVICE_PORT: 3306 + MYSQL_SERVICE_DB_NAME: nacos_config + MYSQL_SERVICE_USER: root + MYSQL_SERVICE_PASSWORD: 123456 + NACOS_AUTH_ENABLE: true + NACOS_AUTH_TOKEN: SecretKey012345678901234567890123456789012345678901234567890123456789 + NACOS_AUTH_IDENTITY_KEY: nacos + NACOS_AUTH_IDENTITY_VALUE: nacos + JVM_XMS: 512m + JVM_XMX: 512m + ports: + - "8848:8848" + - "9848:9848" + volumes: + - ./data/nacos/logs:/home/nacos/logs + depends_on: + - mysql + networks: + - asset-network + + # XXL-Job 2.4 + xxl-job: + image: xuxueli/xxl-job-admin:2.4.0 + container_name: asset-xxl-job + restart: always + environment: + PARAMS: > + --spring.datasource.url=jdbc:mysql://mysql:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai + --spring.datasource.username=root + --spring.datasource.password=123456 + ports: + - "9090:8080" + depends_on: + - mysql + networks: + - asset-network + + # Nginx + nginx: + image: nginx:alpine + container_name: asset-nginx + restart: always + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/html:/usr/share/nginx/html:ro + - ./nginx/logs:/var/log/nginx + networks: + - asset-network + +networks: + asset-network: + driver: bridge diff --git a/pom.xml b/pom.xml index 563379829..ee6390365 100644 --- a/pom.xml +++ b/pom.xml @@ -16,16 +16,9 @@ yudao-module-system yudao-module-infra - yudao-module-member yudao-module-bpm - yudao-module-pay - yudao-module-report - yudao-module-mp - yudao-module-mall - yudao-module-crm - yudao-module-erp - yudao-module-ai - yudao-module-iot + + yudao-module-asset ${project.artifactId} diff --git a/sql/asset-schema-clean.sql b/sql/asset-schema-clean.sql new file mode 100644 index 000000000..aaabd2553 --- /dev/null +++ b/sql/asset-schema-clean.sql @@ -0,0 +1,260 @@ +CREATE TABLE `asset_truck` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `org_id` bigint NOT NULL COMMENT '所属机构', + `plate_number` varchar(20) NOT NULL COMMENT '车牌号', + `vin` varchar(50) NOT NULL COMMENT 'VIN码', + `brand` int NOT NULL COMMENT '品牌(字典)', + `model` int NOT NULL COMMENT '型号(字典)', + `color` varchar(20) DEFAULT NULL COMMENT '颜色', + `engine_num` varchar(50) DEFAULT NULL COMMENT '电机编号', + `hydrogen_capacity` int DEFAULT NULL COMMENT '氢瓶容量(L)', + `reserve_electricity` decimal(10,2) DEFAULT NULL COMMENT '储电量(kwh)', + `buy_time` datetime DEFAULT NULL COMMENT '采购时间', + `mileage` decimal(10,2) DEFAULT 0.00 COMMENT '里程数(KM)', + `truck_rent_status` int NOT NULL DEFAULT 0 COMMENT '租赁状态:0-未备车,7-已备车,1-已交车,2-已还车', + `is_operation` tinyint NOT NULL DEFAULT 0 COMMENT '是否营运:0-否,1-是', + `parking_id` bigint DEFAULT NULL COMMENT '停车场ID', + `stock_area` int DEFAULT NULL COMMENT '库存区域(字典)', + `remarks` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_vin` (`vin`,`deleted`,`tenant_id`), + KEY `idx_plate_number` (`plate_number`), + KEY `idx_org_id` (`org_id`), + KEY `idx_truck_rent_status` (`truck_rent_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆信息表'; +CREATE TABLE `asset_customer` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(100) NOT NULL COMMENT '客户名称', + `credit_code` varchar(50) DEFAULT NULL COMMENT '统一信用代码', + `contact_name` varchar(50) DEFAULT NULL COMMENT '联系人', + `contact_phone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `contact_address` varchar(200) DEFAULT NULL COMMENT '联系地址', + `contact_email` varchar(100) DEFAULT NULL COMMENT '联系邮箱', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户信息表'; +CREATE TABLE `asset_parking` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(100) NOT NULL COMMENT '停车场名称', + `address` varchar(200) DEFAULT NULL COMMENT '地址', + `capacity` int DEFAULT NULL COMMENT '容量', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='停车场表'; +CREATE TABLE `asset_check_item` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `form_code` varchar(50) NOT NULL COMMENT '所属表单:preparation-备车,take-交车,return-还车', + `category` varchar(50) NOT NULL COMMENT '检查项类别', + `code` varchar(50) NOT NULL COMMENT '检查项编码', + `name` varchar(100) NOT NULL COMMENT '检查项名称', + `data_type` int NOT NULL COMMENT '数据类型:1-boolean,2-整数,3-小数,4-百分比,5-字符串,6-图片', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `required` tinyint NOT NULL DEFAULT 0 COMMENT '是否必填:0-否,1-是', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_form_code` (`form_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='检查项配置表'; +CREATE TABLE `asset_preparation` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `truck_id` bigint NOT NULL COMMENT '车辆ID', + `status` int NOT NULL DEFAULT 0 COMMENT '状态:0-待整备,1-整备中,2-已完成', + `parking_id` bigint DEFAULT NULL COMMENT '停车场ID', + `instrument_range` decimal(10,2) DEFAULT NULL COMMENT '仪表盘里程', + `left_hydrogen` decimal(10,2) DEFAULT NULL COMMENT '剩余氢量', + `hydrogen_unit` int DEFAULT NULL COMMENT '氢气单位(字典)', + `left_electricity` decimal(10,2) DEFAULT NULL COMMENT '剩余电量(%)', + `handler_id` bigint DEFAULT NULL COMMENT '负责人ID', + `completion_time` datetime DEFAULT NULL COMMENT '完成时间', + `next_check_date` datetime DEFAULT NULL COMMENT '下次检查日期', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_truck_id` (`truck_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='备车单表'; +CREATE TABLE `asset_preparation_check_data` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `preparation_id` bigint NOT NULL COMMENT '备车单ID', + `check_item_id` bigint NOT NULL COMMENT '检查项ID', + `category` varchar(50) NOT NULL COMMENT '检查项类别', + `code` varchar(50) NOT NULL COMMENT '检查项编码', + `name` varchar(100) NOT NULL COMMENT '检查项名称', + `data_type` int NOT NULL COMMENT '数据类型', + `value` varchar(500) DEFAULT NULL COMMENT '检查值', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_preparation_id` (`preparation_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='备车检查项数据表'; +CREATE TABLE `asset_contract` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `org_id` bigint NOT NULL COMMENT '签约机构', + `contract_no` varchar(50) NOT NULL COMMENT '合同编号', + `customer_id` bigint NOT NULL COMMENT '客户ID', + `project_name` varchar(200) NOT NULL COMMENT '项目名称', + `contract_type` int NOT NULL COMMENT '合同类型(字典)', + `signing_date` date NOT NULL COMMENT '生效日期', + `expire_date` date DEFAULT NULL COMMENT '结束日期', + `pay_way` int DEFAULT NULL COMMENT '付款方式(字典)', + `pay_period` int DEFAULT NULL COMMENT '付款周期(字典)', + `handover_address` varchar(200) DEFAULT NULL COMMENT '交车地点', + `bd` varchar(50) DEFAULT NULL COMMENT '业务经理', + `business_dept_id` bigint DEFAULT NULL COMMENT '业务部门ID', + `status` int NOT NULL DEFAULT 0 COMMENT '状态:0-草稿,1-审批中,2-已通过,3-已拒绝,4-已作废', + `bpm_process_id` varchar(64) DEFAULT NULL COMMENT '审批流程ID', + `parent_id` bigint DEFAULT NULL COMMENT '父合同ID(变更/续签)', + `is_alter` tinyint NOT NULL DEFAULT 0 COMMENT '是否变更合同:0-否,1-是', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_contract_no` (`contract_no`,`deleted`,`tenant_id`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同表'; +CREATE TABLE `asset_contract_truck` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `contract_id` bigint NOT NULL COMMENT '合同ID', + `truck_id` bigint NOT NULL COMMENT '车辆ID', + `estimated_return_date` date DEFAULT NULL COMMENT '预计还车日期', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_truck_id` (`truck_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同车辆关联表'; +CREATE TABLE `asset_rent_task` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `contract_id` bigint NOT NULL COMMENT '合同ID', + `contract_truck_id` bigint NOT NULL COMMENT '合同车辆ID', + `task_type` int NOT NULL COMMENT '任务类型:1-交车,2-还车,3-替换车', + `task_status` int NOT NULL DEFAULT 0 COMMENT '任务状态:0-进行中,1-已完成', + `parent_task_id` bigint DEFAULT NULL COMMENT '父任务ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_task_type` (`task_type`), + KEY `idx_task_status` (`task_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='租赁任务表'; +CREATE TABLE `asset_take` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `task_id` bigint NOT NULL COMMENT '任务ID', + `take_name` varchar(50) NOT NULL COMMENT '提车人姓名', + `take_phone` varchar(20) NOT NULL COMMENT '提车人电话', + `take_id_no` varchar(50) NOT NULL COMMENT '提车人身份证', + `handover_user_id` bigint NOT NULL COMMENT '交车人ID', + `handover_date` datetime NOT NULL COMMENT '交车时间', + `handover_address` varchar(200) NOT NULL COMMENT '交车地点', + `business_manager` varchar(50) DEFAULT NULL COMMENT '业务经理', + `take_mileage` decimal(10,2) DEFAULT NULL COMMENT '交车里程(KM)', + `hydrogen_measure` decimal(10,2) DEFAULT NULL COMMENT '氢SOC', + `hydrogen_unit` int DEFAULT NULL COMMENT '氢SOC单位(字典)', + `electricity` decimal(10,2) DEFAULT NULL COMMENT '电量百分比', + `dashboard_pic` varchar(500) DEFAULT NULL COMMENT '仪表盘照片', + `front_pic` varchar(500) DEFAULT NULL COMMENT '正面照片', + `left_front_pic` varchar(500) DEFAULT NULL COMMENT '左前方照片', + `right_front_pic` varchar(500) DEFAULT NULL COMMENT '右前方照片', + `left_rear_pic` varchar(500) DEFAULT NULL COMMENT '左后方照片', + `right_rear_pic` varchar(500) DEFAULT NULL COMMENT '右后方照片', + `is_driving_training` tinyint DEFAULT 0 COMMENT '是否驾驶培训:0-否,1-是', + `authorizer` varchar(50) DEFAULT NULL COMMENT '授权人', + `authorizer_id_card` varchar(50) DEFAULT NULL COMMENT '授权人身份证', + `authorizer_phone` varchar(20) DEFAULT NULL COMMENT '授权人电话', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_task_id` (`task_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车单表'; +CREATE TABLE `asset_return` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `task_id` bigint NOT NULL COMMENT '任务ID', + `return_date` datetime NOT NULL COMMENT '还车时间', + `return_mileage` decimal(10,2) DEFAULT NULL COMMENT '还车里程(KM)', + `hydrogen_measure` decimal(10,2) DEFAULT NULL COMMENT '氢SOC', + `hydrogen_unit` int DEFAULT NULL COMMENT '氢SOC单位(字典)', + `electricity` decimal(10,2) DEFAULT NULL COMMENT '电量百分比', + `return_driver` varchar(50) NOT NULL COMMENT '还车人', + `return_id_card` varchar(50) NOT NULL COMMENT '还车人身份证', + `return_phone` varchar(20) NOT NULL COMMENT '还车人电话', + `return_location_type` int DEFAULT NULL COMMENT '还车地点类型(字典)', + `return_location` varchar(200) NOT NULL COMMENT '还车地点', + `fee_amount_total` decimal(10,2) DEFAULT 0.00 COMMENT '费用金额总计', + `bill_status` int DEFAULT 0 COMMENT '账单状态:0-未付款,1-已付款', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_task_id` (`task_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='还车单表'; +CREATE TABLE `asset_replace` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `contract_id` bigint NOT NULL COMMENT '合同ID', + `contract_truck_id` bigint NOT NULL COMMENT '合同车辆ID', + `old_task_id` bigint NOT NULL COMMENT '原交车任务ID', + `old_truck_id` bigint NOT NULL COMMENT '原车辆ID', + `new_truck_id` bigint NOT NULL COMMENT '新车辆ID', + `new_task_id` bigint DEFAULT NULL COMMENT '新交车任务ID', + `replace_type` int NOT NULL COMMENT '替换类型:1-临时,2-永久', + `replace_reason_type` int DEFAULT NULL COMMENT '替换原因类型(字典)', + `replace_reason` varchar(500) DEFAULT NULL COMMENT '替换原因', + `status` int NOT NULL DEFAULT 0 COMMENT '状态:0-草稿,1-审批中,2-已通过,3-已拒绝', + `bpm_process_id` varchar(64) DEFAULT NULL COMMENT '审批流程ID', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_old_truck_id` (`old_truck_id`), + KEY `idx_new_truck_id` (`new_truck_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='替换车表'; diff --git a/sql/asset-schema.sql b/sql/asset-schema.sql new file mode 100644 index 000000000..5990d4e8f --- /dev/null +++ b/sql/asset-schema.sql @@ -0,0 +1,333 @@ +# 资产管理系统 - 数据库设计 + +## 一、基础数据模块 + +### 1.1 车辆信息表 (asset_truck) + +```sql +CREATE TABLE `asset_truck` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `org_id` bigint NOT NULL COMMENT '所属机构', + `plate_number` varchar(20) NOT NULL COMMENT '车牌号', + `vin` varchar(50) NOT NULL COMMENT 'VIN码', + `brand` int NOT NULL COMMENT '品牌(字典)', + `model` int NOT NULL COMMENT '型号(字典)', + `color` varchar(20) DEFAULT NULL COMMENT '颜色', + `engine_num` varchar(50) DEFAULT NULL COMMENT '电机编号', + `hydrogen_capacity` int DEFAULT NULL COMMENT '氢瓶容量(L)', + `reserve_electricity` decimal(10,2) DEFAULT NULL COMMENT '储电量(kwh)', + `buy_time` datetime DEFAULT NULL COMMENT '采购时间', + `mileage` decimal(10,2) DEFAULT 0.00 COMMENT '里程数(KM)', + `truck_rent_status` int NOT NULL DEFAULT 0 COMMENT '租赁状态:0-未备车,7-已备车,1-已交车,2-已还车', + `is_operation` tinyint NOT NULL DEFAULT 0 COMMENT '是否营运:0-否,1-是', + `parking_id` bigint DEFAULT NULL COMMENT '停车场ID', + `stock_area` int DEFAULT NULL COMMENT '库存区域(字典)', + `remarks` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_vin` (`vin`,`deleted`,`tenant_id`), + KEY `idx_plate_number` (`plate_number`), + KEY `idx_org_id` (`org_id`), + KEY `idx_truck_rent_status` (`truck_rent_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆信息表'; +``` + +### 1.2 客户信息表 (asset_customer) + +```sql +CREATE TABLE `asset_customer` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(100) NOT NULL COMMENT '客户名称', + `credit_code` varchar(50) DEFAULT NULL COMMENT '统一信用代码', + `contact_name` varchar(50) DEFAULT NULL COMMENT '联系人', + `contact_phone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `contact_address` varchar(200) DEFAULT NULL COMMENT '联系地址', + `contact_email` varchar(100) DEFAULT NULL COMMENT '联系邮箱', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户信息表'; +``` + +### 1.3 停车场表 (asset_parking) + +```sql +CREATE TABLE `asset_parking` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(100) NOT NULL COMMENT '停车场名称', + `address` varchar(200) DEFAULT NULL COMMENT '地址', + `capacity` int DEFAULT NULL COMMENT '容量', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='停车场表'; +``` + +## 二、检查项配置模块 + +### 2.1 检查项配置表 (asset_check_item) + +```sql +CREATE TABLE `asset_check_item` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `form_code` varchar(50) NOT NULL COMMENT '所属表单:preparation-备车,take-交车,return-还车', + `category` varchar(50) NOT NULL COMMENT '检查项类别', + `code` varchar(50) NOT NULL COMMENT '检查项编码', + `name` varchar(100) NOT NULL COMMENT '检查项名称', + `data_type` int NOT NULL COMMENT '数据类型:1-boolean,2-整数,3-小数,4-百分比,5-字符串,6-图片', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `required` tinyint NOT NULL DEFAULT 0 COMMENT '是否必填:0-否,1-是', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_form_code` (`form_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='检查项配置表'; +``` + +## 三、备车模块 + +### 3.1 备车单表 (asset_preparation) + +```sql +CREATE TABLE `asset_preparation` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `truck_id` bigint NOT NULL COMMENT '车辆ID', + `status` int NOT NULL DEFAULT 0 COMMENT '状态:0-待整备,1-整备中,2-已完成', + `parking_id` bigint DEFAULT NULL COMMENT '停车场ID', + `instrument_range` decimal(10,2) DEFAULT NULL COMMENT '仪表盘里程', + `left_hydrogen` decimal(10,2) DEFAULT NULL COMMENT '剩余氢量', + `hydrogen_unit` int DEFAULT NULL COMMENT '氢气单位(字典)', + `left_electricity` decimal(10,2) DEFAULT NULL COMMENT '剩余电量(%)', + `handler_id` bigint DEFAULT NULL COMMENT '负责人ID', + `completion_time` datetime DEFAULT NULL COMMENT '完成时间', + `next_check_date` datetime DEFAULT NULL COMMENT '下次检查日期', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_truck_id` (`truck_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='备车单表'; +``` + +### 3.2 备车检查项数据表 (asset_preparation_check_data) + +```sql +CREATE TABLE `asset_preparation_check_data` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `preparation_id` bigint NOT NULL COMMENT '备车单ID', + `check_item_id` bigint NOT NULL COMMENT '检查项ID', + `category` varchar(50) NOT NULL COMMENT '检查项类别', + `code` varchar(50) NOT NULL COMMENT '检查项编码', + `name` varchar(100) NOT NULL COMMENT '检查项名称', + `data_type` int NOT NULL COMMENT '数据类型', + `value` varchar(500) DEFAULT NULL COMMENT '检查值', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_preparation_id` (`preparation_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='备车检查项数据表'; +``` + +## 四、合同模块 + +### 4.1 合同表 (asset_contract) + +```sql +CREATE TABLE `asset_contract` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `org_id` bigint NOT NULL COMMENT '签约机构', + `contract_no` varchar(50) NOT NULL COMMENT '合同编号', + `customer_id` bigint NOT NULL COMMENT '客户ID', + `project_name` varchar(200) NOT NULL COMMENT '项目名称', + `contract_type` int NOT NULL COMMENT '合同类型(字典)', + `signing_date` date NOT NULL COMMENT '生效日期', + `expire_date` date DEFAULT NULL COMMENT '结束日期', + `pay_way` int DEFAULT NULL COMMENT '付款方式(字典)', + `pay_period` int DEFAULT NULL COMMENT '付款周期(字典)', + `handover_address` varchar(200) DEFAULT NULL COMMENT '交车地点', + `bd` varchar(50) DEFAULT NULL COMMENT '业务经理', + `business_dept_id` bigint DEFAULT NULL COMMENT '业务部门ID', + `status` int NOT NULL DEFAULT 0 COMMENT '状态:0-草稿,1-审批中,2-已通过,3-已拒绝,4-已作废', + `bpm_process_id` varchar(64) DEFAULT NULL COMMENT '审批流程ID', + `parent_id` bigint DEFAULT NULL COMMENT '父合同ID(变更/续签)', + `is_alter` tinyint NOT NULL DEFAULT 0 COMMENT '是否变更合同:0-否,1-是', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_contract_no` (`contract_no`,`deleted`,`tenant_id`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同表'; +``` + +### 4.2 合同车辆关联表 (asset_contract_truck) + +```sql +CREATE TABLE `asset_contract_truck` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `contract_id` bigint NOT NULL COMMENT '合同ID', + `truck_id` bigint NOT NULL COMMENT '车辆ID', + `estimated_return_date` date DEFAULT NULL COMMENT '预计还车日期', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_truck_id` (`truck_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同车辆关联表'; +``` + +## 五、任务模块 + +### 5.1 租赁任务表 (asset_rent_task) + +```sql +CREATE TABLE `asset_rent_task` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `contract_id` bigint NOT NULL COMMENT '合同ID', + `contract_truck_id` bigint NOT NULL COMMENT '合同车辆ID', + `task_type` int NOT NULL COMMENT '任务类型:1-交车,2-还车,3-替换车', + `task_status` int NOT NULL DEFAULT 0 COMMENT '任务状态:0-进行中,1-已完成', + `parent_task_id` bigint DEFAULT NULL COMMENT '父任务ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_task_type` (`task_type`), + KEY `idx_task_status` (`task_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='租赁任务表'; +``` + +## 六、交车/还车/替换车单据表 + +### 6.1 交车单表 (asset_take) + +```sql +CREATE TABLE `asset_take` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `task_id` bigint NOT NULL COMMENT '任务ID', + `take_name` varchar(50) NOT NULL COMMENT '提车人姓名', + `take_phone` varchar(20) NOT NULL COMMENT '提车人电话', + `take_id_no` varchar(50) NOT NULL COMMENT '提车人身份证', + `handover_user_id` bigint NOT NULL COMMENT '交车人ID', + `handover_date` datetime NOT NULL COMMENT '交车时间', + `handover_address` varchar(200) NOT NULL COMMENT '交车地点', + `business_manager` varchar(50) DEFAULT NULL COMMENT '业务经理', + `take_mileage` decimal(10,2) DEFAULT NULL COMMENT '交车里程(KM)', + `hydrogen_measure` decimal(10,2) DEFAULT NULL COMMENT '氢SOC', + `hydrogen_unit` int DEFAULT NULL COMMENT '氢SOC单位(字典)', + `electricity` decimal(10,2) DEFAULT NULL COMMENT '电量百分比', + `dashboard_pic` varchar(500) DEFAULT NULL COMMENT '仪表盘照片', + `front_pic` varchar(500) DEFAULT NULL COMMENT '正面照片', + `left_front_pic` varchar(500) DEFAULT NULL COMMENT '左前方照片', + `right_front_pic` varchar(500) DEFAULT NULL COMMENT '右前方照片', + `left_rear_pic` varchar(500) DEFAULT NULL COMMENT '左后方照片', + `right_rear_pic` varchar(500) DEFAULT NULL COMMENT '右后方照片', + `is_driving_training` tinyint DEFAULT 0 COMMENT '是否驾驶培训:0-否,1-是', + `authorizer` varchar(50) DEFAULT NULL COMMENT '授权人', + `authorizer_id_card` varchar(50) DEFAULT NULL COMMENT '授权人身份证', + `authorizer_phone` varchar(20) DEFAULT NULL COMMENT '授权人电话', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_task_id` (`task_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车单表'; +``` + +### 6.2 还车单表 (asset_return) + +```sql +CREATE TABLE `asset_return` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `task_id` bigint NOT NULL COMMENT '任务ID', + `return_date` datetime NOT NULL COMMENT '还车时间', + `return_mileage` decimal(10,2) DEFAULT NULL COMMENT '还车里程(KM)', + `hydrogen_measure` decimal(10,2) DEFAULT NULL COMMENT '氢SOC', + `hydrogen_unit` int DEFAULT NULL COMMENT '氢SOC单位(字典)', + `electricity` decimal(10,2) DEFAULT NULL COMMENT '电量百分比', + `return_driver` varchar(50) NOT NULL COMMENT '还车人', + `return_id_card` varchar(50) NOT NULL COMMENT '还车人身份证', + `return_phone` varchar(20) NOT NULL COMMENT '还车人电话', + `return_location_type` int DEFAULT NULL COMMENT '还车地点类型(字典)', + `return_location` varchar(200) NOT NULL COMMENT '还车地点', + `fee_amount_total` decimal(10,2) DEFAULT 0.00 COMMENT '费用金额总计', + `bill_status` int DEFAULT 0 COMMENT '账单状态:0-未付款,1-已付款', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_task_id` (`task_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='还车单表'; +``` + +### 6.3 替换车表 (asset_replace) + +```sql +CREATE TABLE `asset_replace` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `contract_id` bigint NOT NULL COMMENT '合同ID', + `contract_truck_id` bigint NOT NULL COMMENT '合同车辆ID', + `old_task_id` bigint NOT NULL COMMENT '原交车任务ID', + `old_truck_id` bigint NOT NULL COMMENT '原车辆ID', + `new_truck_id` bigint NOT NULL COMMENT '新车辆ID', + `new_task_id` bigint DEFAULT NULL COMMENT '新交车任务ID', + `replace_type` int NOT NULL COMMENT '替换类型:1-临时,2-永久', + `replace_reason_type` int DEFAULT NULL COMMENT '替换原因类型(字典)', + `replace_reason` varchar(500) DEFAULT NULL COMMENT '替换原因', + `status` int NOT NULL DEFAULT 0 COMMENT '状态:0-草稿,1-审批中,2-已通过,3-已拒绝', + `bpm_process_id` varchar(64) DEFAULT NULL COMMENT '审批流程ID', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_old_truck_id` (`old_truck_id`), + KEY `idx_new_truck_id` (`new_truck_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='替换车表'; +``` diff --git a/sql/update-2026-03-11-基础数据字段补充.sql b/sql/update-2026-03-11-基础数据字段补充.sql new file mode 100644 index 000000000..296494357 --- /dev/null +++ b/sql/update-2026-03-11-基础数据字段补充.sql @@ -0,0 +1,17 @@ +-- 客户管理表 - 补充字段 +ALTER TABLE asset_customer ADD COLUMN company_name VARCHAR(255) COMMENT '企业名称' AFTER contact_email; +ALTER TABLE asset_customer ADD COLUMN company_phone VARCHAR(20) COMMENT '企业电话' AFTER company_name; +ALTER TABLE asset_customer ADD COLUMN mailing_address VARCHAR(500) COMMENT '邮寄地址' AFTER company_phone; +ALTER TABLE asset_customer ADD COLUMN bank_name VARCHAR(255) COMMENT '开户银行' AFTER mailing_address; +ALTER TABLE asset_customer ADD COLUMN bank_account VARCHAR(50) COMMENT '银行账号' AFTER bank_name; +ALTER TABLE asset_customer ADD COLUMN tax_number VARCHAR(50) COMMENT '纳税人识别号' AFTER bank_account; + +-- 停车场管理表 - 补充字段 +ALTER TABLE asset_parking ADD COLUMN province VARCHAR(50) COMMENT '省份' AFTER capacity; +ALTER TABLE asset_parking ADD COLUMN city VARCHAR(50) COMMENT '城市' AFTER province; +ALTER TABLE asset_parking ADD COLUMN lease_start_date DATE COMMENT '租赁开始时间' AFTER city; +ALTER TABLE asset_parking ADD COLUMN lease_end_date DATE COMMENT '租赁结束时间' AFTER lease_start_date; +ALTER TABLE asset_parking ADD COLUMN manager_name VARCHAR(50) COMMENT '负责人' AFTER lease_end_date; +ALTER TABLE asset_parking ADD COLUMN manager_phone VARCHAR(20) COMMENT '负责人联系方式' AFTER manager_name; +ALTER TABLE asset_parking ADD COLUMN contact_name VARCHAR(50) COMMENT '停车场联系人' AFTER manager_phone; +ALTER TABLE asset_parking ADD COLUMN contact_phone VARCHAR(20) COMMENT '停车场联系方式' AFTER contact_name; diff --git a/yudao-asset-cloud.tar.gz b/yudao-asset-cloud.tar.gz new file mode 100644 index 000000000..94ab7ca05 Binary files /dev/null and b/yudao-asset-cloud.tar.gz differ diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml deleted file mode 100644 index a295dce7a..000000000 --- a/yudao-module-ai/pom.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - cn.iocoder.cloud - yudao - ${revision} - - 4.0.0 - - yudao-module-ai-api - yudao-module-ai-server - - pom - yudao-module-ai - - ${project.artifactId} - - ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。 - 目前已接入各种模型,不限于: - 国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek - 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno - - - \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-api/pom.xml b/yudao-module-ai/yudao-module-ai-api/pom.xml deleted file mode 100644 index 09d27de6a..000000000 --- a/yudao-module-ai/yudao-module-ai-api/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - cn.iocoder.cloud - yudao-module-ai - ${revision} - - 4.0.0 - yudao-module-ai-api - jar - - ${project.artifactId} - - ai 模块 API,暴露给其它模块调用 - - - - - cn.iocoder.cloud - yudao-common - - - - - org.springframework.boot - spring-boot-starter-validation - true - - - \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/api/package-info.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/api/package-info.java deleted file mode 100644 index 4f94f23f8..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/api/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位,没有特别的作用 - */ -package cn.iocoder.yudao.module.ai.api; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java deleted file mode 100644 index 147927495..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * AI 内置聊天角色的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiChatRoleEnum { - - AI_WRITE_ROLE("写作助手", """ - 你是一位出色的写作助手,能够帮助用户生成创意和灵感,并在用户提供场景和提示词时生成对应的回复。你的任务包括: - 1. 撰写建议:根据用户提供的主题或问题,提供详细的写作建议、情节发展方向、角色设定以及背景描写,确保内容结构清晰、有逻辑。 - 2. 回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。 - 除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。 - """), - - AI_MIND_MAP_ROLE("导图助手", """ - 你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子: - # Geek-AI 助手 - ## 完整的开源系统 - ### 前端开源 - ### 后端开源 - ## 支持各种大模型 - ### OpenAI - ### Azure - ### 文心一言 - ### 通义千问 - ## 集成多种收费方式 - ### 支付宝 - ### 微信 - 除此之外不要任何解释性语句。 - """), - ; - - /** - * 角色名 - */ - private final String name; - - /** - * 角色设定 - */ - private final String systemMessage; - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiDocumentSplitStrategyEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiDocumentSplitStrategyEnum.java deleted file mode 100644 index f0a9cd21d..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiDocumentSplitStrategyEnum.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * AI 知识库文档切片策略枚举 - * - * @author runzhen - */ -@AllArgsConstructor -@Getter -public enum AiDocumentSplitStrategyEnum { - - /** - * 自动识别文档类型并选择最佳切片策略 - */ - AUTO("auto", "自动识别"), - - /** - * 基于 Token 数量机械切分(默认策略) - */ - TOKEN("token", "Token 切分"), - - /** - * 按段落切分(以双换行符为分隔) - */ - PARAGRAPH("paragraph", "段落切分"), - - /** - * Markdown QA 格式专用切片器 - * 识别二级标题作为问题,保持问答对完整性 - * 长答案智能切分但保留问题作为上下文 - */ - MARKDOWN_QA("markdown_qa", "Markdown QA 切分"), - - /** - * 语义化切分,保留句子完整性 - * 在段落和句子边界处切分,避免截断 - */ - SEMANTIC("semantic", "语义切分"); - - /** - * 策略代码 - */ - private final String code; - - /** - * 策略名称 - */ - private final String name; - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/DictTypeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/DictTypeConstants.java deleted file mode 100644 index 73782a2cb..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/DictTypeConstants.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -/** - * AI 字典类型的枚举类 - * - * @author xiaoxin - */ -public interface DictTypeConstants { - - // ========== AI Write ========== - String AI_WRITE_FORMAT = "ai_write_format"; // 写作格式 - String AI_WRITE_LENGTH = "ai_write_length"; // 写作长度 - String AI_WRITE_LANGUAGE = "ai_write_language"; // 写作语言 - String AI_WRITE_TONE = "ai_write_tone"; // 写作语气 - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java deleted file mode 100644 index 8a8a38832..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java +++ /dev/null @@ -1,68 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * AI 错误码枚举类 - *

- * ai 系统,使用 1-040-000-000 段 - */ -public interface ErrorCodeConstants { - - // ========== API 密钥 1-040-000-000 ========== - ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "API 密钥不存在"); - ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "API 密钥已禁用!"); - - // ========== API 模型 1-040-001-000 ========== - ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "模型不存在!"); - ErrorCode MODEL_DISABLE = new ErrorCode(1_040_001_001, "模型({})已禁用!"); - ErrorCode MODEL_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认模型"); - ErrorCode MODEL_USE_TYPE_ERROR = new ErrorCode(1_040_001_003, "操作失败,该模型的模型类型不正确"); - - // ========== API 聊天角色 1-040-002-000 ========== - ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "聊天角色不存在"); - ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "聊天角色({})已禁用!"); - - // ========== API 聊天会话 1-040-003-000 ========== - ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "对话不存在!"); - ErrorCode CHAT_CONVERSATION_MODEL_ERROR = new ErrorCode(1_040_003_001, "操作失败,该聊天模型的配置不完整"); - - // ========== API 聊天消息 1-040-004-000 ========== - ErrorCode CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!"); - ErrorCode CHAT_STREAM_ERROR = new ErrorCode(1_040_004_001, "对话生成异常!"); - - // ========== API 绘画 1-040-005-000 ========== - ErrorCode IMAGE_NOT_EXISTS = new ErrorCode(1_040_005_000, "图片不存在!"); - ErrorCode IMAGE_MIDJOURNEY_SUBMIT_FAIL = new ErrorCode(1_040_005_001, "Midjourney 提交失败!原因:{}"); - ErrorCode IMAGE_CUSTOM_ID_NOT_EXISTS = new ErrorCode(1_040_005_002, "Midjourney 按钮 customId 不存在! {}"); - - // ========== API 音乐 1-040-006-000 ========== - ErrorCode MUSIC_NOT_EXISTS = new ErrorCode(1_040_006_000, "音乐不存在!"); - - // ========== API 写作 1-040-007-000 ========== - ErrorCode WRITE_NOT_EXISTS = new ErrorCode(1_040_007_000, "作文不存在!"); - ErrorCode WRITE_STREAM_ERROR = new ErrorCode(1_040_07_001, "写作生成异常!"); - - // ========== API 思维导图 1-040-008-000 ========== - ErrorCode MIND_MAP_NOT_EXISTS = new ErrorCode(1_040_008_000, "思维导图不存在!"); - - // ========== API 知识库 1-040-009-000 ========== - ErrorCode KNOWLEDGE_NOT_EXISTS = new ErrorCode(1_040_009_000, "知识库不存在!"); - - ErrorCode KNOWLEDGE_DOCUMENT_NOT_EXISTS = new ErrorCode(1_040_009_101, "文档不存在!"); - ErrorCode KNOWLEDGE_DOCUMENT_FILE_EMPTY = new ErrorCode(1_040_009_102, "文档内容为空!"); - ErrorCode KNOWLEDGE_DOCUMENT_FILE_DOWNLOAD_FAIL = new ErrorCode(1_040_009_102, "文件下载失败!"); - ErrorCode KNOWLEDGE_DOCUMENT_FILE_READ_FAIL = new ErrorCode(1_040_009_102, "文档加载失败!"); - - ErrorCode KNOWLEDGE_SEGMENT_NOT_EXISTS = new ErrorCode(1_040_009_202, "段落不存在!"); - ErrorCode KNOWLEDGE_SEGMENT_CONTENT_TOO_LONG = new ErrorCode(1_040_009_203, "内容 Token 数为 {},超过最大限制 {}"); - - // ========== AI 工具 1-040-010-000 ========== - ErrorCode TOOL_NOT_EXISTS = new ErrorCode(1_040_010_000, "工具不存在"); - ErrorCode TOOL_NAME_NOT_EXISTS = new ErrorCode(1_040_010_001, "工具({})找不到 Bean"); - - // ========== AI 工作流 1-040-011-000 ========== - ErrorCode WORKFLOW_NOT_EXISTS = new ErrorCode(1_040_011_000, "工作流不存在"); - ErrorCode WORKFLOW_CODE_EXISTS = new ErrorCode(1_040_011_001, "工作流标识已存在"); - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java deleted file mode 100644 index cf8076150..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.image; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * AI 绘画状态的枚举 - * - * @author fansili - */ -@AllArgsConstructor -@Getter -public enum AiImageStatusEnum { - - IN_PROGRESS(10, "进行中"), - SUCCESS(20, "已完成"), - FAIL(30, "已失败"); - - /** - * 状态 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - - public static AiImageStatusEnum valueOfStatus(Integer status) { - for (AiImageStatusEnum statusEnum : AiImageStatusEnum.values()) { - if (statusEnum.getStatus().equals(status)) { - return statusEnum; - } - } - throw new IllegalArgumentException("未知会话状态: " + status); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelTypeEnum.java deleted file mode 100644 index bdba3e891..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelTypeEnum.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.model; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -/** - * AI 模型类型的枚举 - * - * @author 芋道源码 - */ -@Getter -@RequiredArgsConstructor -public enum AiModelTypeEnum implements ArrayValuable { - - CHAT(1, "对话"), - IMAGE(2, "图片"), - VOICE(3, "语音"), - VIDEO(4, "视频"), - EMBEDDING(5, "向量"), - RERANK(6, "重排序"); - - /** - * 类型 - */ - private final Integer type; - /** - * 类型名 - */ - private final String name; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiModelTypeEnum::getType).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiPlatformEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiPlatformEnum.java deleted file mode 100644 index bf15ec1f1..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiPlatformEnum.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.model; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 模型平台 - * - * @author fansili - */ -@Getter -@AllArgsConstructor -public enum AiPlatformEnum implements ArrayValuable { - - // ========== 国内平台 ========== - - TONG_YI("TongYi", "通义千问"), // 阿里 - YI_YAN("YiYan", "文心一言"), // 百度 - DEEP_SEEK("DeepSeek", "DeepSeek"), // DeepSeek - ZHI_PU("ZhiPu", "智谱"), // 智谱 AI - XING_HUO("XingHuo", "星火"), // 讯飞 - DOU_BAO("DouBao", "豆包"), // 字节 - HUN_YUAN("HunYuan", "混元"), // 腾讯 - SILICON_FLOW("SiliconFlow", "硅基流动"), // 硅基流动 - MINI_MAX("MiniMax", "MiniMax"), // 稀宇科技 - MOONSHOT("Moonshot", "月之暗面"), // KIMI - BAI_CHUAN("BaiChuan", "百川智能"), // 百川智能 - - // ========== 国外平台 ========== - - OPENAI("OpenAI", "OpenAI"), // OpenAI 官方 - AZURE_OPENAI("AzureOpenAI", "AzureOpenAI"), // OpenAI 微软 - ANTHROPIC("Anthropic", "Anthropic"), // Anthropic Claude - GEMINI("Gemini", "Gemini"), // 谷歌 Gemini - OLLAMA("Ollama", "Ollama"), - - STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI - MIDJOURNEY("Midjourney", "Midjourney"), // Midjourney - SUNO("Suno", "Suno"), // Suno AI - GROK("Grok","Grok"), // Grok - - ; - - /** - * 平台 - */ - private final String platform; - /** - * 平台名 - */ - private final String name; - - public static final String[] ARRAYS = Arrays.stream(values()).map(AiPlatformEnum::getPlatform).toArray(String[]::new); - - public static AiPlatformEnum validatePlatform(String platform) { - for (AiPlatformEnum platformEnum : AiPlatformEnum.values()) { - if (platformEnum.getPlatform().equals(platform)) { - return platformEnum; - } - } - throw new IllegalArgumentException("非法平台: " + platform); - } - - @Override - public String[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java deleted file mode 100644 index 82052943b..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.music; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 音乐生成模式的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiMusicGenerateModeEnum implements ArrayValuable { - - DESCRIPTION(1, "描述模式"), - LYRIC(2, "歌词模式"); - - /** - * 模式 - */ - private final Integer mode; - /** - * 模式名 - */ - private final String name; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiMusicGenerateModeEnum::getMode).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicStatusEnum.java deleted file mode 100644 index 9340a5976..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicStatusEnum.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.music; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 音乐状态的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiMusicStatusEnum implements ArrayValuable { - - IN_PROGRESS(10, "进行中"), - SUCCESS(20, "已完成"), - FAIL(30, "已失败"); - - /** - * 状态 - */ - private final Integer status; - - /** - * 状态名 - */ - private final String name; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiMusicStatusEnum::getStatus).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/write/AiWriteTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/write/AiWriteTypeEnum.java deleted file mode 100644 index 6d91433b7..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/write/AiWriteTypeEnum.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.write; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 写作类型的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiWriteTypeEnum implements ArrayValuable { - - WRITING(1, "撰写", "请撰写一篇关于 [{}] 的文章。文章的内容格式:{},语气:{},语言:{},长度:{}。请确保涵盖主要内容,不需要除了正文内容外的其他回复,如标题、额外的解释或道歉。"), - REPLY(2, "回复", "请针对如下内容:[{}] 做个回复。回复内容参考:[{}], 回复格式:{},语气:{},语言:{},长度:{}。不需要除了正文内容外的其他回复,如标题、开头、额外的解释或道歉。"); - - /** - * 类型 - */ - private final Integer type; - /** - * 类型名 - */ - private final String name; - - /** - * 模版 - */ - private final String prompt; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiWriteTypeEnum::getType).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/Dockerfile b/yudao-module-ai/yudao-module-ai-server/Dockerfile deleted file mode 100644 index cf053f209..000000000 --- a/yudao-module-ai/yudao-module-ai-server/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性 -## 感谢复旦核博士的建议!灰子哥,牛皮! -FROM eclipse-temurin:21-jre - -## 创建目录,并使用它作为工作目录 -RUN mkdir -p /yudao-module-ai-server -WORKDIR /yudao-module-ai-server -## 将后端项目的 Jar 文件,复制到镜像中 -COPY ./target/yudao-module-ai-server.jar app.jar - -## 设置 TZ 时区 -## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖 -ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m" - -## 暴露后端项目的 48080 端口 -EXPOSE 48090 - -## 启动后端项目 -CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar diff --git a/yudao-module-ai/yudao-module-ai-server/pom.xml b/yudao-module-ai/yudao-module-ai-server/pom.xml deleted file mode 100644 index 890635a5e..000000000 --- a/yudao-module-ai/yudao-module-ai-server/pom.xml +++ /dev/null @@ -1,318 +0,0 @@ - - - - cn.iocoder.cloud - yudao-module-ai - ${revision} - - 4.0.0 - yudao-module-ai-server - jar - - ${project.artifactId} - - ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。 - 目前已接入各种模型,不限于: - 国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek - 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno - - - 1.1.2 - - 1.1.0.0-RC2 - 1.2.6 - - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-env - - - - - cn.iocoder.cloud - yudao-module-system-api - ${revision} - - - cn.iocoder.cloud - yudao-module-infra-api - ${revision} - - - cn.iocoder.cloud - yudao-module-ai-api - ${revision} - - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-tenant - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-security - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-mybatis - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-rpc - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-config - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-job - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-test - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-excel - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-monitor - - - - - org.springframework.ai - spring-ai-starter-model-openai - ${spring-ai.version} - - - io.swagger.core.v3 - swagger-annotations-jakarta - - - - - org.springframework.ai - spring-ai-starter-model-azure-openai - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-anthropic - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-deepseek - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-ollama - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-stability-ai - ${spring-ai.version} - - - - org.springframework.ai - spring-ai-starter-model-zhipuai - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-minimax - ${spring-ai.version} - - - - - com.alibaba.cloud.ai - spring-ai-alibaba-starter-dashscope - ${alibaba-ai.version} - - - - - org.springaicommunity - qianfan-spring-boot-starter - 1.0.0 - - - - org.springaicommunity - moonshot-spring-boot-starter - 1.0.0 - - - - - - org.springframework.ai - spring-ai-starter-vector-store-qdrant - ${spring-ai.version} - - - - - org.springframework.ai - spring-ai-starter-vector-store-redis - ${spring-ai.version} - - - cn.iocoder.cloud - yudao-spring-boot-starter-redis - - - - - org.springframework.ai - spring-ai-starter-vector-store-milvus - ${spring-ai.version} - - - - org.slf4j - slf4j-reload4j - - - - - - - org.springframework.ai - spring-ai-tika-document-reader - ${spring-ai.version} - - - - spring-cloud-function-context - org.springframework.cloud - - - spring-cloud-function-core - org.springframework.cloud - - - - - - - - - org.springframework.ai - spring-ai-starter-mcp-server-webmvc - ${spring-ai.version} - - - io.swagger.core.v3 - swagger-annotations-jakarta - - - - - - org.springframework.ai - spring-ai-starter-mcp-client - ${spring-ai.version} - - - - - dev.tinyflow - tinyflow-java-core - ${tinyflow.version} - - - com.jfinal - enjoy - - - - com.agentsflex - agents-flex-store-elasticsearch - - - - com.agentsflex - agents-flex-search-engine-es - - - - org.codehaus.groovy - groovy-all - - - - org.slf4j - slf4j-simple - - - org.apache.logging.log4j - log4j-slf4j-impl - - - org.slf4j - slf4j-reload4j - - - - - - - - ${project.artifactId} - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - - repackage - - - - - - - \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/AiServerApplication.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/AiServerApplication.java deleted file mode 100644 index ec92b096f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/AiServerApplication.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.ai; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * 项目的启动类 - *

- * 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - * 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - * 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - * - * @author 芋道源码 - */ -@SpringBootApplication(exclude = { - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration.class, - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration.class, -}) // 解决 application-${profile}.yaml 配置文件下,通过 spring.autoconfigure.exclude 无法排除的问题 -public class AiServerApplication { - - public static void main(String[] args) { - // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - - SpringApplication.run(AiServerApplication.class, args); - - // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java deleted file mode 100644 index ddd426d28..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ /dev/null @@ -1,118 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; -import com.fhs.core.trans.anno.TransMethodResult; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 聊天对话") -@RestController -@RequestMapping("/ai/chat/conversation") -@Validated -public class AiChatConversationController { - - @Resource - private AiChatConversationService chatConversationService; - @Resource - private AiChatMessageService chatMessageService; - - @PostMapping("/create-my") - @Operation(summary = "创建【我的】聊天对话") - public CommonResult createChatConversationMy(@RequestBody @Valid AiChatConversationCreateMyReqVO createReqVO) { - return success(chatConversationService.createChatConversationMy(createReqVO, getLoginUserId())); - } - - @PutMapping("/update-my") - @Operation(summary = "更新【我的】聊天对话") - public CommonResult updateChatConversationMy(@RequestBody @Valid AiChatConversationUpdateMyReqVO updateReqVO) { - chatConversationService.updateChatConversationMy(updateReqVO, getLoginUserId()); - return success(true); - } - - @GetMapping("/my-list") - @Operation(summary = "获得【我的】聊天对话列表") - @TransMethodResult - public CommonResult> getChatConversationMyList() { - List list = chatConversationService.getChatConversationListByUserId(getLoginUserId()); - return success(BeanUtils.toBean(list, AiChatConversationRespVO.class)); - } - - @GetMapping("/get-my") - @Operation(summary = "获得【我的】聊天对话") - @Parameter(name = "id", required = true, description = "对话编号", example = "1024") - @TransMethodResult - public CommonResult getChatConversationMy(@RequestParam("id") Long id) { - AiChatConversationDO conversation = chatConversationService.getChatConversation(id); - if (conversation != null && ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { - conversation = null; - } - return success(BeanUtils.toBean(conversation, AiChatConversationRespVO.class)); - } - - @DeleteMapping("/delete-my") - @Operation(summary = "删除聊天对话") - @Parameter(name = "id", required = true, description = "对话编号", example = "1024") - public CommonResult deleteChatConversationMy(@RequestParam("id") Long id) { - chatConversationService.deleteChatConversationMy(id, getLoginUserId()); - return success(true); - } - - @DeleteMapping("/delete-by-unpinned") - @Operation(summary = "删除未置顶的聊天对话") - public CommonResult deleteChatConversationMyByUnpinned() { - chatConversationService.deleteChatConversationMyByUnpinned(getLoginUserId()); - return success(true); - } - - // ========== 对话管理 ========== - - @GetMapping("/page") - @Operation(summary = "获得对话分页", description = "用于【对话管理】菜单") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:query')") - @TransMethodResult - public CommonResult> getChatConversationPage(AiChatConversationPageReqVO pageReqVO) { - PageResult pageResult = chatConversationService.getChatConversationPage(pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - // 拼接关联数据 - Map messageCountMap = chatMessageService.getChatMessageCountMap( - convertList(pageResult.getList(), AiChatConversationDO::getId)); - return success(BeanUtils.toBean(pageResult, AiChatConversationRespVO.class, - conversation -> conversation.setMessageCount(messageCountMap.getOrDefault(conversation.getId(), 0)))); - } - - @Operation(summary = "管理员删除对话") - @DeleteMapping("/delete-by-admin") - @Parameter(name = "id", required = true, description = "对话编号", example = "1024") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:delete')") - public CommonResult deleteChatConversationByAdmin(@RequestParam("id") Long id) { - chatConversationService.deleteChatConversationByAdmin(id); - return success(true); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http deleted file mode 100644 index 017714e09..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http +++ /dev/null @@ -1,66 +0,0 @@ -### 发送消息(段式) -POST {{baseUrl}}/ai/chat/message/send -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581724", - "content": "你是 OpenAI 么?" -} - -### 发送消息(流式) -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581724", - "content": "1+1=?" -} - -### 发送消息(流式)【带文件】 -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581797", - "content": "图片里有什么?", - "attachmentUrls": ["http://test.yudao.iocoder.cn/1755531278.jpeg"] -} - -### 发送消息(流式)【追问带文件】 -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581799", - "content": "说下图片里,有哪些字?", - "useContext": true -} - -### 发送消息(流式)【联网搜索】 -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581799", - "content": "今天是周几?", - "useSearch": true -} - -### 获得指定对话的消息列表 -GET {{baseUrl}}/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581799 -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -### 删除消息 -DELETE {{baseUrl}}/ai/chat/message/delete?id=50 -Authorization: {{token}} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java deleted file mode 100644 index bfd1e41ca..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ /dev/null @@ -1,157 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService; -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Flux; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - 聊天消息") -@RestController -@RequestMapping("/ai/chat/message") -@Slf4j -public class AiChatMessageController { - - @Resource - private AiChatMessageService chatMessageService; - @Resource - private AiChatConversationService chatConversationService; - @Resource - private AiChatRoleService chatRoleService; - @Resource - private AiKnowledgeSegmentService knowledgeSegmentService; - @Resource - private AiKnowledgeDocumentService knowledgeDocumentService; - - @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") - @PostMapping("/send") - public CommonResult sendMessage(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) { - return success(chatMessageService.sendMessage(sendReqVO, getLoginUserId())); - } - - @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") - @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public Flux> sendChatMessageStream(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) { - return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); - } - - @Operation(summary = "获得指定对话的消息列表") - @GetMapping("/list-by-conversation-id") - @Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024") - public CommonResult> getChatMessageListByConversationId( - @RequestParam("conversationId") Long conversationId) { - AiChatConversationDO conversation = chatConversationService.getChatConversation(conversationId); - if (conversation == null || ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { - return success(Collections.emptyList()); - } - // 1. 获取消息列表 - List messageList = chatMessageService.getChatMessageListByConversationId(conversationId); - if (CollUtil.isEmpty(messageList)) { - return success(Collections.emptyList()); - } - - // 2. 拼接数据,主要是知识库段落信息 - Map segmentMap = knowledgeSegmentService.getKnowledgeSegmentMap(convertListByFlatMap(messageList, - message -> CollUtil.isEmpty(message.getSegmentIds()) ? null : message.getSegmentIds().stream())); - Map documentMap = knowledgeDocumentService.getKnowledgeDocumentMap( - convertList(segmentMap.values(), AiKnowledgeSegmentDO::getDocumentId)); - List messageVOList = BeanUtils.toBean(messageList, AiChatMessageRespVO.class); - for (int i = 0; i < messageList.size(); i++) { - AiChatMessageDO message = messageList.get(i); - if (CollUtil.isEmpty(message.getSegmentIds())) { - continue; - } - // 设置知识库段落信息 - messageVOList.get(i).setSegments(convertList(message.getSegmentIds(), segmentId -> { - AiKnowledgeSegmentDO segment = segmentMap.get(segmentId); - if (segment == null) { - return null; - } - AiKnowledgeDocumentDO document = documentMap.get(segment.getDocumentId()); - if (document == null) { - return null; - } - return new AiChatMessageRespVO.KnowledgeSegment().setId(segment.getId()).setContent(segment.getContent()) - .setDocumentId(segment.getDocumentId()).setDocumentName(document.getName()); - })); - } - return success(messageVOList); - } - - @Operation(summary = "删除消息") - @DeleteMapping("/delete") - @Parameter(name = "id", required = true, description = "消息编号", example = "1024") - public CommonResult deleteChatMessage(@RequestParam("id") Long id) { - chatMessageService.deleteChatMessage(id, getLoginUserId()); - return success(true); - } - - @Operation(summary = "删除指定对话的消息") - @DeleteMapping("/delete-by-conversation-id") - @Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024") - public CommonResult deleteChatMessageByConversationId(@RequestParam("conversationId") Long conversationId) { - chatMessageService.deleteChatMessageByConversationId(conversationId, getLoginUserId()); - return success(true); - } - - // ========== 对话管理 ========== - - @GetMapping("/page") - @Operation(summary = "获得消息分页", description = "用于【对话管理】菜单") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:query')") - public CommonResult> getChatMessagePage(AiChatMessagePageReqVO pageReqVO) { - PageResult pageResult = chatMessageService.getChatMessagePage(pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - // 拼接数据 - Map roleMap = chatRoleService.getChatRoleMap( - convertSet(pageResult.getList(), AiChatMessageDO::getRoleId)); - return success(BeanUtils.toBean(pageResult, AiChatMessageRespVO.class, - respVO -> MapUtils.findAndThen(roleMap, respVO.getRoleId(), - role -> respVO.setRoleName(role.getName())))); - } - - @Operation(summary = "管理员删除消息") - @DeleteMapping("/delete-by-admin") - @Parameter(name = "id", required = true, description = "消息编号", example = "1024") - @PreAuthorize("@ss.hasPermission('ai:chat-message:delete')") - public CommonResult deleteChatMessageByAdmin(@RequestParam("id") Long id) { - chatMessageService.deleteChatMessageByAdmin(id); - return success(true); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java deleted file mode 100644 index 84595bea2..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 聊天对话创建【我的】 Request VO") -@Data -public class AiChatConversationCreateMyReqVO { - - @Schema(description = "聊天角色编号", example = "666") - private Long roleId; - - @Schema(description = "知识库编号", example = "1204") - private Long knowledgeId; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java deleted file mode 100644 index 967e866ea..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 聊天对话的分页 Request VO") -@Data -public class AiChatConversationPageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "1024") - private Long userId; - - @Schema(description = "对话标题", example = "你好") - private String title; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java deleted file mode 100644 index 7da37ebc9..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import com.fhs.core.trans.anno.Trans; -import com.fhs.core.trans.constant.TransType; -import com.fhs.core.trans.vo.VO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 聊天对话 Response VO") -@Data -public class AiChatConversationRespVO implements VO { - - @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") - private Long userId; - - @Schema(description = "对话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题") - private String title; - - @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean pinned; - - @Schema(description = "角色编号", example = "1") - @Trans(type = TransType.SIMPLE, target = AiChatRoleDO.class, fields = {"name", "avatar"}, refs = {"roleName", "roleAvatar"}) - private Long roleId; - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = "name", ref = "modelName") - private Long modelId; - - @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922") - private String model; - - @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") - private String modelName; - - @Schema(description = "角色设定", example = "一个快乐的程序员") - private String systemMessage; - - @Schema(description = "温度参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer maxContexts; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - - // ========== 关联 role 信息 ========== - - @Schema(description = "角色头像", example = "https://www.iocoder.cn/1.png") - private String roleAvatar; - - @Schema(description = "角色名字", example = "小黄") - private String roleName; - - // ========== 仅在【对话管理】时加载 ========== - - @Schema(description = "消息数量", example = "20") - private Integer messageCount; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java deleted file mode 100644 index 2b57572c4..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 聊天对话更新【我的】 Request VO") -@Data -public class AiChatConversationUpdateMyReqVO { - - @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "对话编号不能为空") - private Long id; - - @Schema(description = "对话标题", example = "我是一个标题") - private String title; - - @Schema(description = "是否置顶", example = "true") - private Boolean pinned; - - @Schema(description = "模型编号", example = "1") - private Long modelId; - - @Schema(description = "知识库编号", example = "1") - private Long knowledgeId; - - @Schema(description = "角色设定", example = "一个快乐的程序员") - private String systemMessage; - - @Schema(description = "温度参数", example = "0.8") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", example = "10") - private Integer maxContexts; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java deleted file mode 100644 index 7ccb6aa0b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 聊天消息的分页 Request VO") -@Data -public class AiChatMessagePageReqVO extends PageParam { - - @Schema(description = "对话编号", example = "2048") - private Long conversationId; - - @Schema(description = "用户编号", example = "1024") - private Long userId; - - @Schema(description = "消息内容", example = "你好") - private String content; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java deleted file mode 100644 index b0f13e3c2..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天消息 Response VO") -@Data -public class AiChatMessageRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") - private Long conversationId; - - @Schema(description = "回复消息编号", example = "1024") - private Long replyId; - - @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") - private String type; // 参见 MessageType 枚举类 - - @Schema(description = "用户编号", example = "4096") - private Long userId; - - @Schema(description = "角色编号", example = "888") - private Long roleId; - - @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo") - private String model; - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123") - private Long modelId; - - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") - private String content; - - @Schema(description = "推理内容", example = "要达到这个目标,你需要...") - private String reasoningContent; - - @Schema(description = "是否携带上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean useContext; - - @Schema(description = "知识库段落编号数组", example = "[1,2,3]") - private List segmentIds; - - @Schema(description = "知识库段落数组") - private List segments; - - @Schema(description = "联网搜索的网页内容数组") - private List webSearchPages; - - @Schema(description = "附件 URL 数组", example = "https://www.iocoder.cn/1.png") - private List attachmentUrls; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") - private LocalDateTime createTime; - - // ========== 仅在【对话管理】时加载 ========== - - @Schema(description = "角色名字", example = "小黄") - private String roleName; - - @Schema(description = "知识库段落", example = "Java 开发手册") - @Data - public static class KnowledgeSegment { - - @Schema(description = "段落编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - private String content; - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long documentId; - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品使用手册") - private String documentName; - - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java deleted file mode 100644 index 06ce0d10d..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") -@Data -public class AiChatMessageSendReqVO { - - @Schema(description = "聊天对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "聊天对话编号不能为空") - private Long conversationId; - - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "帮我写个 Java 算法") - @NotEmpty(message = "聊天内容不能为空") - private String content; - - @Schema(description = "是否携带上下文", example = "true") - private Boolean useContext; - - @Schema(description = "是否联网搜索", example = "true") - private Boolean useSearch; - - @Schema(description = "附件 URL 数组", example = "https://www.iocoder.cn/1.png") - private List attachmentUrls; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java deleted file mode 100644 index 520712b9b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天消息发送 Response VO") -@Data -public class AiChatMessageSendRespVO { - - @Schema(description = "发送消息", requiredMode = Schema.RequiredMode.REQUIRED) - private Message send; - - @Schema(description = "接收消息", requiredMode = Schema.RequiredMode.REQUIRED) - private Message receive; - - @Schema(description = "消息") - @Data - public static class Message { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") - private String type; // 参见 MessageType 枚举类 - - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") - private String content; - - @Schema(description = "推理内容", example = "要达到这个目标,你需要...") - private String reasoningContent; - - @Schema(description = "知识库段落编号数组", example = "[1,2,3]") - private List segmentIds; - - @Schema(description = "知识库段落数组") - private List segments; - - @Schema(description = "联网搜索的网页内容数组") - private List webSearchPages; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http deleted file mode 100644 index 9047610c0..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http +++ /dev/null @@ -1,42 +0,0 @@ -### 生成图片:OpenAI(DALL) -POST {{baseUrl}}/ai/image/draw -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "OpenAI", - "prompt": "可爱的小喵星人", - "model": "dall-e-3", - "height": "1024", - "width": "1024", - "options": { - "style": "vivid" - } -} - -### 生成图片:StableDiffusion -POST {{baseUrl}}/ai/image/draw -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "StableDiffusion", - "prompt": "中国长城", - "model": "stable-diffusion-v1-6", - "height": "1024", - "width": "1024", - "style": "vivid" -} - -### 生成图片:生成图片(Midjourney) -POST {{baseUrl}}/ai/image/midjourney/imagine -Content-Type: application/json -Authorization: {{token}} - -{ - "prompt": "中国旗袍", - "model": "midjourney", - "width": "1", - "height": "1", - "version": "6.0" -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java deleted file mode 100644 index 1d9503f36..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ /dev/null @@ -1,139 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import cn.iocoder.yudao.module.ai.service.image.AiImageService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 绘画") -@RestController -@RequestMapping("/ai/image") -@Slf4j -public class AiImageController { - - @Resource - private AiImageService imageService; - - @GetMapping("/my-page") - @Operation(summary = "获取【我的】绘图分页") - public CommonResult> getImagePageMy(@Validated AiImagePageReqVO pageReqVO) { - PageResult pageResult = imageService.getImagePageMy(getLoginUserId(), pageReqVO); - return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); - } - - @GetMapping("/public-page") - @Operation(summary = "获取公开的绘图分页") - public CommonResult> getImagePagePublic(AiImagePublicPageReqVO pageReqVO) { - PageResult pageResult = imageService.getImagePagePublic(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); - } - - @GetMapping("/get-my") - @Operation(summary = "获取【我的】绘图记录") - @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult getImageMy(@RequestParam("id") Long id) { - AiImageDO image = imageService.getImage(id); - if (image == null || ObjUtil.notEqual(getLoginUserId(), image.getUserId())) { - return success(null); - } - return success(BeanUtils.toBean(image, AiImageRespVO.class)); - } - - @GetMapping("/my-list-by-ids") - @Operation(summary = "获取【我的】绘图记录列表") - @Parameter(name = "ids", required = true, description = "绘画编号数组", example = "1024,2048") - public CommonResult> getImageListMyByIds(@RequestParam("ids") List ids) { - List imageList = imageService.getImageList(ids); - imageList.removeIf(item -> !ObjUtil.equal(getLoginUserId(), item.getUserId())); - return success(BeanUtils.toBean(imageList, AiImageRespVO.class)); - } - - @Operation(summary = "生成图片") - @PostMapping("/draw") - public CommonResult drawImage(@Valid @RequestBody AiImageDrawReqVO drawReqVO) { - return success(imageService.drawImage(getLoginUserId(), drawReqVO)); - } - - @Operation(summary = "删除【我的】绘画记录") - @DeleteMapping("/delete-my") - @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult deleteImageMy(@RequestParam("id") Long id) { - imageService.deleteImageMy(id, getLoginUserId()); - return success(true); - } - - // ================ midjourney 专属 ================ - - @Operation(summary = "【Midjourney】生成图片") - @PostMapping("/midjourney/imagine") - public CommonResult midjourneyImagine(@Valid @RequestBody AiMidjourneyImagineReqVO reqVO) { - Long imageId = imageService.midjourneyImagine(getLoginUserId(), reqVO); - return success(imageId); - } - - @Operation(summary = "【Midjourney】通知图片进展", description = "由 Midjourney Proxy 回调") - @PostMapping("/midjourney/notify") // 必须是 POST 方法,否则会报错 - @PermitAll - @TenantIgnore - public CommonResult midjourneyNotify(@Valid @RequestBody MidjourneyApi.Notify notify) { - imageService.midjourneyNotify(notify); - return success(true); - } - - @Operation(summary = "【Midjourney】Action 操作(二次生成图片)", description = "例如说:放大、缩小、U1、U2 等") - @PostMapping("/midjourney/action") - public CommonResult midjourneyAction(@Valid @RequestBody AiMidjourneyActionReqVO reqVO) { - Long imageId = imageService.midjourneyAction(getLoginUserId(), reqVO); - return success(imageId); - } - - // ================ 绘图管理 ================ - - @GetMapping("/page") - @Operation(summary = "获得绘画分页") - @PreAuthorize("@ss.hasPermission('ai:image:query')") - public CommonResult> getImagePage(@Valid AiImagePageReqVO pageReqVO) { - PageResult pageResult = imageService.getImagePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); - } - - @PutMapping("/update") - @Operation(summary = "更新绘画") - @PreAuthorize("@ss.hasPermission('ai:image:update')") - public CommonResult updateImage(@Valid @RequestBody AiImageUpdateReqVO updateReqVO) { - imageService.updateImage(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除绘画") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:image:delete')") - public CommonResult deleteImage(@RequestParam("id") Long id) { - imageService.deleteImage(id); - return success(true); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java deleted file mode 100644 index 02225ea49..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; -import org.springframework.ai.openai.OpenAiImageOptions; -import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; - -import java.util.Map; - -@Schema(description = "管理后台 - AI 绘画 Request VO") -@Data -public class AiImageDrawReqVO { - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "模型编号不能为空") - private Long modelId; - - @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "画一个长城") - @NotEmpty(message = "提示词不能为空") - @Size(max = 1200, message = "提示词最大 1200") - private String prompt; - - /** - * 1. dall-e-2 模型:256x256、512x512、1024x1024 - * 2. dall-e-3 模型:1024x1024, 1792x1024, 或 1024x1792 - */ - @Schema(description = "图片高度") - @NotNull(message = "图片高度不能为空") - private Integer height; - - @Schema(description = "图片宽度") - @NotNull(message = "图片宽度不能为空") - private Integer width; - - // ========== 各平台绘画的拓展参数 ========== - - /** - * 绘制参数,不同 platform 的不同参数 - * - * 1. {@link OpenAiImageOptions} - * 2. {@link StabilityAiImageOptions} - */ - @Schema(description = "绘制参数") - private Map options; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java deleted file mode 100644 index 3b48686b9..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 绘画分页 Request VO") -@Data -public class AiImagePageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "28987") - private Long userId; - - @Schema(description = "平台", example = "OpenAI") - private String platform; - - @Schema(description = "提示词", example = "1") - private String prompt; - - @Schema(description = "绘画状态", example = "1") - private Integer status; - - @Schema(description = "是否发布", example = "1") - private Boolean publicStatus; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePublicPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePublicPageReqVO.java deleted file mode 100644 index e7ff80a98..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePublicPageReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘画公开的分页 Request VO") -@Data -public class AiImagePublicPageReqVO extends PageParam { - - @Schema(description = "提示词") - private String prompt; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java deleted file mode 100644 index fa3a957fe..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java +++ /dev/null @@ -1,60 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; - -@Schema(description = "管理后台 - AI 绘画 Response VO") -@Data -public class AiImageRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long userId; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - private String platform; // 参见 AiPlatformEnum 枚举 - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "stable-diffusion-v1-6") - private String model; - - @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "南极的小企鹅") - private String prompt; - - @Schema(description = "图片宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer width; - - @Schema(description = "图片高度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer height; - - @Schema(description = "绘画状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer status; - - @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED, example = "public") - private Boolean publicStatus; - - @Schema(description = "图片地址", example = "https://www.iocoder.cn/1.png") - private String picUrl; - - @Schema(description = "绘画错误信息", example = "图片错误信息") - private String errorMessage; - - @Schema(description = "绘制参数") - private Map options; - - @Schema(description = "mj buttons 按钮") - private List buttons; - - @Schema(description = "完成时间") - private LocalDateTime finishTime; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdateReqVO.java deleted file mode 100644 index 45df01015..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘画修改 Request VO") -@Data -public class AiImageUpdateReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "是否发布", example = "true") - private Boolean publicStatus; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java deleted file mode 100644 index 28803a051..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘图操作(Midjourney) Request VO") -@Data -public class AiMidjourneyActionReqVO { - - @Schema(description = "图片编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "图片编号不能为空") - private Long id; - - @Schema(description = "操作按钮编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MJ::JOB::variation::4::06aa3e66-0e97-49cc-8201-e0295d883de4") - @NotEmpty(message = "操作按钮编号不能为空") - private String customId; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java deleted file mode 100644 index efb590615..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘画生成(Midjourney) Request VO") -@Data -public class AiMidjourneyImagineReqVO { - - @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "中国神龙") - @NotEmpty(message = "提示词不能为空!") - private String prompt; - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "模型编号不能为空") - private Long modelId; - - @Schema(description = "图片宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "图片宽度不能为空") - private Integer width; - - @Schema(description = "图片高度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "图片高度不能为空") - private Integer height; - - @Schema(description = "版本号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6.0") - @NotEmpty(message = "版本号不能为空") - private String version; - - @Schema(description = "参考图", example = "https://www.iocoder.cn/x.png") - private String referImageUrl; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.http b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.http deleted file mode 100644 index a0f127865..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.http +++ /dev/null @@ -1,35 +0,0 @@ -### 创建知识库 -POST {{baseUrl}}/ai/knowledge/create -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "name": "测试标题", - "description": "测试描述", - "embeddingModelId": 30, - "topK": 3, - "similarityThreshold": 0.5, - "status": 0 -} - -### 更新知识库 -PUT {{baseUrl}}/ai/knowledge/update -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "id": 1, - "name": "测试标题(更新)", - "description": "测试描述", - "embeddingModelId": 30, - "topK": 5, - "similarityThreshold": 0.6, - "status": 0 -} - -### 获取知识库分页 -GET {{baseUrl}}/ai/knowledge/page?pageNo=1&pageSize=10 -Authorization: {{token}} -tenant-id: {{adminTenantId}} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java deleted file mode 100644 index b9daa9513..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java +++ /dev/null @@ -1,84 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI 知识库") -@RestController -@RequestMapping("/ai/knowledge") -@Validated -public class AiKnowledgeController { - - @Resource - private AiKnowledgeService knowledgeService; - - @GetMapping("/page") - @Operation(summary = "获取知识库分页") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgePage(@Valid AiKnowledgePageReqVO pageReqVO) { - PageResult pageResult = knowledgeService.getKnowledgePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiKnowledgeRespVO.class)); - } - - @GetMapping("/get") - @Operation(summary = "获得知识库") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult getKnowledge(@RequestParam("id") Long id) { - AiKnowledgeDO knowledge = knowledgeService.getKnowledge(id); - return success(BeanUtils.toBean(knowledge, AiKnowledgeRespVO.class)); - } - - @PostMapping("/create") - @Operation(summary = "创建知识库") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult createKnowledge(@RequestBody @Valid AiKnowledgeSaveReqVO createReqVO) { - return success(knowledgeService.createKnowledge(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新知识库") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledge(@RequestBody @Valid AiKnowledgeSaveReqVO updateReqVO) { - knowledgeService.updateKnowledge(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除知识库") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:knowledge:delete')") - public CommonResult deleteKnowledge(@RequestParam("id") Long id) { - knowledgeService.deleteKnowledge(id); - return success(true); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得知识库的精简列表") - public CommonResult> getKnowledgeSimpleList() { - List list = knowledgeService.getKnowledgeSimpleListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(convertList(list, knowledge -> new AiKnowledgeRespVO() - .setId(knowledge.getId()).setName(knowledge.getName()))); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.http b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.http deleted file mode 100644 index 1c858ed3e..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.http +++ /dev/null @@ -1,35 +0,0 @@ -### 创建知识文档 -POST {{baseUrl}}/ai/knowledge/document/create -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -{ - "knowledgeId": 2, - "name": "测试文档", - "url": "https://static.iocoder.cn/README.md", - "segmentMaxTokens": 800 -} - -### 批量创建知识文档 -POST {{baseUrl}}/ai/knowledge/document/create-list -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -{ - "knowledgeId": 1, - "list": [ - { - "name": "测试文档1", - "url": "https://static.iocoder.cn/README.md", - "segmentMaxTokens": 800 - }, - { - "name": "测试文档2", - "url": "https://static.iocoder.cn/README_yudao.md", - "segmentMaxTokens": 400 - } - ] -} - diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java deleted file mode 100644 index 68fe49a8a..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.*; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - AI 知识库文档") -@RestController -@RequestMapping("/ai/knowledge/document") -@Validated -public class AiKnowledgeDocumentController { - - @Resource - private AiKnowledgeDocumentService documentService; - - @GetMapping("/page") - @Operation(summary = "获取文档分页") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgeDocumentPage( - @Valid AiKnowledgeDocumentPageReqVO pageReqVO) { - PageResult pageResult = documentService.getKnowledgeDocumentPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiKnowledgeDocumentRespVO.class)); - } - - @GetMapping("/get") - @Operation(summary = "获取文档详情") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult getKnowledgeDocument(@RequestParam("id") Long id) { - AiKnowledgeDocumentDO document = documentService.getKnowledgeDocument(id); - return success(BeanUtils.toBean(document, AiKnowledgeDocumentRespVO.class)); - } - - @PostMapping("/create") - @Operation(summary = "新建文档(单个)") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult createKnowledgeDocument(@RequestBody @Valid AiKnowledgeDocumentCreateReqVO reqVO) { - Long id = documentService.createKnowledgeDocument(reqVO); - return success(id); - } - - @PostMapping("/create-list") - @Operation(summary = "新建文档(多个)") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult> createKnowledgeDocumentList( - @RequestBody @Valid AiKnowledgeDocumentCreateListReqVO reqVO) { - List ids = documentService.createKnowledgeDocumentList(reqVO); - return success(ids); - } - - @PutMapping("/update") - @Operation(summary = "更新文档") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeDocument(@Valid @RequestBody AiKnowledgeDocumentUpdateReqVO reqVO) { - documentService.updateKnowledgeDocument(reqVO); - return success(true); - } - - @PutMapping("/update-status") - @Operation(summary = "更新文档状态") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeDocumentStatus( - @Valid @RequestBody AiKnowledgeDocumentUpdateStatusReqVO reqVO) { - documentService.updateKnowledgeDocumentStatus(reqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除文档") - @PreAuthorize("@ss.hasPermission('ai:knowledge:delete')") - public CommonResult deleteKnowledgeDocument(@RequestParam("id") Long id) { - documentService.deleteKnowledgeDocument(id); - return success(true); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.http b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.http deleted file mode 100644 index 09018da3d..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.http +++ /dev/null @@ -1,17 +0,0 @@ -### 切片内容 -GET {{baseUrl}}/ai/knowledge/segment/split?url=https://static.iocoder.cn/README_yudao.md&segmentMaxTokens=800 -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -### 搜索段落内容 -GET {{baseUrl}}/ai/knowledge/segment/search?knowledgeId=2&content=如何使用这个产品&topK=5&similarityThreshold=0.1 -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -### 获取文档处理列表 -GET {{baseUrl}}/ai/knowledge/segment/get-process-list?documentIds=1,2,3 -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java deleted file mode 100644 index 34f324491..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java +++ /dev/null @@ -1,130 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService; -import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchReqBO; -import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchRespBO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.hibernate.validator.constraints.URL; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; - -@Tag(name = "管理后台 - AI 知识库段落") -@RestController -@RequestMapping("/ai/knowledge/segment") -@Validated -public class AiKnowledgeSegmentController { - - @Resource - private AiKnowledgeSegmentService segmentService; - @Resource - private AiKnowledgeDocumentService documentService; - - @GetMapping("/get") - @Operation(summary = "获取段落详情") - @Parameter(name = "id", description = "段落编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult getKnowledgeSegment(@RequestParam("id") Long id) { - AiKnowledgeSegmentDO segment = segmentService.getKnowledgeSegment(id); - return success(BeanUtils.toBean(segment, AiKnowledgeSegmentRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获取段落分页") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgeSegmentPage( - @Valid AiKnowledgeSegmentPageReqVO pageReqVO) { - PageResult pageResult = segmentService.getKnowledgeSegmentPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiKnowledgeSegmentRespVO.class)); - } - - @PostMapping("/create") - @Operation(summary = "创建段落") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult createKnowledgeSegment(@Valid @RequestBody AiKnowledgeSegmentSaveReqVO createReqVO) { - return success(segmentService.createKnowledgeSegment(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新段落内容") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeSegment(@Valid @RequestBody AiKnowledgeSegmentSaveReqVO reqVO) { - segmentService.updateKnowledgeSegment(reqVO); - return success(true); - } - - @PutMapping("/update-status") - @Operation(summary = "启禁用段落内容") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeSegmentStatus( - @Valid @RequestBody AiKnowledgeSegmentUpdateStatusReqVO reqVO) { - segmentService.updateKnowledgeSegmentStatus(reqVO); - return success(true); - } - - @GetMapping("/split") - @Operation(summary = "切片内容") - @Parameters({ - @Parameter(name = "url", description = "文档 URL", required = true), - @Parameter(name = "segmentMaxTokens", description = "分段的最大 Token 数", required = true) - }) - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> splitContent( - @RequestParam("url") @URL String url, - @RequestParam(value = "segmentMaxTokens") Integer segmentMaxTokens) { - List segments = segmentService.splitContent(url, segmentMaxTokens); - return success(BeanUtils.toBean(segments, AiKnowledgeSegmentRespVO.class)); - } - - @GetMapping("/get-process-list") - @Operation(summary = "获取文档处理列表") - @Parameter(name = "documentIds", description = "文档编号列表", required = true, example = "1,2,3") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgeSegmentProcessList( - @RequestParam("documentIds") List documentIds) { - List list = segmentService.getKnowledgeSegmentProcessList(documentIds); - return success(list); - } - - @GetMapping("/search") - @Operation(summary = "搜索段落内容") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> searchKnowledgeSegment( - @Valid AiKnowledgeSegmentSearchReqVO reqVO) { - // 1. 搜索段落 - List segments = segmentService - .searchKnowledgeSegment(BeanUtils.toBean(reqVO, AiKnowledgeSegmentSearchReqBO.class)); - if (CollUtil.isEmpty(segments)) { - return success(Collections.emptyList()); - } - - // 2. 拼接 VO - Map documentMap = documentService.getKnowledgeDocumentMap(convertSet( - segments, AiKnowledgeSegmentSearchRespBO::getDocumentId)); - return success(BeanUtils.toBean(segments, AiKnowledgeSegmentSearchRespVO.class, - segment -> MapUtils.findAndThen(documentMap, segment.getDocumentId(), - document -> segment.setDocumentName(document.getName())))); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentCreateListReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentCreateListReqVO.java deleted file mode 100644 index 6545c0bc1..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentCreateListReqVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import java.util.List; - -@Schema(description = "管理后台 - AI 知识库文档批量创建 Request VO") -@Data -public class AiKnowledgeDocumentCreateListReqVO { - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204") - @NotNull(message = "知识库编号不能为空") - private Long knowledgeId; - - @Schema(description = "分段的最大 Token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "800") - @NotNull(message = "分段的最大 Token 数不能为空") - private Integer segmentMaxTokens; - - @Schema(description = "文档列表", requiredMode = Schema.RequiredMode.REQUIRED) - @NotEmpty(message = "文档列表不能为空") - private List list; - - @Schema(description = "文档") - @Data - public static class Document { - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "三方登陆") - @NotBlank(message = "文档名称不能为空") - private String name; - - @Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn") - @URL(message = "文档 URL 格式不正确") - private String url; - - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentPageReqVO.java deleted file mode 100644 index 15bb603c2..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentPageReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档的分页 Request VO") -@Data -public class AiKnowledgeDocumentPageReqVO extends PageParam { - - @Schema(description = "知识库编号", example = "1") - private Long knowledgeId; - - @Schema(description = "文档名称", example = "Java 开发手册") - private String name; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentRespVO.java deleted file mode 100644 index 7aef94a3f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentRespVO.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 知识库文档 Response VO") -@Data -public class AiKnowledgeDocumentRespVO { - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long knowledgeId; - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - private String name; - - @Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn") - private String url; - - @Schema(description = "文档内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 是一门面向对象的语言.....") - private String content; - - @Schema(description = "文档内容长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") - private Integer contentLength; - - @Schema(description = "文档 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer tokens; - - @Schema(description = "分片最大 Token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "512") - private Integer segmentMaxTokens; - - @Schema(description = "召回次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer retrievalCount; - - @Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateReqVO.java deleted file mode 100644 index e6dbe5cbd..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档更新 Request VO") -@Data -public class AiKnowledgeDocumentUpdateReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "名称", example = "Java 开发手册") - private String name; - - @Schema(description = "分片最大 Token 数", example = "1000") - private Integer segmentMaxTokens; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateStatusReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateStatusReqVO.java deleted file mode 100644 index 93d393ab4..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateStatusReqVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档更新状态 Request VO") -@Data -public class AiKnowledgeDocumentUpdateStatusReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "状态不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java deleted file mode 100644 index 1d2e49307..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - - -@Schema(description = "管理后台 - AI 知识库文档的创建 Request VO") -@Data -public class AiKnowledgeDocumentCreateReqVO { - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204") - @NotNull(message = "知识库编号不能为空") - private Long knowledgeId; - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "三方登陆") - @NotBlank(message = "文档名称不能为空") - private String name; - - @Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn") - @URL(message = "文档 URL 格式不正确") - private String url; - - @Schema(description = "分段的最大 Token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "800") - @NotNull(message = "分段的最大 Token 数不能为空") - private Integer segmentMaxTokens; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgePageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgePageReqVO.java deleted file mode 100644 index dc7943cf2..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgePageReqVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 知识库的分页 Request VO") -@Data -public class AiKnowledgePageReqVO extends PageParam { - - @Schema(description = "知识库名称", example = "芋艿") - private String name; - - @Schema(description = "是否启用", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeRespVO.java deleted file mode 100644 index 5e83b85a7..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeRespVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 知识库 Response VO") -@Data -public class AiKnowledgeRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南") - private String name; - - @Schema(description = "知识库描述", example = "帮助你快速构建系统") - private String description; - - @Schema(description = "向量模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "14") - private Long embeddingModelId; - - @Schema(description = "向量模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "qwen-72b-chat") - private String embeddingModel; - - @Schema(description = "topK", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") - private Integer topK; - - @Schema(description = "相似度阈值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.7") - private Double similarityThreshold; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeSaveReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeSaveReqVO.java deleted file mode 100644 index 774b7234a..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeSaveReqVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库新增/修改 Request VO") -@Data -public class AiKnowledgeSaveReqVO { - - @Schema(description = "对话编号", example = "1204") - private Long id; - - @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南") - @NotBlank(message = "知识库名称不能为空") - private String name; - - @Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "存储 ruoyi-vue-pro 操作文档") - private String description; - - @Schema(description = "向量模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "向量模型不能为空") - private Long embeddingModelId; - - @Schema(description = "topK", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") - @NotNull(message = "topK 不能为空") - private Integer topK; - - @Schema(description = "相似性阈值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.5") - @NotNull(message = "相似性阈值不能为空") - private Double similarityThreshold; - - @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "是否启用不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java deleted file mode 100644 index dd3b90300..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库分段的分页 Request VO") -@Data -public class AiKnowledgeSegmentPageReqVO extends PageParam { - - @Schema(description = "文档编号", example = "1") - private Long documentId; - - @Schema(description = "分段内容关键字", example = "Java 开发") - private String content; - - @Schema(description = "分段状态", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentProcessRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentProcessRespVO.java deleted file mode 100644 index a6b95265b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentProcessRespVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库段落向量进度 Response VO") -@Data -public class AiKnowledgeSegmentProcessRespVO { - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long documentId; - - @Schema(description = "总段落数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Long count; - - @Schema(description = "已向量化段落数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - private Long embeddingCount; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentRespVO.java deleted file mode 100644 index 24c452621..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentRespVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档分片 Response VO") -@Data -public class AiKnowledgeSegmentRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long documentId; - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long knowledgeId; - - @Schema(description = "向量库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1858496a-1dde-4edf-a43e-0aed08f37f8c") - private String vectorId; - - @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - private String content; - - @Schema(description = "切片内容长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer contentLength; - - @Schema(description = "token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer tokens; - - @Schema(description = "召回次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer retrievalCount; - - @Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private Long createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSaveReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSaveReqVO.java deleted file mode 100644 index 0c5dad11d..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSaveReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; - -@Schema(description = "管理后台 - AI 新增/修改知识库段落 request VO") -@Data -public class AiKnowledgeSegmentSaveReqVO { - - @Schema(description = "编号", example = "24790") - private Long id; - - @Schema(description = "知识库文档编号", example = "1024") - private Long documentId; - - @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - @NotEmpty(message = "切片内容不能为空") - private String content; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchReqVO.java deleted file mode 100644 index 3b3cd984b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchReqVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - AI 知识库段落搜索 Request VO") -@Data -public class AiKnowledgeSegmentSearchReqVO { - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "知识库编号不能为空") - private Long knowledgeId; - - @Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "如何使用这个产品") - @NotEmpty(message = "内容不能为空") - private String content; - - @Schema(description = "最大返回数量", example = "5") - private Integer topK; - - @Schema(description = "相似度阈值", example = "0.7") - private Double similarityThreshold; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchRespVO.java deleted file mode 100644 index 50bbc5c86..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库段落搜索 Response VO") -@Data -public class AiKnowledgeSegmentSearchRespVO extends AiKnowledgeSegmentRespVO { - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品使用手册") - private String documentName; - - @Schema(description = "相似度分数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.95") - private Double score; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateStatusReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateStatusReqVO.java deleted file mode 100644 index 2516c7dfb..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateStatusReqVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - - -@Schema(description = "管理后台 - AI 知识库段落的更新状态 Request VO") -@Data -public class AiKnowledgeSegmentUpdateStatusReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "是否启用不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/AiMindMapController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/AiMindMapController.java deleted file mode 100644 index db015e514..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/AiMindMapController.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; -import cn.iocoder.yudao.module.ai.service.mindmap.AiMindMapService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Flux; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 思维导图") -@RestController -@RequestMapping("/ai/mind-map") -public class AiMindMapController { - - @Resource - private AiMindMapService mindMapService; - - @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @Operation(summary = "导图生成(流式)", description = "流式返回,响应较快") - public Flux> generateMindMap(@RequestBody @Valid AiMindMapGenerateReqVO generateReqVO) { - return mindMapService.generateMindMap(generateReqVO, getLoginUserId()); - } - - // ================ 导图管理 ================ - - @DeleteMapping("/delete") - @Operation(summary = "删除思维导图") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:mind-map:delete')") - public CommonResult deleteMindMap(@RequestParam("id") Long id) { - mindMapService.deleteMindMap(id); - return success(true); - } - - @GetMapping("/page") - @Operation(summary = "获得思维导图分页") - @PreAuthorize("@ss.hasPermission('ai:mind-map:query')") - public CommonResult> getMindMapPage(@Valid AiMindMapPageReqVO pageReqVO) { - PageResult pageResult = mindMapService.getMindMapPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiMindMapRespVO.class)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapGenerateReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapGenerateReqVO.java deleted file mode 100644 index 08404bb0f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapGenerateReqVO.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -@Schema(description = "管理后台 - AI 思维导图生成 Request VO") -@Data -public class AiMindMapGenerateReqVO { - - @Schema(description = "思维导图内容提示", example = "Java 学习路线") - @NotBlank(message = "思维导图内容提示不能为空") - private String prompt; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapPageReqVO.java deleted file mode 100644 index f7769b4e6..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapPageReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 思维导图分页 Request VO") -@Data -public class AiMindMapPageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "4325") - private Long userId; - - @Schema(description = "生成内容提示", example = "Java 学习路线") - private String prompt; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapRespVO.java deleted file mode 100644 index f65e809e9..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapRespVO.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 思维导图 Response VO") -@Data -public class AiMindMapRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3373") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4325") - private Long userId; - - @Schema(description = "生成内容提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 学习路线") - private String prompt; - - @Schema(description = "生成的思维导图内容") - private String generatedContent; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - private String platform; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java deleted file mode 100644 index c109b033c..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java +++ /dev/null @@ -1,83 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI API 密钥") -@RestController -@RequestMapping("/ai/api-key") -@Validated -public class AiApiKeyController { - - @Resource - private AiApiKeyService apiKeyService; - - @PostMapping("/create") - @Operation(summary = "创建 API 密钥") - @PreAuthorize("@ss.hasPermission('ai:api-key:create')") - public CommonResult createApiKey(@Valid @RequestBody AiApiKeySaveReqVO createReqVO) { - return success(apiKeyService.createApiKey(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新 API 密钥") - @PreAuthorize("@ss.hasPermission('ai:api-key:update')") - public CommonResult updateApiKey(@Valid @RequestBody AiApiKeySaveReqVO updateReqVO) { - apiKeyService.updateApiKey(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除 API 密钥") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:api-key:delete')") - public CommonResult deleteApiKey(@RequestParam("id") Long id) { - apiKeyService.deleteApiKey(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得 API 密钥") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:api-key:query')") - public CommonResult getApiKey(@RequestParam("id") Long id) { - AiApiKeyDO apiKey = apiKeyService.getApiKey(id); - return success(BeanUtils.toBean(apiKey, AiApiKeyRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得 API 密钥分页") - @PreAuthorize("@ss.hasPermission('ai:api-key:query')") - public CommonResult> getApiKeyPage(@Valid AiApiKeyPageReqVO pageReqVO) { - PageResult pageResult = apiKeyService.getApiKeyPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiApiKeyRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得 API 密钥分页列表") - public CommonResult> getApiKeySimpleList() { - List list = apiKeyService.getApiKeyList(); - return success(convertList(list, key -> new AiModelRespVO().setId(key.getId()).setName(key.getName()))); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java deleted file mode 100644 index 804e21152..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ /dev/null @@ -1,128 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import com.fhs.core.trans.anno.TransMethodResult; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 聊天角色") -@RestController -@RequestMapping("/ai/chat-role") -@Validated -public class AiChatRoleController { - - @Resource - private AiChatRoleService chatRoleService; - - @GetMapping("/my-page") - @Operation(summary = "获得【我的】聊天角色分页") - @TransMethodResult - public CommonResult> getChatRoleMyPage(@Valid AiChatRolePageReqVO pageReqVO) { - PageResult pageResult = chatRoleService.getChatRoleMyPage(pageReqVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class)); - } - - @GetMapping("/get-my") - @Operation(summary = "获得【我的】聊天角色") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @TransMethodResult - public CommonResult getChatRoleMy(@RequestParam("id") Long id) { - AiChatRoleDO chatRole = chatRoleService.getChatRole(id); - if (ObjUtil.notEqual(chatRole.getUserId(), getLoginUserId())) { - return success(null); - } - return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class)); - } - - @PostMapping("/create-my") - @Operation(summary = "创建【我的】聊天角色") - public CommonResult createChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO createReqVO) { - return success(chatRoleService.createChatRoleMy(createReqVO, getLoginUserId())); - } - - @PutMapping("/update-my") - @Operation(summary = "更新【我的】聊天角色") - public CommonResult updateChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO updateReqVO) { - chatRoleService.updateChatRoleMy(updateReqVO, getLoginUserId()); - return success(true); - } - - @DeleteMapping("/delete-my") - @Operation(summary = "删除【我的】聊天角色") - @Parameter(name = "id", description = "编号", required = true) - public CommonResult deleteChatRoleMy(@RequestParam("id") Long id) { - chatRoleService.deleteChatRoleMy(id, getLoginUserId()); - return success(true); - } - - @GetMapping("/category-list") - @Operation(summary = "获得聊天角色的分类列表") - public CommonResult> getChatRoleCategoryList() { - return success(chatRoleService.getChatRoleCategoryList()); - } - - // ========== 角色管理 ========== - - @PostMapping("/create") - @Operation(summary = "创建聊天角色") - @PreAuthorize("@ss.hasPermission('ai:chat-role:create')") - public CommonResult createChatRole(@Valid @RequestBody AiChatRoleSaveReqVO createReqVO) { - return success(chatRoleService.createChatRole(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新聊天角色") - @PreAuthorize("@ss.hasPermission('ai:chat-role:update')") - public CommonResult updateChatRole(@Valid @RequestBody AiChatRoleSaveReqVO updateReqVO) { - chatRoleService.updateChatRole(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除聊天角色") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:chat-role:delete')") - public CommonResult deleteChatRole(@RequestParam("id") Long id) { - chatRoleService.deleteChatRole(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得聊天角色") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:chat-role:query')") - @TransMethodResult - public CommonResult getChatRole(@RequestParam("id") Long id) { - AiChatRoleDO chatRole = chatRoleService.getChatRole(id); - return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得聊天角色分页") - @PreAuthorize("@ss.hasPermission('ai:chat-role:query')") - public CommonResult> getChatRolePage(@Valid AiChatRolePageReqVO pageReqVO) { - PageResult pageResult = chatRoleService.getChatRolePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiModelController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiModelController.java deleted file mode 100644 index 86dd4d0a6..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiModelController.java +++ /dev/null @@ -1,89 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.service.model.AiModelService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI 模型") -@RestController -@RequestMapping("/ai/model") -@Validated -public class AiModelController { - - @Resource - private AiModelService modelService; - - @PostMapping("/create") - @Operation(summary = "创建模型") - @PreAuthorize("@ss.hasPermission('ai:model:create')") - public CommonResult createModel(@Valid @RequestBody AiModelSaveReqVO createReqVO) { - return success(modelService.createModel(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新模型") - @PreAuthorize("@ss.hasPermission('ai:model:update')") - public CommonResult updateModel(@Valid @RequestBody AiModelSaveReqVO updateReqVO) { - modelService.updateModel(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除模型") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:model:delete')") - public CommonResult deleteModel(@RequestParam("id") Long id) { - modelService.deleteModel(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得模型") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:model:query')") - public CommonResult getModel(@RequestParam("id") Long id) { - AiModelDO model = modelService.getModel(id); - return success(BeanUtils.toBean(model, AiModelRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得模型分页") - @PreAuthorize("@ss.hasPermission('ai:model:query')") - public CommonResult> getModelPage(@Valid AiModelPageReqVO pageReqVO) { - PageResult pageResult = modelService.getModelPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiModelRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得模型列表") - @Parameter(name = "type", description = "类型", required = true, example = "1") - @Parameter(name = "platform", description = "平台", example = "midjourney") - public CommonResult> getModelSimpleList( - @RequestParam("type") Integer type, - @RequestParam(value = "platform", required = false) String platform) { - List list = modelService.getModelListByStatusAndType( - CommonStatusEnum.ENABLE.getStatus(), type, platform); - return success(convertList(list, model -> new AiModelRespVO().setId(model.getId()) - .setName(model.getName()).setModel(model.getModel()).setPlatform(model.getPlatform()))); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiToolController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiToolController.java deleted file mode 100644 index e98f87e0b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiToolController.java +++ /dev/null @@ -1,84 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO; -import cn.iocoder.yudao.module.ai.service.model.AiToolService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI 工具") -@RestController -@RequestMapping("/ai/tool") -@Validated -public class AiToolController { - - @Resource - private AiToolService toolService; - - @PostMapping("/create") - @Operation(summary = "创建工具") - @PreAuthorize("@ss.hasPermission('ai:tool:create')") - public CommonResult createTool(@Valid @RequestBody AiToolSaveReqVO createReqVO) { - return success(toolService.createTool(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新工具") - @PreAuthorize("@ss.hasPermission('ai:tool:update')") - public CommonResult updateTool(@Valid @RequestBody AiToolSaveReqVO updateReqVO) { - toolService.updateTool(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除工具") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:tool:delete')") - public CommonResult deleteTool(@RequestParam("id") Long id) { - toolService.deleteTool(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得工具") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:tool:query')") - public CommonResult getTool(@RequestParam("id") Long id) { - AiToolDO tool = toolService.getTool(id); - return success(BeanUtils.toBean(tool, AiToolRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得工具分页") - @PreAuthorize("@ss.hasPermission('ai:tool:query')") - public CommonResult> getToolPage(@Valid AiToolPageReqVO pageReqVO) { - PageResult pageResult = toolService.getToolPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiToolRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得工具列表") - public CommonResult> getToolSimpleList() { - List list = toolService.getToolListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(convertList(list, tool -> new AiToolRespVO() - .setId(tool.getId()).setName(tool.getName()))); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java deleted file mode 100644 index 063696244..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; - -import lombok.*; -import java.util.*; -import io.swagger.v3.oas.annotations.media.Schema; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import org.springframework.format.annotation.DateTimeFormat; -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI API 密钥分页 Request VO") -@Data -public class AiApiKeyPageReqVO extends PageParam { - - @Schema(description = "名称", example = "文心一言") - private String name; - - @Schema(description = "平台", example = "OpenAI") - private String platform; - - @Schema(description = "状态", example = "1") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java deleted file mode 100644 index 55d6d802b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -@Schema(description = "管理后台 - AI API 密钥 Response VO") -@Data -public class AiApiKeyRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23538") - private Long id; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "文心一言") - private String name; - - @Schema(description = "密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "ABC") - private String apiKey; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - private String platform; - - @Schema(description = "自定义 API 地址", example = "https://aip.baidubce.com") - private String url; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java deleted file mode 100644 index 8fbc8fde7..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import jakarta.validation.constraints.*; - -@Schema(description = "管理后台 - AI API 密钥新增/修改 Request VO") -@Data -public class AiApiKeySaveReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23538") - private Long id; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "文心一言") - @NotEmpty(message = "名称不能为空") - private String name; - - @Schema(description = "密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "ABC") - @NotEmpty(message = "密钥不能为空") - private String apiKey; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - @NotEmpty(message = "平台不能为空") - private String platform; - - @Schema(description = "自定义 API 地址", example = "https://aip.baidubce.com") - private String url; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "状态不能为空") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java deleted file mode 100644 index 0a9d08de5..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -import lombok.*; -import io.swagger.v3.oas.annotations.media.Schema; -import cn.iocoder.yudao.framework.common.pojo.PageParam; - -@Schema(description = "管理后台 - AI 聊天角色分页 Request VO") -@Data -public class AiChatRolePageReqVO extends PageParam { - - @Schema(description = "角色名称", example = "李四") - private String name; - - @Schema(description = "角色类别", example = "创作") - private String category; - - @Schema(description = "是否公开", example = "1") - private Boolean publicStatus; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java deleted file mode 100644 index 2ef9565cc..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.fhs.core.trans.anno.Trans; -import com.fhs.core.trans.constant.TransType; -import com.fhs.core.trans.vo.VO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天角色 Response VO") -@Data -public class AiChatRoleRespVO implements VO { - - @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32746") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "9442") - private Long userId; - - @Schema(description = "模型编号", example = "17640") - @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = { "name", "model" }, refs = { "modelName", "model" }) - private Long modelId; - @Schema(description = "模型名字", example = "张三") - private String modelName; - @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - private String name; - - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") - private String avatar; - - @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作") - private String category; - - @Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer sort; - - @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - private String description; - - @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED) - private String systemMessage; - - @Schema(description = "引用的知识库编号列表", example = "1,2,3") - private List knowledgeIds; - - @Schema(description = "引用的工具编号列表", example = "1,2,3") - private List toolIds; - - @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") - private List mcpClientNames; - - @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Boolean publicStatus; - - @Schema(description = "状态", example = "1") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java deleted file mode 100644 index bd4a05723..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天角色新增/修改【我的】 Request VO") -@Data -public class AiChatRoleSaveMyReqVO { - - @Schema(description = "角色编号", example = "32746") - private Long id; - - @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @NotEmpty(message = "角色名称不能为空") - private String name; - - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") - @NotEmpty(message = "角色头像不能为空") - @URL(message = "角色头像必须是 URL 格式") - private String avatar; - - @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - @NotEmpty(message = "角色描述不能为空") - private String description; - - @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") - @NotEmpty(message = "角色设定不能为空") - private String systemMessage; - - @Schema(description = "引用的知识库编号列表", example = "1,2,3") - private List knowledgeIds; - - @Schema(description = "引用的工具编号列表", example = "1,2,3") - private List toolIds; - - @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") - private List mcpClientNames; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java deleted file mode 100644 index 8f2913dd5..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import jakarta.validation.constraints.*; -import org.hibernate.validator.constraints.URL; - -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天角色新增/修改 Request VO") -@Data -public class AiChatRoleSaveReqVO { - - @Schema(description = "角色编号", example = "32746") - private Long id; - - @Schema(description = "模型编号", example = "17640") - private Long modelId; - - @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @NotEmpty(message = "角色名称不能为空") - private String name; - - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") - @NotEmpty(message = "角色头像不能为空") - @URL(message = "角色头像必须是 URL 格式") - private String avatar; - - @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作") - @NotEmpty(message = "角色类别不能为空") - private String category; - - @Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "角色排序不能为空") - private Integer sort; - - @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - @NotEmpty(message = "角色描述不能为空") - private String description; - - @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") - @NotEmpty(message = "角色设定不能为空") - private String systemMessage; - - @Schema(description = "引用的知识库编号列表", example = "1,2,3") - private List knowledgeIds; - - @Schema(description = "引用的工具编号列表", example = "1,2,3") - private List toolIds; - - @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") - private List mcpClientNames; - - @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "是否公开不能为空") - private Boolean publicStatus; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "状态不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelPageReqVO.java deleted file mode 100644 index af8d1121a..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelPageReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import lombok.*; -import io.swagger.v3.oas.annotations.media.Schema; -import cn.iocoder.yudao.framework.common.pojo.PageParam; - -@Schema(description = "管理后台 - API 模型分页 Request VO") -@Data -public class AiModelPageReqVO extends PageParam { - - @Schema(description = "模型名字", example = "张三") - private String name; - - @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "模型平台", example = "OpenAI") - private String platform; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelRespVO.java deleted file mode 100644 index b50b70a08..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelRespVO.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 模型 Response VO") -@Data -public class AiModelRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2630") - private Long id; - - @Schema(description = "API 秘钥编号", example = "22042") - private Long keyId; - - @Schema(description = "模型名字", example = "张三") - private String name; - - @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "模型平台", example = "OpenAI") - private String platform; - - @Schema(description = "模型类型", example = "1") - private Integer type; - - @Schema(description = "排序", example = "1") - private Integer sort; - - @Schema(description = "状态", example = "2") - private Integer status; - - @Schema(description = "温度参数", example = "1") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", example = "8192") - private Integer maxContexts; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelSaveReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelSaveReqVO.java deleted file mode 100644 index 95ed6bf3c..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelSaveReqVO.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiModelTypeEnum; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - API 模型新增/修改 Request VO") -@Data -public class AiModelSaveReqVO { - - @Schema(description = "编号", example = "2630") - private Long id; - - @Schema(description = "API 秘钥编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22042") - @NotNull(message = "API 秘钥编号不能为空") - private Long keyId; - - @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") - @NotEmpty(message = "模型名字不能为空") - private String name; - - @Schema(description = "模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125") - @NotEmpty(message = "模型标识不能为空") - private String model; - - @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - @NotEmpty(message = "模型平台不能为空") - @InEnum(AiPlatformEnum.class) - private String platform; - - @Schema(description = "模型类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "模型类型不能为空") - @InEnum(AiModelTypeEnum.class) - private Integer type; - - @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "排序不能为空") - private Integer sort; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @InEnum(CommonStatusEnum.class) - @NotNull(message = "状态不能为空") - private Integer status; - - @Schema(description = "温度参数", example = "1") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", example = "8192") - private Integer maxContexts; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolPageReqVO.java deleted file mode 100644 index dc8b04c50..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolPageReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 工具分页 Request VO") -@Data -public class AiToolPageReqVO extends PageParam { - - @Schema(description = "工具名称", example = "王五") - private String name; - - @Schema(description = "工具描述", example = "你猜") - private String description; - - @Schema(description = "状态", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolRespVO.java deleted file mode 100644 index 6d5a02e68..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolRespVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 工具 Response VO") -@Data -public class AiToolRespVO { - - @Schema(description = "工具编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "19661") - private Long id; - - @Schema(description = "工具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") - private String name; - - @Schema(description = "工具描述", example = "你猜") - private String description; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolSaveReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolSaveReqVO.java deleted file mode 100644 index c85cfc33e..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolSaveReqVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; - -@Schema(description = "管理后台 - AI 工具新增/修改 Request VO") -@Data -public class AiToolSaveReqVO { - - @Schema(description = "工具编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "19661") - private Long id; - - @Schema(description = "工具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") - @NotEmpty(message = "工具名称不能为空") - private String name; - - @Schema(description = "工具描述", example = "你猜") - private String description; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http deleted file mode 100644 index ae68c82ea..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http +++ /dev/null @@ -1,26 +0,0 @@ -### 生成音乐:Suno + 歌词模式 -POST {{baseUrl}}/ai/music/generate -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "Suno", - "generateMode": 2, - "prompt": "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。", - "model": "chirp-v3.5", - "tags": ["Happy"], - "title": "Happy Song" -} - -### 生成音乐:Suno + 描述模式 -POST {{baseUrl}}/ai/music/generate -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "Suno", - "generateMode": 1, - "model": "chirp-v3.5", - "prompt": "happy music", - "makeInstrumental": false -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java deleted file mode 100644 index 6c09e4b30..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java +++ /dev/null @@ -1,98 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.music.vo.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; -import cn.iocoder.yudao.module.ai.service.music.AiMusicService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 音乐") -@RestController -@RequestMapping("/ai/music") -public class AiMusicController { - - @Resource - private AiMusicService musicService; - - @GetMapping("/my-page") - @Operation(summary = "获得【我的】音乐分页") - public CommonResult> getMusicMyPage(@Valid AiMusicPageReqVO pageReqVO) { - PageResult pageResult = musicService.getMusicMyPage(pageReqVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, AiMusicRespVO.class)); - } - - @PostMapping("/generate") - @Operation(summary = "音乐生成") - public CommonResult> generateMusic(@RequestBody @Valid AiSunoGenerateReqVO reqVO) { - return success(musicService.generateMusic(getLoginUserId(), reqVO)); - } - - @Operation(summary = "删除【我的】音乐记录") - @DeleteMapping("/delete-my") - @Parameter(name = "id", required = true, description = "音乐编号", example = "1024") - public CommonResult deleteMusicMy(@RequestParam("id") Long id) { - musicService.deleteMusicMy(id, getLoginUserId()); - return success(true); - } - - @GetMapping("/get-my") - @Operation(summary = "获取【我的】音乐") - @Parameter(name = "id", required = true, description = "音乐编号", example = "1024") - public CommonResult getMusicMy(@RequestParam("id") Long id) { - AiMusicDO music = musicService.getMusic(id); - if (music == null || ObjUtil.notEqual(getLoginUserId(), music.getUserId())) { - return success(null); - } - return success(BeanUtils.toBean(music, AiMusicRespVO.class)); - } - - @PostMapping("/update-my") - @Operation(summary = "修改【我的】音乐 目前只支持修改标题") - @Parameter(name = "title", required = true, description = "音乐名称", example = "夜空中最亮的星") - public CommonResult updateMy(AiMusicUpdateMyReqVO updateReqVO) { - musicService.updateMyMusic(updateReqVO, getLoginUserId()); - return success(true); - } - - // ================ 音乐管理 ================ - - @GetMapping("/page") - @Operation(summary = "获得音乐分页") - @PreAuthorize("@ss.hasPermission('ai:music:query')") - public CommonResult> getMusicPage(@Valid AiMusicPageReqVO pageReqVO) { - PageResult pageResult = musicService.getMusicPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiMusicRespVO.class)); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除音乐") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:music:delete')") - public CommonResult deleteMusic(@RequestParam("id") Long id) { - musicService.deleteMusic(id); - return success(true); - } - - @PutMapping("/update") - @Operation(summary = "更新音乐") - @PreAuthorize("@ss.hasPermission('ai:music:update')") - public CommonResult updateMusic(@Valid @RequestBody AiMusicUpdateReqVO updateReqVO) { - musicService.updateMusic(updateReqVO); - return success(true); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java deleted file mode 100644 index 678edae3d..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 音乐分页 Request VO") -@Data -public class AiMusicPageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "12212") - private Long userId; - - @Schema(description = "音乐名称", example = "夜空中最亮的星") - private String title; - - @Schema(description = "音乐状态", example = "20") - @InEnum(AiMusicStatusEnum.class) - private Integer status; - - @Schema(description = "生成模式", example = "1") - @InEnum(AiMusicGenerateModeEnum.class) - private Integer generateMode; - - @Schema(description = "是否发布", example = "true") - private Boolean publicStatus; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicRespVO.java deleted file mode 100644 index 05044a4e7..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicRespVO.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 音乐 Response VO") -@Data -public class AiMusicRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12212") - private Long userId; - - @Schema(description = "音乐名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "夜空中最亮的星") - private String title; - - @Schema(description = "歌词", example = "oh~卖糕的") - private String lyric; - - @Schema(description = "图片地址", example = "https://www.iocoder.cn") - private String imageUrl; - - @Schema(description = "音频地址", example = "https://www.iocoder.cn") - private String audioUrl; - - @Schema(description = "视频地址", example = "https://www.iocoder.cn") - private String videoUrl; - - @Schema(description = "音乐状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") - private Integer status; - - @Schema(description = "描述词", example = "一首轻快的歌曲") - private String gptDescriptionPrompt; - - @Schema(description = "提示词", example = "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。") - private String prompt; - - @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "Suno") - private String platform; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "chirp-v3.5") - private String model; - - @Schema(description = "生成模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer generateMode; - - @Schema(description = "音乐风格标签") - private List tags; - - @Schema(description = "音乐时长", example = "[\"pop\",\"jazz\",\"punk\"]") - private Double duration; - - @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean publicStatus; - - @Schema(description = "任务编号", example = "11369") - private String taskId; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateMyReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateMyReqVO.java deleted file mode 100644 index 457670115..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateMyReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 修改我的音乐 Request VO") -@Data -public class AiMusicUpdateMyReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "音乐名称", example = "夜空中最亮的星") - private String title; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateReqVO.java deleted file mode 100644 index 447bc9765..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 音乐修改 Request VO") -@Data -public class AiMusicUpdateReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "是否发布", example = "true") - private Boolean publicStatus; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java deleted file mode 100644 index f72d2b54a..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - AI 音乐生成 Request VO") -@Data -public class AiSunoGenerateReqVO { - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "Suno") - @NotBlank(message = "平台不能为空") - private String platform; // 参见 AiPlatformEnum 枚举 - - /** - * 1. 描述模式:描述词 + 是否纯音乐 + 模型 - * 2. 歌词模式:歌词 + 音乐风格 + 标题 + 模型 - */ - @Schema(description = "生成模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "生成模式不能为空") - private Integer generateMode; // 参见 AiMusicGenerateModeEnum 枚举 - - @Schema(description = "用于生成音乐音频的歌词提示", - example = """ - 1.描述模式:创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。 - 2.歌词模式: - [Verse] - 阳光下奔跑 多么欢快 - 假期就要来 心都飞起来 - 朋友在一旁 笑声又灿烂 - 无忧无虑的 每一天甜蜜 - [Chorus] - 马上放假了 快来庆祝 - 一起去旅行 快去冒险 - 日子太短暂 别再等待 - 马上放假了 梦想起飞 - """) - private String prompt; - - @Schema(description = "是否纯音乐", example = "true") - private Boolean makeInstrumental; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "chirp-v3.5") - @NotEmpty(message = "模型不能为空") - private String model; - - @Schema(description = "音乐风格", example = "[\"pop\",\"jazz\",\"punk\"]") - private List tags; - - @Schema(description = "音乐/歌曲名称", example = "夜空中最亮的星") - private String title; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.http b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.http deleted file mode 100644 index 8dc1b0c0f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.http +++ /dev/null @@ -1,12 +0,0 @@ -### 测试 AI 工作流 -POST {{baseUrl}}/ai/workflow/test -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "id": 4, - "params": { - "message": "1 + 1 = ?" - } -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java deleted file mode 100644 index d558d9045..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java +++ /dev/null @@ -1,77 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; -import cn.iocoder.yudao.module.ai.service.workflow.AiWorkflowService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - AI 工作流") -@RestController -@RequestMapping("/ai/workflow") -@Slf4j -public class AiWorkflowController { - - @Resource - private AiWorkflowService workflowService; - - @PostMapping("/create") - @Operation(summary = "创建 AI 工作流") - @PreAuthorize("@ss.hasPermission('ai:workflow:create')") - public CommonResult createWorkflow(@Valid @RequestBody AiWorkflowSaveReqVO createReqVO) { - return success(workflowService.createWorkflow(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新 AI 工作流") - @PreAuthorize("@ss.hasPermission('ai:workflow:update')") - public CommonResult updateWorkflow(@Valid @RequestBody AiWorkflowSaveReqVO updateReqVO) { - workflowService.updateWorkflow(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除 AI 工作流") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:workflow:delete')") - public CommonResult deleteWorkflow(@RequestParam("id") Long id) { - workflowService.deleteWorkflow(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得 AI 工作流") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:workflow:query')") - public CommonResult getWorkflow(@RequestParam("id") Long id) { - AiWorkflowDO workflow = workflowService.getWorkflow(id); - return success(BeanUtils.toBean(workflow, AiWorkflowRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得 AI 工作流分页") - @PreAuthorize("@ss.hasPermission('ai:workflow:query')") - public CommonResult> getWorkflowPage(@Valid AiWorkflowPageReqVO pageReqVO) { - PageResult pageResult = workflowService.getWorkflowPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiWorkflowRespVO.class)); - } - - @PostMapping("/test") - @Operation(summary = "测试 AI 工作流") - @PreAuthorize("@ss.hasPermission('ai:workflow:test')") - public CommonResult testWorkflow(@Valid @RequestBody AiWorkflowTestReqVO testReqVO) { - return success(workflowService.testWorkflow(testReqVO)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java deleted file mode 100644 index e55b85ea9..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 工作流分页 Request VO") -@Data -public class AiWorkflowPageReqVO extends PageParam { - - @Schema(description = "名称", example = "工作流") - private String name; - - @Schema(description = "标识", example = "FLOW") - private String code; - - @Schema(description = "状态", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java deleted file mode 100644 index e3a28ad64..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 工作流 Response VO") -@Data -public class AiWorkflowRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "工作流标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") - private String code; - - @Schema(description = "工作流名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") - private String name; - - @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") - private String remark; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "工作流模型 JSON", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - private String graph; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") - private LocalDateTime createTime; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java deleted file mode 100644 index 0a63c3773..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 工作流新增/修改 Request VO") -@Data -public class AiWorkflowSaveReqVO { - - @Schema(description = "编号", example = "1") - private Long id; - - @Schema(description = "工作流标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") - @NotEmpty(message = "工作流标识不能为空") - private String code; - - @Schema(description = "工作流名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") - @NotEmpty(message = "工作流名称不能为空") - private String name; - - @Schema(description = "备注", example = "FLOW") - private String remark; - - @Schema(description = "工作流模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - @NotEmpty(message = "工作流模型不能为空") - private String graph; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") - @NotNull(message = "状态不能为空") - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java deleted file mode 100644 index 37b455cc0..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -import cn.hutool.core.util.StrUtil; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.AssertTrue; -import lombok.Data; - -import java.util.Map; - -@Schema(description = "管理后台 - AI 工作流测试 Request VO") -@Data -public class AiWorkflowTestReqVO { - - @Schema(description = "工作流编号", example = "1024") - private Long id; - - @Schema(description = "工作流模型", example = "{}") - private String graph; - - @Schema(description = "参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - private Map params; - - @AssertTrue(message = "工作流或模型,必须传递一个") - public boolean isGraphValid() { - return id != null || StrUtil.isNotEmpty(graph); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/AiWriteController.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/AiWriteController.java deleted file mode 100644 index 7ef208b9a..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/AiWriteController.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWritePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO; -import cn.iocoder.yudao.module.ai.service.write.AiWriteService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Flux; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 写作") -@RestController -@RequestMapping("/ai/write") -public class AiWriteController { - - @Resource - private AiWriteService writeService; - - @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @Operation(summary = "写作生成(流式)", description = "流式返回,响应较快") - public Flux> generateWriteContent(@RequestBody @Valid AiWriteGenerateReqVO generateReqVO) { - return writeService.generateWriteContent(generateReqVO, getLoginUserId()); - } - - // ================ 写作管理 ================ - - @DeleteMapping("/delete") - @Operation(summary = "删除写作") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:write:delete')") - public CommonResult deleteWrite(@RequestParam("id") Long id) { - writeService.deleteWrite(id); - return success(true); - } - - @GetMapping("/page") - @Operation(summary = "获得写作分页") - @PreAuthorize("@ss.hasPermission('ai:write:query')") - public CommonResult> getWritePage(@Valid AiWritePageReqVO pageReqVO) { - PageResult pageResult = writeService.getWritePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiWriteRespVO.class)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteGenerateReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteGenerateReqVO.java deleted file mode 100644 index 21c60420d..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteGenerateReqVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write.vo; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 写作生成 Request VO") -@Data -public class AiWriteGenerateReqVO { - - @Schema(description = "写作类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @InEnum(value = AiWriteTypeEnum.class, message = "写作类型必须是 {value}") - private Integer type; - - @Schema(description = "写作内容提示", example = "1.撰写:田忌赛马;2.回复:不批") - private String prompt; - - @Schema(description = "原文", example = "领导我要辞职") - private String originalContent; - - @Schema(description = "长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "长度不能为空") - private Integer length; - - @Schema(description = "格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "格式不能为空") - private Integer format; - - @Schema(description = "语气", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "语气不能为空") - private Integer tone; - - @Schema(description = "语言", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "语言不能为空") - private Integer language; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWritePageReqVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWritePageReqVO.java deleted file mode 100644 index 04f99ae13..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWritePageReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - AI 写作分页 Request VO") -@Data -public class AiWritePageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "28404") - private Long userId; - - @Schema(description = "写作类型", example = "1") - private Integer type; - - @Schema(description = "平台", example = "TongYi") - private String platform; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteRespVO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteRespVO.java deleted file mode 100644 index 4160de9ad..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteRespVO.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 写作 Response VO") -@Data -public class AiWriteRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5311") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28404") - private Long userId; - - @Schema(description = "写作类型", example = "1") - private Integer type; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "TongYi") - private String platform; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "qwen") - private String model; - - @Schema(description = "生成内容提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "撰写:田忌赛马") - private String prompt; - - @Schema(description = "生成的内容", example = "你非常不错") - private String generatedContent; - - @Schema(description = "原文", example = "真的么?") - private String originalContent; - - @Schema(description = "长度提示词", example = "1") - private Integer length; - - @Schema(description = "格式提示词", example = "2") - private Integer format; - - @Schema(description = "语气提示词", example = "3") - private Integer tone; - - @Schema(description = "语言提示词", example = "4") - private Integer language; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java deleted file mode 100644 index 05b1ce233..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * TODO 芋艿:站位,无特殊作用 - */ -package cn.iocoder.yudao.module.ai.controller.app; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java deleted file mode 100644 index 68dfddfa3..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 RESTful API 给前端: - * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 - * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 - */ -package cn.iocoder.yudao.module.ai.controller; diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java deleted file mode 100644 index 23aec276d..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ /dev/null @@ -1,100 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.chat; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -import java.time.LocalDateTime; - -/** - * AI Chat 对话 DO - * - * 用户每次发起 Chat 聊天时,会创建一个 {@link AiChatConversationDO} 对象,将它的消息关联在一起 - * - * @author fansili - * @since 2024/4/14 17:35 - */ -@TableName("ai_chat_conversation") -@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiChatConversationDO extends BaseDO { - - public static final String TITLE_DEFAULT = "新对话"; - - /** - * ID 编号,自增 - */ - @TableId - private Long id; - - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 对话标题 - * - * 默认由系统自动生成,可用户手动修改 - */ - private String title; - /** - * 是否置顶 - */ - private Boolean pinned; - /** - * 置顶时间 - */ - private LocalDateTime pinnedTime; - - /** - * 角色编号 - * - * 关联 {@link AiChatRoleDO#getId()} - */ - private Long roleId; - - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} 字段 - */ - private Long modelId; - /** - * 模型标志 - * - * 冗余 {@link AiModelDO#getModel()} 字段 - */ - private String model; - - // ========== 对话配置 ========== - - /** - * 角色设定 - */ - private String systemMessage; - /** - * 温度参数 - * - * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 - */ - private Double temperature; - /** - * 单条回复的最大 Token 数量 - */ - private Integer maxTokens; - /** - * 上下文的最大 Message 数量 - */ - private Integer maxContexts; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java deleted file mode 100644 index 6885fedf6..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ /dev/null @@ -1,126 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.chat; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; -import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.ai.chat.messages.MessageType; - -import java.util.List; - -/** - * AI Chat 消息 DO - * - * @since 2024/4/14 17:35 - * @since 2024/4/14 17:35 - */ -@TableName(value = "ai_chat_message", autoResultMap = true) -@KeySequence("ai_chat_message_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiChatMessageDO extends BaseDO { - - /** - * 编号,作为每条聊天记录的唯一标识符 - */ - @TableId - private Long id; - - /** - * 对话编号 - * - * 关联 {@link AiChatConversationDO#getId()} 字段 - */ - private Long conversationId; - /** - * 回复消息编号 - * - * 关联 {@link #id} 字段 - * - * 大模型回复的消息编号,用于“问答”的关联 - */ - private Long replyId; - - /** - * 消息类型 - * - * 也等价于 OpenAPI 的 role 字段 - * - * 枚举 {@link MessageType} - */ - private String type; - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - /** - * 角色编号 - * - * 关联 {@link AiChatRoleDO#getId()} 字段 - */ - private Long roleId; - - /** - * 模型标志 - * - * 冗余 {@link AiModelDO#getModel()} - */ - private String model; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} 字段 - */ - private Long modelId; - - /** - * 聊天内容 - */ - private String content; - /** - * 推理内容 - */ - private String reasoningContent; - - /** - * 是否携带上下文 - */ - private Boolean useContext; - - /** - * 知识库段落编号数组 - * - * 关联 {@link AiKnowledgeSegmentDO#getId()} 字段 - */ - @TableField(typeHandler = LongListTypeHandler.class) - private List segmentIds; - - /** - * 联网搜索的网页内容数组 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List webSearchPages; - - /** - * 附件 URL 数组 - */ - @TableField(typeHandler = StringListTypeHandler.class) - private List attachmentUrls; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java deleted file mode 100644 index 72acf72df..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ /dev/null @@ -1,127 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.image; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.Data; -import org.springframework.ai.openai.OpenAiImageOptions; -import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; - -/** - * AI 绘画 DO - * - * @author fansili - */ -@TableName(value = "ai_image", autoResultMap = true) -@KeySequence("ai_image_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiImageDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - * - * 关联 {@link AdminUserRespDTO#getId()} - */ - private Long userId; - - /** - * 提示词 - */ - private String prompt; - - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long modelId; - /** - * 模型标识 - * - * 冗余 {@link AiModelDO#getModel()} - */ - private String model; - - /** - * 图片宽度 - */ - private Integer width; - /** - * 图片高度 - */ - private Integer height; - - /** - * 生成状态 - * - * 枚举 {@link AiImageStatusEnum} - */ - private Integer status; - - /** - * 完成时间 - */ - private LocalDateTime finishTime; - - /** - * 绘画错误信息 - */ - private String errorMessage; - - /** - * 图片地址 - */ - private String picUrl; - /** - * 是否公开 - */ - private Boolean publicStatus; - - /** - * 绘制参数,不同 platform 的不同参数 - * - * 1. {@link OpenAiImageOptions} - * 2. {@link StabilityAiImageOptions} - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private Map options; - - /** - * mj buttons 按钮 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List buttons; - - /** - * 任务编号 - * - * 1. midjourney proxy:关联的 task id - */ - private String taskId; - -} - diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java deleted file mode 100644 index e1327a50e..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 知识库 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_knowledge", autoResultMap = true) -@KeySequence("ai_knowledge_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiKnowledgeDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 知识库名称 - */ - private String name; - /** - * 知识库描述 - */ - private String description; - - /** - * 向量模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long embeddingModelId; - /** - * 模型标识 - * - * 冗余 {@link AiModelDO#getModel()} - */ - private String embeddingModel; - - /** - * topK - */ - private Integer topK; - /** - * 相似度阈值 - */ - private Double similarityThreshold; - - /** - * 状态 - *

- * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java deleted file mode 100644 index ac014e926..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java +++ /dev/null @@ -1,69 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 知识库-文档 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_knowledge_document") -@KeySequence("ai_knowledge_document_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiKnowledgeDocumentDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 知识库编号 - *

- * 关联 {@link AiKnowledgeDO#getId()} - */ - private Long knowledgeId; - /** - * 文档名称 - */ - private String name; - /** - * 文件 URL - */ - private String url; - /** - * 内容 - */ - private String content; - /** - * 文档长度 - */ - private Integer contentLength; - - /** - * 文档 token 数量 - */ - private Integer tokens; - /** - * 分片最大 Token 数 - */ - private Integer segmentMaxTokens; - - /** - * 召回次数 - */ - private Integer retrievalCount; - - /** - * 状态 - *

- * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java deleted file mode 100644 index cccbd6846..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 知识库-文档分段 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_knowledge_segment") -@KeySequence("ai_knowledge_segment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiKnowledgeSegmentDO extends BaseDO { - - /** - * 向量库的编号 - 空值 - */ - public static final String VECTOR_ID_EMPTY = ""; - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 知识库编号 - *

- * 关联 {@link AiKnowledgeDO#getId()} - */ - private Long knowledgeId; - /** - * 文档编号 - *

- * 关联 {@link AiKnowledgeDocumentDO#getId()} - */ - private Long documentId; - /** - * 切片内容 - */ - private String content; - /** - * 切片内容长度 - */ - private Integer contentLength; - - /** - * 向量库的编号 - */ - private String vectorId; - /** - * token 数量 - */ - private Integer tokens; - - /** - * 召回次数 - */ - private Integer retrievalCount; - - /** - * 状态 - *

- * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java deleted file mode 100644 index db788b7e8..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.mindmap; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 思维导图 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_mind_map") -@KeySequence("ai_mind_map_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiMindMapDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - *

- * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 平台 - *

- * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long modelId; - /** - * 模型 - */ - private String model; - - /** - * 生成内容提示 - */ - private String prompt; - - /** - * 生成的内容 - */ - private String generatedContent; - - /** - * 错误信息 - */ - private String errorMessage; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java deleted file mode 100644 index a29f8f116..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * AI API 秘钥 DO - * - * @author 芋道源码 - */ -@TableName("ai_api_key") -@KeySequence("ai_api_key_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiApiKeyDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 名称 - */ - private String name; - /** - * 密钥 - */ - private String apiKey; - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * API 地址 - */ - private String url; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java deleted file mode 100644 index d20b25e88..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java +++ /dev/null @@ -1,111 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; -import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -import java.util.List; - -/** - * AI 聊天角色 DO - * - * @author fansili - * @since 2024/4/24 19:39 - */ -@TableName(value = "ai_chat_role", autoResultMap = true) -@KeySequence("ai_chat_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiChatRoleDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 角色名称 - */ - private String name; - /** - * 角色头像 - */ - private String avatar; - /** - * 角色分类 - */ - private String category; - /** - * 角色描述 - */ - private String description; - /** - * 角色设定 - */ - private String systemMessage; - - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} 字段 - */ - private Long modelId; - - /** - * 引用的知识库编号列表 - * - * 关联 {@link AiKnowledgeDO#getId()} 字段 - */ - @TableField(typeHandler = LongListTypeHandler.class) - private List knowledgeIds; - /** - * 引用的工具编号列表 - * - * 关联 {@link AiToolDO#getId()} 字段 - */ - @TableField(typeHandler = LongListTypeHandler.class) - private List toolIds; - /** - * 引用的 MCP Client 名字列表 - * - * 关联 spring.ai.mcp.client 下的名字 - */ - @TableField(typeHandler = StringListTypeHandler.class) - private List mcpClientNames; - - /** - * 是否公开 - * - * 1. true - 公开;由管理员在【角色管理】所创建 - * 2. false - 私有;由个人在【我的角色】所创建 - */ - private Boolean publicStatus; - - /** - * 排序值 - */ - private Integer sort; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiModelDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiModelDO.java deleted file mode 100644 index 9e54f94c5..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiModelDO.java +++ /dev/null @@ -1,88 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiModelTypeEnum; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * AI 模型 DO - * - * 默认模型:{@link #status} 为开启,并且 {@link #sort} 排序第一 - * - * @author fansili - * @since 2024/4/24 19:39 - */ -@TableName("ai_model") -@KeySequence("ai_model_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiModelDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * API 秘钥编号 - * - * 关联 {@link AiApiKeyDO#getId()} - */ - private Long keyId; - /** - * 模型名称 - */ - private String name; - /** - * 模型标志 - */ - private String model; - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 类型 - * - * 枚举 {@link AiModelTypeEnum} - */ - private Integer type; - - /** - * 排序值 - */ - private Integer sort; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - - // ========== 对话配置 ========== - - /** - * 温度参数 - * - * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 - */ - private Double temperature; - /** - * 单条回复的最大 Token 数量 - */ - private Integer maxTokens; - /** - * 上下文的最大 Message 数量 - */ - private Integer maxContexts; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiToolDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiToolDO.java deleted file mode 100644 index 71322132f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiToolDO.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.tool.function.DirectoryListToolFunction; -import cn.iocoder.yudao.module.ai.tool.function.WeatherQueryToolFunction; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * AI 工具 DO - * - * @author 芋道源码 - */ -@TableName("ai_tool") -@KeySequence("ai_tool_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiToolDO extends BaseDO { - - /** - * 工具编号 - */ - @TableId - private Long id; - /** - * 工具名称 - * - * 对应 Bean 的名字,例如说: - * 1. {@link DirectoryListToolFunction} 的 Bean 名字是 directory_list - * 2. {@link WeatherQueryToolFunction} 的 Bean 名字是 weather_query - */ - private String name; - /** - * 工具描述 - */ - private String description; - /** - * 状态 - * - * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} - */ - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/music/AiMusicDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/music/AiMusicDO.java deleted file mode 100644 index cc16133a7..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/music/AiMusicDO.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.music; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.Data; - -import java.util.List; - -/** - * AI 音乐 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_music", autoResultMap = true) -@KeySequence("ai_music_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiMusicDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - *

- * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 音乐名称 - */ - private String title; - - /** - * 歌词 - */ - private String lyric; - - /** - * 图片地址 - */ - private String imageUrl; - /** - * 音频地址 - */ - private String audioUrl; - /** - * 视频地址 - */ - private String videoUrl; - - /** - * 音乐状态 - *

- * 枚举 {@link AiMusicStatusEnum} - */ - private Integer status; - - /** - * 生成模式 - *

- * 枚举 {@link AiMusicGenerateModeEnum} - */ - private Integer generateMode; - - /** - * 描述词 - */ - private String description; - - /** - * 平台 - *

- * 枚举 {@link AiPlatformEnum} - */ - private String platform; - // TODO @芋艿:modelId? - /** - * 模型 - */ - private String model; - - /** - * 音乐风格标签 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List tags; - - /** - * 音乐时长 - */ - private Double duration; - - /** - * 是否公开 - */ - private Boolean publicStatus; - - /** - * 任务编号 - */ - private String taskId; - - /** - * 错误信息 - */ - private String errorMessage; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java deleted file mode 100644 index d844f7da2..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.workflow; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 工作流 DO - * - * @author lesan - */ -@TableName(value = "ai_workflow", autoResultMap = true) -@KeySequence("ai_workflow") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiWorkflowDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 工作流名称 - */ - private String name; - /** - * 工作流标识 - */ - private String code; - - /** - * 工作流模型 JSON 数据 - */ - private String graph; - - /** - * 备注 - */ - private String remark; - - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java deleted file mode 100644 index 75e1e29ce..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java +++ /dev/null @@ -1,104 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.write; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.enums.DictTypeConstants; -import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 写作 DO - * - * @author xiaoxin - */ -@TableName("ai_write") -@KeySequence("ai_write_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiWriteDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 写作类型 - *

- * 枚举 {@link AiWriteTypeEnum} - */ - private Integer type; - - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long modelId; - /** - * 模型 - */ - private String model; - - /** - * 生成内容提示 - */ - private String prompt; - - /** - * 生成的内容 - */ - private String generatedContent; - /** - * 原文 - */ - private String originalContent; - - /** - * 长度提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_LENGTH} - */ - private Integer length; - /** - * 格式提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_FORMAT} - */ - private Integer format; - /** - * 语气提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_TONE} - */ - private Integer tone; - /** - * 语言提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_LANGUAGE} - */ - private Integer language; - - /** - * 错误信息 - */ - private String errorMessage; - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java deleted file mode 100644 index ce9da2f24..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.chat; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 聊天对话 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface AiChatConversationMapper extends BaseMapperX { - - default List selectListByUserId(Long userId) { - return selectList(AiChatConversationDO::getUserId, userId); - } - - default List selectListByUserIdAndPinned(Long userId, boolean pinned) { - return selectList(new LambdaQueryWrapperX() - .eq(AiChatConversationDO::getUserId, userId) - .eq(AiChatConversationDO::getPinned, pinned)); - } - - default PageResult selectChatConversationPage(AiChatConversationPageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiChatConversationDO::getUserId, pageReqVO.getUserId()) - .likeIfPresent(AiChatConversationDO::getTitle, pageReqVO.getTitle()) - .betweenIfPresent(AiChatConversationDO::getCreateTime, pageReqVO.getCreateTime()) - .orderByDesc(AiChatConversationDO::getId)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java deleted file mode 100644 index 5020f3944..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.chat; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * AI 聊天对话 Mapper - * - * @author fansili - */ -@Mapper -public interface AiChatMessageMapper extends BaseMapperX { - - default List selectListByConversationId(Long conversationId) { - return selectList(new LambdaQueryWrapperX() - .eq(AiChatMessageDO::getConversationId, conversationId) - .orderByAsc(AiChatMessageDO::getId)); - } - - default Map selectCountMapByConversationId(Collection conversationIds) { - // SQL count 查询 - List> result = selectMaps(new QueryWrapper() - .select("COUNT(id) AS count, conversation_id AS conversationId") - .in("conversation_id", conversationIds) - .groupBy("conversation_id")); - if (CollUtil.isEmpty(result)) { - return Collections.emptyMap(); - } - // 转换数据 - return CollectionUtils.convertMap(result, - record -> MapUtil.getLong(record, "conversationId"), - record -> MapUtil.getInt(record, "count" )); - } - - default PageResult selectPage(AiChatMessagePageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiChatMessageDO::getConversationId, pageReqVO.getConversationId()) - .eqIfPresent(AiChatMessageDO::getUserId, pageReqVO.getUserId()) - .likeIfPresent(AiChatMessageDO::getContent, pageReqVO.getContent()) - .betweenIfPresent(AiChatMessageDO::getCreateTime, pageReqVO.getCreateTime()) - .orderByDesc(AiChatMessageDO::getId)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java deleted file mode 100644 index f87c9472b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.image; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePublicPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 绘图 Mapper - * - * @author fansili - */ -@Mapper -public interface AiImageMapper extends BaseMapperX { - - default AiImageDO selectByTaskId(String taskId) { - return selectOne(AiImageDO::getTaskId, taskId); - } - - default PageResult selectPage(AiImagePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiImageDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiImageDO::getPlatform, reqVO.getPlatform()) - .eqIfPresent(AiImageDO::getStatus, reqVO.getStatus()) - .eqIfPresent(AiImageDO::getPublicStatus, reqVO.getPublicStatus()) - .betweenIfPresent(AiImageDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiImageDO::getId)); - } - - default PageResult selectPageMy(Long userId, AiImagePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiImageDO::getPrompt, reqVO.getPrompt()) - // 情况一:公开 - .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiImageDO::getPublicStatus, reqVO.getPublicStatus()) - // 情况二:私有 - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiImageDO::getUserId, userId) - .orderByDesc(AiImageDO::getId)); - } - - default PageResult selectPage(AiImagePublicPageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiImageDO::getPublicStatus, Boolean.TRUE) - .likeIfPresent(AiImageDO::getPrompt, pageReqVO.getPrompt()) - .orderByDesc(AiImageDO::getId)); - } - - default List selectListByStatusAndPlatform(Integer status, String platform) { - return selectList(AiImageDO::getStatus, status, - AiImageDO::getPlatform, platform); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java deleted file mode 100644 index 55f04bb32..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -/** - * AI 知识库文档 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiKnowledgeDocumentMapper extends BaseMapperX { - - default PageResult selectPage(AiKnowledgeDocumentPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiKnowledgeDocumentDO::getKnowledgeId, reqVO.getKnowledgeId()) - .likeIfPresent(AiKnowledgeDocumentDO::getName, reqVO.getName()) - .orderByDesc(AiKnowledgeDocumentDO::getId)); - } - - default void updateRetrievalCountIncr(Collection ids) { - update(new LambdaUpdateWrapper() - .setSql(" retrieval_count = retrieval_count + 1") - .in(AiKnowledgeDocumentDO::getId, ids)); - } - - default List selectListByStatus(Integer status) { - return selectList(AiKnowledgeDocumentDO::getStatus, status); - } - - default List selectListByKnowledgeId(Long knowledgeId) { - return selectList(AiKnowledgeDocumentDO::getKnowledgeId, knowledgeId); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeMapper.java deleted file mode 100644 index 3433c0b97..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 知识库 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiKnowledgeMapper extends BaseMapperX { - - default PageResult selectPage(AiKnowledgePageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiKnowledgeDO::getName, pageReqVO.getName()) - .eqIfPresent(AiKnowledgeDO::getStatus, pageReqVO.getStatus()) - .betweenIfPresent(AiKnowledgeDO::getCreateTime, pageReqVO.getCreateTime()) - .orderByDesc(AiKnowledgeDO::getId)); - } - - default List selectListByStatus(Integer status) { - return selectList(AiKnowledgeDO::getStatus, status); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java deleted file mode 100644 index 2b7daacda..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentProcessRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.github.yulichang.wrapper.MPJLambdaWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -/** - * AI 知识库分片 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiKnowledgeSegmentMapper extends BaseMapperX { - - default PageResult selectPage(AiKnowledgeSegmentPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eq(AiKnowledgeSegmentDO::getDocumentId, reqVO.getDocumentId()) - .likeIfPresent(AiKnowledgeSegmentDO::getContent, reqVO.getContent()) - .eqIfPresent(AiKnowledgeSegmentDO::getStatus, reqVO.getStatus()) - .orderByDesc(AiKnowledgeSegmentDO::getId)); - } - - default List selectListByVectorIds(List vectorIds) { - return selectList(new LambdaQueryWrapperX() - .in(AiKnowledgeSegmentDO::getVectorId, vectorIds) - .orderByDesc(AiKnowledgeSegmentDO::getId)); - } - - default List selectListByDocumentId(Long documentId) { - return selectList(new LambdaQueryWrapperX() - .eq(AiKnowledgeSegmentDO::getDocumentId, documentId) - .orderByDesc(AiKnowledgeSegmentDO::getId)); - } - - default List selectListByKnowledgeIdAndStatus(Long knowledgeId, Integer status) { - return selectList(AiKnowledgeSegmentDO::getKnowledgeId, knowledgeId, - AiKnowledgeSegmentDO::getStatus, status); - } - - default List selectProcessList(Collection documentIds) { - MPJLambdaWrapper wrapper = new MPJLambdaWrapperX() - .selectAs(AiKnowledgeSegmentDO::getDocumentId, AiKnowledgeSegmentProcessRespVO::getDocumentId) - .selectCount(AiKnowledgeSegmentDO::getId, "count") - .select("COUNT(CASE WHEN vector_id IS NOT NULL AND vector_id <> '" + AiKnowledgeSegmentDO.VECTOR_ID_EMPTY + "' THEN 1 ELSE NULL END) AS embeddingCount") - .in(AiKnowledgeSegmentDO::getDocumentId, documentIds) - .groupBy(AiKnowledgeSegmentDO::getDocumentId); - return selectJoinList(AiKnowledgeSegmentProcessRespVO.class, wrapper); - } - - default void updateRetrievalCountIncrByIds(List ids) { - update(new LambdaUpdateWrapper() - .setSql(" retrieval_count = retrieval_count + 1") - .in(AiKnowledgeSegmentDO::getId, ids)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java deleted file mode 100644 index 0292ef473..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.mindmap; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI 思维导图 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiMindMapMapper extends BaseMapperX { - - default PageResult selectPage(AiMindMapPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiMindMapDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiMindMapDO::getPrompt, reqVO.getPrompt()) - .betweenIfPresent(AiMindMapDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiMindMapDO::getId)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java deleted file mode 100644 index 0a2efe36f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI API 密钥 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface AiApiKeyMapper extends BaseMapperX { - - default PageResult selectPage(AiApiKeyPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiApiKeyDO::getName, reqVO.getName()) - .eqIfPresent(AiApiKeyDO::getPlatform, reqVO.getPlatform()) - .eqIfPresent(AiApiKeyDO::getStatus, reqVO.getStatus()) - .orderByDesc(AiApiKeyDO::getId)); - } - - default AiApiKeyDO selectFirstByPlatformAndStatus(String platform, Integer status) { - return selectOne(new QueryWrapperX() - .eq("platform", platform) - .eq("status", status) - .limitN(1) - .orderByAsc("id")); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatMapper.java deleted file mode 100644 index bfe2caf52..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import org.apache.ibatis.annotations.Mapper; - -import javax.annotation.Nullable; -import java.util.List; - -/** - * API 模型 Mapper - * - * @author fansili - */ -@Mapper -public interface AiChatMapper extends BaseMapperX { - - default AiModelDO selectFirstByStatus(Integer type, Integer status) { - return selectOne(new QueryWrapperX() - .eq("type", type) - .eq("status", status) - .limitN(1) - .orderByAsc("sort")); - } - - default PageResult selectPage(AiModelPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiModelDO::getName, reqVO.getName()) - .eqIfPresent(AiModelDO::getModel, reqVO.getModel()) - .eqIfPresent(AiModelDO::getPlatform, reqVO.getPlatform()) - .orderByAsc(AiModelDO::getSort)); - } - - default List selectListByStatusAndType(Integer status, Integer type, - @Nullable String platform) { - return selectList(new LambdaQueryWrapperX() - .eq(AiModelDO::getStatus, status) - .eq(AiModelDO::getType, type) - .eqIfPresent(AiModelDO::getPlatform, platform) - .orderByAsc(AiModelDO::getSort)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java deleted file mode 100644 index ed91edf3f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 聊天角色 Mapper - * - * @author fansili - */ -@Mapper -public interface AiChatRoleMapper extends BaseMapperX { - - default PageResult selectPage(AiChatRolePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) - .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory()) - .eqIfPresent(AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus()) - .orderByAsc(AiChatRoleDO::getSort)); - } - - default PageResult selectPageByMy(AiChatRolePageReqVO reqVO, Long userId) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) - .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory()) - // 情况一:公开 - .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus()) - // 情况二:私有 - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getUserId, userId) - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) - .orderByAsc(AiChatRoleDO::getSort)); - } - - default List selectListGroupByCategory(Integer status) { - return selectList(new LambdaQueryWrapperX() - .select(AiChatRoleDO::getCategory) - .eq(AiChatRoleDO::getStatus, status) - .groupBy(AiChatRoleDO::getCategory)); - } - - default List selectListByName(String name) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(AiChatRoleDO::getName, name) - .orderByAsc(AiChatRoleDO::getSort)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiToolMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiToolMapper.java deleted file mode 100644 index d5d296692..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiToolMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 工具 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface AiToolMapper extends BaseMapperX { - - default PageResult selectPage(AiToolPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiToolDO::getName, reqVO.getName()) - .eqIfPresent(AiToolDO::getDescription, reqVO.getDescription()) - .eqIfPresent(AiToolDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(AiToolDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiToolDO::getId)); - } - - default List selectListByStatus(Integer status) { - return selectList(new LambdaQueryWrapperX() - .eq(AiToolDO::getStatus, status) - .orderByDesc(AiToolDO::getId)); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/music/AiMusicMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/music/AiMusicMapper.java deleted file mode 100644 index 025f5e018..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/music/AiMusicMapper.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.music; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 音乐 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiMusicMapper extends BaseMapperX { - - default List selectListByStatus(Integer status) { - return selectList(AiMusicDO::getStatus, status); - } - - default PageResult selectPage(AiMusicPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiMusicDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiMusicDO::getTitle, reqVO.getTitle()) - .eqIfPresent(AiMusicDO::getStatus, reqVO.getStatus()) - .eqIfPresent(AiMusicDO::getGenerateMode, reqVO.getGenerateMode()) - .betweenIfPresent(AiMusicDO::getCreateTime, reqVO.getCreateTime()) - .eqIfPresent(AiMusicDO::getPublicStatus, reqVO.getPublicStatus()) - .orderByDesc(AiMusicDO::getId)); - } - - default PageResult selectPageByMy(AiMusicPageReqVO reqVO, Long userId) { - return selectPage(reqVO, new LambdaQueryWrapperX() - // 情况一:公开 - .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiMusicDO::getPublicStatus, reqVO.getPublicStatus()) - // 情况二:私有 - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiMusicDO::getUserId, userId) - .orderByAsc(AiMusicDO::getId)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java deleted file mode 100644 index 3770dbf0b..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.workflow; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.workflow.vo.AiWorkflowPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI 工作流 Mapper - * - * @author lesan - */ -@Mapper -public interface AiWorkflowMapper extends BaseMapperX { - - default AiWorkflowDO selectByCode(String code) { - return selectOne(AiWorkflowDO::getCode, code); - } - - default PageResult selectPage(AiWorkflowPageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiWorkflowDO::getStatus, pageReqVO.getStatus()) - .likeIfPresent(AiWorkflowDO::getName, pageReqVO.getName()) - .likeIfPresent(AiWorkflowDO::getCode, pageReqVO.getCode()) - .betweenIfPresent(AiWorkflowDO::getCreateTime, pageReqVO.getCreateTime())); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/write/AiWriteMapper.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/write/AiWriteMapper.java deleted file mode 100644 index c4983eb44..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/write/AiWriteMapper.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.write; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWritePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI 写作 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiWriteMapper extends BaseMapperX { - - default PageResult selectPage(AiWritePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiWriteDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiWriteDO::getType, reqVO.getType()) - .eqIfPresent(AiWriteDO::getPlatform, reqVO.getPlatform()) - .betweenIfPresent(AiWriteDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiWriteDO::getId)); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java deleted file mode 100644 index 9009cbc8c..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java +++ /dev/null @@ -1,323 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.config; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.AiModelFactory; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.AiModelFactoryImpl; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini.GeminiChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.grok.GrokChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowApiConstants; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchClient; -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.bocha.AiBoChaWebSearchClient; -import cn.iocoder.yudao.module.ai.tool.method.PersonService; -import io.micrometer.observation.ObservationRegistry; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.deepseek.DeepSeekChatModel; -import org.springframework.ai.deepseek.DeepSeekChatOptions; -import org.springframework.ai.deepseek.api.DeepSeekApi; -import org.springframework.ai.embedding.BatchingStrategy; -import org.springframework.ai.embedding.TokenCountBatchingStrategy; -import org.springframework.ai.model.tool.ToolCallingManager; -import org.springframework.ai.openai.OpenAiChatModel; -import org.springframework.ai.openai.OpenAiChatOptions; -import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.support.ToolCallbacks; -import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; -import org.springframework.ai.tokenizer.TokenCountEstimator; -import org.springframework.ai.tool.ToolCallback; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties; -import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties; -import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.List; -import java.util.Optional; - -/** - * 芋道 AI 自动配置 - * - * @author fansili - */ -@Configuration -@EnableConfigurationProperties({ YudaoAiProperties.class, - QdrantVectorStoreProperties.class, // 解析 Qdrant 配置 - RedisVectorStoreProperties.class, // 解析 Redis 配置 - MilvusVectorStoreProperties.class, MilvusServiceClientProperties.class // 解析 Milvus 配置 -}) -@Slf4j -public class AiAutoConfiguration { - - @Bean - public AiModelFactory aiModelFactory() { - return new AiModelFactoryImpl(); - } - - @Bean - @ConditionalOnMissingBean - public ObservationRegistry observationRegistry() { - // 特殊:兜底有 ObservationRegistry Bean,避免相关的 ChatModel 创建报错。相关 issue:https://t.zsxq.com/CuPu4 - return ObservationRegistry.NOOP; - } - - // ========== 各种 AI Client 创建 ========== - - @Bean - @ConditionalOnProperty(value = "yudao.ai.gemini.enable", havingValue = "true") - public GeminiChatModel geminiChatModel(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.Gemini properties = yudaoAiProperties.getGemini(); - return buildGeminiChatClient(properties); - } - - public GeminiChatModel buildGeminiChatClient(YudaoAiProperties.Gemini properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(GeminiChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(GeminiChatModel.BASE_URL) - .completionsPath(GeminiChatModel.COMPLETE_PATH) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new GeminiChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true") - public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.DouBao properties = yudaoAiProperties.getDoubao(); - return buildDouBaoChatClient(properties); - } - - public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBao properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(DouBaoChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(DouBaoChatModel.BASE_URL) - .completionsPath(DouBaoChatModel.COMPLETE_PATH) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new DouBaoChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.siliconflow.enable", havingValue = "true") - public SiliconFlowChatModel siliconFlowChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.SiliconFlow properties = yudaoAiProperties.getSiliconflow(); - return buildSiliconFlowChatClient(properties); - } - - public SiliconFlowChatModel buildSiliconFlowChatClient(YudaoAiProperties.SiliconFlow properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(SiliconFlowApiConstants.MODEL_DEFAULT); - } - DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder() - .deepSeekApi(DeepSeekApi.builder() - .baseUrl(SiliconFlowApiConstants.DEFAULT_BASE_URL) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(DeepSeekChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new SiliconFlowChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.hunyuan.enable", havingValue = "true") - public HunYuanChatModel hunYuanChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.HunYuan properties = yudaoAiProperties.getHunyuan(); - return buildHunYuanChatClient(properties); - } - - public HunYuanChatModel buildHunYuanChatClient(YudaoAiProperties.HunYuan properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(HunYuanChatModel.MODEL_DEFAULT); - } - // 特殊:由于混元大模型不提供 deepseek,而是通过知识引擎,所以需要区分下 URL - if (StrUtil.isEmpty(properties.getBaseUrl())) { - properties.setBaseUrl( - StrUtil.startWithIgnoreCase(properties.getModel(), "deepseek") ? HunYuanChatModel.DEEP_SEEK_BASE_URL - : HunYuanChatModel.BASE_URL); - } - // 创建 DeepSeekChatModel、HunYuanChatModel 对象 - DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder() - .deepSeekApi(DeepSeekApi.builder() - .baseUrl(properties.getBaseUrl()) - .completionsPath(HunYuanChatModel.COMPLETE_PATH) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(DeepSeekChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new HunYuanChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true") - public XingHuoChatModel xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.XingHuo properties = yudaoAiProperties.getXinghuo(); - return buildXingHuoChatClient(properties); - } - - public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuo properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(XingHuoChatModel.MODEL_DEFAULT); - } - OpenAiApi.Builder builder = OpenAiApi.builder() - .baseUrl(XingHuoChatModel.BASE_URL_V1) - .apiKey(properties.getAppKey() + ":" + properties.getSecretKey()); - if ("x1".equals(properties.getModel())) { - builder.baseUrl(XingHuoChatModel.BASE_URL_V2) - .completionsPath(XingHuoChatModel.BASE_COMPLETIONS_PATH_V2); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(builder.build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - // TODO @芋艿:星火的 function call 有 bug,会报 ToolResponseMessage must have an id 错误!!! - .toolCallingManager(getToolCallingManager()) - .build(); - return new XingHuoChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.baichuan.enable", havingValue = "true") - public BaiChuanChatModel baiChuanChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.BaiChuan properties = yudaoAiProperties.getBaichuan(); - return buildBaiChuanChatClient(properties); - } - - public BaiChuanChatModel buildBaiChuanChatClient(YudaoAiProperties.BaiChuan properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(BaiChuanChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(BaiChuanChatModel.BASE_URL) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new BaiChuanChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.midjourney.enable", havingValue = "true") - public MidjourneyApi midjourneyApi(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.Midjourney config = yudaoAiProperties.getMidjourney(); - return new MidjourneyApi(config.getBaseUrl(), config.getApiKey(), config.getNotifyUrl()); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.suno.enable", havingValue = "true") - public SunoApi sunoApi(YudaoAiProperties yudaoAiProperties) { - return new SunoApi(yudaoAiProperties.getSuno().getBaseUrl()); - } - - public ChatModel buildGrokChatClient(YudaoAiProperties.Grok properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(GrokChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(Optional.ofNullable(properties.getBaseUrl()) - .orElse(GrokChatModel.BASE_URL)) - .completionsPath(GrokChatModel.COMPLETE_PATH) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new DouBaoChatModel(openAiChatModel); - } - - // ========== RAG 相关 ========== - - @Bean - public TokenCountEstimator tokenCountEstimator() { - return new JTokkitTokenCountEstimator(); - } - - @Bean - public BatchingStrategy batchingStrategy() { - return new TokenCountBatchingStrategy(); - } - - private static ToolCallingManager getToolCallingManager() { - return SpringUtil.getBean(ToolCallingManager.class); - } - - // ========== Web Search 相关 ========== - - @Bean - @ConditionalOnProperty(value = "yudao.ai.web-search.enable", havingValue = "true") - public AiWebSearchClient webSearchClient(YudaoAiProperties yudaoAiProperties) { - return new AiBoChaWebSearchClient(yudaoAiProperties.getWebSearch().getApiKey()); - } - - // ========== MCP 相关 ========== - - /** - * 参考自 MCP Server Boot Starter - */ - @Bean - public List toolCallbacks(PersonService personService) { - return List.of(ToolCallbacks.from(personService)); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java deleted file mode 100644 index 986c24c18..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java +++ /dev/null @@ -1,186 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * 芋道 AI 配置类 - * - * @author fansili - * @since 1.0 - */ -@ConfigurationProperties(prefix = "yudao.ai") -@Data -public class YudaoAiProperties { - - /** - * 谷歌 Gemini - */ - private Gemini gemini; - - /** - * 字节豆包 - */ - private DouBao doubao; - - /** - * 腾讯混元 - */ - private HunYuan hunyuan; - - /** - * 硅基流动 - */ - private SiliconFlow siliconflow; - - /** - * 讯飞星火 - */ - private XingHuo xinghuo; - - /** - * 百川 - */ - private BaiChuan baichuan; - - /** - * Midjourney 绘图 - */ - private Midjourney midjourney; - - /** - * Suno 音乐 - */ - @SuppressWarnings("SpellCheckingInspection") - private Suno suno; - - /** - * 网络搜索 - */ - private WebSearch webSearch; - - @Data - public static class Gemini { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class DouBao { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class HunYuan { - - private String enable; - private String baseUrl; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class SiliconFlow { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class XingHuo { - - private String enable; - private String appId; - private String appKey; - private String secretKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class BaiChuan { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class Midjourney { - - private String enable; - private String baseUrl; - - private String apiKey; - private String notifyUrl; - - } - - @Data - public static class Suno { - - private boolean enable; - - private String baseUrl; - - } - - @Data - public static class Grok { - - private String enable; - private String apiKey; - private String baseUrl; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class WebSearch { - - private boolean enable; - - private String apiKey; - - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactory.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactory.java deleted file mode 100644 index 1c0b808b9..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactory.java +++ /dev/null @@ -1,113 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.embedding.EmbeddingModel; -import org.springframework.ai.image.ImageModel; -import org.springframework.ai.vectorstore.VectorStore; - -import java.util.Map; - -/** - * AI Model 模型工厂的接口类 - * - * @author fansili - */ -public interface AiModelFactory { - - /** - * 基于指定配置,获得 ChatModel 对象 - * - * 如果不存在,则进行创建 - * - * @param platform 平台 - * @param apiKey API KEY - * @param url API URL - * @return ChatModel 对象 - */ - ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url); - - /** - * 基于默认配置,获得 ChatModel 对象 - * - * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 - * - * @param platform 平台 - * @return ChatModel 对象 - */ - ChatModel getDefaultChatModel(AiPlatformEnum platform); - - /** - * 基于默认配置,获得 ImageModel 对象 - * - * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 - * - * @param platform 平台 - * @return ImageModel 对象 - */ - ImageModel getDefaultImageModel(AiPlatformEnum platform); - - /** - * 基于指定配置,获得 ImageModel 对象 - * - * 如果不存在,则进行创建 - * - * @param platform 平台 - * @param apiKey API KEY - * @param url API URL - * @return ImageModel 对象 - */ - ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url); - - /** - * 基于指定配置,获得 MidjourneyApi 对象 - * - * 如果不存在,则进行创建 - * - * @param apiKey API KEY - * @param url API URL - * @return MidjourneyApi 对象 - */ - MidjourneyApi getOrCreateMidjourneyApi(String apiKey, String url); - - /** - * 基于指定配置,获得 SunoApi 对象 - * - * 如果不存在,则进行创建 - * - * @param apiKey API KEY - * @param url API URL - * @return SunoApi 对象 - */ - SunoApi getOrCreateSunoApi(String apiKey, String url); - - /** - * 基于指定配置,获得 EmbeddingModel 对象 - * - * 如果不存在,则进行创建 - * - * @param platform 平台 - * @param apiKey API KEY - * @param url API URL - * @param model 模型 - * @return ChatModel 对象 - */ - EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url, String model); - - /** - * 基于指定配置,获得 VectorStore 对象 - * - * 如果不存在,则进行创建 - * - * @param type 向量存储类型 - * @param embeddingModel 向量模型 - * @param metadataFields 元数据字段 - * @return VectorStore 对象 - */ - VectorStore getOrCreateVectorStore(Class type, - EmbeddingModel embeddingModel, - Map> metadataFields); - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java deleted file mode 100644 index f8067dea2..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java +++ /dev/null @@ -1,845 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Singleton; -import cn.hutool.core.lang.func.Func0; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.RuntimeUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration; -import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini.GeminiChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowApiConstants; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration; -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingAutoConfiguration; -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeImageAutoConfiguration; -import com.alibaba.cloud.ai.dashscope.api.DashScopeApi; -import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi; -import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel; -import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; -import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel; -import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; -import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; -import com.azure.ai.openai.OpenAIClientBuilder; -import com.azure.core.credential.KeyCredential; -import io.micrometer.observation.ObservationRegistry; -import io.milvus.client.MilvusServiceClient; -import io.qdrant.client.QdrantClient; -import io.qdrant.client.QdrantGrpcClient; -import lombok.SneakyThrows; -import org.springaicommunity.moonshot.MoonshotChatModel; -import org.springaicommunity.moonshot.MoonshotChatOptions; -import org.springaicommunity.moonshot.api.MoonshotApi; -import org.springaicommunity.moonshot.autoconfigure.MoonshotChatAutoConfiguration; -import org.springaicommunity.qianfan.QianFanChatModel; -import org.springaicommunity.qianfan.QianFanEmbeddingModel; -import org.springaicommunity.qianfan.QianFanEmbeddingOptions; -import org.springaicommunity.qianfan.QianFanImageModel; -import org.springaicommunity.qianfan.api.QianFanApi; -import org.springaicommunity.qianfan.api.QianFanImageApi; -import org.springaicommunity.qianfan.autoconfigure.QianFanChatAutoConfiguration; -import org.springaicommunity.qianfan.autoconfigure.QianFanEmbeddingAutoConfiguration; -import org.springframework.ai.azure.openai.AzureOpenAiChatModel; -import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.deepseek.DeepSeekChatModel; -import org.springframework.ai.deepseek.DeepSeekChatOptions; -import org.springframework.ai.deepseek.api.DeepSeekApi; -import org.springframework.ai.document.MetadataMode; -import org.springframework.ai.embedding.BatchingStrategy; -import org.springframework.ai.embedding.EmbeddingModel; -import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention; -import org.springframework.ai.image.ImageModel; -import org.springframework.ai.minimax.MiniMaxChatModel; -import org.springframework.ai.minimax.MiniMaxChatOptions; -import org.springframework.ai.minimax.MiniMaxEmbeddingModel; -import org.springframework.ai.minimax.MiniMaxEmbeddingOptions; -import org.springframework.ai.minimax.api.MiniMaxApi; -import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration; -import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; -import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration; -import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties; -import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration; -import org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration; -import org.springframework.ai.model.minimax.autoconfigure.MiniMaxEmbeddingAutoConfiguration; -import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration; -import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; -import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration; -import org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration; -import org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration; -import org.springframework.ai.model.tool.ToolCallingManager; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration; -import org.springframework.ai.ollama.OllamaChatModel; -import org.springframework.ai.ollama.OllamaEmbeddingModel; -import org.springframework.ai.ollama.api.OllamaApi; -import org.springframework.ai.ollama.api.OllamaEmbeddingOptions; -import org.springframework.ai.openai.OpenAiChatModel; -import org.springframework.ai.openai.OpenAiEmbeddingModel; -import org.springframework.ai.openai.OpenAiEmbeddingOptions; -import org.springframework.ai.openai.OpenAiImageModel; -import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.openai.api.OpenAiImageApi; -import org.springframework.ai.openai.api.common.OpenAiApiConstants; -import org.springframework.ai.anthropic.AnthropicChatModel; -import org.springframework.ai.anthropic.api.AnthropicApi; -import org.springframework.ai.stabilityai.StabilityAiImageModel; -import org.springframework.ai.stabilityai.api.StabilityAiApi; -import org.springframework.ai.vectorstore.SimpleVectorStore; -import org.springframework.ai.vectorstore.VectorStore; -import org.springframework.ai.vectorstore.milvus.MilvusVectorStore; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientConnectionDetails; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties; -import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; -import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; -import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; -import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration; -import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties; -import org.springframework.ai.vectorstore.redis.RedisVectorStore; -import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration; -import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties; -import org.springframework.ai.zhipuai.*; -import org.springframework.ai.zhipuai.api.ZhiPuAiApi; -import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; -import org.springframework.web.client.RestClient; -import redis.clients.jedis.JedisPooled; - -import java.io.File; -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static org.springframework.ai.retry.RetryUtils.DEFAULT_RETRY_TEMPLATE; - -/** - * AI Model 模型工厂的实现类 - * - * @author 芋道源码 - */ -public class AiModelFactoryImpl implements AiModelFactory { - - @Override - public ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url) { - String cacheKey = buildClientCacheKey(ChatModel.class, platform, apiKey, url); - return Singleton.get(cacheKey, (Func0) () -> { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return buildTongYiChatModel(apiKey); - case YI_YAN: - return buildYiYanChatModel(apiKey); - case DEEP_SEEK: - return buildDeepSeekChatModel(apiKey); - case DOU_BAO: - return buildDouBaoChatModel(apiKey); - case HUN_YUAN: - return buildHunYuanChatModel(apiKey, url); - case SILICON_FLOW: - return buildSiliconFlowChatModel(apiKey); - case ZHI_PU: - return buildZhiPuChatModel(apiKey, url); - case MINI_MAX: - return buildMiniMaxChatModel(apiKey, url); - case MOONSHOT: - return buildMoonshotChatModel(apiKey, url); - case XING_HUO: - return buildXingHuoChatModel(apiKey); - case BAI_CHUAN: - return buildBaiChuanChatModel(apiKey); - case OPENAI: - return buildOpenAiChatModel(apiKey, url); - case AZURE_OPENAI: - return buildAzureOpenAiChatModel(apiKey, url); - case ANTHROPIC: - return buildAnthropicChatModel(apiKey, url); - case GEMINI: - return buildGeminiChatModel(apiKey); - case OLLAMA: - return buildOllamaChatModel(url); - case GROK: - return buildGrokChatModel(apiKey,url); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - }); - } - - @Override - public ChatModel getDefaultChatModel(AiPlatformEnum platform) { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return SpringUtil.getBean(DashScopeChatModel.class); - case YI_YAN: - return SpringUtil.getBean(QianFanChatModel.class); - case DEEP_SEEK: - return SpringUtil.getBean(DeepSeekChatModel.class); - case DOU_BAO: - return SpringUtil.getBean(DouBaoChatModel.class); - case HUN_YUAN: - return SpringUtil.getBean(HunYuanChatModel.class); - case SILICON_FLOW: - return SpringUtil.getBean(SiliconFlowChatModel.class); - case ZHI_PU: - return SpringUtil.getBean(ZhiPuAiChatModel.class); - case MINI_MAX: - return SpringUtil.getBean(MiniMaxChatModel.class); - case MOONSHOT: - return SpringUtil.getBean(MoonshotChatModel.class); - case XING_HUO: - return SpringUtil.getBean(XingHuoChatModel.class); - case BAI_CHUAN: - return SpringUtil.getBean(BaiChuanChatModel.class); - case OPENAI: - return SpringUtil.getBean(OpenAiChatModel.class); - case AZURE_OPENAI: - return SpringUtil.getBean(AzureOpenAiChatModel.class); - case ANTHROPIC: - return SpringUtil.getBean(AnthropicChatModel.class); - case GEMINI: - return SpringUtil.getBean(GeminiChatModel.class); - case OLLAMA: - return SpringUtil.getBean(OllamaChatModel.class); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - } - - @Override - public ImageModel getDefaultImageModel(AiPlatformEnum platform) { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return SpringUtil.getBean(DashScopeImageModel.class); - case YI_YAN: - return SpringUtil.getBean(QianFanImageModel.class); - case ZHI_PU: - return SpringUtil.getBean(ZhiPuAiImageModel.class); - case SILICON_FLOW: - return SpringUtil.getBean(SiliconFlowImageModel.class); - case OPENAI: - return SpringUtil.getBean(OpenAiImageModel.class); - case STABLE_DIFFUSION: - return SpringUtil.getBean(StabilityAiImageModel.class); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - } - - @Override - public ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url) { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return buildTongYiImagesModel(apiKey); - case YI_YAN: - return buildQianFanImageModel(apiKey); - case ZHI_PU: - return buildZhiPuAiImageModel(apiKey, url); - case OPENAI: - return buildOpenAiImageModel(apiKey, url); - case SILICON_FLOW: - return buildSiliconFlowImageModel(apiKey,url); - case STABLE_DIFFUSION: - return buildStabilityAiImageModel(apiKey, url); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - } - - @Override - public MidjourneyApi getOrCreateMidjourneyApi(String apiKey, String url) { - String cacheKey = buildClientCacheKey(MidjourneyApi.class, AiPlatformEnum.MIDJOURNEY.getPlatform(), apiKey, - url); - return Singleton.get(cacheKey, (Func0) () -> { - YudaoAiProperties.Midjourney properties = SpringUtil.getBean(YudaoAiProperties.class) - .getMidjourney(); - return new MidjourneyApi(url, apiKey, properties.getNotifyUrl()); - }); - } - - @Override - public SunoApi getOrCreateSunoApi(String apiKey, String url) { - String cacheKey = buildClientCacheKey(SunoApi.class, AiPlatformEnum.SUNO.getPlatform(), apiKey, url); - return Singleton.get(cacheKey, (Func0) () -> new SunoApi(url)); - } - - @Override - @SuppressWarnings("EnhancedSwitchMigration") - public EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url, String model) { - String cacheKey = buildClientCacheKey(EmbeddingModel.class, platform, apiKey, url, model); - return Singleton.get(cacheKey, (Func0) () -> { - switch (platform) { - case TONG_YI: - return buildTongYiEmbeddingModel(apiKey, model); - case YI_YAN: - return buildYiYanEmbeddingModel(apiKey, model); - case ZHI_PU: - return buildZhiPuEmbeddingModel(apiKey, url, model); - case MINI_MAX: - return buildMiniMaxEmbeddingModel(apiKey, url, model); - case OPENAI: - return buildOpenAiEmbeddingModel(apiKey, url, model); - case AZURE_OPENAI: - return buildAzureOpenAiEmbeddingModel(apiKey, url, model); - case OLLAMA: - return buildOllamaEmbeddingModel(url, model); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - }); - } - - @Override - public VectorStore getOrCreateVectorStore(Class type, - EmbeddingModel embeddingModel, - Map> metadataFields) { - String cacheKey = buildClientCacheKey(VectorStore.class, embeddingModel, type); - return Singleton.get(cacheKey, (Func0) () -> { - if (type == SimpleVectorStore.class) { - return buildSimpleVectorStore(embeddingModel); - } - if (type == QdrantVectorStore.class) { - return buildQdrantVectorStore(embeddingModel); - } - if (type == RedisVectorStore.class) { - return buildRedisVectorStore(embeddingModel, metadataFields); - } - if (type == MilvusVectorStore.class) { - return buildMilvusVectorStore(embeddingModel); - } - throw new IllegalArgumentException(StrUtil.format("未知类型({})", type)); - }); - } - - private static String buildClientCacheKey(Class clazz, Object... params) { - if (ArrayUtil.isEmpty(params)) { - return clazz.getName(); - } - return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_")); - } - - // ========== 各种创建 spring-ai 客户端的方法 ========== - - /** - * 可参考 {@link DashScopeChatAutoConfiguration} 的 dashscopeChatModel 方法 - */ - private static DashScopeChatModel buildTongYiChatModel(String key) { - DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build(); - DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL) - .withTemperature(0.7).build(); - return DashScopeChatModel.builder() - .dashScopeApi(dashScopeApi) - .defaultOptions(options) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link DashScopeImageAutoConfiguration} 的 dashScopeImageModel 方法 - */ - private static DashScopeImageModel buildTongYiImagesModel(String key) { - DashScopeImageApi dashScopeImageApi = DashScopeImageApi.builder().apiKey(key).build(); - return DashScopeImageModel.builder() - .dashScopeApi(dashScopeImageApi) - .build(); - } - - /** - * 可参考 {@link QianFanChatAutoConfiguration} 的 qianFanChatModel 方法 - */ - private static QianFanChatModel buildYiYanChatModel(String key) { - // TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6 - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); - String appKey = keys.get(0); - String secretKey = keys.get(1); - QianFanApi qianFanApi = new QianFanApi(appKey, secretKey); - return new QianFanChatModel(qianFanApi); - } - - /** - * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanImageModel 方法 - */ - private QianFanImageModel buildQianFanImageModel(String key) { - // TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6 - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); - String appKey = keys.get(0); - String secretKey = keys.get(1); - QianFanImageApi qianFanApi = new QianFanImageApi(appKey, secretKey); - return new QianFanImageModel(qianFanApi); - } - - /** - * 可参考 {@link DeepSeekChatAutoConfiguration} 的 deepSeekChatModel 方法 - */ - private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) { - DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build(); - DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL) - .temperature(0.7).build(); - return DeepSeekChatModel.builder() - .deepSeekApi(deepSeekApi) - .defaultOptions(options) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AiAutoConfiguration#douBaoChatClient(YudaoAiProperties)} - */ - private ChatModel buildDouBaoChatModel(String apiKey) { - YudaoAiProperties.DouBao properties = new YudaoAiProperties.DouBao() - .setApiKey(apiKey); - return new AiAutoConfiguration().buildDouBaoChatClient(properties); - } - - /** - * 可参考 {@link AiAutoConfiguration#hunYuanChatClient(YudaoAiProperties)} - */ - private ChatModel buildHunYuanChatModel(String apiKey, String url) { - YudaoAiProperties.HunYuan properties = new YudaoAiProperties.HunYuan() - .setBaseUrl(url).setApiKey(apiKey); - return new AiAutoConfiguration().buildHunYuanChatClient(properties); - } - - /** - * 可参考 {@link AiAutoConfiguration#siliconFlowChatClient(YudaoAiProperties)} - */ - private ChatModel buildSiliconFlowChatModel(String apiKey) { - YudaoAiProperties.SiliconFlow properties = new YudaoAiProperties.SiliconFlow() - .setApiKey(apiKey); - return new AiAutoConfiguration().buildSiliconFlowChatClient(properties); - } - - /** - * 可参考 {@link ZhiPuAiChatAutoConfiguration} 的 zhiPuAiChatModel 方法 - */ - private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { - ZhiPuAiApi.Builder zhiPuAiApiBuilder = ZhiPuAiApi.builder().apiKey(apiKey); - if (StrUtil.isNotEmpty(url)) { - zhiPuAiApiBuilder.baseUrl(url); - } - ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); - return new ZhiPuAiChatModel(zhiPuAiApiBuilder.build(), options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE, - getObservationRegistry().getIfAvailable()); - } - - /** - * 可参考 {@link ZhiPuAiImageAutoConfiguration} 的 zhiPuAiImageModel 方法 - */ - private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) { - ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey) - : new ZhiPuAiImageApi(url, apiKey, RestClient.builder()); - return new ZhiPuAiImageModel(zhiPuAiApi); - } - - /** - * 可参考 {@link MiniMaxChatAutoConfiguration} 的 miniMaxChatModel 方法 - */ - private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) { - MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey) - : new MiniMaxApi(url, apiKey); - MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); - return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE); - } - - /** - * 可参考 {@link MoonshotChatAutoConfiguration} 的 moonshotChatModel 方法 - */ - private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) { - MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder() - .apiKey(apiKey); - if (StrUtil.isNotEmpty(url)) { - moonshotApiBuilder.baseUrl(url); - } - MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build(); - return MoonshotChatModel.builder() - .moonshotApi(moonshotApiBuilder.build()) - .defaultOptions(options) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)} - */ - private static XingHuoChatModel buildXingHuoChatModel(String key) { - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "XingHuoChatClient 的密钥需要 (appKey|secretKey) 格式"); - YudaoAiProperties.XingHuo properties = new YudaoAiProperties.XingHuo() - .setAppKey(keys.get(0)).setSecretKey(keys.get(1)); - return new AiAutoConfiguration().buildXingHuoChatClient(properties); - } - - /** - * 可参考 {@link AiAutoConfiguration#baiChuanChatClient(YudaoAiProperties)} - */ - private BaiChuanChatModel buildBaiChuanChatModel(String apiKey) { - YudaoAiProperties.BaiChuan properties = new YudaoAiProperties.BaiChuan() - .setApiKey(apiKey); - return new AiAutoConfiguration().buildBaiChuanChatClient(properties); - } - - /** - * 可参考 {@link OpenAiChatAutoConfiguration} 的 openAiChatModel 方法 - */ - private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { - url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); - OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build(); - return OpenAiChatModel.builder() - .openAiApi(openAiApi) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AzureOpenAiChatAutoConfiguration} - */ - private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) { - // TODO @芋艿:使用前,请测试,暂时没密钥!!! - OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() - .endpoint(url).credential(new KeyCredential(apiKey)); - return AzureOpenAiChatModel.builder() - .openAIClientBuilder(openAIClientBuilder) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AnthropicChatAutoConfiguration} 的 anthropicApi 方法 - */ - private static AnthropicChatModel buildAnthropicChatModel(String apiKey, String url) { - AnthropicApi.Builder builder = AnthropicApi.builder().apiKey(apiKey); - if (StrUtil.isNotEmpty(url)) { - builder.baseUrl(url); - } - AnthropicApi anthropicApi = builder.build(); - return AnthropicChatModel.builder() - .anthropicApi(anthropicApi) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AiAutoConfiguration#buildGeminiChatClient(YudaoAiProperties.Gemini)} - */ - private static GeminiChatModel buildGeminiChatModel(String apiKey) { - YudaoAiProperties.Gemini properties = SpringUtil.getBean(YudaoAiProperties.class) - .getGemini().setApiKey(apiKey); - return new AiAutoConfiguration().buildGeminiChatClient(properties); - } - - /** - * 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法 - */ - private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { - url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); - OpenAiImageApi openAiApi = OpenAiImageApi.builder().baseUrl(url).apiKey(openAiToken).build(); - return new OpenAiImageModel(openAiApi); - } - - /** - * 创建 SiliconFlowImageModel 对象 - */ - private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) { - url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL); - SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken); - return new SiliconFlowImageModel(openAiApi); - } - - /** - * 可参考 {@link OllamaChatAutoConfiguration} 的 ollamaChatModel 方法 - */ - private static OllamaChatModel buildOllamaChatModel(String url) { - OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); - return OllamaChatModel.builder() - .ollamaApi(ollamaApi) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link StabilityAiImageAutoConfiguration} 的 stabilityAiImageModel 方法 - */ - private StabilityAiImageModel buildStabilityAiImageModel(String apiKey, String url) { - url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); - StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url); - return new StabilityAiImageModel(stabilityAiApi); - } - - private ChatModel buildGrokChatModel(String apiKey,String url) { - YudaoAiProperties.Grok properties = new YudaoAiProperties.Grok() - .setBaseUrl(url) - .setApiKey(apiKey); - return new AiAutoConfiguration().buildGrokChatClient(properties); - } - - // ========== 各种创建 EmbeddingModel 的方法 ========== - - /** - * 可参考 {@link DashScopeEmbeddingAutoConfiguration} 的 dashscopeEmbeddingModel 方法 - */ - private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) { - DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build(); - DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build(); - return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions); - } - - /** - * 可参考 {@link ZhiPuAiEmbeddingAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法 - */ - private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) { - ZhiPuAiApi.Builder zhiPuAiApiBuilder = ZhiPuAiApi.builder().apiKey(apiKey); - if (StrUtil.isNotEmpty(url)) { - zhiPuAiApiBuilder.baseUrl(url); - } - ZhiPuAiEmbeddingOptions zhiPuAiEmbeddingOptions = ZhiPuAiEmbeddingOptions.builder().model(model).build(); - return new ZhiPuAiEmbeddingModel(zhiPuAiApiBuilder.build(), MetadataMode.EMBED, zhiPuAiEmbeddingOptions); - } - - /** - * 可参考 {@link MiniMaxEmbeddingAutoConfiguration} 的 miniMaxEmbeddingModel 方法 - */ - private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) { - MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey) - : new MiniMaxApi(url, apiKey); - MiniMaxEmbeddingOptions miniMaxEmbeddingOptions = MiniMaxEmbeddingOptions.builder().model(model).build(); - return new MiniMaxEmbeddingModel(miniMaxApi, MetadataMode.EMBED, miniMaxEmbeddingOptions); - } - - /** - * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanEmbeddingModel 方法 - */ - private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) { - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); - String appKey = keys.get(0); - String secretKey = keys.get(1); - QianFanApi qianFanApi = new QianFanApi(appKey, secretKey); - QianFanEmbeddingOptions qianFanEmbeddingOptions = QianFanEmbeddingOptions.builder().model(model).build(); - return new QianFanEmbeddingModel(qianFanApi, MetadataMode.EMBED, qianFanEmbeddingOptions); - } - - private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) { - OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); - OllamaEmbeddingOptions ollamaOptions = OllamaEmbeddingOptions.builder().model(model).build(); - return OllamaEmbeddingModel.builder() - .ollamaApi(ollamaApi) - .defaultOptions(ollamaOptions) - .build(); - } - - /** - * 可参考 {@link OpenAiEmbeddingAutoConfiguration} 的 openAiEmbeddingModel 方法 - */ - private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) { - url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); - OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build(); - OpenAiEmbeddingOptions openAiEmbeddingProperties = OpenAiEmbeddingOptions.builder().model(model).build(); - return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties); - } - - /** - * 可参考 {@link AzureOpenAiEmbeddingAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法 - */ - private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) { - // TODO @芋艿:手头暂时没密钥,使用建议再测试下 - AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration(); - // 创建 OpenAIClientBuilder 对象 - OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() - .endpoint(url).credential(new KeyCredential(apiKey)); - // 获取 AzureOpenAiChatProperties 对象 - AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class); - return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties, - getObservationRegistry(), getEmbeddingModelObservationConvention()); - } - - // ========== 各种创建 VectorStore 的方法 ========== - - /** - * 注意:仅适合本地测试使用,生产建议还是使用 Qdrant、Milvus 等 - */ - @SneakyThrows - @SuppressWarnings("ResultOfMethodCallIgnored") - private SimpleVectorStore buildSimpleVectorStore(EmbeddingModel embeddingModel) { - SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel).build(); - // 启动加载 - File file = new File(StrUtil.format("{}/vector_store/simple_{}.json", - FileUtil.getUserHomePath(), embeddingModel.getClass().getSimpleName())); - if (!file.exists()) { - FileUtil.mkParentDirs(file); - file.createNewFile(); - } else if (file.length() > 0) { - vectorStore.load(file); - } - // 定时持久化,每分钟一次 - Timer timer = new Timer("SimpleVectorStoreTimer-" + file.getAbsolutePath()); - timer.scheduleAtFixedRate(new TimerTask() { - - @Override - public void run() { - vectorStore.save(file); - } - - }, Duration.ofMinutes(1).toMillis(), Duration.ofMinutes(1).toMillis()); - // 关闭时,进行持久化 - RuntimeUtil.addShutdownHook(() -> vectorStore.save(file)); - return vectorStore; - } - - /** - * 参考 {@link QdrantVectorStoreAutoConfiguration} 的 vectorStore 方法 - */ - @SneakyThrows - private QdrantVectorStore buildQdrantVectorStore(EmbeddingModel embeddingModel) { - QdrantVectorStoreAutoConfiguration configuration = new QdrantVectorStoreAutoConfiguration(); - QdrantVectorStoreProperties properties = SpringUtil.getBean(QdrantVectorStoreProperties.class); - // 参考 QdrantVectorStoreAutoConfiguration 实现,创建 QdrantClient 对象 - QdrantGrpcClient.Builder grpcClientBuilder = QdrantGrpcClient.newBuilder( - properties.getHost(), properties.getPort(), properties.isUseTls()); - if (StrUtil.isNotEmpty(properties.getApiKey())) { - grpcClientBuilder.withApiKey(properties.getApiKey()); - } - QdrantClient qdrantClient = new QdrantClient(grpcClientBuilder.build()); - // 创建 QdrantVectorStore 对象 - QdrantVectorStore vectorStore = configuration.vectorStore(embeddingModel, properties, qdrantClient, - getObservationRegistry(), getCustomObservationConvention(), getBatchingStrategy()); - // 初始化索引 - vectorStore.afterPropertiesSet(); - return vectorStore; - } - - /** - * 参考 {@link RedisVectorStoreAutoConfiguration} 的 vectorStore 方法 - */ - private RedisVectorStore buildRedisVectorStore(EmbeddingModel embeddingModel, - Map> metadataFields) { - // 创建 JedisPooled 对象 - RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); - JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort(), - redisProperties.getUsername(), redisProperties.getPassword()); - // 创建 RedisVectorStoreProperties 对象 - RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class); - RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel) - .indexName(properties.getIndexName()).prefix(properties.getPrefix()) - .initializeSchema(properties.isInitializeSchema()) - .metadataFields(convertList(metadataFields.entrySet(), entry -> { - String fieldName = entry.getKey(); - Class fieldType = entry.getValue(); - if (Number.class.isAssignableFrom(fieldType)) { - return RedisVectorStore.MetadataField.numeric(fieldName); - } - if (Boolean.class.isAssignableFrom(fieldType)) { - return RedisVectorStore.MetadataField.tag(fieldName); - } - return RedisVectorStore.MetadataField.text(fieldName); - })) - .observationRegistry(getObservationRegistry().getObject()) - .customObservationConvention(getCustomObservationConvention().getObject()) - .batchingStrategy(getBatchingStrategy()) - .build(); - // 初始化索引 - redisVectorStore.afterPropertiesSet(); - return redisVectorStore; - } - - /** - * 参考 {@link MilvusVectorStoreAutoConfiguration} 的 vectorStore 方法 - */ - @SneakyThrows - private MilvusVectorStore buildMilvusVectorStore(EmbeddingModel embeddingModel) { - MilvusVectorStoreAutoConfiguration configuration = new MilvusVectorStoreAutoConfiguration(); - // 获取配置属性 - MilvusVectorStoreProperties serverProperties = SpringUtil.getBean(MilvusVectorStoreProperties.class); - MilvusServiceClientProperties clientProperties = SpringUtil.getBean(MilvusServiceClientProperties.class); - - // 创建 MilvusServiceClient 对象 - MilvusServiceClient milvusClient = configuration.milvusClient(serverProperties, clientProperties, - new MilvusServiceClientConnectionDetails() { - - @Override - public String getHost() { - return clientProperties.getHost(); - } - - @Override - public int getPort() { - return clientProperties.getPort(); - } - - } - ); - // 创建 MilvusVectorStore 对象 - MilvusVectorStore vectorStore = configuration.vectorStore(milvusClient, embeddingModel, serverProperties, - getBatchingStrategy(), getObservationRegistry(), getCustomObservationConvention()); - - // 初始化索引 - vectorStore.afterPropertiesSet(); - return vectorStore; - } - - private static ObjectProvider getObservationRegistry() { - return new ObjectProvider<>() { - - @Override - public ObservationRegistry getObject() throws BeansException { - return SpringUtil.getBean(ObservationRegistry.class); - } - - }; - } - - private static ObjectProvider getCustomObservationConvention() { - return new ObjectProvider<>() { - - @Override - public VectorStoreObservationConvention getObject() throws BeansException { - return new DefaultVectorStoreObservationConvention(); - } - - }; - } - - private static BatchingStrategy getBatchingStrategy() { - return SpringUtil.getBean(BatchingStrategy.class); - } - - private static ToolCallingManager getToolCallingManager() { - return SpringUtil.getBean(ToolCallingManager.class); - } - - private static ObjectProvider getEmbeddingModelObservationConvention() { - return new ObjectProvider<>() { - - @Override - public EmbeddingModelObservationConvention getObject() throws BeansException { - return SpringUtil.getBean(EmbeddingModelObservationConvention.class); - } - - }; - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/baichuan/BaiChuanChatModel.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/baichuan/BaiChuanChatModel.java deleted file mode 100644 index 5fb71c942..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/baichuan/BaiChuanChatModel.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatModel; -import reactor.core.publisher.Flux; - -/** - * 百川 {@link ChatModel} 实现类 - * - * @author 芋道源码 - */ -@Slf4j -@RequiredArgsConstructor -public class BaiChuanChatModel implements ChatModel { - - public static final String BASE_URL = "https://api.baichuan-ai.com"; - - public static final String MODEL_DEFAULT = "Baichuan4-Turbo"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final OpenAiChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/doubao/DouBaoChatModel.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/doubao/DouBaoChatModel.java deleted file mode 100644 index a542cb372..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/doubao/DouBaoChatModel.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import reactor.core.publisher.Flux; - -/** - * 字节豆包 {@link ChatModel} 实现类 - * - * @author fansili - */ -@Slf4j -@RequiredArgsConstructor -public class DouBaoChatModel implements ChatModel { - - public static final String BASE_URL = "https://ark.cn-beijing.volces.com/api"; - public static final String COMPLETE_PATH = "/v3/chat/completions"; - - public static final String MODEL_DEFAULT = "doubao-1-5-lite-32k-250115"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final ChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/gemini/GeminiChatModel.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/gemini/GeminiChatModel.java deleted file mode 100644 index 378a0af1f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/gemini/GeminiChatModel.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatModel; -import reactor.core.publisher.Flux; - -/** - * 谷歌 Gemini {@link ChatModel} 实现类,基于 Google AI Studio 提供的 OpenAI 兼容方案 - * - * @author 芋道源码 - */ -@Slf4j -@RequiredArgsConstructor -public class GeminiChatModel implements ChatModel { - - public static final String BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"; - public static final String COMPLETE_PATH = "/chat/completions"; - - public static final String MODEL_DEFAULT = "gemini-2.5-flash"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final OpenAiChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/grok/GrokChatModel.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/grok/GrokChatModel.java deleted file mode 100644 index 06eed2504..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/grok/GrokChatModel.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.grok; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import reactor.core.publisher.Flux; - -/** - * Grok {@link ChatModel} 实现类 - * - * - */ -@Slf4j -@RequiredArgsConstructor -public class GrokChatModel implements ChatModel { - - public static final String BASE_URL = "https://api.x.ai"; - public static final String COMPLETE_PATH = "/v1/chat/completions"; - public static final String MODEL_DEFAULT = "grok-4-fast-reasoning"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final ChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/hunyuan/HunYuanChatModel.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/hunyuan/HunYuanChatModel.java deleted file mode 100644 index 9513c6c5f..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/hunyuan/HunYuanChatModel.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import reactor.core.publisher.Flux; - -/** - * 腾云混元 {@link ChatModel} 实现类 - * - * 1. 混元大模型:基于 知识引擎原子能力 实现 - * 2. 知识引擎原子能力:基于 知识引擎原子能力 实现 - * - * @author fansili - */ -@Slf4j -@RequiredArgsConstructor -public class HunYuanChatModel implements ChatModel { - - public static final String BASE_URL = "https://api.hunyuan.cloud.tencent.com"; - public static final String COMPLETE_PATH = "/v1/chat/completions"; - - public static final String MODEL_DEFAULT = "hunyuan-turbo"; - - public static final String DEEP_SEEK_BASE_URL = "https://api.lkeap.cloud.tencent.com"; - - public static final String DEEP_SEEK_MODEL_DEFAULT = "deepseek-v3"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final ChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/midjourney/api/MidjourneyApi.java b/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/midjourney/api/MidjourneyApi.java deleted file mode 100644 index 051ef3185..000000000 --- a/yudao-module-ai/yudao-module-ai-server/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/midjourney/api/MidjourneyApi.java +++ /dev/null @@ -1,351 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Midjourney API - * - * @author fansili - * @since 1.0 - */ -@Slf4j -public class MidjourneyApi { - - private final Predicate STATUS_PREDICATE = status -> !status.is2xxSuccessful(); - - private final Function>> EXCEPTION_FUNCTION = - reqParam -> response -> response.bodyToMono(String.class).handle((responseBody, sink) -> { - HttpRequest request = response.request(); - log.error("[midjourney-api] 调用失败!请求方式:[{}],请求地址:[{}],请求参数:[{}],响应数据: [{}]", - request.getMethod(), request.getURI(), reqParam, responseBody); - sink.error(new IllegalStateException("[midjourney-api] 调用失败!")); - }); - - private final WebClient webClient; - - /** - * 回调地址 - */ - private final String notifyUrl; - - public MidjourneyApi(String baseUrl, String apiKey, String notifyUrl) { - this.webClient = WebClient.builder() - .baseUrl(baseUrl) - .defaultHeaders(httpHeaders -> { - httpHeaders.setContentType(MediaType.APPLICATION_JSON); - httpHeaders.setBearerAuth(apiKey); - }) - .build(); - this.notifyUrl = notifyUrl; - } - - /** - * imagine - 根据提示词提交绘画任务 - * - * @param request 请求 - * @return 提交结果 - */ - public SubmitResponse imagine(ImagineRequest request) { - if (StrUtil.isEmpty(request.getNotifyHook())) { - request.setNotifyHook(notifyUrl); - } - String response = post("/submit/imagine", request); - return JsonUtils.parseObject(response, SubmitResponse.class); - } - - /** - * action - 放大、缩小、U1、U2... - * - * @param request 请求 - * @return 提交结果 - */ - public SubmitResponse action(ActionRequest request) { - if (StrUtil.isEmpty(request.getNotifyHook())) { - request.setNotifyHook(notifyUrl); - } - String response = post("/submit/action", request); - return JsonUtils.parseObject(response, SubmitResponse.class); - } - - /** - * 批量查询 task 任务 - * - * @param ids 任务编号数组 - * @return task 任务 - */ - public List getTaskList(Collection ids) { - String res = post("/task/list-by-condition", ImmutableMap.of("ids", ids)); - return JsonUtils.parseArray(res, Notify.class); - } - - private String post(String uri, Object body) { - return webClient.post() - .uri(uri) - .body(Mono.just(JsonUtils.toJsonString(body)), String.class) - .retrieve() - .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(body)) - .bodyToMono(String.class) - .block(); - } - - // ========== record 结构 ========== - - /** - * Imagine 请求(生成图片) - */ - @Data - public static final class ImagineRequest { - - /** - * 垫图(参考图) base64 数组 - */ - private List base64Array; - /** - * 提示词 - */ - private String prompt; - /** - * 通知地址 - */ - private String notifyHook; - /** - * 自定义参数 - */ - private String state; - - public ImagineRequest(List base64Array, String prompt, String notifyHook, String state) { - this.base64Array = base64Array; - this.prompt = prompt; - this.notifyHook = notifyHook; - this.state = state; - } - - public static String buildState(Integer width, Integer height, String version, String model) { - StringBuilder params = new StringBuilder(); - // --ar 来设置尺寸 - params.append(String.format(" --ar %s:%s ", width, height)); - // --niji 模型 - if (ModelEnum.NIJI.getModel().equals(model)) { - params.append(String.format(" --niji %s ", version)); - } else { - params.append(String.format(" --v %s ", version)); - } - return params.toString(); - } - - } - - /** - * Action 请求 - */ - @Data - public static final class ActionRequest { - - private String customId; - private String taskId; - private String notifyHook; - - public ActionRequest(String taskId, String customId, String notifyHook) { - this.customId = customId; - this.taskId = taskId; - this.notifyHook = notifyHook; - } - - } - - /** - * Submit 统一返回 - * - * @param code 状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误) - * @param description 描述 - * @param properties 扩展字段 - * @param result 任务ID - */ - public record SubmitResponse(String code, - String description, - Map properties, - String result) { - } - - /** - * 通知 request - * - * @param id job id - * @param action 任务类型 {@link TaskActionEnum} - * @param status 任务状态 {@link TaskStatusEnum} - * @param prompt 提示词 - * @param promptEn 提示词-英文 - * @param description 任务描述 - * @param state 自定义参数 - * @param submitTime 提交时间 - * @param startTime 开始执行时间 - * @param finishTime 结束时间 - * @param imageUrl 图片url - * @param progress 任务进度 - * @param failReason 失败原因 - * @param buttons 任务完成后的可执行按钮 - */ - public record Notify(String id, - String action, - String status, - - String prompt, - String promptEn, - - String description, - String state, - - Long submitTime, - Long startTime, - Long finishTime, - - String imageUrl, - String progress, - String failReason, - List