Commit dfc3c6227c6180206305996b12bd3e12d416f3ea
1 parent
f8ca6341
fix:【ai 大模型】混元支持 thinking 返回
Showing
4 changed files
with
62 additions
and
18 deletions
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java
| @@ -14,6 +14,9 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo | @@ -14,6 +14,9 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo | ||
| 14 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; | 14 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; |
| 15 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; | 15 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; |
| 16 | import lombok.extern.slf4j.Slf4j; | 16 | import lombok.extern.slf4j.Slf4j; |
| 17 | +import org.springframework.ai.deepseek.DeepSeekChatModel; | ||
| 18 | +import org.springframework.ai.deepseek.DeepSeekChatOptions; | ||
| 19 | +import org.springframework.ai.deepseek.api.DeepSeekApi; | ||
| 17 | import org.springframework.ai.embedding.BatchingStrategy; | 20 | import org.springframework.ai.embedding.BatchingStrategy; |
| 18 | import org.springframework.ai.embedding.TokenCountBatchingStrategy; | 21 | import org.springframework.ai.embedding.TokenCountBatchingStrategy; |
| 19 | import org.springframework.ai.model.tool.ToolCallingManager; | 22 | import org.springframework.ai.model.tool.ToolCallingManager; |
| @@ -152,13 +155,14 @@ public class AiAutoConfiguration { | @@ -152,13 +155,14 @@ public class AiAutoConfiguration { | ||
| 152 | StrUtil.startWithIgnoreCase(properties.getModel(), "deepseek") ? HunYuanChatModel.DEEP_SEEK_BASE_URL | 155 | StrUtil.startWithIgnoreCase(properties.getModel(), "deepseek") ? HunYuanChatModel.DEEP_SEEK_BASE_URL |
| 153 | : HunYuanChatModel.BASE_URL); | 156 | : HunYuanChatModel.BASE_URL); |
| 154 | } | 157 | } |
| 155 | - // 创建 OpenAiChatModel、HunYuanChatModel 对象 | ||
| 156 | - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | ||
| 157 | - .openAiApi(OpenAiApi.builder() | 158 | + // 创建 DeepSeekChatModel、HunYuanChatModel 对象 |
| 159 | + DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder() | ||
| 160 | + .deepSeekApi(DeepSeekApi.builder() | ||
| 158 | .baseUrl(properties.getBaseUrl()) | 161 | .baseUrl(properties.getBaseUrl()) |
| 162 | + .completionsPath(HunYuanChatModel.COMPLETE_PATH) | ||
| 159 | .apiKey(properties.getApiKey()) | 163 | .apiKey(properties.getApiKey()) |
| 160 | .build()) | 164 | .build()) |
| 161 | - .defaultOptions(OpenAiChatOptions.builder() | 165 | + .defaultOptions(DeepSeekChatOptions.builder() |
| 162 | .model(properties.getModel()) | 166 | .model(properties.getModel()) |
| 163 | .temperature(properties.getTemperature()) | 167 | .temperature(properties.getTemperature()) |
| 164 | .maxTokens(properties.getMaxTokens()) | 168 | .maxTokens(properties.getMaxTokens()) |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/hunyuan/HunYuanChatModel.java
| @@ -6,7 +6,6 @@ import org.springframework.ai.chat.model.ChatModel; | @@ -6,7 +6,6 @@ import org.springframework.ai.chat.model.ChatModel; | ||
| 6 | import org.springframework.ai.chat.model.ChatResponse; | 6 | import org.springframework.ai.chat.model.ChatResponse; |
| 7 | import org.springframework.ai.chat.prompt.ChatOptions; | 7 | import org.springframework.ai.chat.prompt.ChatOptions; |
| 8 | import org.springframework.ai.chat.prompt.Prompt; | 8 | import org.springframework.ai.chat.prompt.Prompt; |
| 9 | -import org.springframework.ai.openai.OpenAiChatModel; | ||
| 10 | import reactor.core.publisher.Flux; | 9 | import reactor.core.publisher.Flux; |
| 11 | 10 | ||
| 12 | /** | 11 | /** |
| @@ -22,6 +21,7 @@ import reactor.core.publisher.Flux; | @@ -22,6 +21,7 @@ import reactor.core.publisher.Flux; | ||
| 22 | public class HunYuanChatModel implements ChatModel { | 21 | public class HunYuanChatModel implements ChatModel { |
| 23 | 22 | ||
| 24 | public static final String BASE_URL = "https://api.hunyuan.cloud.tencent.com"; | 23 | public static final String BASE_URL = "https://api.hunyuan.cloud.tencent.com"; |
| 24 | + public static final String COMPLETE_PATH = "/v1/chat/completions"; | ||
| 25 | 25 | ||
| 26 | public static final String MODEL_DEFAULT = "hunyuan-turbo"; | 26 | public static final String MODEL_DEFAULT = "hunyuan-turbo"; |
| 27 | 27 | ||
| @@ -32,7 +32,7 @@ public class HunYuanChatModel implements ChatModel { | @@ -32,7 +32,7 @@ public class HunYuanChatModel implements ChatModel { | ||
| 32 | /** | 32 | /** |
| 33 | * 兼容 OpenAI 接口,进行复用 | 33 | * 兼容 OpenAI 接口,进行复用 |
| 34 | */ | 34 | */ |
| 35 | - private final OpenAiChatModel openAiChatModel; | 35 | + private final ChatModel openAiChatModel; |
| 36 | 36 | ||
| 37 | @Override | 37 | @Override |
| 38 | public ChatResponse call(Prompt prompt) { | 38 | public ChatResponse call(Prompt prompt) { |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java
| @@ -52,6 +52,7 @@ public class AiUtils { | @@ -52,6 +52,7 @@ public class AiUtils { | ||
| 52 | case DOU_BAO: // 复用 DeepSeek 客户端 | 52 | case DOU_BAO: // 复用 DeepSeek 客户端 |
| 53 | return DeepSeekChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 53 | return DeepSeekChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 54 | .toolNames(toolNames).toolContext(toolContext).build(); | 54 | .toolNames(toolNames).toolContext(toolContext).build(); |
| 55 | + case HUN_YUAN: // 复用 DeepSeek 客户端 | ||
| 55 | case ZHI_PU: | 56 | case ZHI_PU: |
| 56 | return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 57 | return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 57 | .toolNames(toolNames).toolContext(toolContext).build(); | 58 | .toolNames(toolNames).toolContext(toolContext).build(); |
| @@ -63,7 +64,6 @@ public class AiUtils { | @@ -63,7 +64,6 @@ public class AiUtils { | ||
| 63 | .toolNames(toolNames).toolContext(toolContext).build(); | 64 | .toolNames(toolNames).toolContext(toolContext).build(); |
| 64 | case OPENAI: | 65 | case OPENAI: |
| 65 | case GEMINI: // 复用 OpenAI 客户端 | 66 | case GEMINI: // 复用 OpenAI 客户端 |
| 66 | - case HUN_YUAN: // 复用 OpenAI 客户端 | ||
| 67 | case XING_HUO: // 复用 OpenAI 客户端 | 67 | case XING_HUO: // 复用 OpenAI 客户端 |
| 68 | case SILICON_FLOW: // 复用 OpenAI 客户端 | 68 | case SILICON_FLOW: // 复用 OpenAI 客户端 |
| 69 | case BAI_CHUAN: // 复用 OpenAI 客户端 | 69 | case BAI_CHUAN: // 复用 OpenAI 客户端 |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/HunYuanChatModelTests.java
| @@ -8,9 +8,9 @@ import org.springframework.ai.chat.messages.SystemMessage; | @@ -8,9 +8,9 @@ import org.springframework.ai.chat.messages.SystemMessage; | ||
| 8 | import org.springframework.ai.chat.messages.UserMessage; | 8 | import org.springframework.ai.chat.messages.UserMessage; |
| 9 | import org.springframework.ai.chat.model.ChatResponse; | 9 | import org.springframework.ai.chat.model.ChatResponse; |
| 10 | import org.springframework.ai.chat.prompt.Prompt; | 10 | import org.springframework.ai.chat.prompt.Prompt; |
| 11 | -import org.springframework.ai.openai.OpenAiChatModel; | ||
| 12 | -import org.springframework.ai.openai.OpenAiChatOptions; | ||
| 13 | -import org.springframework.ai.openai.api.OpenAiApi; | 11 | +import org.springframework.ai.deepseek.DeepSeekChatModel; |
| 12 | +import org.springframework.ai.deepseek.DeepSeekChatOptions; | ||
| 13 | +import org.springframework.ai.deepseek.api.DeepSeekApi; | ||
| 14 | import reactor.core.publisher.Flux; | 14 | import reactor.core.publisher.Flux; |
| 15 | 15 | ||
| 16 | import java.util.ArrayList; | 16 | import java.util.ArrayList; |
| @@ -23,12 +23,13 @@ import java.util.List; | @@ -23,12 +23,13 @@ import java.util.List; | ||
| 23 | */ | 23 | */ |
| 24 | public class HunYuanChatModelTests { | 24 | public class HunYuanChatModelTests { |
| 25 | 25 | ||
| 26 | - private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | ||
| 27 | - .openAiApi(OpenAiApi.builder() | 26 | + private final DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder() |
| 27 | + .deepSeekApi(DeepSeekApi.builder() | ||
| 28 | .baseUrl(HunYuanChatModel.BASE_URL) | 28 | .baseUrl(HunYuanChatModel.BASE_URL) |
| 29 | - .apiKey("sk-bcd") // apiKey | 29 | + .completionsPath(HunYuanChatModel.COMPLETE_PATH) |
| 30 | + .apiKey("sk-abc") // apiKey | ||
| 30 | .build()) | 31 | .build()) |
| 31 | - .defaultOptions(OpenAiChatOptions.builder() | 32 | + .defaultOptions(DeepSeekChatOptions.builder() |
| 32 | .model(HunYuanChatModel.MODEL_DEFAULT) // 模型 | 33 | .model(HunYuanChatModel.MODEL_DEFAULT) // 模型 |
| 33 | .temperature(0.7) | 34 | .temperature(0.7) |
| 34 | .build()) | 35 | .build()) |
| @@ -64,12 +65,33 @@ public class HunYuanChatModelTests { | @@ -64,12 +65,33 @@ public class HunYuanChatModelTests { | ||
| 64 | flux.doOnNext(System.out::println).then().block(); | 65 | flux.doOnNext(System.out::println).then().block(); |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | - private final OpenAiChatModel deepSeekOpenAiChatModel = OpenAiChatModel.builder() | ||
| 68 | - .openAiApi(OpenAiApi.builder() | 68 | + @Test |
| 69 | + @Disabled | ||
| 70 | + public void testStream_thinking() { | ||
| 71 | + // 准备参数 | ||
| 72 | + List<Message> messages = new ArrayList<>(); | ||
| 73 | + messages.add(new UserMessage("详细分析下,如何设计一个电商系统?")); | ||
| 74 | + DeepSeekChatOptions options = DeepSeekChatOptions.builder() | ||
| 75 | + .model("hunyuan-a13b") | ||
| 76 | +// .model("hunyuan-turbos-latest") | ||
| 77 | + .build(); | ||
| 78 | + | ||
| 79 | + // 调用 | ||
| 80 | + Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages, options)); | ||
| 81 | + // 打印结果 | ||
| 82 | + flux.doOnNext(response -> { | ||
| 83 | +// System.out.println(response); | ||
| 84 | + System.out.println(response.getResult().getOutput()); | ||
| 85 | + }).then().block(); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + private final DeepSeekChatModel deepSeekOpenAiChatModel = DeepSeekChatModel.builder() | ||
| 89 | + .deepSeekApi(DeepSeekApi.builder() | ||
| 69 | .baseUrl(HunYuanChatModel.DEEP_SEEK_BASE_URL) | 90 | .baseUrl(HunYuanChatModel.DEEP_SEEK_BASE_URL) |
| 91 | + .completionsPath(HunYuanChatModel.COMPLETE_PATH) | ||
| 70 | .apiKey("sk-abc") // apiKey | 92 | .apiKey("sk-abc") // apiKey |
| 71 | .build()) | 93 | .build()) |
| 72 | - .defaultOptions(OpenAiChatOptions.builder() | 94 | + .defaultOptions(DeepSeekChatOptions.builder() |
| 73 | // .model(HunYuanChatModel.DEEP_SEEK_MODEL_DEFAULT) // 模型("deepseek-v3") | 95 | // .model(HunYuanChatModel.DEEP_SEEK_MODEL_DEFAULT) // 模型("deepseek-v3") |
| 74 | .model("deepseek-r1") // 模型("deepseek-r1") | 96 | .model("deepseek-r1") // 模型("deepseek-r1") |
| 75 | .temperature(0.7) | 97 | .temperature(0.7) |
| @@ -94,7 +116,7 @@ public class HunYuanChatModelTests { | @@ -94,7 +116,7 @@ public class HunYuanChatModelTests { | ||
| 94 | 116 | ||
| 95 | @Test | 117 | @Test |
| 96 | @Disabled | 118 | @Disabled |
| 97 | - public void testStream_deekseek() { | 119 | + public void testStream_deepseek() { |
| 98 | // 准备参数 | 120 | // 准备参数 |
| 99 | List<Message> messages = new ArrayList<>(); | 121 | List<Message> messages = new ArrayList<>(); |
| 100 | messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | 122 | messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); |
| @@ -106,5 +128,23 @@ public class HunYuanChatModelTests { | @@ -106,5 +128,23 @@ public class HunYuanChatModelTests { | ||
| 106 | flux.doOnNext(System.out::println).then().block(); | 128 | flux.doOnNext(System.out::println).then().block(); |
| 107 | } | 129 | } |
| 108 | 130 | ||
| 131 | + @Test | ||
| 132 | + @Disabled | ||
| 133 | + public void testStream_deepseek_thinking() { | ||
| 134 | + // 准备参数 | ||
| 135 | + List<Message> messages = new ArrayList<>(); | ||
| 136 | + messages.add(new UserMessage("详细分析下,如何设计一个电商系统?")); | ||
| 137 | + DeepSeekChatOptions options = DeepSeekChatOptions.builder() | ||
| 138 | + .model("deepseek-r1") | ||
| 139 | + .build(); | ||
| 140 | + | ||
| 141 | + // 调用 | ||
| 142 | + Flux<ChatResponse> flux = deepSeekChatModel.stream(new Prompt(messages, options)); | ||
| 143 | + // 打印结果 | ||
| 144 | + flux.doOnNext(response -> { | ||
| 145 | +// System.out.println(response); | ||
| 146 | + System.out.println(response.getResult().getOutput()); | ||
| 147 | + }).then().block(); | ||
| 148 | + } | ||
| 109 | 149 | ||
| 110 | } | 150 | } |