diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java
index dab4d5a..1518523 100644
--- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java
+++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java
@@ -1,7 +1,9 @@
package cn.iocoder.yudao.module.ai.util;
+import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
@@ -33,6 +35,28 @@ public class AiUtils {
public static final String TOOL_CONTEXT_LOGIN_USER = "LOGIN_USER";
public static final String TOOL_CONTEXT_TENANT_ID = "TENANT_ID";
+ /**
+ * 通义千问支持多模态的模型
+ *
+ * @see 模型广场
+ * @see 必须开启 withMultiModel 参数
+ */
+ public static final Set TONG_YI_MULTI_MODELS = SetUtils.asSet(
+ // qwen3.5 / 3.6 系列(统一多模态主干)
+ "qwen3.6-plus", "qwen3.6-flash",
+ "qwen3.5-plus", "qwen3.5-flash",
+ // qwen-vl 视觉理解
+ "qwen3-vl-plus", "qwen3-vl-flash",
+ "qwen-vl-max", "qwen-vl-plus",
+ "qwen2.5-vl-72b-instruct", "qwen2.5-vl-32b-instruct",
+ "qwen2.5-vl-7b-instruct", "qwen2.5-vl-3b-instruct",
+ // qvq 视觉推理
+ "qvq-max", "qvq-plus",
+ // qwen-omni 全模态
+ "qwen3.5-omni-plus", "qwen3.5-omni-flash",
+ "qwen3-omni-flash", "qwen-omni-turbo"
+ );
+
public static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens) {
return buildChatOptions(platform, model, temperature, maxTokens, null, null);
}
@@ -44,9 +68,10 @@ public class AiUtils {
// noinspection EnhancedSwitchMigration
switch (platform) {
case TONG_YI:
- return DashScopeChatOptions.builder().withModel(model).withTemperature(temperature).withMaxToken(maxTokens)
- .withEnableThinking(true) // TODO 芋艿:默认都开启 thinking 模式,后续可以让用户配置
- .withToolCallbacks(toolCallbacks).withToolContext(toolContext).build();
+ return DashScopeChatOptions.builder().model(model).temperature(temperature).maxToken(maxTokens)
+ .enableThinking(true) // TODO 芋艿:默认都开启 thinking 模式,后续可以让用户配置
+ .multiModel(TONG_YI_MULTI_MODELS.contains(model)) // 是否多模态模型
+ .toolCallbacks(toolCallbacks).toolContext(toolContext).build();
case YI_YAN:
return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
case DEEP_SEEK:
@@ -125,10 +150,13 @@ public class AiUtils {
|| response.getResult().getOutput() == null) {
return null;
}
- if (response.getResult().getOutput() instanceof DeepSeekAssistantMessage) {
- return ((DeepSeekAssistantMessage) (response.getResult().getOutput())).getReasoningContent();
+ AssistantMessage output = response.getResult().getOutput();
+ // DeepSeek 通过专属 AssistantMessage 暴露 reasoningContent
+ if (output instanceof DeepSeekAssistantMessage) {
+ return ((DeepSeekAssistantMessage) output).getReasoningContent();
}
- return null;
+ // 通义千问等通过 metadata 透传 reasoningContent
+ return MapUtil.getStr(output.getMetadata(), "reasoningContent");
}
}
\ No newline at end of file
diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java
index 23bd5d9..056709d 100644
--- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java
+++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java
@@ -34,15 +34,15 @@ public class TongYiChatModelTests {
private final DashScopeChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(DashScopeApi.builder()
- .apiKey("sk-47aa124781be4bfb95244cc62f63f7d0")
+ .apiKey("sk-cd9f39e99ea54840bd1888282325f55a") // https://bailian.console.aliyun.com/cn-beijing/?tab=model#/api-key 获取密钥
.build())
.defaultOptions(DashScopeChatOptions.builder()
-// .withModel("qwen1.5-72b-chat") // 模型
- .withModel("qwen3-235b-a22b-thinking-2507") // 模型
-// .withModel("deepseek-r1") // 模型(deepseek-r1)
-// .withModel("deepseek-v3") // 模型(deepseek-v3)
-// .withModel("deepseek-r1-distill-qwen-1.5b") // 模型(deepseek-r1-distill-qwen-1.5b)
-// .withEnableThinking(true)
+ .multiModel(true) // 注意:当使用 qwen3.6-plus 等多模态模型,需要设置为 true,可见 https://help.aliyun.com/zh/model-studio/error-code#error-url 链接
+ .model("qwen3.6-plus") // 模型
+// .model("deepseek-r1") // 模型(deepseek-r1)
+// .model("deepseek-v3") // 模型(deepseek-v3)
+// .model("deepseek-r1-distill-qwen-1.5b") // 模型(deepseek-r1-distill-qwen-1.5b)
+// .enableThinking(true)
.build())
.build();
@@ -85,9 +85,9 @@ public class TongYiChatModelTests {
List messages = new ArrayList<>();
messages.add(new UserMessage("详细分析下,如何设计一个电商系统?"));
DashScopeChatOptions options = DashScopeChatOptions.builder()
- .withModel("qwen3-235b-a22b-thinking-2507")
+ .model("qwen3.6-plus").multiModel(true)
// .withModel("qwen-max-2025-01-25")
- .withEnableThinking(true) // 必须设置,否则会报错
+ .enableThinking(true) // 必须设置,否则会报错
.build();
// 调用
@@ -112,8 +112,8 @@ public class TongYiChatModelTests {
Document document01 = new Document("abc");
Document document02 = new Document("sapring");
RerankOptions options = DashScopeRerankOptions.builder()
- .withTopN(1)
- .withModel("gte-rerank-v2")
+ .topN(1)
+ .model("gte-rerank-v2")
.build();
RerankRequest rerankRequest = new RerankRequest(
query,