Commit 2ae90b9edc327db77e77d9aaa7e15cfbf62853b1
Merge remote-tracking branch 'origin/master-jdk21-ai' into master-jdk21-ai
Showing
15 changed files
with
209 additions
and
145 deletions
script/idea/http-client.env.json
| 1 | { | 1 | { |
| 2 | "local": { | 2 | "local": { |
| 3 | "baseUrl": "http://127.0.0.1:48080/admin-api", | 3 | "baseUrl": "http://127.0.0.1:48080/admin-api", |
| 4 | - "token": "Bearer 1c2ce60de96a4fb0bf5bea9604099a3d", | 4 | + "token": "test1", |
| 5 | "adminTenentId": "1", | 5 | "adminTenentId": "1", |
| 6 | 6 | ||
| 7 | "appApi": "http://127.0.0.1:48080/app-api", | 7 | "appApi": "http://127.0.0.1:48080/app-api", |
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java
| @@ -39,6 +39,7 @@ public enum AiChatRoleEnum implements IntArrayValuable { | @@ -39,6 +39,7 @@ public enum AiChatRoleEnum implements IntArrayValuable { | ||
| 39 | 除此之外不要任何解释性语句。 | 39 | 除此之外不要任何解释性语句。 |
| 40 | """); | 40 | """); |
| 41 | 41 | ||
| 42 | + // TODO @xin:这个 role 是不是删除掉好点哈。= = 目前主要是没做角色枚举。这里多了 role 反倒容易误解哈 | ||
| 42 | /** | 43 | /** |
| 43 | * 角色 | 44 | * 角色 |
| 44 | */ | 45 | */ |
yudao-module-ai/yudao-module-ai-biz/pom.xml
| @@ -60,9 +60,5 @@ | @@ -60,9 +60,5 @@ | ||
| 60 | <groupId>cn.iocoder.boot</groupId> | 60 | <groupId>cn.iocoder.boot</groupId> |
| 61 | <artifactId>yudao-spring-boot-starter-test</artifactId> | 61 | <artifactId>yudao-spring-boot-starter-test</artifactId> |
| 62 | </dependency> | 62 | </dependency> |
| 63 | - <dependency> | ||
| 64 | - <groupId>cn.iocoder.boot</groupId> | ||
| 65 | - <artifactId>yudao-spring-boot-starter-excel</artifactId> | ||
| 66 | - </dependency> | ||
| 67 | </dependencies> | 63 | </dependencies> |
| 68 | </project> | 64 | </project> |
| 69 | \ No newline at end of file | 65 | \ No newline at end of file |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java
| @@ -12,8 +12,7 @@ import lombok.Data; | @@ -12,8 +12,7 @@ import lombok.Data; | ||
| 12 | * | 12 | * |
| 13 | * @author xiaoxin | 13 | * @author xiaoxin |
| 14 | */ | 14 | */ |
| 15 | -// TODO @xin:如果没 typehandler 的需求,autoResultMap 可以去掉哈 | ||
| 16 | -@TableName(value = "ai_mind_map", autoResultMap = true) | 15 | +@TableName(value = "ai_mind_map") |
| 17 | @Data | 16 | @Data |
| 18 | public class AiMindMapDO extends BaseDO { | 17 | public class AiMindMapDO extends BaseDO { |
| 19 | 18 | ||
| @@ -25,7 +24,7 @@ public class AiMindMapDO extends BaseDO { | @@ -25,7 +24,7 @@ public class AiMindMapDO extends BaseDO { | ||
| 25 | 24 | ||
| 26 | /** | 25 | /** |
| 27 | * 用户编号 | 26 | * 用户编号 |
| 28 | - * | 27 | + * <p> |
| 29 | * 关联 AdminUserDO 的 userId 字段 | 28 | * 关联 AdminUserDO 的 userId 字段 |
| 30 | */ | 29 | */ |
| 31 | private Long userId; | 30 | private Long userId; |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java
| @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; | @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; | ||
| 5 | import org.apache.ibatis.annotations.Mapper; | 5 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | - * AI 音乐 Mapper | 8 | + * AI 思维导图 Mapper |
| 9 | * | 9 | * |
| 10 | * @author xiaoxin | 10 | * @author xiaoxin |
| 11 | */ | 11 | */ |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
| @@ -111,7 +111,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | @@ -111,7 +111,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | ||
| 111 | AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model, | 111 | AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model, |
| 112 | userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext()); | 112 | userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext()); |
| 113 | 113 | ||
| 114 | - // 3.2 创建 chat 需要的 Prompt | 114 | + // 3.2 构建 Prompt,并进行调用 |
| 115 | Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO); | 115 | Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO); |
| 116 | Flux<ChatResponse> streamResponse = chatModel.stream(prompt); | 116 | Flux<ChatResponse> streamResponse = chatModel.stream(prompt); |
| 117 | 117 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
| @@ -31,6 +31,7 @@ import org.springframework.ai.image.ImageOptions; | @@ -31,6 +31,7 @@ import org.springframework.ai.image.ImageOptions; | ||
| 31 | import org.springframework.ai.image.ImagePrompt; | 31 | import org.springframework.ai.image.ImagePrompt; |
| 32 | import org.springframework.ai.image.ImageResponse; | 32 | import org.springframework.ai.image.ImageResponse; |
| 33 | import org.springframework.ai.openai.OpenAiImageOptions; | 33 | import org.springframework.ai.openai.OpenAiImageOptions; |
| 34 | +import org.springframework.ai.qianfan.QianFanImageOptions; | ||
| 34 | import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; | 35 | import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; |
| 35 | import org.springframework.scheduling.annotation.Async; | 36 | import org.springframework.scheduling.annotation.Async; |
| 36 | import org.springframework.stereotype.Service; | 37 | import org.springframework.stereotype.Service; |
| @@ -142,6 +143,11 @@ public class AiImageServiceImpl implements AiImageService { | @@ -142,6 +143,11 @@ public class AiImageServiceImpl implements AiImageService { | ||
| 142 | .withModel(draw.getModel()).withN(1) | 143 | .withModel(draw.getModel()).withN(1) |
| 143 | .withHeight(draw.getHeight()).withWidth(draw.getWidth()) | 144 | .withHeight(draw.getHeight()).withWidth(draw.getWidth()) |
| 144 | .build(); | 145 | .build(); |
| 146 | + } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.YI_YAN.getPlatform())) { | ||
| 147 | + return QianFanImageOptions.builder() | ||
| 148 | + .withModel(draw.getModel()).withN(1) | ||
| 149 | + .withHeight(draw.getHeight()).withWidth(draw.getWidth()) | ||
| 150 | + .build(); | ||
| 145 | } | 151 | } |
| 146 | throw new IllegalArgumentException("不支持的 AI 平台:" + draw.getPlatform()); | 152 | throw new IllegalArgumentException("不支持的 AI 平台:" + draw.getPlatform()); |
| 147 | } | 153 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/mindmap/AiMindMapServiceImpl.java
| 1 | package cn.iocoder.yudao.module.ai.service.mindmap; | 1 | package cn.iocoder.yudao.module.ai.service.mindmap; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | 6 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; |
| 6 | import cn.iocoder.yudao.framework.ai.core.util.AiUtils; | 7 | import cn.iocoder.yudao.framework.ai.core.util.AiUtils; |
| @@ -31,13 +32,12 @@ import reactor.core.publisher.Flux; | @@ -31,13 +32,12 @@ import reactor.core.publisher.Flux; | ||
| 31 | 32 | ||
| 32 | import java.util.ArrayList; | 33 | import java.util.ArrayList; |
| 33 | import java.util.List; | 34 | import java.util.List; |
| 34 | -import java.util.Objects; | ||
| 35 | 35 | ||
| 36 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; | 36 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; |
| 37 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 37 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | - * AI 写作 Service 实现类 | 40 | + * AI 思维导图 Service 实现类 |
| 41 | * | 41 | * |
| 42 | * @author xiaoxin | 42 | * @author xiaoxin |
| 43 | */ | 43 | */ |
| @@ -57,38 +57,28 @@ public class AiMindMapServiceImpl implements AiMindMapService { | @@ -57,38 +57,28 @@ public class AiMindMapServiceImpl implements AiMindMapService { | ||
| 57 | 57 | ||
| 58 | @Override | 58 | @Override |
| 59 | public Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId) { | 59 | public Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId) { |
| 60 | - // 1.1 获取脑图模型 尝试获取思维导图助手角色,如果没有则使用默认模型 | ||
| 61 | - AiChatRoleDO mindMapRole = CollUtil.getFirst(chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_MIND_MAP_ROLE.getName())); | ||
| 62 | - AiChatModelDO model; | ||
| 63 | - String systemMessage; | ||
| 64 | - if (Objects.nonNull(mindMapRole) && Objects.nonNull(mindMapRole.getModelId())) { | ||
| 65 | - model = chatModalService.getChatModel(mindMapRole.getModelId()); | ||
| 66 | - systemMessage = mindMapRole.getSystemMessage(); | ||
| 67 | - } else { | ||
| 68 | - model = chatModalService.getRequiredDefaultChatModel(); | ||
| 69 | - systemMessage = AiChatRoleEnum.AI_MIND_MAP_ROLE.getSystemMessage(); | ||
| 70 | - } | ||
| 71 | - | 60 | + // 1. 获取脑图模型。尝试获取思维导图助手角色,如果没有则使用默认模型 |
| 61 | + AiChatRoleDO role = CollUtil.getFirst( | ||
| 62 | + chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_MIND_MAP_ROLE.getName())); | ||
| 63 | + // 1.1 获取脑图执行模型 | ||
| 64 | + AiChatModelDO model = getModel(role); | ||
| 65 | + // 1.2 获取角色设定消息 | ||
| 66 | + String systemMessage = role != null && StrUtil.isNotBlank(role.getSystemMessage()) | ||
| 67 | + ? role.getSystemMessage() : AiChatRoleEnum.AI_MIND_MAP_ROLE.getSystemMessage(); | ||
| 68 | + // 1.3 校验平台 | ||
| 72 | AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); | 69 | AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); |
| 73 | ChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); | 70 | ChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); |
| 74 | 71 | ||
| 75 | - // 2 插入思维导图信息 | ||
| 76 | - AiMindMapDO mindMapDO = BeanUtils.toBean(generateReqVO, AiMindMapDO.class, e -> e.setUserId(userId).setModel(model.getModel()).setPlatform(platform.getPlatform())); | 72 | + // 2. 插入思维导图信息 |
| 73 | + AiMindMapDO mindMapDO = BeanUtils.toBean(generateReqVO, AiMindMapDO.class, | ||
| 74 | + mindMap -> mindMap.setUserId(userId).setModel(model.getModel()).setPlatform(platform.getPlatform())); | ||
| 77 | mindMapMapper.insert(mindMapDO); | 75 | mindMapMapper.insert(mindMapDO); |
| 78 | 76 | ||
| 79 | - ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); | ||
| 80 | - // 3.1 角色设定 | ||
| 81 | - List<Message> chatMessages = new ArrayList<>(); | ||
| 82 | - if (StrUtil.isNotBlank(systemMessage)) { | ||
| 83 | - chatMessages.add(new SystemMessage(systemMessage)); | ||
| 84 | - } | ||
| 85 | - // 3.2 用户输入 | ||
| 86 | - chatMessages.add(new UserMessage(generateReqVO.getPrompt())); | ||
| 87 | - // 3.3 构建提示词 | ||
| 88 | - Prompt prompt = new Prompt(chatMessages, chatOptions); | ||
| 89 | - | 77 | + // 3.1 构建 Prompt,并进行调用 |
| 78 | + Prompt prompt = buildPrompt(generateReqVO, model, systemMessage); | ||
| 90 | Flux<ChatResponse> streamResponse = chatModel.stream(prompt); | 79 | Flux<ChatResponse> streamResponse = chatModel.stream(prompt); |
| 91 | - // 3.4 流式返回 | 80 | + |
| 81 | + // 3.2 流式返回 | ||
| 92 | StringBuffer contentBuffer = new StringBuffer(); | 82 | StringBuffer contentBuffer = new StringBuffer(); |
| 93 | return streamResponse.map(chunk -> { | 83 | return streamResponse.map(chunk -> { |
| 94 | String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; | 84 | String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; |
| @@ -109,4 +99,36 @@ public class AiMindMapServiceImpl implements AiMindMapService { | @@ -109,4 +99,36 @@ public class AiMindMapServiceImpl implements AiMindMapService { | ||
| 109 | 99 | ||
| 110 | } | 100 | } |
| 111 | 101 | ||
| 102 | + private Prompt buildPrompt(AiMindMapGenerateReqVO generateReqVO, AiChatModelDO model, String systemMessage) { | ||
| 103 | + // 1. 构建 message 列表 | ||
| 104 | + List<Message> chatMessages = buildMessages(generateReqVO, systemMessage); | ||
| 105 | + // 2. 构建 options 对象 | ||
| 106 | + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); | ||
| 107 | + ChatOptions options = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); | ||
| 108 | + return new Prompt(chatMessages, options); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + private static List<Message> buildMessages(AiMindMapGenerateReqVO generateReqVO, String systemMessage) { | ||
| 112 | + List<Message> chatMessages = new ArrayList<>(); | ||
| 113 | + // 1. 角色设定 | ||
| 114 | + if (StrUtil.isNotBlank(systemMessage)) { | ||
| 115 | + chatMessages.add(new SystemMessage(systemMessage)); | ||
| 116 | + } | ||
| 117 | + // 2. 用户输入 | ||
| 118 | + chatMessages.add(new UserMessage(generateReqVO.getPrompt())); | ||
| 119 | + return chatMessages; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + private AiChatModelDO getModel(AiChatRoleDO role) { | ||
| 123 | + AiChatModelDO model = null; | ||
| 124 | + if (role != null && role.getModelId() != null) { | ||
| 125 | + model = chatModalService.getChatModel(role.getModelId()); | ||
| 126 | + } | ||
| 127 | + if (model != null) { | ||
| 128 | + model = chatModalService.getRequiredDefaultChatModel(); | ||
| 129 | + } | ||
| 130 | + Assert.notNull(model, "[AI] 获取不到模型"); | ||
| 131 | + return model; | ||
| 132 | + } | ||
| 133 | + | ||
| 112 | } | 134 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
| 1 | package cn.iocoder.yudao.module.ai.service.write; | 1 | package cn.iocoder.yudao.module.ai.service.write; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | 6 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; |
| 6 | import cn.iocoder.yudao.framework.ai.core.util.AiUtils; | 7 | import cn.iocoder.yudao.framework.ai.core.util.AiUtils; |
| @@ -67,19 +68,15 @@ public class AiWriteServiceImpl implements AiWriteService { | @@ -67,19 +68,15 @@ public class AiWriteServiceImpl implements AiWriteService { | ||
| 67 | 68 | ||
| 68 | @Override | 69 | @Override |
| 69 | public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) { | 70 | public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) { |
| 70 | - // 1.1 获取写作模型 尝试获取写作助手角色,如果没有则使用默认模型 | ||
| 71 | - AiChatRoleDO writeRole = CollUtil.getFirst(chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_WRITE_ROLE.getName())); | ||
| 72 | - // TODO @xin:如果有 writeRole,但是没 modeId,是不是也可以用 systemMessage 哈?建议的写法是:先通过 modelId 获取 model。如果 model == null,则 chatModalService.getRequiredDefaultChatModel();如果还是 null,则抛出异常;。。。。。。。。。。。。。。然后,systemMessage = writeRole != null && writeRole.systemPrompt != "" 这样处理。 | ||
| 73 | - AiChatModelDO model; | ||
| 74 | - String systemMessage; | ||
| 75 | - if (Objects.nonNull(writeRole) && Objects.nonNull(writeRole.getModelId())) { | ||
| 76 | - model = chatModalService.getChatModel(writeRole.getModelId()); | ||
| 77 | - systemMessage = writeRole.getSystemMessage(); | ||
| 78 | - } else { | ||
| 79 | - model = chatModalService.getRequiredDefaultChatModel(); | ||
| 80 | - systemMessage = AiChatRoleEnum.AI_WRITE_ROLE.getSystemMessage(); | ||
| 81 | - } | ||
| 82 | - // 1.2 校验平台 | 71 | + // 1 获取写作模型。尝试获取写作助手角色,没有则使用默认模型 |
| 72 | + AiChatRoleDO writeRole = CollUtil.getFirst( | ||
| 73 | + chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_WRITE_ROLE.getName())); | ||
| 74 | + // 1.1 获取写作执行模型 | ||
| 75 | + AiChatModelDO model = getModel(writeRole); | ||
| 76 | + // 1.2 获取角色设定消息 | ||
| 77 | + String systemMessage = Objects.nonNull(writeRole) && StrUtil.isNotBlank(writeRole.getSystemMessage()) | ||
| 78 | + ? writeRole.getSystemMessage() : AiChatRoleEnum.AI_WRITE_ROLE.getSystemMessage(); | ||
| 79 | + // 1.3 校验平台 | ||
| 83 | AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); | 80 | AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); |
| 84 | StreamingChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); | 81 | StreamingChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); |
| 85 | 82 | ||
| @@ -88,21 +85,11 @@ public class AiWriteServiceImpl implements AiWriteService { | @@ -88,21 +85,11 @@ public class AiWriteServiceImpl implements AiWriteService { | ||
| 88 | write -> write.setUserId(userId).setPlatform(platform.getPlatform()).setModel(model.getModel())); | 85 | write -> write.setUserId(userId).setPlatform(platform.getPlatform()).setModel(model.getModel())); |
| 89 | writeMapper.insert(writeDO); | 86 | writeMapper.insert(writeDO); |
| 90 | 87 | ||
| 91 | - // 3. 调用大模型,写作生成 | ||
| 92 | - ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); | ||
| 93 | - // 3.1 角色设定 | ||
| 94 | - // TODO @xin:要不把 90 到 97 这部分,合并到一个方法里。目的是:让这个方法的主干更明确 | ||
| 95 | - List<Message> chatMessages = new ArrayList<>(); | ||
| 96 | - if (StrUtil.isNotBlank(systemMessage)) { | ||
| 97 | - chatMessages.add(new SystemMessage(systemMessage)); | ||
| 98 | - } | ||
| 99 | - // 3.2 用户输入 | ||
| 100 | - chatMessages.add(new UserMessage(buildWritingPrompt(generateReqVO))); | ||
| 101 | - // 3.3 构建提示词 | ||
| 102 | - Prompt prompt = new Prompt(chatMessages, chatOptions); | 88 | + // 3.1 构建 Prompt,并进行调用 |
| 89 | + Prompt prompt = buildPrompt(generateReqVO, model, systemMessage); | ||
| 103 | Flux<ChatResponse> streamResponse = chatModel.stream(prompt); | 90 | Flux<ChatResponse> streamResponse = chatModel.stream(prompt); |
| 104 | 91 | ||
| 105 | - // 4. 流式返回 | 92 | + // 3.2 流式返回 |
| 106 | StringBuffer contentBuffer = new StringBuffer(); | 93 | StringBuffer contentBuffer = new StringBuffer(); |
| 107 | return streamResponse.map(chunk -> { | 94 | return streamResponse.map(chunk -> { |
| 108 | String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; | 95 | String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; |
| @@ -122,7 +109,39 @@ public class AiWriteServiceImpl implements AiWriteService { | @@ -122,7 +109,39 @@ public class AiWriteServiceImpl implements AiWriteService { | ||
| 122 | }).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.WRITE_STREAM_ERROR))); | 109 | }).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.WRITE_STREAM_ERROR))); |
| 123 | } | 110 | } |
| 124 | 111 | ||
| 125 | - private String buildWritingPrompt(AiWriteGenerateReqVO generateReqVO) { | 112 | + private AiChatModelDO getModel(AiChatRoleDO writeRole) { |
| 113 | + AiChatModelDO model = null; | ||
| 114 | + if (Objects.nonNull(writeRole) && Objects.nonNull(writeRole.getModelId())) { | ||
| 115 | + model = chatModalService.getChatModel(writeRole.getModelId()); | ||
| 116 | + } | ||
| 117 | + if (Objects.isNull(model)) { | ||
| 118 | + model = chatModalService.getRequiredDefaultChatModel(); | ||
| 119 | + } | ||
| 120 | + Assert.notNull(model, "[AI] 获取不到模型"); | ||
| 121 | + return model; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + private Prompt buildPrompt(AiWriteGenerateReqVO generateReqVO, AiChatModelDO model, String systemMessage) { | ||
| 125 | + // 1. 构建 message 列表 | ||
| 126 | + List<Message> chatMessages = buildMessages(generateReqVO, systemMessage); | ||
| 127 | + // 2. 构建 options 对象 | ||
| 128 | + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); | ||
| 129 | + ChatOptions options = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); | ||
| 130 | + return new Prompt(chatMessages, options); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + private List<Message> buildMessages(AiWriteGenerateReqVO generateReqVO, String systemMessage) { | ||
| 134 | + List<Message> chatMessages = new ArrayList<>(); | ||
| 135 | + if (StrUtil.isNotBlank(systemMessage)) { | ||
| 136 | + // 1.1 角色设定 | ||
| 137 | + chatMessages.add(new SystemMessage(systemMessage)); | ||
| 138 | + } | ||
| 139 | + // 1.2 用户输入 | ||
| 140 | + chatMessages.add(new UserMessage(buildUserMessage(generateReqVO))); | ||
| 141 | + return chatMessages; | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + private String buildUserMessage(AiWriteGenerateReqVO generateReqVO) { | ||
| 126 | String format = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_FORMAT, generateReqVO.getFormat()); | 145 | String format = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_FORMAT, generateReqVO.getFormat()); |
| 127 | String tone = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_TONE, generateReqVO.getTone()); | 146 | String tone = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_TONE, generateReqVO.getTone()); |
| 128 | String language = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LANGUAGE, generateReqVO.getLanguage()); | 147 | String language = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LANGUAGE, generateReqVO.getLanguage()); |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
| @@ -18,12 +18,15 @@ import com.alibaba.cloud.ai.tongyi.TongYiConnectionProperties; | @@ -18,12 +18,15 @@ import com.alibaba.cloud.ai.tongyi.TongYiConnectionProperties; | ||
| 18 | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatModel; | 18 | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatModel; |
| 19 | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatProperties; | 19 | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatProperties; |
| 20 | import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel; | 20 | import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel; |
| 21 | +import com.alibaba.cloud.ai.tongyi.image.TongYiImagesProperties; | ||
| 21 | import com.alibaba.dashscope.aigc.generation.Generation; | 22 | import com.alibaba.dashscope.aigc.generation.Generation; |
| 23 | +import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis; | ||
| 22 | import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; | 24 | import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; |
| 23 | import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; | 25 | import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; |
| 24 | import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; | 26 | import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; |
| 25 | import org.springframework.ai.autoconfigure.qianfan.QianFanChatProperties; | 27 | import org.springframework.ai.autoconfigure.qianfan.QianFanChatProperties; |
| 26 | import org.springframework.ai.autoconfigure.qianfan.QianFanConnectionProperties; | 28 | import org.springframework.ai.autoconfigure.qianfan.QianFanConnectionProperties; |
| 29 | +import org.springframework.ai.autoconfigure.qianfan.QianFanImageProperties; | ||
| 27 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; | 30 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; |
| 28 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties; | 31 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties; |
| 29 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; | 32 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; |
| @@ -111,6 +114,10 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -111,6 +114,10 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 111 | public ImageModel getDefaultImageModel(AiPlatformEnum platform) { | 114 | public ImageModel getDefaultImageModel(AiPlatformEnum platform) { |
| 112 | //noinspection EnhancedSwitchMigration | 115 | //noinspection EnhancedSwitchMigration |
| 113 | switch (platform) { | 116 | switch (platform) { |
| 117 | + case TONG_YI: | ||
| 118 | + return SpringUtil.getBean(TongYiImagesModel.class); | ||
| 119 | + case YI_YAN: | ||
| 120 | + return SpringUtil.getBean(QianFanImageModel.class); | ||
| 114 | case OPENAI: | 121 | case OPENAI: |
| 115 | return SpringUtil.getBean(OpenAiImageModel.class); | 122 | return SpringUtil.getBean(OpenAiImageModel.class); |
| 116 | case STABLE_DIFFUSION: | 123 | case STABLE_DIFFUSION: |
| @@ -124,14 +131,14 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -124,14 +131,14 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 124 | public ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url) { | 131 | public ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url) { |
| 125 | //noinspection EnhancedSwitchMigration | 132 | //noinspection EnhancedSwitchMigration |
| 126 | switch (platform) { | 133 | switch (platform) { |
| 134 | + case TONG_YI: | ||
| 135 | + return buildTongYiImagesModel(apiKey); | ||
| 136 | + case YI_YAN: | ||
| 137 | + return buildQianFanImageModel(apiKey); | ||
| 127 | case OPENAI: | 138 | case OPENAI: |
| 128 | return buildOpenAiImageModel(apiKey, url); | 139 | return buildOpenAiImageModel(apiKey, url); |
| 129 | case STABLE_DIFFUSION: | 140 | case STABLE_DIFFUSION: |
| 130 | return buildStabilityAiImageModel(apiKey, url); | 141 | return buildStabilityAiImageModel(apiKey, url); |
| 131 | - case TONG_YI: | ||
| 132 | - return SpringUtil.getBean(TongYiImagesModel.class); | ||
| 133 | - case YI_YAN: | ||
| 134 | - return buildQianFanImageModel(apiKey); | ||
| 135 | default: | 142 | default: |
| 136 | throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); | 143 | throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); |
| 137 | } | 144 | } |
| @@ -175,6 +182,14 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -175,6 +182,14 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 175 | return new TongYiAutoConfiguration().tongYiChatClient(generation, chatOptions, connectionProperties); | 182 | return new TongYiAutoConfiguration().tongYiChatClient(generation, chatOptions, connectionProperties); |
| 176 | } | 183 | } |
| 177 | 184 | ||
| 185 | + private static TongYiImagesModel buildTongYiImagesModel(String key) { | ||
| 186 | + ImageSynthesis imageSynthesis = SpringUtil.getBean(ImageSynthesis.class); | ||
| 187 | + TongYiImagesProperties imagesOptions = SpringUtil.getBean(TongYiImagesProperties.class); | ||
| 188 | + TongYiConnectionProperties connectionProperties = new TongYiConnectionProperties(); | ||
| 189 | + connectionProperties.setApiKey(key); | ||
| 190 | + return new TongYiAutoConfiguration().tongYiImagesClient(imageSynthesis, imagesOptions, connectionProperties); | ||
| 191 | + } | ||
| 192 | + | ||
| 178 | /** | 193 | /** |
| 179 | * 可参考 {@link QianFanAutoConfiguration#qianFanChatModel(QianFanConnectionProperties, QianFanChatProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)} | 194 | * 可参考 {@link QianFanAutoConfiguration#qianFanChatModel(QianFanConnectionProperties, QianFanChatProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)} |
| 180 | */ | 195 | */ |
| @@ -188,6 +203,18 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -188,6 +203,18 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 188 | } | 203 | } |
| 189 | 204 | ||
| 190 | /** | 205 | /** |
| 206 | + * 可参考 {@link QianFanAutoConfiguration#qianFanImageModel(QianFanConnectionProperties, QianFanImageProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)} | ||
| 207 | + */ | ||
| 208 | + private QianFanImageModel buildQianFanImageModel(String key) { | ||
| 209 | + List<String> keys = StrUtil.split(key, '|'); | ||
| 210 | + Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); | ||
| 211 | + String appKey = keys.get(0); | ||
| 212 | + String secretKey = keys.get(1); | ||
| 213 | + QianFanImageApi qianFanApi = new QianFanImageApi(appKey, secretKey); | ||
| 214 | + return new QianFanImageModel(qianFanApi); | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + /** | ||
| 191 | * 可参考 {@link YudaoAiAutoConfiguration#deepSeekChatModel(YudaoAiProperties)} | 218 | * 可参考 {@link YudaoAiAutoConfiguration#deepSeekChatModel(YudaoAiProperties)} |
| 192 | */ | 219 | */ |
| 193 | private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) { | 220 | private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) { |
| @@ -246,8 +273,4 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -246,8 +273,4 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 246 | return new StabilityAiImageModel(stabilityAiApi); | 273 | return new StabilityAiImageModel(stabilityAiApi); |
| 247 | } | 274 | } |
| 248 | 275 | ||
| 249 | - private QianFanImageModel buildQianFanImageModel(String key) { | ||
| 250 | - List<String> keys = StrUtil.split(key, '|'); | ||
| 251 | - return new QianFanImageModel(new QianFanImageApi(keys.get(0), keys.get(1))); | ||
| 252 | - } | ||
| 253 | } | 276 | } |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageModelTests.java
| @@ -21,7 +21,7 @@ public class OpenAiImageModelTests { | @@ -21,7 +21,7 @@ public class OpenAiImageModelTests { | ||
| 21 | "https://api.holdai.top", | 21 | "https://api.holdai.top", |
| 22 | "sk-dZEPiVaNcT3FHhef51996bAa0bC74806BeAb620dA5Da10Bf", | 22 | "sk-dZEPiVaNcT3FHhef51996bAa0bC74806BeAb620dA5Da10Bf", |
| 23 | RestClient.builder()); | 23 | RestClient.builder()); |
| 24 | - private final OpenAiImageModel imageClient = new OpenAiImageModel(imageApi); | 24 | + private final OpenAiImageModel imageModel = new OpenAiImageModel(imageApi); |
| 25 | 25 | ||
| 26 | @Test | 26 | @Test |
| 27 | @Disabled | 27 | @Disabled |
| @@ -34,7 +34,7 @@ public class OpenAiImageModelTests { | @@ -34,7 +34,7 @@ public class OpenAiImageModelTests { | ||
| 34 | ImagePrompt prompt = new ImagePrompt("中国长城!", options); | 34 | ImagePrompt prompt = new ImagePrompt("中国长城!", options); |
| 35 | 35 | ||
| 36 | // 方法调用 | 36 | // 方法调用 |
| 37 | - ImageResponse response = imageClient.call(prompt); | 37 | + ImageResponse response = imageModel.call(prompt); |
| 38 | // 打印结果 | 38 | // 打印结果 |
| 39 | System.out.println(response); | 39 | System.out.println(response); |
| 40 | } | 40 | } |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/QianFanImageTests.java
| 1 | package cn.iocoder.yudao.framework.ai.image; | 1 | package cn.iocoder.yudao.framework.ai.image; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 3 | +import org.junit.jupiter.api.Disabled; |
| 4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 5 | -import org.springframework.ai.image.ImageOptionsBuilder; | ||
| 6 | import org.springframework.ai.image.ImagePrompt; | 5 | import org.springframework.ai.image.ImagePrompt; |
| 7 | import org.springframework.ai.image.ImageResponse; | 6 | import org.springframework.ai.image.ImageResponse; |
| 8 | import org.springframework.ai.qianfan.QianFanImageModel; | 7 | import org.springframework.ai.qianfan.QianFanImageModel; |
| 9 | import org.springframework.ai.qianfan.QianFanImageOptions; | 8 | import org.springframework.ai.qianfan.QianFanImageOptions; |
| 10 | -import org.springframework.ai.qianfan.api.QianFanApi; | ||
| 11 | import org.springframework.ai.qianfan.api.QianFanImageApi; | 9 | import org.springframework.ai.qianfan.api.QianFanImageApi; |
| 12 | 10 | ||
| 11 | +import static cn.iocoder.yudao.framework.ai.image.StabilityAiImageModelTests.viewImage; | ||
| 12 | + | ||
| 13 | /** | 13 | /** |
| 14 | - * 百度千帆 image | 14 | + * {@link QianFanImageModel} 集成测试类 |
| 15 | */ | 15 | */ |
| 16 | public class QianFanImageTests { | 16 | public class QianFanImageTests { |
| 17 | 17 | ||
| 18 | - @Test | ||
| 19 | - public void callTest() { | ||
| 20 | - // todo @芋艿 千帆sdk有个错误,暂时没找到问题 | ||
| 21 | - QianFanImageApi qianFanImageApi = new QianFanImageApi( | ||
| 22 | - "ghbbvbW2t7HK7WtYmEITAupm", "njJEr5AsQ5fkB3ucYYDjiQqsOZK20SGb"); | ||
| 23 | - QianFanImageModel qianFanImageModel = new QianFanImageModel(qianFanImageApi); | 18 | + private final QianFanImageApi imageApi = new QianFanImageApi( |
| 19 | + "qS8k8dYr2nXunagK4SSU8Xjj", "pHGbx51ql2f0hOyabQvSZezahVC3hh3e"); | ||
| 20 | + private final QianFanImageModel imageModel = new QianFanImageModel(imageApi); | ||
| 24 | 21 | ||
| 22 | + @Test | ||
| 23 | + @Disabled | ||
| 24 | + public void testCall() { | ||
| 25 | + // 准备参数 | ||
| 26 | + // 只支持 1024x1024、768x768、768x1024、1024x768、576x1024、1024x576 | ||
| 25 | QianFanImageOptions imageOptions = QianFanImageOptions.builder() | 27 | QianFanImageOptions imageOptions = QianFanImageOptions.builder() |
| 26 | - .withWidth(512) | ||
| 27 | - .withHeight(512) | 28 | + .withModel(QianFanImageApi.ImageModel.Stable_Diffusion_XL.getValue()) |
| 29 | + .withWidth(1024).withHeight(1024) | ||
| 30 | + .withN(1) | ||
| 28 | .build(); | 31 | .build(); |
| 29 | - ImagePrompt imagePrompt = new ImagePrompt("薄涂炫酷少女头像,田野花朵盛开", imageOptions); | ||
| 30 | - ImageResponse call = qianFanImageModel.call(imagePrompt); | ||
| 31 | - System.err.println(JsonUtils.toJsonString(call)); | ||
| 32 | - } | ||
| 33 | - | ||
| 34 | - @Test | ||
| 35 | - public void call2Test() { | ||
| 36 | - // 官方测试 test https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-qianfan/src/test/java/org/springframework/ai/qianfan/image/QianFanImageModelIT.java | ||
| 37 | - var options = ImageOptionsBuilder.builder().withHeight(1024).withWidth(1024).build(); | ||
| 38 | - var instructions = "薄涂炫酷少女头像,田野花朵盛开"; | ||
| 39 | - | ||
| 40 | - ImagePrompt imagePrompt = new ImagePrompt(instructions, options); | ||
| 41 | - | ||
| 42 | - QianFanImageApi qianFanImageApi = new QianFanImageApi( | ||
| 43 | - "ghbbvbW2t7HK7WtYmEITAupm", "njJEr5AsQ5fkB3ucYYDjiQqsOZK20SGb"); | ||
| 44 | - QianFanImageModel imageModel = new QianFanImageModel(qianFanImageApi); | ||
| 45 | - ImageResponse imageResponse = imageModel.call(imagePrompt); | 32 | + ImagePrompt prompt = new ImagePrompt("good", imageOptions); |
| 33 | + | ||
| 34 | + // 方法调用 | ||
| 35 | + ImageResponse response = imageModel.call(prompt); | ||
| 36 | + // 打印结果 | ||
| 37 | + String b64Json = response.getResult().getOutput().getB64Json(); | ||
| 38 | + System.out.println(response); | ||
| 39 | + viewImage(b64Json); | ||
| 46 | } | 40 | } |
| 47 | 41 | ||
| 48 | } | 42 | } |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/StabilityAiImageModelTests.java
| @@ -24,7 +24,7 @@ public class StabilityAiImageModelTests { | @@ -24,7 +24,7 @@ public class StabilityAiImageModelTests { | ||
| 24 | 24 | ||
| 25 | private final StabilityAiApi imageApi = new StabilityAiApi( | 25 | private final StabilityAiApi imageApi = new StabilityAiApi( |
| 26 | "sk-e53UqbboF8QJCscYvzJscJxJXoFcFg4iJjl1oqgE7baJETmx"); | 26 | "sk-e53UqbboF8QJCscYvzJscJxJXoFcFg4iJjl1oqgE7baJETmx"); |
| 27 | - private final StabilityAiImageModel imageClient = new StabilityAiImageModel(imageApi); | 27 | + private final StabilityAiImageModel imageModel = new StabilityAiImageModel(imageApi); |
| 28 | 28 | ||
| 29 | @Test | 29 | @Test |
| 30 | @Disabled | 30 | @Disabled |
| @@ -37,7 +37,7 @@ public class StabilityAiImageModelTests { | @@ -37,7 +37,7 @@ public class StabilityAiImageModelTests { | ||
| 37 | ImagePrompt prompt = new ImagePrompt("great wall", options); | 37 | ImagePrompt prompt = new ImagePrompt("great wall", options); |
| 38 | 38 | ||
| 39 | // 方法调用 | 39 | // 方法调用 |
| 40 | - ImageResponse response = imageClient.call(prompt); | 40 | + ImageResponse response = imageModel.call(prompt); |
| 41 | // 打印结果 | 41 | // 打印结果 |
| 42 | String b64Json = response.getResult().getOutput().getB64Json(); | 42 | String b64Json = response.getResult().getOutput().getB64Json(); |
| 43 | System.out.println(response); | 43 | System.out.println(response); |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/TongYiImagesModelTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.image; | ||
| 2 | + | ||
| 3 | +import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel; | ||
| 4 | +import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis; | ||
| 5 | +import com.alibaba.dashscope.utils.Constants; | ||
| 6 | +import org.junit.jupiter.api.Disabled; | ||
| 7 | +import org.junit.jupiter.api.Test; | ||
| 8 | +import org.springframework.ai.image.ImageOptions; | ||
| 9 | +import org.springframework.ai.image.ImagePrompt; | ||
| 10 | +import org.springframework.ai.image.ImageResponse; | ||
| 11 | +import org.springframework.ai.openai.OpenAiImageOptions; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * {@link com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel} 集成测试类 | ||
| 15 | + * | ||
| 16 | + * @author fansili | ||
| 17 | + */ | ||
| 18 | +public class TongYiImagesModelTest { | ||
| 19 | + | ||
| 20 | + private final ImageSynthesis imageApi = new ImageSynthesis(); | ||
| 21 | + private final TongYiImagesModel imageModel = new TongYiImagesModel(imageApi); | ||
| 22 | + | ||
| 23 | + static { | ||
| 24 | + Constants.apiKey = "sk-Zsd81gZYg7"; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Test | ||
| 28 | + @Disabled | ||
| 29 | + public void imageCallTest() { | ||
| 30 | + // 准备参数 | ||
| 31 | + ImageOptions options = OpenAiImageOptions.builder() | ||
| 32 | + .withModel(ImageSynthesis.Models.WANX_V1) | ||
| 33 | + .withHeight(256).withWidth(256) | ||
| 34 | + .build(); | ||
| 35 | + ImagePrompt prompt = new ImagePrompt("中国长城!", options); | ||
| 36 | + | ||
| 37 | + // 方法调用 | ||
| 38 | + ImageResponse response = imageModel.call(prompt); | ||
| 39 | + // 打印结果 | ||
| 40 | + System.out.println(response); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/TongYiImagesModelTests.java deleted
| 1 | -package cn.iocoder.yudao.framework.ai.image; | ||
| 2 | - | ||
| 3 | -import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis; | ||
| 4 | -import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisParam; | ||
| 5 | -import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisResult; | ||
| 6 | -import com.alibaba.dashscope.exception.NoApiKeyException; | ||
| 7 | -import com.alibaba.dashscope.utils.Constants; | ||
| 8 | -import com.alibaba.fastjson.JSON; | ||
| 9 | -import org.junit.jupiter.api.Test; | ||
| 10 | - | ||
| 11 | -import java.util.Map; | ||
| 12 | - | ||
| 13 | -// TODO @fan:改成 TongYiImagesModel 哈 | ||
| 14 | -/** | ||
| 15 | - * 通义万象 | ||
| 16 | - */ | ||
| 17 | -public class TongYiImagesModelTests { | ||
| 18 | - | ||
| 19 | - @Test | ||
| 20 | - public void imageCallTest() throws NoApiKeyException { | ||
| 21 | - // 设置 api key | ||
| 22 | - Constants.apiKey = "sk-Zsd81gZYg7"; | ||
| 23 | - ImageSynthesisParam param = | ||
| 24 | - ImageSynthesisParam.builder() | ||
| 25 | - .model(ImageSynthesis.Models.WANX_V1) | ||
| 26 | - .n(4) | ||
| 27 | - .size("1024*1024") | ||
| 28 | - .prompt("雄鹰自由自在的在蓝天白云下飞翔") | ||
| 29 | - .build(); | ||
| 30 | - // 创建 ImageSynthesis | ||
| 31 | - ImageSynthesis is = new ImageSynthesis(); | ||
| 32 | - // 调用 call 生成 image | ||
| 33 | - ImageSynthesisResult call = is.call(param); | ||
| 34 | - System.err.println(JSON.toJSON(call)); | ||
| 35 | - for (Map<String, String> result : call.getOutput().getResults()) { | ||
| 36 | - System.err.println("地址: " + result.get("url")); | ||
| 37 | - } | ||
| 38 | - } | ||
| 39 | -} |