mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-15 20:08:18 +08:00
feat(llm): per-Model HTTP read-timeout override
This commit is contained in:
parent
0c7554212b
commit
55f4ba1195
@ -1095,6 +1095,16 @@ public class AgentGraphBuilder {
|
|||||||
|
|
||||||
/** Transitional public visibility for {@code chatmodel} sub-package builders; will move into the builder in PR-0b. */
|
/** Transitional public visibility for {@code chatmodel} sub-package builders; will move into the builder in PR-0b. */
|
||||||
public OpenAiApi buildOpenAiApi(ModelProviderEntity provider) {
|
public OpenAiApi buildOpenAiApi(ModelProviderEntity provider) {
|
||||||
|
return buildOpenAiApi(provider, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 overload — accepts a per-model read-timeout override
|
||||||
|
* (seconds). Threaded into both the sync RestClient and streaming
|
||||||
|
* WebClient so timeout behavior is consistent across blocking and
|
||||||
|
* streaming chat completions. Null falls back to the default 180s.
|
||||||
|
*/
|
||||||
|
public OpenAiApi buildOpenAiApi(ModelProviderEntity provider, Integer readTimeoutOverride) {
|
||||||
if (provider == null || !modelProviderService.isProviderConfigured(provider.getProviderId())) {
|
if (provider == null || !modelProviderService.isProviderConfigured(provider.getProviderId())) {
|
||||||
throw new MateClawException("err.agent.provider_not_configured", "Provider 未完成配置,请在模型设置中填写有效的 API Key 和 Base URL");
|
throw new MateClawException("err.agent.provider_not_configured", "Provider 未完成配置,请在模型设置中填写有效的 API Key 和 Base URL");
|
||||||
}
|
}
|
||||||
@ -1116,9 +1126,9 @@ public class AgentGraphBuilder {
|
|||||||
MultiValueMap<String, String> headers = buildOpenAiHeaders(kwargs);
|
MultiValueMap<String, String> headers = buildOpenAiHeaders(kwargs);
|
||||||
String completionsPath = resolveOpenAiCompletionsPath(baseUrl, kwargs);
|
String completionsPath = resolveOpenAiCompletionsPath(baseUrl, kwargs);
|
||||||
RestClient.Builder restClientBuilder = applyHttpTimeouts(
|
RestClient.Builder restClientBuilder = applyHttpTimeouts(
|
||||||
restClientBuilderProvider.getIfAvailable(RestClient::builder));
|
restClientBuilderProvider.getIfAvailable(RestClient::builder), readTimeoutOverride);
|
||||||
WebClient.Builder webClientBuilder = applyHttpTimeoutsToWebClient(
|
WebClient.Builder webClientBuilder = applyHttpTimeoutsToWebClient(
|
||||||
webClientBuilderProvider.getIfAvailable(WebClient::builder));
|
webClientBuilderProvider.getIfAvailable(WebClient::builder), readTimeoutOverride);
|
||||||
|
|
||||||
// Spring AI OpenAiApi 构造函数会先 set User-Agent 为 "spring-ai",再 addAll 我们的 headers,
|
// Spring AI OpenAiApi 构造函数会先 set User-Agent 为 "spring-ai",再 addAll 我们的 headers,
|
||||||
// 导致自定义 User-Agent 被追加而非覆盖。因此对需要伪装客户端身份的 provider(如 kimi-code),
|
// 导致自定义 User-Agent 被追加而非覆盖。因此对需要伪装客户端身份的 provider(如 kimi-code),
|
||||||
@ -1475,11 +1485,19 @@ public class AgentGraphBuilder {
|
|||||||
* readTimeout=180s(覆盖 nginx 60s 网关超时 + 留足真实长响应余量;超时后由上层 retry 接管)。
|
* readTimeout=180s(覆盖 nginx 60s 网关超时 + 留足真实长响应余量;超时后由上层 retry 接管)。
|
||||||
*/
|
*/
|
||||||
private RestClient.Builder applyHttpTimeouts(RestClient.Builder builder) {
|
private RestClient.Builder applyHttpTimeouts(RestClient.Builder builder) {
|
||||||
|
return applyHttpTimeouts(builder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 overload — accepts a per-model read-timeout override
|
||||||
|
* (seconds). Null falls back to the default 180s.
|
||||||
|
*/
|
||||||
|
private RestClient.Builder applyHttpTimeouts(RestClient.Builder builder, Integer readTimeoutOverride) {
|
||||||
HttpClient httpClient = HttpClient.newBuilder()
|
HttpClient httpClient = HttpClient.newBuilder()
|
||||||
.connectTimeout(Duration.ofSeconds(10))
|
.connectTimeout(vip.mate.llm.chatmodel.HttpTimeouts.CONNECT_TIMEOUT)
|
||||||
.build();
|
.build();
|
||||||
JdkClientHttpRequestFactory rf = new JdkClientHttpRequestFactory(httpClient);
|
JdkClientHttpRequestFactory rf = new JdkClientHttpRequestFactory(httpClient);
|
||||||
rf.setReadTimeout(Duration.ofSeconds(180));
|
rf.setReadTimeout(vip.mate.llm.chatmodel.HttpTimeouts.resolveReadTimeout(readTimeoutOverride));
|
||||||
return builder.requestFactory(rf);
|
return builder.requestFactory(rf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1499,12 +1517,20 @@ public class AgentGraphBuilder {
|
|||||||
* starter is excluded by design).
|
* starter is excluded by design).
|
||||||
*/
|
*/
|
||||||
private WebClient.Builder applyHttpTimeoutsToWebClient(WebClient.Builder builder) {
|
private WebClient.Builder applyHttpTimeoutsToWebClient(WebClient.Builder builder) {
|
||||||
|
return applyHttpTimeoutsToWebClient(builder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 overload — same per-model override semantics as
|
||||||
|
* {@link #applyHttpTimeouts(RestClient.Builder, Integer)}.
|
||||||
|
*/
|
||||||
|
private WebClient.Builder applyHttpTimeoutsToWebClient(WebClient.Builder builder, Integer readTimeoutOverride) {
|
||||||
HttpClient httpClient = HttpClient.newBuilder()
|
HttpClient httpClient = HttpClient.newBuilder()
|
||||||
.connectTimeout(Duration.ofSeconds(10))
|
.connectTimeout(vip.mate.llm.chatmodel.HttpTimeouts.CONNECT_TIMEOUT)
|
||||||
.build();
|
.build();
|
||||||
org.springframework.http.client.reactive.JdkClientHttpConnector connector =
|
org.springframework.http.client.reactive.JdkClientHttpConnector connector =
|
||||||
new org.springframework.http.client.reactive.JdkClientHttpConnector(httpClient);
|
new org.springframework.http.client.reactive.JdkClientHttpConnector(httpClient);
|
||||||
connector.setReadTimeout(Duration.ofSeconds(180));
|
connector.setReadTimeout(vip.mate.llm.chatmodel.HttpTimeouts.resolveReadTimeout(readTimeoutOverride));
|
||||||
return builder.clientConnector(connector);
|
return builder.clientConnector(connector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public class AgentAnthropicChatModelBuilder implements ChatModelBuilder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChatModel build(ModelConfigEntity model, ModelProviderEntity provider, RetryTemplate retry) {
|
public ChatModel build(ModelConfigEntity model, ModelProviderEntity provider, RetryTemplate retry) {
|
||||||
AnthropicApi api = buildAnthropicApi(provider);
|
AnthropicApi api = buildAnthropicApi(provider, model.getRequestTimeoutSeconds());
|
||||||
AnthropicChatOptions options = buildAnthropicOptions(model);
|
AnthropicChatOptions options = buildAnthropicOptions(model);
|
||||||
return AnthropicChatModel.builder()
|
return AnthropicChatModel.builder()
|
||||||
.anthropicApi(api)
|
.anthropicApi(api)
|
||||||
@ -74,6 +74,14 @@ public class AgentAnthropicChatModelBuilder implements ChatModelBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AnthropicApi buildAnthropicApi(ModelProviderEntity provider) {
|
AnthropicApi buildAnthropicApi(ModelProviderEntity provider) {
|
||||||
|
return buildAnthropicApi(provider, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 overload — accepts a per-model read-timeout override
|
||||||
|
* (seconds). Null falls back to the default 180s.
|
||||||
|
*/
|
||||||
|
AnthropicApi buildAnthropicApi(ModelProviderEntity provider, Integer readTimeoutOverride) {
|
||||||
if (provider == null || !modelProviderService.isProviderConfigured(provider.getProviderId())) {
|
if (provider == null || !modelProviderService.isProviderConfigured(provider.getProviderId())) {
|
||||||
throw new MateClawException("err.agent.anthropic_not_configured",
|
throw new MateClawException("err.agent.anthropic_not_configured",
|
||||||
"Anthropic Provider 未完成配置,请在模型设置中填写有效的 API Key 和 Base URL");
|
"Anthropic Provider 未完成配置,请在模型设置中填写有效的 API Key 和 Base URL");
|
||||||
@ -85,9 +93,9 @@ public class AgentAnthropicChatModelBuilder implements ChatModelBuilder {
|
|||||||
}
|
}
|
||||||
String baseUrl = provider.getBaseUrl();
|
String baseUrl = provider.getBaseUrl();
|
||||||
RestClient.Builder restClientBuilder = applyHttpTimeouts(
|
RestClient.Builder restClientBuilder = applyHttpTimeouts(
|
||||||
restClientBuilderProvider.getIfAvailable(RestClient::builder));
|
restClientBuilderProvider.getIfAvailable(RestClient::builder), readTimeoutOverride);
|
||||||
WebClient.Builder webClientBuilder = applyHttpTimeoutsToWebClient(
|
WebClient.Builder webClientBuilder = applyHttpTimeoutsToWebClient(
|
||||||
webClientBuilderProvider.getIfAvailable(WebClient::builder));
|
webClientBuilderProvider.getIfAvailable(WebClient::builder), readTimeoutOverride);
|
||||||
|
|
||||||
AnthropicApi.Builder builder = AnthropicApi.builder()
|
AnthropicApi.Builder builder = AnthropicApi.builder()
|
||||||
.apiKey(apiKey.trim())
|
.apiKey(apiKey.trim())
|
||||||
@ -194,11 +202,20 @@ public class AgentAnthropicChatModelBuilder implements ChatModelBuilder {
|
|||||||
* duplicating the snippet.</p>
|
* duplicating the snippet.</p>
|
||||||
*/
|
*/
|
||||||
static RestClient.Builder applyHttpTimeouts(RestClient.Builder builder) {
|
static RestClient.Builder applyHttpTimeouts(RestClient.Builder builder) {
|
||||||
|
return applyHttpTimeouts(builder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 overload — accepts a per-model read-timeout override
|
||||||
|
* (seconds). Null / zero / negative falls back to {@link vip.mate.llm.chatmodel.HttpTimeouts#DEFAULT_READ_TIMEOUT}
|
||||||
|
* so unset model configs keep the historical 180s.
|
||||||
|
*/
|
||||||
|
static RestClient.Builder applyHttpTimeouts(RestClient.Builder builder, Integer readTimeoutOverride) {
|
||||||
HttpClient httpClient = HttpClient.newBuilder()
|
HttpClient httpClient = HttpClient.newBuilder()
|
||||||
.connectTimeout(Duration.ofSeconds(10))
|
.connectTimeout(vip.mate.llm.chatmodel.HttpTimeouts.CONNECT_TIMEOUT)
|
||||||
.build();
|
.build();
|
||||||
JdkClientHttpRequestFactory rf = new JdkClientHttpRequestFactory(httpClient);
|
JdkClientHttpRequestFactory rf = new JdkClientHttpRequestFactory(httpClient);
|
||||||
rf.setReadTimeout(Duration.ofSeconds(180));
|
rf.setReadTimeout(vip.mate.llm.chatmodel.HttpTimeouts.resolveReadTimeout(readTimeoutOverride));
|
||||||
return builder.requestFactory(rf);
|
return builder.requestFactory(rf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,12 +231,20 @@ public class AgentAnthropicChatModelBuilder implements ChatModelBuilder {
|
|||||||
* doesn't pull in reactor-netty (excluded by this project's pom).
|
* doesn't pull in reactor-netty (excluded by this project's pom).
|
||||||
*/
|
*/
|
||||||
static WebClient.Builder applyHttpTimeoutsToWebClient(WebClient.Builder builder) {
|
static WebClient.Builder applyHttpTimeoutsToWebClient(WebClient.Builder builder) {
|
||||||
|
return applyHttpTimeoutsToWebClient(builder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 overload — same per-model override semantics as
|
||||||
|
* {@link #applyHttpTimeouts(RestClient.Builder, Integer)}.
|
||||||
|
*/
|
||||||
|
static WebClient.Builder applyHttpTimeoutsToWebClient(WebClient.Builder builder, Integer readTimeoutOverride) {
|
||||||
HttpClient httpClient = HttpClient.newBuilder()
|
HttpClient httpClient = HttpClient.newBuilder()
|
||||||
.connectTimeout(Duration.ofSeconds(10))
|
.connectTimeout(vip.mate.llm.chatmodel.HttpTimeouts.CONNECT_TIMEOUT)
|
||||||
.build();
|
.build();
|
||||||
org.springframework.http.client.reactive.JdkClientHttpConnector connector =
|
org.springframework.http.client.reactive.JdkClientHttpConnector connector =
|
||||||
new org.springframework.http.client.reactive.JdkClientHttpConnector(httpClient);
|
new org.springframework.http.client.reactive.JdkClientHttpConnector(httpClient);
|
||||||
connector.setReadTimeout(Duration.ofSeconds(180));
|
connector.setReadTimeout(vip.mate.llm.chatmodel.HttpTimeouts.resolveReadTimeout(readTimeoutOverride));
|
||||||
return builder.clientConnector(connector);
|
return builder.clientConnector(connector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,7 +96,7 @@ public class AgentClaudeCodeChatModelBuilder implements ChatModelBuilder {
|
|||||||
String accessToken = oauthService.getValidToken();
|
String accessToken = oauthService.getValidToken();
|
||||||
|
|
||||||
// 2) Build the Anthropic API client wired with OAuth headers.
|
// 2) Build the Anthropic API client wired with OAuth headers.
|
||||||
AnthropicApi api = buildOauthAnthropicApi(accessToken);
|
AnthropicApi api = buildOauthAnthropicApi(accessToken, model.getRequestTimeoutSeconds());
|
||||||
|
|
||||||
// 3) Reuse the canonical Anthropic options builder — same Claude 4.7
|
// 3) Reuse the canonical Anthropic options builder — same Claude 4.7
|
||||||
// sampling-params handling, thinking-budget mapping, prompt cache.
|
// sampling-params handling, thinking-budget mapping, prompt cache.
|
||||||
@ -122,6 +122,15 @@ public class AgentClaudeCodeChatModelBuilder implements ChatModelBuilder {
|
|||||||
* can verify header composition without spinning up a chat model.
|
* can verify header composition without spinning up a chat model.
|
||||||
*/
|
*/
|
||||||
AnthropicApi buildOauthAnthropicApi(String accessToken) {
|
AnthropicApi buildOauthAnthropicApi(String accessToken) {
|
||||||
|
return buildOauthAnthropicApi(accessToken, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 overload — same OAuth-stamped Anthropic client, with a
|
||||||
|
* per-model read-timeout override threaded through to the underlying
|
||||||
|
* RestClient + WebClient timeouts.
|
||||||
|
*/
|
||||||
|
AnthropicApi buildOauthAnthropicApi(String accessToken, Integer readTimeoutOverride) {
|
||||||
String authHeader = apiHeaders.bearerAuth(accessToken);
|
String authHeader = apiHeaders.bearerAuth(accessToken);
|
||||||
String userAgent = apiHeaders.userAgent();
|
String userAgent = apiHeaders.userAgent();
|
||||||
String xApp = apiHeaders.xApp();
|
String xApp = apiHeaders.xApp();
|
||||||
@ -135,7 +144,7 @@ public class AgentClaudeCodeChatModelBuilder implements ChatModelBuilder {
|
|||||||
// rate-limited harder than spec'd. Reference: openclaw
|
// rate-limited harder than spec'd. Reference: openclaw
|
||||||
// anthropic-transport-stream.ts:567-574.
|
// anthropic-transport-stream.ts:567-574.
|
||||||
RestClient.Builder restClientBuilder = AgentAnthropicChatModelBuilder.applyHttpTimeouts(
|
RestClient.Builder restClientBuilder = AgentAnthropicChatModelBuilder.applyHttpTimeouts(
|
||||||
restClientBuilderProvider.getIfAvailable(RestClient::builder))
|
restClientBuilderProvider.getIfAvailable(RestClient::builder), readTimeoutOverride)
|
||||||
.defaultHeader(HttpHeaders.AUTHORIZATION, authHeader)
|
.defaultHeader(HttpHeaders.AUTHORIZATION, authHeader)
|
||||||
.defaultHeader(HttpHeaders.USER_AGENT, userAgent)
|
.defaultHeader(HttpHeaders.USER_AGENT, userAgent)
|
||||||
.defaultHeader(HttpHeaders.ACCEPT, "application/json")
|
.defaultHeader(HttpHeaders.ACCEPT, "application/json")
|
||||||
@ -152,7 +161,8 @@ public class AgentClaudeCodeChatModelBuilder implements ChatModelBuilder {
|
|||||||
// staring at SDK internals.
|
// staring at SDK internals.
|
||||||
.requestInterceptor(new RateLimitDiagnosticInterceptor());
|
.requestInterceptor(new RateLimitDiagnosticInterceptor());
|
||||||
|
|
||||||
WebClient.Builder webClientBuilder = webClientBuilderProvider.getIfAvailable(WebClient::builder)
|
WebClient.Builder webClientBuilder = AgentAnthropicChatModelBuilder.applyHttpTimeoutsToWebClient(
|
||||||
|
webClientBuilderProvider.getIfAvailable(WebClient::builder), readTimeoutOverride)
|
||||||
.defaultHeader(HttpHeaders.AUTHORIZATION, authHeader)
|
.defaultHeader(HttpHeaders.AUTHORIZATION, authHeader)
|
||||||
.defaultHeader(HttpHeaders.USER_AGENT, userAgent)
|
.defaultHeader(HttpHeaders.USER_AGENT, userAgent)
|
||||||
.defaultHeader(HttpHeaders.ACCEPT, "application/json")
|
.defaultHeader(HttpHeaders.ACCEPT, "application/json")
|
||||||
|
|||||||
@ -42,7 +42,10 @@ public class AgentOpenAiCompatibleChatModelBuilder implements ChatModelBuilder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChatModel build(ModelConfigEntity model, ModelProviderEntity provider, RetryTemplate retry) {
|
public ChatModel build(ModelConfigEntity model, ModelProviderEntity provider, RetryTemplate retry) {
|
||||||
OpenAiApi api = agentGraphBuilder.buildOpenAiApi(provider);
|
// RFC-03 Lane B1 — pass model.requestTimeoutSeconds so providers /
|
||||||
|
// models with extended-thinking p99s don't false-positive on the
|
||||||
|
// hardcoded 180s read timeout.
|
||||||
|
OpenAiApi api = agentGraphBuilder.buildOpenAiApi(provider, model.getRequestTimeoutSeconds());
|
||||||
OpenAiChatOptions options = agentGraphBuilder.buildOpenAiOptions(model, provider);
|
OpenAiChatOptions options = agentGraphBuilder.buildOpenAiOptions(model, provider);
|
||||||
ChatModel raw = OpenAiChatModel.builder()
|
ChatModel raw = OpenAiChatModel.builder()
|
||||||
.openAiApi(api)
|
.openAiApi(api)
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
package vip.mate.llm.chatmodel;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 — central resolver for the per-LLM-request HTTP read
|
||||||
|
* timeout, so {@link vip.mate.llm.model.ModelConfigEntity#getRequestTimeoutSeconds()}
|
||||||
|
* can override the legacy 180s default without each chatmodel builder
|
||||||
|
* inventing its own fallback chain.
|
||||||
|
*
|
||||||
|
* <p>Used by:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code AgentAnthropicChatModelBuilder.applyHttpTimeouts}</li>
|
||||||
|
* <li>{@code AgentAnthropicChatModelBuilder.applyHttpTimeoutsToWebClient}</li>
|
||||||
|
* <li>{@code AgentClaudeCodeChatModelBuilder} (via Anthropic helper)</li>
|
||||||
|
* <li>{@code AgentGraphBuilder} legacy timeout helpers</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>Connect timeout stays at the canonical 10s — long-tail thinking
|
||||||
|
* latency manifests on the read path, not on connect.
|
||||||
|
*/
|
||||||
|
public final class HttpTimeouts {
|
||||||
|
|
||||||
|
/** Connect timeout — never overridable; 10s is enough for any sane endpoint. */
|
||||||
|
public static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(10);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default read timeout when no per-model override is set. Matches the
|
||||||
|
* historical hardcoded value so unset rows behave identically to the
|
||||||
|
* pre-RFC-03 baseline.
|
||||||
|
*/
|
||||||
|
public static final Duration DEFAULT_READ_TIMEOUT = Duration.ofSeconds(180);
|
||||||
|
|
||||||
|
private HttpTimeouts() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the effective read timeout: the override if positive, else the
|
||||||
|
* canonical 180s default. Null and non-positive values fall back, so
|
||||||
|
* callers can pass {@code modelConfig.getRequestTimeoutSeconds()} directly
|
||||||
|
* without null-checks.
|
||||||
|
*/
|
||||||
|
public static Duration resolveReadTimeout(Integer override) {
|
||||||
|
if (override == null || override <= 0) {
|
||||||
|
return DEFAULT_READ_TIMEOUT;
|
||||||
|
}
|
||||||
|
return Duration.ofSeconds(override);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,21 @@ public class ModelConfigEntity {
|
|||||||
/** 模型最大输入 token 数(上下文窗口),0 或 null 表示使用全局默认 */
|
/** 模型最大输入 token 数(上下文窗口),0 或 null 表示使用全局默认 */
|
||||||
private Integer maxInputTokens;
|
private Integer maxInputTokens;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC-03 Lane B1 — per-model HTTP read timeout (seconds).
|
||||||
|
*
|
||||||
|
* <p>Null / zero / negative → fall back to the global default of 180s
|
||||||
|
* (existing behavior, see {@code AgentAnthropicChatModelBuilder.applyHttpTimeouts}
|
||||||
|
* and the corresponding helper in {@code AgentGraphBuilder}). A positive
|
||||||
|
* value overrides for this specific model.
|
||||||
|
*
|
||||||
|
* <p>Use cases: {@code o1-pro} / Claude thinking-mode / large-prompt
|
||||||
|
* generation calls that legitimately exceed 3 min, where the default
|
||||||
|
* raises false-positive timeouts; conversely {@code haiku}-class models
|
||||||
|
* that p99 well under 30s, where a tighter timeout fails fast.
|
||||||
|
*/
|
||||||
|
private Integer requestTimeoutSeconds;
|
||||||
|
|
||||||
private Double topP;
|
private Double topP;
|
||||||
|
|
||||||
private Boolean enableSearch;
|
private Boolean enableSearch;
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
-- V75: Per-model HTTP read timeout (RFC-03 Lane B1).
|
||||||
|
-- Lets thinking models (o1-pro, claude opus extended-thinking, qwen3-max
|
||||||
|
-- with deep reasoning) override the default 180s read timeout when their
|
||||||
|
-- p99 legitimately exceeds it. Null / zero keeps the existing global
|
||||||
|
-- default — no behavior change for existing rows.
|
||||||
|
|
||||||
|
ALTER TABLE mate_model_config ADD COLUMN IF NOT EXISTS request_timeout_seconds INTEGER;
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
-- V75: Per-model HTTP read timeout (RFC-03 Lane B1).
|
||||||
|
-- Lets thinking models (o1-pro, claude opus extended-thinking, qwen3-max
|
||||||
|
-- with deep reasoning) override the default 180s read timeout when their
|
||||||
|
-- p99 legitimately exceeds it. Null / zero keeps the existing global
|
||||||
|
-- default — no behavior change for existing rows.
|
||||||
|
--
|
||||||
|
-- MySQL lacks `ADD COLUMN IF NOT EXISTS`; use INFORMATION_SCHEMA guard.
|
||||||
|
SET @c := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'mate_model_config'
|
||||||
|
AND COLUMN_NAME = 'request_timeout_seconds');
|
||||||
|
SET @s := IF(@c = 0,
|
||||||
|
'ALTER TABLE mate_model_config ADD COLUMN request_timeout_seconds INT DEFAULT NULL',
|
||||||
|
'SELECT 1');
|
||||||
|
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||||
Loading…
Reference in New Issue
Block a user