Commit 4ef55fa921ae3b95c47b606fdf1a7dd6a57194a1

Authored by xiaoxin
2 parents 793aeea2 1093e295

Merge remote-tracking branch 'origin/master-jdk21-ai' into master-jdk21-ai

# Conflicts:
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http
Showing 14 changed files with 86 additions and 110 deletions
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http
1   -
2   -### chat call
3   -POST {{baseUrl}}/admin-api/ai/chat/message/send
  1 +### 发送消息(段式)
  2 +POST {{baseUrl}}/ai/chat/message/send
4 3 Content-Type: application/json
5 4 Authorization: {{token}}
6 5  
7 6 {
8   - "conversationId": "1781604279872581649",
  7 + "conversationId": "1781604279872581724",
9 8 "content": "你是 OpenAI 么?"
10 9 }
11 10  
12   -
13 11 ### 发送消息(流式)
14 12 POST {{baseUrl}}/ai/chat/message/send-stream
15 13 Content-Type: application/json
... ... @@ -20,11 +18,10 @@ Authorization: {{token}}
20 18 "content": "1+1=?"
21 19 }
22 20  
23   -### message list
24   -GET {{baseUrl}}/admin-api/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581649
  21 +### 获得指定对话的消息列表
  22 +GET {{baseUrl}}/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581649
25 23 Authorization: {{token}}
26 24  
27   -
28   -### message delete
29   -DELETE {{baseUrl}}/admin-api/ai/chat/message/delete?id=50
30   -Authorization: {{token}}
  25 +### 删除消息
  26 +DELETE {{baseUrl}}/ai/chat/message/delete?id=50
  27 +Authorization: {{token}}
31 28 \ No newline at end of file
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java
... ... @@ -21,10 +21,10 @@ import io.swagger.v3.oas.annotations.Parameter;
21 21 import io.swagger.v3.oas.annotations.tags.Tag;
22 22 import jakarta.annotation.Resource;
23 23 import jakarta.annotation.security.PermitAll;
  24 +import jakarta.validation.Valid;
