fix: 修复推理模型连接验证截断
- 响应达到输出上限时使用 512 Token 单次重试 - 为自部署 vLLM/SGLang 传递关闭思考参数 - 补充截断重试与请求参数回归测试
This commit is contained in:
@@ -61,6 +61,43 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
Assert.assertEquals(MsgRole.USER, factory.getMessageBatches().get(0).get(1).getRole());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证能力探测达到输出上限时使用更大预算重试一次。
|
||||
*/
|
||||
@Test
|
||||
public void shouldRetryProbeWithLargerBudgetWhenResponseIsLengthLimited() {
|
||||
RecordingModelFactory factory = new RecordingModelFactory(
|
||||
Flux.just(lengthLimitedResponse()),
|
||||
Flux.just(toolResponse(TEST_NONCE, null)));
|
||||
|
||||
ChatModelVerificationResult result = verifier(factory).verify(model(false));
|
||||
|
||||
Assert.assertEquals(ModelVerificationStatus.PASSED, result.getStatus());
|
||||
Assert.assertEquals(Boolean.TRUE, result.getSupportTool());
|
||||
Assert.assertEquals(List.of(1, 1), factory.getToolCounts());
|
||||
Assert.assertEquals(List.of(128, 512), factory.getFactoryMaxTokens());
|
||||
Assert.assertEquals(List.of(128, 512), factory.getRequestMaxTokens());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证自部署 vLLM/SGLang 入口通过聊天模板参数关闭思考。
|
||||
*/
|
||||
@Test
|
||||
public void shouldDisableThinkingThroughChatTemplateKwargsForSelfHostedEndpoint() {
|
||||
RecordingModelFactory factory = new RecordingModelFactory(
|
||||
Flux.just(toolResponse(TEST_NONCE, null)));
|
||||
|
||||
ChatModelVerificationResult result = verifier(factory).verify(
|
||||
model(false, "self-hosted"));
|
||||
|
||||
Assert.assertEquals(ModelVerificationStatus.PASSED, result.getStatus());
|
||||
Map<String, Object> bodyParams = factory.getFactoryAdditionalBodyParams().get(0);
|
||||
Assert.assertEquals(Boolean.FALSE, bodyParams.get("enable_thinking"));
|
||||
Assert.assertEquals(
|
||||
Map.of("enable_thinking", false),
|
||||
bodyParams.get("chat_template_kwargs"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证模型返回普通文本时连接通过但工具能力保持关闭。
|
||||
*/
|
||||
@@ -143,6 +180,17 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
* @return 测试模型
|
||||
*/
|
||||
private Model model(boolean supportImage) {
|
||||
return model(supportImage, "gpustack");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建携带指定供应商类型的待验证模型。
|
||||
*
|
||||
* @param supportImage 是否支持图片
|
||||
* @param providerType 供应商类型
|
||||
* @return 测试模型
|
||||
*/
|
||||
private Model model(boolean supportImage, String providerType) {
|
||||
Model model = new Model();
|
||||
model.setId(BigInteger.TEN);
|
||||
model.setModelName("test-model");
|
||||
@@ -151,7 +199,7 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
model.setApiKey("test-key");
|
||||
model.setSupportImage(supportImage);
|
||||
ModelProvider provider = new ModelProvider();
|
||||
provider.setProviderType("gpustack");
|
||||
provider.setProviderType(providerType);
|
||||
model.setModelProvider(provider);
|
||||
return model;
|
||||
}
|
||||
@@ -182,6 +230,18 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建达到输出上限的响应。
|
||||
*
|
||||
* @return 输出被截断的 AgentScope 响应
|
||||
*/
|
||||
private ChatResponse lengthLimitedResponse() {
|
||||
return ChatResponse.builder()
|
||||
.content(List.of(TextBlock.builder().text("incomplete").build()))
|
||||
.finishReason("length")
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建探测工具调用响应。
|
||||
*
|
||||
@@ -212,8 +272,14 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
private final List<Flux<ChatResponse>> responses;
|
||||
/** 模型工厂收到的流式参数。 */
|
||||
private final List<Boolean> factoryStreams = new ArrayList<>();
|
||||
/** 模型工厂收到的最大输出 Token 数。 */
|
||||
private final List<Integer> factoryMaxTokens = new ArrayList<>();
|
||||
/** 模型工厂收到的额外请求体参数。 */
|
||||
private final List<Map<String, Object>> factoryAdditionalBodyParams = new ArrayList<>();
|
||||
/** 模型请求收到的流式参数。 */
|
||||
private final List<Boolean> requestStreams = new ArrayList<>();
|
||||
/** 模型请求收到的最大输出 Token 数。 */
|
||||
private final List<Integer> requestMaxTokens = new ArrayList<>();
|
||||
/** 模型请求收到的消息批次。 */
|
||||
private final List<List<Msg>> messageBatches = new ArrayList<>();
|
||||
/** 每次请求携带的工具数量。 */
|
||||
@@ -244,6 +310,9 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
AgentGenerationOptions generationOptions) {
|
||||
int requestIndex = factoryStreams.size();
|
||||
factoryStreams.add(Boolean.TRUE.equals(generationOptions.getStream()));
|
||||
factoryMaxTokens.add(generationOptions.getMaxTokens());
|
||||
factoryAdditionalBodyParams.add(Map.copyOf(
|
||||
generationOptions.getAdditionalBodyParams()));
|
||||
Flux<ChatResponse> response = responses.get(requestIndex);
|
||||
return new io.agentscope.core.model.Model() {
|
||||
/**
|
||||
@@ -260,6 +329,7 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
List<ToolSchema> tools,
|
||||
GenerateOptions options) {
|
||||
requestStreams.add(Boolean.TRUE.equals(options.getStream()));
|
||||
requestMaxTokens.add(options.getMaxTokens());
|
||||
messageBatches.add(List.copyOf(inputMessages));
|
||||
toolCounts.add(tools.size());
|
||||
toolChoices.add(options.getToolChoice());
|
||||
@@ -287,6 +357,24 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
return factoryStreams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型工厂收到的最大输出 Token 数。
|
||||
*
|
||||
* @return 最大输出 Token 数列表
|
||||
*/
|
||||
private List<Integer> getFactoryMaxTokens() {
|
||||
return factoryMaxTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型工厂收到的额外请求体参数。
|
||||
*
|
||||
* @return 额外请求体参数列表
|
||||
*/
|
||||
private List<Map<String, Object>> getFactoryAdditionalBodyParams() {
|
||||
return factoryAdditionalBodyParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求流式参数。
|
||||
*
|
||||
@@ -296,6 +384,15 @@ public class AgentScopeChatModelConnectivityVerifierTest {
|
||||
return requestStreams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型请求收到的最大输出 Token 数。
|
||||
*
|
||||
* @return 最大输出 Token 数列表
|
||||
*/
|
||||
private List<Integer> getRequestMaxTokens() {
|
||||
return requestMaxTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取每次请求的验证消息批次。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user