From f4a0058e88ab97b6c4af52a155ff1975dd7129b5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 May 2024 10:36:25 +0800 Subject: [PATCH] 【代码评审】AI:qwen 的接入调整 --- yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java | 2 +- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java | 8 ++++---- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java | 6 ++---- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java | 9 +++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java | 8 ++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java | 16 ++++++++++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java | 11 +++++++++++ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java | 157 ------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java | 47 ----------------------------------------------- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java | 122 -------------------------------------------------------------------------------------------------------------------------- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java | 60 ------------------------------------------------------------ yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java | 9 --------- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java | 8 -------- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java | 16 ---------------- yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java | 11 ----------- yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java | 8 ++++---- 20 files changed, 441 insertions(+), 443 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java index 14dc2b8..e7a64c2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.models.tongyi.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import org.springframework.ai.ollama.OllamaChatClient; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 13f8f71..f942b12 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.ai.config; import cn.hutool.core.io.IoUtil; -import org.springframework.ai.models.tongyi.QianWenChatClient; -import org.springframework.ai.models.tongyi.QianWenChatModal; -import org.springframework.ai.models.tongyi.QianWenOptions; -import org.springframework.ai.models.tongyi.api.QianWenApi; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index a85fffe..fc41069 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -5,10 +5,9 @@ import lombok.Getter; // TODO 芋艿:这块,看看要不要调整下; /** - * ai 模型平台 + * AI 模型平台 * - * author: fansili - * time: 2024/3/11 10:12 + * @author fansili */ @Getter @AllArgsConstructor @@ -18,7 +17,6 @@ public enum AiPlatformEnum { OLLAMA("Ollama", "Ollama"), YI_YAN("YiYan", "文心一言"), // 百度 XING_HUO("XingHuo", "星火"), // 讯飞 - QIAN_WEN("qianwen", "千问"), // 阿里 OPEN_AI_DALL("dall", "dall"), diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java new file mode 100644 index 0000000..85fa771 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java @@ -0,0 +1,157 @@ +package cn.iocoder.yudao.framework.ai.core.model.tongyi; + +import cn.iocoder.yudao.framework.ai.core.exception.ChatException; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; +import org.springframework.ai.chat.*; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; +import com.alibaba.dashscope.aigc.generation.GenerationResult; +import com.alibaba.dashscope.aigc.generation.models.QwenParam; +import com.alibaba.dashscope.common.Message; +import com.google.common.collect.Lists; +import io.reactivex.Flowable; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.http.ResponseEntity; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryListener; +import org.springframework.retry.support.RetryTemplate; +import reactor.core.publisher.Flux; + +import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; + +// TODO @芋艿:暂时不需要重构;等 spring cloud alibaba 的 ai 发布最新的 +/** + * 阿里 通义千问 client + *

+ * 文档地址:https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp + *

