Commit 75a91a2c467a52caa844cf86b7dea6572125e939
1 parent
69b05a30
【代码评审】AI:音乐接入
Showing
10 changed files
with
26 additions
and
19 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateEnum.java
| @@ -12,6 +12,7 @@ import lombok.Getter; | @@ -12,6 +12,7 @@ import lombok.Getter; | ||
| 12 | @Getter | 12 | @Getter |
| 13 | public enum AiMusicGenerateEnum { | 13 | public enum AiMusicGenerateEnum { |
| 14 | 14 | ||
| 15 | + // TODO @xin:用数字哈。项目目前枚举都是数字 | ||
| 15 | LYRIC("lyric", "歌词模式"), | 16 | LYRIC("lyric", "歌词模式"), |
| 16 | DESCRIPTION("description", "描述模式"); | 17 | DESCRIPTION("description", "描述模式"); |
| 17 | 18 | ||
| @@ -32,4 +33,5 @@ public enum AiMusicGenerateEnum { | @@ -32,4 +33,5 @@ public enum AiMusicGenerateEnum { | ||
| 32 | } | 33 | } |
| 33 | throw new IllegalArgumentException("未知模式: " + mode); | 34 | throw new IllegalArgumentException("未知模式: " + mode); |
| 34 | } | 35 | } |
| 36 | + | ||
| 35 | } | 37 | } |
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicStatusEnum.java
| @@ -12,6 +12,7 @@ import lombok.Getter; | @@ -12,6 +12,7 @@ import lombok.Getter; | ||
| 12 | @Getter | 12 | @Getter |
| 13 | public enum AiMusicStatusEnum { | 13 | public enum AiMusicStatusEnum { |
| 14 | 14 | ||
| 15 | + // TODO @xin:用数字哈。项目目前枚举都是数字 | ||
| 15 | // @xin 文档中无失败这个返回值 | 16 | // @xin 文档中无失败这个返回值 |
| 16 | STREAMING("streaming", "进行中"), | 17 | STREAMING("streaming", "进行中"), |
| 17 | COMPLETE("complete", "完成"); | 18 | COMPLETE("complete", "完成"); |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java
| @@ -16,12 +16,13 @@ import java.util.List; | @@ -16,12 +16,13 @@ import java.util.List; | ||
| 16 | 16 | ||
| 17 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 17 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 18 | 18 | ||
| 19 | -@Tag(name = "管理后台 - AI 音乐生成") | 19 | +@Tag(name = "管理后台 - AI 音乐") |
| 20 | @RestController | 20 | @RestController |
| 21 | @RequestMapping("/ai/music") | 21 | @RequestMapping("/ai/music") |
| 22 | -@RequiredArgsConstructor | 22 | +@RequiredArgsConstructor // TODO @xin:通过 @Resource 注入哈 |
| 23 | public class AiMusicController { | 23 | public class AiMusicController { |
| 24 | 24 | ||
| 25 | + // TODO @xin:变量不用有 ai 前缀 | ||
| 25 | private final AiMusicService aiMusicService; | 26 | private final AiMusicService aiMusicService; |
| 26 | 27 | ||
| 27 | @PostMapping("/generate") | 28 | @PostMapping("/generate") |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoReqVO.java
| @@ -6,7 +6,7 @@ import lombok.Data; | @@ -6,7 +6,7 @@ import lombok.Data; | ||
| 6 | 6 | ||
| 7 | import java.util.List; | 7 | import java.util.List; |
| 8 | 8 | ||
| 9 | - | 9 | +// TODO @xin:1)ai 前缀;2)AiSunoGenerateReqVO,要有生成哈。3)swaggger 缺少的属性,也最好加下,类似 example,类上的 swagger 等 |
| 10 | /** | 10 | /** |
| 11 | * @author xiaoxin | 11 | * @author xiaoxin |
| 12 | */ | 12 | */ |
| @@ -19,7 +19,8 @@ public class SunoReqVO { | @@ -19,7 +19,8 @@ public class SunoReqVO { | ||
| 19 | @Schema(description = "是否纯音乐") | 19 | @Schema(description = "是否纯音乐") |
| 20 | private Boolean makeInstrumental; | 20 | private Boolean makeInstrumental; |
| 21 | 21 | ||
| 22 | - @Schema(description = "模型版本 ") | 22 | + // TODO @xin:我们自己是不是用 modelVersion?还是什么梗精准,减少非必要的缩写 |
| 23 | + @Schema(description = "模型版本") | ||
| 23 | private String mv; | 24 | private String mv; |
| 24 | 25 | ||
| 25 | @Schema(description = "音乐风格") | 26 | @Schema(description = "音乐风格") |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/music/AiMusicDO.java
| @@ -12,6 +12,7 @@ import lombok.Data; | @@ -12,6 +12,7 @@ import lombok.Data; | ||
| 12 | 12 | ||
| 13 | import java.util.List; | 13 | import java.util.List; |
| 14 | 14 | ||
| 15 | +// TODO @xin:注释完善下 | ||
| 15 | /** | 16 | /** |
| 16 | * @Author xiaoxin | 17 | * @Author xiaoxin |
| 17 | * @Date 2024/6/5 | 18 | * @Date 2024/6/5 |
| @@ -94,7 +95,6 @@ public class AiMusicDO extends BaseDO { | @@ -94,7 +95,6 @@ public class AiMusicDO extends BaseDO { | ||
| 94 | */ | 95 | */ |
| 95 | private String errorMessage; | 96 | private String errorMessage; |
| 96 | 97 | ||
| 97 | - | ||
| 98 | /** | 98 | /** |
| 99 | * 音乐风格标签 | 99 | * 音乐风格标签 |
| 100 | */ | 100 | */ |
| @@ -106,7 +106,7 @@ public class AiMusicDO extends BaseDO { | @@ -106,7 +106,7 @@ public class AiMusicDO extends BaseDO { | ||
| 106 | */ | 106 | */ |
| 107 | private String taskId; | 107 | private String taskId; |
| 108 | 108 | ||
| 109 | - | 109 | + // TODO @xin:用 @TableField(typeHandler = JacksonTypeHandler.class) 替代即可 |
| 110 | public static class AiMusicTagsHandler extends AbstractJsonTypeHandler<Object> { | 110 | public static class AiMusicTagsHandler extends AbstractJsonTypeHandler<Object> { |
| 111 | 111 | ||
| 112 | @Override | 112 | @Override |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/SunoJob.java
| @@ -15,6 +15,7 @@ import java.util.HashMap; | @@ -15,6 +15,7 @@ import java.util.HashMap; | ||
| 15 | import java.util.List; | 15 | import java.util.List; |
| 16 | import java.util.Map; | 16 | import java.util.Map; |
| 17 | 17 | ||
| 18 | +// TODO @xin:不要直接叫这个名字哈,要有它的目的 | ||
| 18 | /** | 19 | /** |
| 19 | * 处理 Suno Job | 20 | * 处理 Suno Job |
| 20 | * @author xiaoxin | 21 | * @author xiaoxin |
| @@ -30,6 +31,7 @@ public class SunoJob implements JobHandler { | @@ -30,6 +31,7 @@ public class SunoJob implements JobHandler { | ||
| 30 | 31 | ||
| 31 | @Override | 32 | @Override |
| 32 | public String execute(String param) { | 33 | public String execute(String param) { |
| 34 | + // TODO @xin:可以考虑,整个逻辑都下沉到 Service 里,有点类似 AccessLogCleanJob | ||
| 33 | List<AiMusicDO> unCompletedTask = musicService.getUnCompletedTask(); | 35 | List<AiMusicDO> unCompletedTask = musicService.getUnCompletedTask(); |
| 34 | 36 | ||
| 35 | if (CollUtil.isEmpty(unCompletedTask)) { | 37 | if (CollUtil.isEmpty(unCompletedTask)) { |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicConvert.java
| @@ -30,8 +30,10 @@ public class AiMusicConvert { | @@ -30,8 +30,10 @@ public class AiMusicConvert { | ||
| 30 | .setTags(StrUtil.isNotBlank(musicData.tags()) ? List.of(musicData.tags().split(StrPool.COMMA)) : null); | 30 | .setTags(StrUtil.isNotBlank(musicData.tags()) ? List.of(musicData.tags().split(StrPool.COMMA)) : null); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | - public static List<AiMusicDO> convertFrom(List<SunoApi.MusicData> musicDataList) { | ||
| 34 | - return musicDataList.stream() | 33 | + // TODO @xin:一般情况下,不用 convert,直接逻辑里 convert 就好啦。 |
| 34 | + public static List<AiMusicDO> convertFrom(List<SunoApi.MusicData> list) { | ||
| 35 | + // TODO @xin:可以使用 CollectionUtils.convertList 简洁一点 | ||
| 36 | + return list.stream() | ||
| 35 | .map(AiMusicConvert::convertFrom) | 37 | .map(AiMusicConvert::convertFrom) |
| 36 | .collect(Collectors.toList()); | 38 | .collect(Collectors.toList()); |
| 37 | } | 39 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicService.java
| @@ -12,7 +12,6 @@ import java.util.List; | @@ -12,7 +12,6 @@ import java.util.List; | ||
| 12 | */ | 12 | */ |
| 13 | public interface AiMusicService { | 13 | public interface AiMusicService { |
| 14 | 14 | ||
| 15 | - | ||
| 16 | /** | 15 | /** |
| 17 | * 音乐生成 | 16 | * 音乐生成 |
| 18 | * | 17 | * |
| @@ -21,7 +20,6 @@ public interface AiMusicService { | @@ -21,7 +20,6 @@ public interface AiMusicService { | ||
| 21 | */ | 20 | */ |
| 22 | List<Long> generateMusic(SunoReqVO reqVO); | 21 | List<Long> generateMusic(SunoReqVO reqVO); |
| 23 | 22 | ||
| 24 | - | ||
| 25 | /** | 23 | /** |
| 26 | * 获取未完成状态的任务 | 24 | * 获取未完成状态的任务 |
| 27 | * | 25 | * |
| @@ -29,8 +27,6 @@ public interface AiMusicService { | @@ -29,8 +27,6 @@ public interface AiMusicService { | ||
| 29 | */ | 27 | */ |
| 30 | List<AiMusicDO> getUnCompletedTask(); | 28 | List<AiMusicDO> getUnCompletedTask(); |
| 31 | 29 | ||
| 32 | - | ||
| 33 | Boolean updateBatch(List<AiMusicDO> aiMusicDOList); | 30 | Boolean updateBatch(List<AiMusicDO> aiMusicDOList); |
| 34 | 31 | ||
| 35 | - | ||
| 36 | } | 32 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicServiceImpl.java
| @@ -21,6 +21,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti | @@ -21,6 +21,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti | ||
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * AI 音乐 Service 实现类 | 23 | * AI 音乐 Service 实现类 |
| 24 | + * | ||
| 24 | * @author xiaoxin | 25 | * @author xiaoxin |
| 25 | */ | 26 | */ |
| 26 | @Service | 27 | @Service |
| @@ -29,11 +30,13 @@ public class AiMusicServiceImpl implements AiMusicService { | @@ -29,11 +30,13 @@ public class AiMusicServiceImpl implements AiMusicService { | ||
| 29 | 30 | ||
| 30 | @Resource | 31 | @Resource |
| 31 | private SunoApi sunoApi; | 32 | private SunoApi sunoApi; |
| 33 | + | ||
| 32 | @Resource | 34 | @Resource |
| 33 | private AiMusicMapper musicMapper; | 35 | private AiMusicMapper musicMapper; |
| 34 | 36 | ||
| 35 | @Override | 37 | @Override |
| 36 | public List<Long> generateMusic(SunoReqVO reqVO) { | 38 | public List<Long> generateMusic(SunoReqVO reqVO) { |
| 39 | + // TODO @xin:是不是可以 if else 调用对应的 API,然后 insertMusicData 逻辑 | ||
| 37 | AiMusicGenerateEnum generateEnum = AiMusicGenerateEnum.valueOfMode(reqVO.getGenerateMode()); | 40 | AiMusicGenerateEnum generateEnum = AiMusicGenerateEnum.valueOfMode(reqVO.getGenerateMode()); |
| 38 | return switch (generateEnum) { | 41 | return switch (generateEnum) { |
| 39 | case DESCRIPTION -> descriptionMode(reqVO); | 42 | case DESCRIPTION -> descriptionMode(reqVO); |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java
| @@ -19,8 +19,8 @@ import java.util.function.Predicate; | @@ -19,8 +19,8 @@ import java.util.function.Predicate; | ||
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | * Suno API | 21 | * Suno API |
| 22 | - * <b> | ||
| 23 | - * 文档地址:https://github.com/status2xx/suno-api/blob/main/README_CN.md | 22 | + * |
| 23 | + * 对接 Suno Proxy:<a href="https://github.com/gcui-art/suno-api">suno-api</a> | ||
| 24 | * | 24 | * |
| 25 | * @author xiaoxin | 25 | * @author xiaoxin |
| 26 | */ | 26 | */ |
| @@ -31,14 +31,14 @@ public class SunoApi { | @@ -31,14 +31,14 @@ public class SunoApi { | ||
| 31 | 31 | ||
| 32 | private final Predicate<HttpStatusCode> STATUS_PREDICATE = status -> !status.is2xxSuccessful(); | 32 | private final Predicate<HttpStatusCode> STATUS_PREDICATE = status -> !status.is2xxSuccessful(); |
| 33 | 33 | ||
| 34 | - private final Function<Object, Function<ClientResponse, Mono<? extends Throwable>>> EXCEPTION_FUNCTION = reqParam -> response -> response.bodyToMono(String.class) | ||
| 35 | - .handle((respBody, sink) -> { | 34 | + private final Function<Object, Function<ClientResponse, Mono<? extends Throwable>>> EXCEPTION_FUNCTION = |
| 35 | + reqParam -> response -> response.bodyToMono(String.class).handle((responseBody, sink) -> { | ||
| 36 | HttpRequest request = response.request(); | 36 | HttpRequest request = response.request(); |
| 37 | - log.error("[suno-api] 调用失败!请求方式:[{}], 请求地址:[{}], 请求参数:[{}], 响应数据: [{}]", request.getMethod(), request.getURI(), reqParam, respBody); | 37 | + log.error("[suno-api] 调用失败!请求方式:[{}],请求地址:[{}],请求参数:[{}],响应数据: [{}]", |
| 38 | + request.getMethod(), request.getURI(), reqParam, responseBody); | ||
| 38 | sink.error(new IllegalStateException("[suno-api] 调用失败!")); | 39 | sink.error(new IllegalStateException("[suno-api] 调用失败!")); |
| 39 | }); | 40 | }); |
| 40 | 41 | ||
| 41 | - | ||
| 42 | public SunoApi(String baseUrl) { | 42 | public SunoApi(String baseUrl) { |
| 43 | this.webClient = WebClient.builder() | 43 | this.webClient = WebClient.builder() |
| 44 | .baseUrl(baseUrl) | 44 | .baseUrl(baseUrl) |
| @@ -111,7 +111,6 @@ public class SunoApi { | @@ -111,7 +111,6 @@ public class SunoApi { | ||
| 111 | .block(); | 111 | .block(); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | - | ||
| 115 | /** | 114 | /** |
| 116 | * 根据提示生成音频 | 115 | * 根据提示生成音频 |
| 117 | * | 116 | * |