Commit 75a91a2c467a52caa844cf86b7dea6572125e939

Authored by YunaiV
1 parent 69b05a30

【代码评审】AI:音乐接入

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 *