24 25 import lombok.extern.slf4j.Slf4j;
25 26 import org.springframework.http.MediaType;
26 27 import org.springframework.security.access.prepost.PreAuthorize;
27   -import org.springframework.validation.annotation.Validated;
28 28 import org.springframework.web.bind.annotation.*;
29 29 import reactor.core.publisher.Flux;
30 30  
... ... @@ -51,14 +51,14 @@ public class AiChatMessageController {
51 51  
52 52 @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢")
53 53 @PostMapping("/send")
54   - public CommonResult<AiChatMessageRespVO> sendMessage(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) {
55   - return success(chatMessageService.sendMessage(sendReqVO));
  54 + public CommonResult<AiChatMessageSendRespVO> sendMessage(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) {
  55 + return success(chatMessageService.sendMessage(sendReqVO, getLoginUserId()));
56 56 }
57 57  
58 58 @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快")
59 59 @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
60 60 @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题
61   - public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) {
  61 + public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) {
62 62 return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId());
63 63 }
64 64  
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java
... ... @@ -31,14 +31,6 @@ public class AiChatMessageSendRespVO {
31 31 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
32 32 private LocalDateTime createTime;
33 33  
34   - // ========== 扩展字段 ==========
35   -
36   - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://iocoder.cn/1.png")
37   - private String userAvatar;
38   -
39   - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://iocoder.cn/2.png")
40   - private String roleAvatar;
41   -
42 34 }
43 35  
44 36 }
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java
... ... @@ -68,7 +68,7 @@ public class AiImageController {
68 68  
69 69 @Operation(summary = "生成图片")
70 70 @PostMapping("/draw")
71   - public CommonResult<Long> drawImage(@Validated @RequestBody AiImageDrawReqVO drawReqVO) {
  71 + public CommonResult<Long> drawImage(@Valid @RequestBody AiImageDrawReqVO drawReqVO) {
72 72 return success(imageService.drawImage(getLoginUserId(), drawReqVO));
73 73 }
74 74  
... ... @@ -84,7 +84,7 @@ public class AiImageController {
84 84  
85 85 @Operation(summary = "【Midjourney】生成图片")
86 86 @PostMapping("/midjourney/imagine")
87   - public CommonResult<Long> midjourneyImagine(@Validated @RequestBody AiMidjourneyImagineReqVO reqVO) {
  87 + public CommonResult<Long> midjourneyImagine(@Valid @RequestBody AiMidjourneyImagineReqVO reqVO) {
88 88 Long imageId = imageService.midjourneyImagine(getLoginUserId(), reqVO);
89 89 return success(imageId);
90 90 }
... ... @@ -92,14 +92,14 @@ public class AiImageController {
92 92 @Operation(summary = "【Midjourney】通知图片进展", description = "由 Midjourney Proxy 回调")
93 93 @PostMapping("/midjourney/notify") // 必须是 POST 方法,否则会报错
94 94 @PermitAll
95   - public CommonResult<Boolean> midjourneyNotify(@Validated @RequestBody MidjourneyApi.Notify notify) {
  95 + public CommonResult<Boolean> midjourneyNotify(@Valid @RequestBody MidjourneyApi.Notify notify) {
96 96 imageService.midjourneyNotify(notify);
97 97 return success(true);
98 98 }
99 99  
100 100 @Operation(summary = "【Midjourney】Action 操作(二次生成图片)", description = "例如说:放大、缩小、U1、U2 等")
101 101 @PostMapping("/midjourney/action")
102   - public CommonResult<Long> midjourneyAction(@Validated @RequestBody AiMidjourneyActionReqVO reqVO) {
  102 + public CommonResult<Long> midjourneyAction(@Valid @RequestBody AiMidjourneyActionReqVO reqVO) {
103 103 Long imageId = imageService.midjourneyAction(getLoginUserId(), reqVO);
104 104 return success(imageId);
105 105 }
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http
... ... @@ -6,8 +6,8 @@ Authorization: {{token}}
6 6 {
7 7 "platform": "Suno",
8 8 "generateMode": 2,
9   - "prompt": "周末啦!",
10   - "model": "chirp-v3-5",
  9 + "prompt": "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。",
  10 + "model": "chirp-v3.5",
11 11 "tags": ["Happy"],
12 12 "title": "Happy Song"
13 13 }
... ... @@ -20,7 +20,7 @@ Authorization: {{token}}
20 20 {
21 21 "platform": "Suno",
22 22 "generateMode": 1,
23   - "model": "chirp-v3-5",
24   - "prompt": "今天是星球六,结果是个下雨天,希望心情很美丽",
  23 + "model": "chirp-v3.5",
  24 + "prompt": "happy music",
25 25 "makeInstrumental": false
26 26 }
27 27 \ No newline at end of file
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java
... ... @@ -38,6 +38,10 @@ public class AiMusicController {
38 38 @PostMapping("/generate")
39 39 @Operation(summary = "音乐生成")
40 40 public CommonResult<List<Long>> generateMusic(@RequestBody @Valid AiSunoGenerateReqVO reqVO) {
  41 +// if (true) {
  42 +// musicService.syncMusic();
  43 +// return null;
  44 +// }
41 45 return success(musicService.generateMusic(getLoginUserId(), reqVO));
42 46 }
43 47  
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java
... ... @@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.ai.service.chat;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5   -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO;
6   -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*;
  5 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
  6 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
  7 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
7 8 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
8 9 import reactor.core.publisher.Flux;
9 10  
... ... @@ -22,9 +23,10 @@ public interface AiChatMessageService {
22 23 * 发送消息
23 24 *
24 25 * @param sendReqVO 发送信息
  26 + * @param userId 用户编号
25 27 * @return 发送结果
26 28 */
27   - AiChatMessageRespVO sendMessage(AiChatMessageSendReqVO sendReqVO);
  29 + AiChatMessageSendRespVO sendMessage(AiChatMessageSendReqVO sendReqVO, Long userId);
28 30  
29 31 /**
30 32 * 发送消息
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
... ... @@ -10,22 +10,20 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
10 10 import cn.iocoder.yudao.framework.common.pojo.PageResult;
11 11 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
12 12 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
13   -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
14 13 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
15 14 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
16 15 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
17 16 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
18 17 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
19   -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
20 18 import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
21 19 import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants;
22 20 import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
23 21 import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
24   -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
25 22 import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions;
26 23 import jakarta.annotation.Resource;
27 24 import lombok.extern.slf4j.Slf4j;
28 25 import org.springframework.ai.chat.messages.*;
  26 +import org.springframework.ai.chat.model.ChatModel;
29 27 import org.springframework.ai.chat.model.ChatResponse;
30 28 import org.springframework.ai.chat.model.StreamingChatModel;
31 29 import org.springframework.ai.chat.prompt.ChatOptions;
... ... @@ -64,47 +62,37 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
64 62 @Resource
65 63 private AiChatModelService chatModalService;
66 64 @Resource
67   - private AiChatRoleService chatRoleService;
68   - @Resource
69 65 private AiApiKeyService apiKeyService;
70 66  
71 67 @Transactional(rollbackFor = Exception.class)
72   - public AiChatMessageRespVO sendMessage(AiChatMessageSendReqVO req) {
73   - return null; // TODO 芋艿:一起改
74   -// Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
75   -// // 查询对话
76   -// AiChatConversationDO conversation = chatConversationService.validateExists(req.getConversationId());
77   -// // 获取对话模型
78   -// AiChatModelDO chatModel = chatModalService.validateChatModel(conversation.getModelId());
79   -// // 获取角色信息
80   -// AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null;
81   -// // 获取 client 类型
82   -// AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform());
83   -// // 保存 chat message
84   -// createChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(),
85   -// chatModel.getModel(), chatModel.getId(), req.getContent());
86   -// String content = null;
87   -// int tokens = 0;
88   -// try {
89   -// // 创建 chat 需要的 Prompt
90   -// Prompt prompt = new Prompt(req.getContent());
91   -// // TODO @芋艿 @范 看要不要支持这些
92   -//// req.setTopK(req.getTopK());
93   -//// req.setTopP(req.getTopP());
94   -//// req.setTemperature(req.getTemperature());
95   -// // 发送 call 调用
96   -// ChatClient chatClient = chatClientFactory.getChatClient(platformEnum);
97   -// ChatResponse call = chatClient.call(prompt);
98   -// content = call.getResult().getOutput().getContent();
99   -// // 更新 conversation
100   -// } catch (Exception e) {
101   -// content = ExceptionUtil.getMessage(e);
102   -// } finally {
103   -// // 保存 chat message
104   -// createChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(),
105   -// chatModel.getModel(), chatModel.getId(), content);
106   -// }
107   -// return new AiChatMessageRespVO().setContent(content);
  68 + public AiChatMessageSendRespVO sendMessage(AiChatMessageSendReqVO sendReqVO, Long userId) {
  69 + // 1.1 校验对话存在
  70 + AiChatConversationDO conversation = chatConversationService.validateChatConversationExists(sendReqVO.getConversationId());
  71 + if (ObjUtil.notEqual(conversation.getUserId(), userId)) {
  72 + throw exception(CHAT_CONVERSATION_NOT_EXISTS);
  73 + }
  74 + List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId());
  75 + // 1.2 校验模型
  76 + AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());
  77 + ChatModel chatClient = apiKeyService.getChatClient(model.getKeyId());
  78 +
  79 + // 2. 插入 user 发送消息
  80 + AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
  81 + userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext());
  82 +
  83 + // 3.1 插入 assistant 接收消息
  84 + AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
  85 + userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext());
  86 +
  87 + // 3.2 创建 chat 需要的 Prompt
  88 + Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO);
  89 + ChatResponse chatResponse = chatClient.call(prompt);
  90 +
  91 + // 3.3 段式返回
  92 + String newContent = chatResponse.getResult().getOutput().getContent();
  93 + chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(newContent));
  94 + return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class))
  95 + .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent));
108 96 }
109 97  
110 98 @Override
... ... @@ -112,14 +100,12 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
112 100 // 1.1 校验对话存在
113 101 AiChatConversationDO conversation = chatConversationService.validateChatConversationExists(sendReqVO.getConversationId());
114 102 if (ObjUtil.notEqual(conversation.getUserId(), userId)) {
115   - throw exception(CHAT_CONVERSATION_NOT_EXISTS); // TODO 芋艿:异常情况的对接;
  103 + throw exception(CHAT_CONVERSATION_NOT_EXISTS);
116 104 }
117 105 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId());
118 106 // 1.2 校验模型
119 107 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());
120   - StreamingChatModel chatClient = apiKeyService.getStreamingChatClient(model.getKeyId());
121   - // 1.3 获取用户头像、角色头像
122   - AiChatRoleDO role = conversation.getRoleId() != null ? chatRoleService.getChatRole(conversation.getRoleId()) : null;
  108 + StreamingChatModel chatClient = apiKeyService.getChatClient(model.getKeyId());
123 109  
124 110 // 2. 插入 user 发送消息
125 111 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
... ... @@ -149,9 +135,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
149 135 // TODO @芋艿:失败的情况下,要不要删除消息
150 136 log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable);
151 137 chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage()));
152   - }).onErrorResume(error -> {
153   - return Flux.just(error(ErrorCodeConstants.CHAT_STREAM_ERROR));
154   - });
  138 + }).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.CHAT_STREAM_ERROR)));
155 139 }
156 140  
157 141 private Prompt buildPrompt(AiChatConversationDO conversation, List<AiChatMessageDO> messages,
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java
... ... @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageR
8 8 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO;
9 9 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
10 10 import jakarta.validation.Valid;
11   -import org.springframework.ai.chat.model.StreamingChatModel;
  11 +import org.springframework.ai.chat.model.ChatModel;
12 12 import org.springframework.ai.image.ImageModel;
13 13  
14 14 import java.util.List;
... ... @@ -76,12 +76,12 @@ public interface AiApiKeyService {
76 76 // ========== 与 spring-ai 集成 ==========
77 77  
78 78 /**
79   - * 获得 StreamingChatClient 对象
  79 + * 获得 ChatModel 对象
80 80 *
81 81 * @param id 编号
82   - * @return StreamingChatClient 对象
  82 + * @return ChatModel 对象
83 83 */
84   - StreamingChatModel getStreamingChatClient(Long id);
  84 + ChatModel getChatClient(Long id);
85 85  
86 86 /**
87 87 * 获得 ImageClient 对象
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
... ... @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveR
12 12 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
13 13 import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper;
14 14 import jakarta.annotation.Resource;
15   -import org.springframework.ai.chat.model.StreamingChatModel;
  15 +import org.springframework.ai.chat.model.ChatModel;
16 16 import org.springframework.ai.image.ImageModel;
17 17 import org.springframework.stereotype.Service;
18 18 import org.springframework.validation.annotation.Validated;
... ... @@ -98,10 +98,10 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
98 98 // ========== 与 spring-ai 集成 ==========
99 99  
100 100 @Override
101   - public StreamingChatModel getStreamingChatClient(Long id) {
  101 + public ChatModel getChatClient(Long id) {
102 102 AiApiKeyDO apiKey = validateApiKey(id);
103 103 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
104   - return clientFactory.getOrCreateStreamingChatClient(platform, apiKey.getApiKey(), apiKey.getUrl());
  104 + return clientFactory.getOrCreateChatClient(platform, apiKey.getApiKey(), apiKey.getUrl());
105 105 }
106 106  
107 107 @Override
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicServiceImpl.java
... ... @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.infra.api.file.FileApi;
21 21 import jakarta.annotation.Resource;
22 22 import lombok.extern.slf4j.Slf4j;
23 23 import org.springframework.stereotype.Service;
  24 +import org.springframework.transaction.annotation.Transactional;
24 25  
25 26 import java.util.*;
26 27  
... ... @@ -49,6 +50,7 @@ public class AiMusicServiceImpl implements AiMusicService {
49 50 private FileApi fileApi;
50 51  
51 52 @Override
  53 + @Transactional(rollbackFor = Exception.class)
52 54 public List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO) {
53 55 // 1. 调用 Suno 生成音乐
54 56 SunoApi sunoApi = apiKeyService.getSunoApi();
... ... @@ -164,14 +166,9 @@ public class AiMusicServiceImpl implements AiMusicService {
164 166 */
165 167 private List<AiMusicDO> buildMusicDOList(List<SunoApi.MusicData> musicList) {
166 168 return convertList(musicList, musicData -> {
167   - Integer status;
168   - if (Objects.equals("complete", musicData.status())) {
169   - status = AiMusicStatusEnum.SUCCESS.getStatus();
170   - } else if (Objects.equals("error", musicData.status())) {
171   - status = AiMusicStatusEnum.FAIL.getStatus();
172   - } else {
173   - status = AiMusicStatusEnum.IN_PROGRESS.getStatus();
174   - }
  169 + Integer status = Objects.equals("complete", musicData.status()) ? AiMusicStatusEnum.SUCCESS.getStatus()
  170 + : Objects.equals("error", musicData.status()) ? AiMusicStatusEnum.FAIL.getStatus()
  171 + : AiMusicStatusEnum.IN_PROGRESS.getStatus();
175 172 return new AiMusicDO()
176 173 .setTaskId(musicData.id()).setModel(musicData.modelName())
177 174 .setDescription(musicData.gptDescriptionPrompt())
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
... ... @@ -53,7 +53,7 @@ public class AiWriteServiceImpl implements AiWriteService {
53 53 // 1.1 校验模型
54 54 // TODO @xin:可以约定大于配置先,查询某个名字。例如说,写作助手!然后写作助手,上面是有个 model 的,可以使用它。
55 55 AiChatModelDO model = chatModalService.validateChatModel(14L);
56   - StreamingChatModel chatClient = apiKeyService.getStreamingChatClient(model.getKeyId());
  56 + StreamingChatModel chatClient = apiKeyService.getChatClient(model.getKeyId());
57 57 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
58 58 ChatOptions chatOptions = buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens());
59 59  
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java
... ... @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.ai.core.factory;
3 3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
4 4 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
5 5 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
6   -import org.springframework.ai.chat.model.StreamingChatModel;
  6 +import org.springframework.ai.chat.model.ChatModel;
7 7 import org.springframework.ai.image.ImageModel;
8 8  
9 9 /**
... ... @@ -14,26 +14,26 @@ import org.springframework.ai.image.ImageModel;
14 14 public interface AiClientFactory {
15 15  
16 16 /**
17   - * 基于指定配置,获得 StreamingChatClient 对象
  17 + * 基于指定配置,获得 ChatModel 对象
18 18 *
19 19 * 如果不存在,则进行创建
20 20 *
21 21 * @param platform 平台
22 22 * @param apiKey API KEY
23 23 * @param url API URL
24   - * @return StreamingChatClient 对象
  24 + * @return ChatModel 对象
25 25 */
26   - StreamingChatModel getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url);
  26 + ChatModel getOrCreateChatClient(AiPlatformEnum platform, String apiKey, String url);
27 27  
28 28 /**
29   - * 基于默认配置,获得 StreamingChatClient 对象
  29 + * 基于默认配置,获得 ChatModel 对象
30 30 *
31 31 * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置
32 32 *
33 33 * @param platform 平台
34   - * @return StreamingChatClient 对象
  34 + * @return ChatModel 对象
35 35 */
36   - StreamingChatModel getDefaultStreamingChatClient(AiPlatformEnum platform);
  36 + ChatModel getDefaultChatClient(AiPlatformEnum platform);
37 37  
38 38 /**
39 39 * 基于默认配置,获得 ImageClient 对象
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java
... ... @@ -23,7 +23,7 @@ import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
23 23 import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration;
24 24 import org.springframework.ai.autoconfigure.qianfan.QianFanChatProperties;
25 25 import org.springframework.ai.autoconfigure.qianfan.QianFanConnectionProperties;
26   -import org.springframework.ai.chat.model.StreamingChatModel;
  26 +import org.springframework.ai.chat.model.ChatModel;
27 27 import org.springframework.ai.image.ImageModel;
28 28 import org.springframework.ai.ollama.OllamaChatModel;
29 29 import org.springframework.ai.ollama.api.OllamaApi;
... ... @@ -50,9 +50,9 @@ import java.util.List;
50 50 public class AiClientFactoryImpl implements AiClientFactory {
51 51  
52 52 @Override
53   - public StreamingChatModel getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url) {
54   - String cacheKey = buildClientCacheKey(StreamingChatModel.class, platform, apiKey, url);
55   - return Singleton.get(cacheKey, (Func0<StreamingChatModel>) () -> {
  53 + public ChatModel getOrCreateChatClient(AiPlatformEnum platform, String apiKey, String url) {
  54 + String cacheKey = buildClientCacheKey(ChatModel.class, platform, apiKey, url);
  55 + return Singleton.get(cacheKey, (Func0<ChatModel>) () -> {
56 56 //noinspection EnhancedSwitchMigration
57 57 switch (platform) {
58 58 case OPENAI:
... ... @@ -74,7 +74,7 @@ public class AiClientFactoryImpl implements AiClientFactory {
74 74 }
75 75  
76 76 @Override
77   - public StreamingChatModel getDefaultStreamingChatClient(AiPlatformEnum platform) {
  77 + public ChatModel getDefaultChatClient(AiPlatformEnum platform) {
78 78 //noinspection EnhancedSwitchMigration
79 79 switch (platform) {
80 80 case OPENAI:
... ...