From 3bde0ab02b075ceb723f4c8a75d3db56a08c1635 Mon Sep 17 00:00:00 2001 From: Jason Yao Date: Sat, 6 Jun 2026 21:46:19 -0400 Subject: [PATCH] =?UTF-8?q?fix(management):=20=E6=B5=8B=E8=AF=95=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E8=BF=9E=E6=8E=A5=E6=97=B6=E8=B7=B3=E8=BF=87=20HTTP?= =?UTF-8?q?=20=E9=87=8D=E8=AF=95=20(#530)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 测试连接复用了默认重试模板(10 次 + 指数退避,并重试 ResourceAccessException),错误或不可达 endpoint 会让前端卡住数分钟。 测试路径改用不重试模板,运行时模型继续保留默认重试容错。 --- .../aimodelconfig/DynamicModelFactory.java | 19 ++++++++++++++++--- .../aimodelconfig/ModelConfigOpsService.java | 4 ++-- .../ModelConfigOpsServiceTest.java | 8 ++++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/DynamicModelFactory.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/DynamicModelFactory.java index d57a1458d..f00d5226c 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/DynamicModelFactory.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/DynamicModelFactory.java @@ -35,6 +35,7 @@ import org.springframework.ai.retry.RetryUtils; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.retry.support.RetryTemplate; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -48,11 +49,16 @@ @RequiredArgsConstructor public class DynamicModelFactory { + public static final RetryTemplate NO_RETRY_TEMPLATE = RetryTemplate.builder().maxAttempts(1).build(); + /** * 统一使用 OpenAiChatModel,通过 baseUrl 实现多厂商兼容 */ public ChatModel createChatModel(ModelConfigDTO config) { + return createChatModel(config, RetryUtils.DEFAULT_RETRY_TEMPLATE); + } + public ChatModel createChatModel(ModelConfigDTO config, RetryTemplate retryTemplate) { log.info("Creating NEW ChatModel instance. Provider: {}, Model: {}, BaseUrl: {}", config.getProvider(), config.getModelName(), config.getBaseUrl()); // 1. 验证参数 @@ -79,13 +85,21 @@ public ChatModel createChatModel(ModelConfigDTO config) { .streamUsage(true) .build(); // 4. 返回统一的 OpenAiChatModel - return OpenAiChatModel.builder().openAiApi(openAiApi).defaultOptions(openAiChatOptions).build(); + return OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(openAiChatOptions) + .retryTemplate(retryTemplate) + .build(); } /** * Embedding 同理 */ public EmbeddingModel createEmbeddingModel(ModelConfigDTO config) { + return createEmbeddingModel(config, RetryUtils.DEFAULT_RETRY_TEMPLATE); + } + + public EmbeddingModel createEmbeddingModel(ModelConfigDTO config, RetryTemplate retryTemplate) { log.info("Creating NEW EmbeddingModel instance. Provider: {}, Model: {}, BaseUrl: {}", config.getProvider(), config.getModelName(), config.getBaseUrl()); checkBasic(config); @@ -103,8 +117,7 @@ public EmbeddingModel createEmbeddingModel(ModelConfigDTO config) { OpenAiApi openAiApi = apiBuilder.build(); return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, - OpenAiEmbeddingOptions.builder().model(config.getModelName()).build(), - RetryUtils.DEFAULT_RETRY_TEMPLATE); + OpenAiEmbeddingOptions.builder().model(config.getModelName()).build(), retryTemplate); } private static void checkBasic(ModelConfigDTO config) { diff --git a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsService.java b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsService.java index 732ee20a6..8d9d1b95a 100644 --- a/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsService.java +++ b/data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsService.java @@ -135,7 +135,7 @@ private void testChatModel(ModelConfigDTO config) { config.getModelName()); // 1. 创建临时模型 - ChatModel tempModel = modelFactory.createChatModel(config); + ChatModel tempModel = modelFactory.createChatModel(config, DynamicModelFactory.NO_RETRY_TEMPLATE); // 2. 发起最轻量的请求 String promptText = "Hello"; @@ -154,7 +154,7 @@ private void testEmbeddingModel(ModelConfigDTO config) { log.info("Testing Embedding Model connection, provider: {} modelName: {}", config.getProvider(), config.getModelName()); // 1. 创建临时模型 - EmbeddingModel tempModel = modelFactory.createEmbeddingModel(config); + EmbeddingModel tempModel = modelFactory.createEmbeddingModel(config, DynamicModelFactory.NO_RETRY_TEMPLATE); // 2. 发起请求 float[] embedding = tempModel.embed("Test"); diff --git a/data-agent-management/src/test/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsServiceTest.java b/data-agent-management/src/test/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsServiceTest.java index fc7b351a3..b82ea9af9 100644 --- a/data-agent-management/src/test/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsServiceTest.java +++ b/data-agent-management/src/test/java/com/alibaba/cloud/ai/dataagent/service/aimodelconfig/ModelConfigOpsServiceTest.java @@ -114,7 +114,7 @@ void testTestConnection_chat() { dto.setModelName("gpt-4"); ChatModel chatModel = mock(ChatModel.class); - when(modelFactory.createChatModel(dto)).thenReturn(chatModel); + when(modelFactory.createChatModel(dto, DynamicModelFactory.NO_RETRY_TEMPLATE)).thenReturn(chatModel); when(chatModel.call("Hello")).thenReturn("Hi there"); assertDoesNotThrow(() -> service.testConnection(dto)); @@ -128,7 +128,7 @@ void testTestConnection_embedding() { dto.setModelName("text-embedding"); EmbeddingModel embeddingModel = mock(EmbeddingModel.class); - when(modelFactory.createEmbeddingModel(dto)).thenReturn(embeddingModel); + when(modelFactory.createEmbeddingModel(dto, DynamicModelFactory.NO_RETRY_TEMPLATE)).thenReturn(embeddingModel); when(embeddingModel.embed("Test")).thenReturn(new float[] { 0.1f, 0.2f }); assertDoesNotThrow(() -> service.testConnection(dto)); @@ -148,7 +148,7 @@ void testTestConnection_chatReturnsEmpty() { dto.setModelType("CHAT"); ChatModel chatModel = mock(ChatModel.class); - when(modelFactory.createChatModel(dto)).thenReturn(chatModel); + when(modelFactory.createChatModel(dto, DynamicModelFactory.NO_RETRY_TEMPLATE)).thenReturn(chatModel); when(chatModel.call("Hello")).thenReturn(""); assertThrows(RuntimeException.class, () -> service.testConnection(dto)); @@ -160,7 +160,7 @@ void testTestConnection_embeddingReturnsEmpty() { dto.setModelType("EMBEDDING"); EmbeddingModel embeddingModel = mock(EmbeddingModel.class); - when(modelFactory.createEmbeddingModel(dto)).thenReturn(embeddingModel); + when(modelFactory.createEmbeddingModel(dto, DynamicModelFactory.NO_RETRY_TEMPLATE)).thenReturn(embeddingModel); when(embeddingModel.embed("Test")).thenReturn(new float[0]); assertThrows(RuntimeException.class, () -> service.testConnection(dto));