+ * author: fansili + * time: 2024/3/13 21:06 + */ +@Slf4j +public class QianWenChatClient implements ChatClient, StreamingChatClient { + + private QianWenApi qianWenApi; + + private QianWenOptions qianWenOptions; + + public QianWenChatClient() { + } + + public QianWenChatClient(QianWenApi qianWenApi) { + this.qianWenApi = qianWenApi; + } + + public QianWenChatClient(QianWenApi qianWenApi, QianWenOptions qianWenOptions) { + this.qianWenApi = qianWenApi; + this.qianWenOptions = qianWenOptions; + } + + // TODO @fansili:看看咋公用出来,允许传入类似异常之类的参数; + public final RetryTemplate retryTemplate = RetryTemplate.builder() + // 最大重试次数 10 + .maxAttempts(10) + .retryOn(YiYanApiException.class) + // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms + .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) + .withListener(new RetryListener() { + @Override + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { + log.warn("重试异常:" + context.getRetryCount(), throwable); + } + }) + .build(); + + @Override + public ChatResponse call(Prompt prompt) { + return this.retryTemplate.execute(ctx -> { + // ctx 会有重试的信息 + // 创建 request 请求,stream模式需要供应商支持 + QwenParam request = this.createRequest(prompt, false); + // 调用 callWithFunctionSupport 发送请求 + ResponseEntity responseEntity = qianWenApi.chatCompletionEntity(request); + // 获取结果封装 chatCompletion + GenerationResult response = responseEntity.getBody(); +// if (!response.isSuccess()) { +// return new ChatResponse(List.of(new Generation(String.format("failed to create completion, requestId: %s, code: %s, message: %s\n", +// response.getRequestId(), response.getCode(), response.getMessage())))); +// } + // 转换为 Generation 返回 + return new ChatResponse(response.getOutput().getChoices().stream() + .map(choices -> new Generation(choices.getMessage().getContent())) + .collect(Collectors.toList())); + }); + } + + private QwenParam createRequest(Prompt prompt, boolean stream) { + // 获取 ChatOptions + QianWenOptions chatOptions = getChatOptions(prompt); + // + List messageList = Lists.newArrayList(); + prompt.getInstructions().stream().forEach(instruction -> { + Message message = new Message(); + message.setRole(instruction.getMessageType().getValue()); + message.setContent(instruction.getContent()); + messageList.add(message); + }); + return QwenParam.builder() + .model(qianWenApi.getQianWenChatModal().getModel()) + .prompt(prompt.getContents()) + .messages(messageList) + .maxTokens(chatOptions.getMaxTokens()) + .resultFormat(QwenParam.ResultFormat.MESSAGE) + .topP(Double.valueOf(chatOptions.getTopP())) + .topK(chatOptions.getTopK()) + .temperature(chatOptions.getTemperature()) + // 控制流式输出模式,即后面的内容会包含已经输出的内容;设置为True,将开启增量输出模式,后面的输出不会包含已经输出的内容,您需要自行拼接整体输出 + .incrementalOutput(true) + /* set the random seed, optional, default to 1234 if not set */ + .seed(100) + .apiKey(qianWenApi.getApiKey()) + .build(); + } + + private @NotNull QianWenOptions getChatOptions(Prompt prompt) { + // 两个都为null 则没有配置文件 + if (qianWenOptions == null && prompt.getOptions() == null) { + throw new ChatException("ChatOptions 未配置参数!"); + } + // 优先使用 Prompt 里面的 ChatOptions + ChatOptions options = qianWenOptions; + if (prompt.getOptions() != null) { + options = (ChatOptions) prompt.getOptions(); + } + // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 + if (!(options instanceof QianWenOptions)) { + throw new ChatException("Prompt 传入的不是 QianWenOptions!"); + } + return (QianWenOptions) options; + } + + @Override + public Flux stream(Prompt prompt) { + // ctx 会有重试的信息 + // 创建 request 请求,stream模式需要供应商支持 + QwenParam request = this.createRequest(prompt, true); + // 调用 callWithFunctionSupport 发送请求 + Flowable responseResult = this.qianWenApi.chatCompletionStream(request); + + return Flux.create(fluxSink -> + responseResult.subscribe( + value -> fluxSink.next( + new ChatResponse(value.getOutput().getChoices().stream() + .map(choices -> new Generation(choices.getMessage().getContent())) + .collect(Collectors.toList())) + ), + error -> fluxSink.error(error), + () -> fluxSink.complete() + ) + ); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java new file mode 100644 index 0000000..e1cbcd5 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.framework.ai.core.model.tongyi; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 千问 chat 模型 + * + * 模型地址:https://help.aliyun.com/document_detail/2712576.html + * 模型介绍:https://help.aliyun.com/document_detail/2666503.html?spm=a2c4g.2701795.0.0.26eb34dfKzcWN4 + * + * @author fansili + * @time 2024/4/26 10:15 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum QianWenChatModal { + + // 千问付费模型 + QWEN_TURBO("通义千问超大规模语言模型", "qwen-turbo"), + QWEN_PLUS("通义千问超大规模语言模型增强版", "qwen-plus"), + QWEN_MAX("通义千问千亿级别超大规模语言模型", "qwen-max"), + QWEN_MAX_0403("通义千问千亿级别超大规模语言模型-0403", "qwen-max-0403"), + QWEN_MAX_0107("通义千问千亿级别超大规模语言模型-0107", "qwen-max-0107"), + QWEN_MAX_1201("通义千问千亿级别超大规模语言模型-1201", "qwen-max-1201"), + QWEN_MAX_LONGCONTEXT("通义千问千亿级别超大规模语言模型-28k tokens", "qwen-max-longcontext"), + + // 开源模型 + // https://help.aliyun.com/document_detail/2666503.html?spm=a2c4g.2701795.0.0.26eb34dfKzcWN4 + QWEN_72B_CHAT("通义千问1.5对外开源的72B规模参数量的经过人类指令对齐的chat模型", "qwen-72b-chat"), + + ; + + private String name; + + private String model; + + public static QianWenChatModal valueOfModel(String model) { + for (QianWenChatModal itemEnum : QianWenChatModal.values()) { + if (itemEnum.getModel().equals(model)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + model); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java new file mode 100644 index 0000000..b6dba53 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.framework.ai.core.model.tongyi; + +import org.springframework.ai.chat.prompt.ChatOptions; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 阿里云 千问 属性 + * + * 地址:https://help.aliyun.com/document_detail/2684682.html?spm=a2c4g.2621347.0.0.195117e7Ytpkyo + * + * author: fansili + * time: 2024/3/15 19:57 + */ +@Data +@Accessors(chain = true) +public class QianWenOptions implements ChatOptions { + + /** + * 用户与模型的对话历史 + */ + private List messages; + /** + * 生成时,核采样方法的概率阈值。例如,取值为0.8时,仅保留累计概率之和大于等于0.8的概率分布中的token, + * 作为随机采样的候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的随机性越低。 + * 默认值为0.8。注意,取值不要大于等于1 + */ + private Float topP; + /** + * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量。其中qwen1.5-14b-chat、qwen1.5-7b-chat、qwen-14b-chat和qwen-7b-chat最大值和默认值均为1500,qwen-1.8b-chat、qwen-1.8b-longcontext-chat和qwen-72b-chat最大值和默认值均为2000 + */ + private Integer maxTokens = 1500; + + // + // 适配 ChatOptions + + @Override + public Float getTemperature() { + return null; + } + +// @Override +// public void setTemperature(Float temperature) { +// +// } +// +// @Override +// public void setTopP(Float topP) { +// this.topP = topP; +// } + + @Override + public Integer getTopK() { + return null; + } + +// @Override +// public void setTopK(Integer topK) { +// +// } + + @Data + @Accessors + public static class Message { + /** + * 角色: system、user或assistant + */ + private String role; + /** + * 提示词或模型内容 + */ + private String content; + } + + @Data + @Accessors + public static class Parameters { + /** + * 输出格式, 默认为"text" + * "text"表示旧版本的text + * "message"表示兼容openai的message + */ + private String resultFormat; + /** + * 生成时,采样候选集的大小。例如,取值为50时,仅将单次生成中得分最高的50个token组成随机采样的候选集。 + * 取值越大,生成的随机性越高;取值越小,生成的确定性越高。 + * 注意:如果top_k参数为空或者top_k的值大于100,表示不启用top_k策略,此时仅有top_p策略生效,默认是空。 + */ + private Integer topK; + /** + * 生成时使用的随机数种子,用户控制模型生成内容的随机性。 + * seed支持无符号64位整数,默认值为1234。在使用seed时,模型将尽可能生成相同或相似的结果,但目前不保证每次生成的结果完全相同。 + */ + private Integer seed; + /** + * 用于控制随机性和多样性的程度。具体来说,temperature值控制了生成文本时对每个候选词的概率分布进行平滑的程度。 + * 较高的temperature值会降低概率分布的峰值,使得更多的低概率词被选择, + * 生成结果更加多样化;而较低的temperature值则会增强概率分布的峰值,使得高概率词更容易被选择,生成结果更加确定。 + * 取值范围: [0, 2),系统默认值1.0。不建议取值为0,无意义。 + */ + private Float temperature; + /** + * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量。 + * 其中qwen-turbo 最大值和默认值为1500, qwen-max、qwen-max-1201 、qwen-max-longcontext 和 qwen-plus最大值和默认值均为2000。 + */ + private Integer maxTokens; + /** + * stop参数用于实现内容生成过程的精确控制,在生成内容即将包含指定的字符串或token_ids时自动停止,生成内容不包含指定的内容。 + * 例如,如果指定stop为"你好",表示将要生成"你好"时停止;如果指定stop为[37763, 367],表示将要生成"Observation"时停止。 + */ + private List stop; + /** + * 用于控制流式输出模式,默认False,即后面内容会包含已经输出的内容;设置为True,将开启增量输出模式, + * 后面输出不会包含已经输出的内容,您需要自行拼接整体输出,参考流式输出示例代码。 + */ + private Boolean incrementalOutput; + } +} + + diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java new file mode 100644 index 0000000..6d3e7cd --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; + +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.exception.AiException; +import com.alibaba.dashscope.aigc.generation.Generation; +import com.alibaba.dashscope.aigc.generation.GenerationResult; +import com.alibaba.dashscope.aigc.generation.models.QwenParam; +import com.alibaba.dashscope.exception.InputRequiredException; +import com.alibaba.dashscope.exception.NoApiKeyException; +import io.reactivex.Flowable; +import lombok.Getter; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; + +// TODO done @fansili:是不是挪到 api 包里?按照 spring ai 的结构;根目录只放 client 和 options + +/** + * 阿里 通义千问 + *

+ * author: fansili + * time: 2024/3/13 21:09 + */ +@Getter +public class QianWenApi { + + // api key 获取地址:https://bailian.console.aliyun.com/?spm=5176.28197581.0.0.38db29a4G3GcVb&apiKey=1#/api-key + private String apiKey = "sk-Zsd81gZYg7"; + private Generation gen = new Generation(); + private QianWenChatModal qianWenChatModal; + + public QianWenApi(String apiKey, QianWenChatModal qianWenChatModal) { + this.apiKey = apiKey; + this.qianWenChatModal = qianWenChatModal; + } + + public ResponseEntity chatCompletionEntity(QwenParam request) { + GenerationResult call; + try { + call = gen.call(request); + } catch (NoApiKeyException e) { + throw new AiException("没有找到apiKey!" + e.getMessage()); + } catch (InputRequiredException e) { + throw new AiException("chat缺少必填字段!" + e.getMessage()); + } + // 阿里云的这个 http code 随便设置,外面判断是否成功用的 CompletionsResponse.isSuccess + return new ResponseEntity<>(call, HttpStatusCode.valueOf(200)); + } + + public Flowable chatCompletionStream(QwenParam request) { + Flowable resultFlowable; + try { + resultFlowable = gen.streamCall(request); + } catch (NoApiKeyException e) { + throw new AiException("没有找到apiKey!" + e.getMessage()); + } catch (InputRequiredException e) { + throw new AiException("chat缺少必填字段!" + e.getMessage()); + } + return resultFlowable; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java new file mode 100644 index 0000000..1e7748d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; + + +/** + * author: fansili + * time: 2024/3/13 21:07 + */ +public class QianWenChatCompletion { +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java new file mode 100644 index 0000000..318829b --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; + +/** + * author: fansili + * time: 2024/3/13 21:07 + */ +public class QianWenChatCompletionMessage { +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java new file mode 100644 index 0000000..b1d72d1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; + +import com.alibaba.dashscope.aigc.generation.models.QwenParam; + +/** + * 千问 + * + * author: fansili + * time: 2024/3/13 21:07 + */ +public class QianWenChatCompletionRequest extends QwenParam { + + protected QianWenChatCompletionRequest(QwenParamBuilder b) { + super(b); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java new file mode 100644 index 0000000..11ed0c1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java @@ -0,0 +1,11 @@ +/** + * 阿里的 通义千问 + * + * 链接:https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all + * + * 千问所有模型:https://bailian.console.aliyun.com/?spm=5176.28515448.J_TC9GqcHi2edq9zUs9ZsDQ.1.417338b17zJTjy#/efm/my_model + * + * author: fansili + * time: 2024/3/13 21:05 + */ +package cn.iocoder.yudao.framework.ai.core.model.tongyi; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java deleted file mode 100644 index 31e60d1..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java +++ /dev/null @@ -1,157 +0,0 @@ -package org.springframework.ai.models.tongyi; - -import cn.iocoder.yudao.framework.ai.core.exception.ChatException; -import org.springframework.ai.chat.*; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.tongyi.api.QianWenApi; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; -import com.alibaba.dashscope.aigc.generation.GenerationResult; -import com.alibaba.dashscope.aigc.generation.models.QwenParam; -import com.alibaba.dashscope.common.Message; -import com.google.common.collect.Lists; -import io.reactivex.Flowable; -import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; -import org.springframework.http.ResponseEntity; -import org.springframework.retry.RetryCallback; -import org.springframework.retry.RetryContext; -import org.springframework.retry.RetryListener; -import org.springframework.retry.support.RetryTemplate; -import reactor.core.publisher.Flux; - -import java.time.Duration; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 阿里 通义千问 client - *

- * 文档地址:https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp - *

- * author: fansili - * time: 2024/3/13 21:06 - */ -@Slf4j -public class QianWenChatClient implements ChatClient, StreamingChatClient { - - private QianWenApi qianWenApi; - - private QianWenOptions qianWenOptions; - - - public QianWenChatClient() { - } - - public QianWenChatClient(QianWenApi qianWenApi) { - this.qianWenApi = qianWenApi; - } - - public QianWenChatClient(QianWenApi qianWenApi, QianWenOptions qianWenOptions) { - this.qianWenApi = qianWenApi; - this.qianWenOptions = qianWenOptions; - } - - // TODO @fansili:看看咋公用出来,允许传入类似异常之类的参数; - public final RetryTemplate retryTemplate = RetryTemplate.builder() - // 最大重试次数 10 - .maxAttempts(10) - .retryOn(YiYanApiException.class) - // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms - .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) - .withListener(new RetryListener() { - @Override - public void onError(RetryContext context, - RetryCallback callback, Throwable throwable) { - log.warn("重试异常:" + context.getRetryCount(), throwable); - } - }) - .build(); - - @Override - public ChatResponse call(Prompt prompt) { - return this.retryTemplate.execute(ctx -> { - // ctx 会有重试的信息 - // 创建 request 请求,stream模式需要供应商支持 - QwenParam request = this.createRequest(prompt, false); - // 调用 callWithFunctionSupport 发送请求 - ResponseEntity responseEntity = qianWenApi.chatCompletionEntity(request); - // 获取结果封装 chatCompletion - GenerationResult response = responseEntity.getBody(); -// if (!response.isSuccess()) { -// return new ChatResponse(List.of(new Generation(String.format("failed to create completion, requestId: %s, code: %s, message: %s\n", -// response.getRequestId(), response.getCode(), response.getMessage())))); -// } - // 转换为 Generation 返回 - return new ChatResponse(response.getOutput().getChoices().stream() - .map(choices -> new Generation(choices.getMessage().getContent())) - .collect(Collectors.toList())); - }); - } - - private QwenParam createRequest(Prompt prompt, boolean stream) { - // 获取 ChatOptions - QianWenOptions chatOptions = getChatOptions(prompt); - // - List messageList = Lists.newArrayList(); - prompt.getInstructions().stream().forEach(instruction -> { - Message message = new Message(); - message.setRole(instruction.getMessageType().getValue()); - message.setContent(instruction.getContent()); - messageList.add(message); - }); - return QwenParam.builder() - .model(qianWenApi.getQianWenChatModal().getModel()) - .prompt(prompt.getContents()) - .messages(messageList) - .maxTokens(chatOptions.getMaxTokens()) - .resultFormat(QwenParam.ResultFormat.MESSAGE) - .topP(Double.valueOf(chatOptions.getTopP())) - .topK(chatOptions.getTopK()) - .temperature(chatOptions.getTemperature()) - // 控制流式输出模式,即后面的内容会包含已经输出的内容;设置为True,将开启增量输出模式,后面的输出不会包含已经输出的内容,您需要自行拼接整体输出 - .incrementalOutput(true) - /* set the random seed, optional, default to 1234 if not set */ - .seed(100) - .apiKey(qianWenApi.getApiKey()) - .build(); - } - - private @NotNull QianWenOptions getChatOptions(Prompt prompt) { - // 两个都为null 则没有配置文件 - if (qianWenOptions == null && prompt.getOptions() == null) { - throw new ChatException("ChatOptions 未配置参数!"); - } - // 优先使用 Prompt 里面的 ChatOptions - ChatOptions options = qianWenOptions; - if (prompt.getOptions() != null) { - options = (ChatOptions) prompt.getOptions(); - } - // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 - if (!(options instanceof QianWenOptions)) { - throw new ChatException("Prompt 传入的不是 QianWenOptions!"); - } - return (QianWenOptions) options; - } - - @Override - public Flux stream(Prompt prompt) { - // ctx 会有重试的信息 - // 创建 request 请求,stream模式需要供应商支持 - QwenParam request = this.createRequest(prompt, true); - // 调用 callWithFunctionSupport 发送请求 - Flowable responseResult = this.qianWenApi.chatCompletionStream(request); - - return Flux.create(fluxSink -> - responseResult.subscribe( - value -> fluxSink.next( - new ChatResponse(value.getOutput().getChoices().stream() - .map(choices -> new Generation(choices.getMessage().getContent())) - .collect(Collectors.toList())) - ), - error -> fluxSink.error(error), - () -> fluxSink.complete() - ) - ); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java deleted file mode 100644 index 9474a8d..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.springframework.ai.models.tongyi; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 千问 chat 模型 - * - * 模型地址:https://help.aliyun.com/document_detail/2712576.html - * 模型介绍:https://help.aliyun.com/document_detail/2666503.html?spm=a2c4g.2701795.0.0.26eb34dfKzcWN4 - * - * @author fansili - * @time 2024/4/26 10:15 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum QianWenChatModal { - - // 千问付费模型 - QWEN_TURBO("通义千问超大规模语言模型", "qwen-turbo"), - QWEN_PLUS("通义千问超大规模语言模型增强版", "qwen-plus"), - QWEN_MAX("通义千问千亿级别超大规模语言模型", "qwen-max"), - QWEN_MAX_0403("通义千问千亿级别超大规模语言模型-0403", "qwen-max-0403"), - QWEN_MAX_0107("通义千问千亿级别超大规模语言模型-0107", "qwen-max-0107"), - QWEN_MAX_1201("通义千问千亿级别超大规模语言模型-1201", "qwen-max-1201"), - QWEN_MAX_LONGCONTEXT("通义千问千亿级别超大规模语言模型-28k tokens", "qwen-max-longcontext"), - - // 开源模型 - // https://help.aliyun.com/document_detail/2666503.html?spm=a2c4g.2701795.0.0.26eb34dfKzcWN4 - QWEN_72B_CHAT("通义千问1.5对外开源的72B规模参数量的经过人类指令对齐的chat模型", "qwen-72b-chat"), - - ; - - private String name; - - private String model; - - public static QianWenChatModal valueOfModel(String model) { - for (QianWenChatModal itemEnum : QianWenChatModal.values()) { - if (itemEnum.getModel().equals(model)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + model); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java deleted file mode 100644 index 39db366..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.springframework.ai.models.tongyi; - -import org.springframework.ai.chat.prompt.ChatOptions; -import lombok.Data; -import lombok.experimental.Accessors; - -import java.util.List; - -/** - * 阿里云 千问 属性 - * - * 地址:https://help.aliyun.com/document_detail/2684682.html?spm=a2c4g.2621347.0.0.195117e7Ytpkyo - * - * author: fansili - * time: 2024/3/15 19:57 - */ -@Data -@Accessors(chain = true) -public class QianWenOptions implements ChatOptions { - - /** - * 用户与模型的对话历史 - */ - private List messages; - /** - * 生成时,核采样方法的概率阈值。例如,取值为0.8时,仅保留累计概率之和大于等于0.8的概率分布中的token, - * 作为随机采样的候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的随机性越低。 - * 默认值为0.8。注意,取值不要大于等于1 - */ - private Float topP; - /** - * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量。其中qwen1.5-14b-chat、qwen1.5-7b-chat、qwen-14b-chat和qwen-7b-chat最大值和默认值均为1500,qwen-1.8b-chat、qwen-1.8b-longcontext-chat和qwen-72b-chat最大值和默认值均为2000 - */ - private Integer maxTokens = 1500; - - // - // 适配 ChatOptions - - @Override - public Float getTemperature() { - return null; - } - -// @Override -// public void setTemperature(Float temperature) { -// -// } -// -// @Override -// public void setTopP(Float topP) { -// this.topP = topP; -// } - - @Override - public Integer getTopK() { - return null; - } - -// @Override -// public void setTopK(Integer topK) { -// -// } - - @Data - @Accessors - public static class Message { - /** - * 角色: system、user或assistant - */ - private String role; - /** - * 提示词或模型内容 - */ - private String content; - } - - @Data - @Accessors - public static class Parameters { - /** - * 输出格式, 默认为"text" - * "text"表示旧版本的text - * "message"表示兼容openai的message - */ - private String resultFormat; - /** - * 生成时,采样候选集的大小。例如,取值为50时,仅将单次生成中得分最高的50个token组成随机采样的候选集。 - * 取值越大,生成的随机性越高;取值越小,生成的确定性越高。 - * 注意:如果top_k参数为空或者top_k的值大于100,表示不启用top_k策略,此时仅有top_p策略生效,默认是空。 - */ - private Integer topK; - /** - * 生成时使用的随机数种子,用户控制模型生成内容的随机性。 - * seed支持无符号64位整数,默认值为1234。在使用seed时,模型将尽可能生成相同或相似的结果,但目前不保证每次生成的结果完全相同。 - */ - private Integer seed; - /** - * 用于控制随机性和多样性的程度。具体来说,temperature值控制了生成文本时对每个候选词的概率分布进行平滑的程度。 - * 较高的temperature值会降低概率分布的峰值,使得更多的低概率词被选择, - * 生成结果更加多样化;而较低的temperature值则会增强概率分布的峰值,使得高概率词更容易被选择,生成结果更加确定。 - * 取值范围: [0, 2),系统默认值1.0。不建议取值为0,无意义。 - */ - private Float temperature; - /** - * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量。 - * 其中qwen-turbo 最大值和默认值为1500, qwen-max、qwen-max-1201 、qwen-max-longcontext 和 qwen-plus最大值和默认值均为2000。 - */ - private Integer maxTokens; - /** - * stop参数用于实现内容生成过程的精确控制,在生成内容即将包含指定的字符串或token_ids时自动停止,生成内容不包含指定的内容。 - * 例如,如果指定stop为"你好",表示将要生成"你好"时停止;如果指定stop为[37763, 367],表示将要生成"Observation"时停止。 - */ - private List stop; - /** - * 用于控制流式输出模式,默认False,即后面内容会包含已经输出的内容;设置为True,将开启增量输出模式, - * 后面输出不会包含已经输出的内容,您需要自行拼接整体输出,参考流式输出示例代码。 - */ - private Boolean incrementalOutput; - } -} - - diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java deleted file mode 100644 index 2e90511..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.springframework.ai.models.tongyi.api; - -import org.springframework.ai.models.tongyi.QianWenChatModal; -import cn.iocoder.yudao.framework.ai.core.exception.AiException; -import com.alibaba.dashscope.aigc.generation.Generation; -import com.alibaba.dashscope.aigc.generation.GenerationResult; -import com.alibaba.dashscope.aigc.generation.models.QwenParam; -import com.alibaba.dashscope.exception.InputRequiredException; -import com.alibaba.dashscope.exception.NoApiKeyException; -import io.reactivex.Flowable; -import lombok.Getter; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.ResponseEntity; - -// TODO done @fansili:是不是挪到 api 包里?按照 spring ai 的结构;根目录只放 client 和 options - -/** - * 阿里 通义千问 - *

- * author: fansili - * time: 2024/3/13 21:09 - */ -@Getter -public class QianWenApi { - - // api key 获取地址:https://bailian.console.aliyun.com/?spm=5176.28197581.0.0.38db29a4G3GcVb&apiKey=1#/api-key - private String apiKey = "sk-Zsd81gZYg7"; - private Generation gen = new Generation(); - private QianWenChatModal qianWenChatModal; - - public QianWenApi(String apiKey, QianWenChatModal qianWenChatModal) { - this.apiKey = apiKey; - this.qianWenChatModal = qianWenChatModal; - } - - public ResponseEntity chatCompletionEntity(QwenParam request) { - GenerationResult call; - try { - call = gen.call(request); - } catch (NoApiKeyException e) { - throw new AiException("没有找到apiKey!" + e.getMessage()); - } catch (InputRequiredException e) { - throw new AiException("chat缺少必填字段!" + e.getMessage()); - } - // 阿里云的这个 http code 随便设置,外面判断是否成功用的 CompletionsResponse.isSuccess - return new ResponseEntity<>(call, HttpStatusCode.valueOf(200)); - } - - public Flowable chatCompletionStream(QwenParam request) { - Flowable resultFlowable; - try { - resultFlowable = gen.streamCall(request); - } catch (NoApiKeyException e) { - throw new AiException("没有找到apiKey!" + e.getMessage()); - } catch (InputRequiredException e) { - throw new AiException("chat缺少必填字段!" + e.getMessage()); - } - return resultFlowable; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java deleted file mode 100644 index 1c3c610..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.springframework.ai.models.tongyi.api; - - -/** - * author: fansili - * time: 2024/3/13 21:07 - */ -public class QianWenChatCompletion { -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java deleted file mode 100644 index 4e5d023..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.springframework.ai.models.tongyi.api; - -/** - * author: fansili - * time: 2024/3/13 21:07 - */ -public class QianWenChatCompletionMessage { -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java deleted file mode 100644 index 04b6984..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.springframework.ai.models.tongyi.api; - -import com.alibaba.dashscope.aigc.generation.models.QwenParam; - -/** - * 千问 - * - * author: fansili - * time: 2024/3/13 21:07 - */ -public class QianWenChatCompletionRequest extends QwenParam { - - protected QianWenChatCompletionRequest(QwenParamBuilder b) { - super(b); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java deleted file mode 100644 index 8d7793b..0000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 阿里的 通义千问 - * - * 链接:https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all - * - * 千问所有模型:https://bailian.console.aliyun.com/?spm=5176.28515448.J_TC9GqcHi2edq9zUs9ZsDQ.1.417338b17zJTjy#/efm/my_model - * - * author: fansili - * time: 2024/3/13 21:05 - */ -package org.springframework.ai.models.tongyi; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 99e2b5f..a003d1b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -4,10 +4,10 @@ import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.tongyi.QianWenChatClient; -import org.springframework.ai.models.tongyi.QianWenChatModal; -import org.springframework.ai.models.tongyi.QianWenOptions; -import org.springframework.ai.models.tongyi.api.QianWenApi; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; import com.alibaba.dashscope.common.Message; -- libgit2 0.21.4