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