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 | 12 | @Getter |
| 13 | 13 | public enum AiMusicGenerateEnum { |
| 14 | 14 | |
| 15 | + // TODO @xin:用数字哈。项目目前枚举都是数字 | |
| 15 | 16 | LYRIC("lyric", "歌词模式"), |
| 16 | 17 | DESCRIPTION("description", "描述模式"); |
| 17 | 18 | |
| ... | ... | @@ -32,4 +33,5 @@ public enum AiMusicGenerateEnum { |
| 32 | 33 | } |
| 33 | 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
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 | 16 | |
| 17 | 17 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 18 | 18 | |
| 19 | -@Tag(name = "管理后台 - AI 音乐生成") | |
| 19 | +@Tag(name = "管理后台 - AI 音乐") | |
| 20 | 20 | @RestController |
| 21 | 21 | @RequestMapping("/ai/music") |
| 22 | -@RequiredArgsConstructor | |
| 22 | +@RequiredArgsConstructor // TODO @xin:通过 @Resource 注入哈 | |
| 23 | 23 | public class AiMusicController { |
| 24 | 24 | |
| 25 | + // TODO @xin:变量不用有 ai 前缀 | |
| 25 | 26 | private final AiMusicService aiMusicService; |
| 26 | 27 | |
| 27 | 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 | 6 | |
| 7 | 7 | import java.util.List; |
| 8 | 8 | |
| 9 | - | |
| 9 | +// TODO @xin:1)ai 前缀;2)AiSunoGenerateReqVO,要有生成哈。3)swaggger 缺少的属性,也最好加下,类似 example,类上的 swagger 等 | |
| 10 | 10 | /** |
| 11 | 11 | * @author xiaoxin |
| 12 | 12 | */ |
| ... | ... | @@ -19,7 +19,8 @@ public class SunoReqVO { |
| 19 | 19 | @Schema(description = "是否纯音乐") |
| 20 | 20 | private Boolean makeInstrumental; |
| 21 | 21 | |
| 22 | - @Schema(description = "模型版本 ") | |
| 22 | + // TODO @xin:我们自己是不是用 modelVersion?还是什么梗精准,减少非必要的缩写 | |
| 23 | + @Schema(description = "模型版本") | |
| 23 | 24 | private String mv; |
| 24 | 25 | |
| 25 | 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 | 12 | |
| 13 | 13 | import java.util.List; |
| 14 | 14 | |
| 15 | +// TODO @xin:注释完善下 | |
| 15 | 16 | /** |
| 16 | 17 | * @Author xiaoxin |
| 17 | 18 | * @Date 2024/6/5 |
| ... | ... | @@ -94,7 +95,6 @@ public class AiMusicDO extends BaseDO { |
| 94 | 95 | */ |
| 95 | 96 | private String errorMessage; |
| 96 | 97 | |
| 97 | - | |
| 98 | 98 | /** |
| 99 | 99 | * 音乐风格标签 |
| 100 | 100 | */ |
| ... | ... | @@ -106,7 +106,7 @@ public class AiMusicDO extends BaseDO { |
| 106 | 106 | */ |
| 107 | 107 | private String taskId; |
| 108 | 108 | |
| 109 | - | |
| 109 | + // TODO @xin:用 @TableField(typeHandler = JacksonTypeHandler.class) 替代即可 | |
| 110 | 110 | public static class AiMusicTagsHandler extends AbstractJsonTypeHandler<Object> { |
| 111 | 111 | |
| 112 | 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 | 15 | import java.util.List; |
| 16 | 16 | import java.util.Map; |
| 17 | 17 | |
| 18 | +// TODO @xin:不要直接叫这个名字哈,要有它的目的 | |
| 18 | 19 | /** |
| 19 | 20 | * 处理 Suno Job |
| 20 | 21 | * @author xiaoxin |
| ... | ... | @@ -30,6 +31,7 @@ public class SunoJob implements JobHandler { |
| 30 | 31 | |
| 31 | 32 | @Override |
| 32 | 33 | public String execute(String param) { |
| 34 | + // TODO @xin:可以考虑,整个逻辑都下沉到 Service 里,有点类似 AccessLogCleanJob | |
| 33 | 35 | List<AiMusicDO> unCompletedTask = musicService.getUnCompletedTask(); |
| 34 | 36 | |
| 35 | 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 | 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 | 37 | .map(AiMusicConvert::convertFrom) |
| 36 | 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 | 12 | */ |
| 13 | 13 | public interface AiMusicService { |
| 14 | 14 | |
| 15 | - | |
| 16 | 15 | /** |
| 17 | 16 | * 音乐生成 |
| 18 | 17 | * |
| ... | ... | @@ -21,7 +20,6 @@ public interface AiMusicService { |
| 21 | 20 | */ |
| 22 | 21 | List<Long> generateMusic(SunoReqVO reqVO); |
| 23 | 22 | |
| 24 | - | |
| 25 | 23 | /** |
| 26 | 24 | * 获取未完成状态的任务 |
| 27 | 25 | * |
| ... | ... | @@ -29,8 +27,6 @@ public interface AiMusicService { |
| 29 | 27 | */ |
| 30 | 28 | List<AiMusicDO> getUnCompletedTask(); |
| 31 | 29 | |
| 32 | - | |
| 33 | 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 | 21 | |
| 22 | 22 | /** |
| 23 | 23 | * AI 音乐 Service 实现类 |
| 24 | + * | |
| 24 | 25 | * @author xiaoxin |
| 25 | 26 | */ |
| 26 | 27 | @Service |
| ... | ... | @@ -29,11 +30,13 @@ public class AiMusicServiceImpl implements AiMusicService { |
| 29 | 30 | |
| 30 | 31 | @Resource |
| 31 | 32 | private SunoApi sunoApi; |
| 33 | + | |
| 32 | 34 | @Resource |
| 33 | 35 | private AiMusicMapper musicMapper; |
| 34 | 36 | |
| 35 | 37 | @Override |
| 36 | 38 | public List<Long> generateMusic(SunoReqVO reqVO) { |
| 39 | + // TODO @xin:是不是可以 if else 调用对应的 API,然后 insertMusicData 逻辑 | |
| 37 | 40 | AiMusicGenerateEnum generateEnum = AiMusicGenerateEnum.valueOfMode(reqVO.getGenerateMode()); |
| 38 | 41 | return switch (generateEnum) { |
| 39 | 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 | 19 | |
| 20 | 20 | /** |
| 21 | 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 | 25 | * @author xiaoxin |
| 26 | 26 | */ |
| ... | ... | @@ -31,14 +31,14 @@ public class SunoApi { |
| 31 | 31 | |
| 32 | 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 | 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 | 39 | sink.error(new IllegalStateException("[suno-api] 调用失败!")); |
| 39 | 40 | }); |
| 40 | 41 | |
| 41 | - | |
| 42 | 42 | public SunoApi(String baseUrl) { |
| 43 | 43 | this.webClient = WebClient.builder() |
| 44 | 44 | .baseUrl(baseUrl) |
| ... | ... | @@ -111,7 +111,6 @@ public class SunoApi { |
| 111 | 111 | .block(); |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | - | |
| 115 | 114 | /** |
| 116 | 115 | * 根据提示生成音频 |
| 117 | 116 | * | ... | ... |