Give visual and reasoning models their own first-chunk timeouts

Vision and reasoning requests reused the chat model's 10s first-chunk
timeout, but both legitimately need longer before the first chunk:
vision must download the image server-side first, and reasoning has a
thinking warmup. Logs showed frequent TimeoutCancellationException at
10s/15s for imageRecognition and reasoning.

Add separate visualFirstChunkTimeout (120s) and reasoningFirstChunkTimeout
(90s) config, and raise each service's socket timeout to at least its
first-chunk budget so the socket layer doesn't sever the connection
before the first-chunk timeout can apply. Chat endpoints are unchanged.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
2026-06-26 14:06:00 +08:00
co-authored by Claude Opus 4.8
parent 826dc460df
commit bc61e99013
2 changed files with 16 additions and 4 deletions
+10 -4
View File
@@ -146,22 +146,28 @@ object LargeLanguageModels {
// 初始化推理模型
if (PluginConfig.reasoningModelApi.isNotBlank() && PluginConfig.reasoningModelToken.isNotBlank()) {
// 推理模型出首块前常有思考预热,比对话慢,使用单独放宽的首块超时;
// socket 超时(两次读间隔,等首块时也归它管)不能小于首块预算,否则首块超时形同虚设
val reasoningFirstChunk = PluginConfig.reasoningFirstChunkTimeout.milliseconds
reasoning = ModelService(
baseUrl = PluginConfig.reasoningModelApi,
token = PluginConfig.reasoningModelToken,
timeout = timeout,
firstChunkTimeout = firstChunkTimeout,
timeout = maxOf(timeout, reasoningFirstChunk),
firstChunkTimeout = reasoningFirstChunk,
extraBody = parseExtraBody(PluginConfig.reasoningModelExtraBody)
)
}
// 初始化视觉模型
if (PluginConfig.visualModelApi.isNotBlank() && PluginConfig.visualModelToken.isNotBlank()) {
// 视觉模型需服务端先下载图片再出首块,比对话天然慢,使用单独放宽的首块超时;
// socket 超时(两次读间隔,等首块时也归它管)不能小于首块预算,否则首块超时形同虚设
val visualFirstChunk = PluginConfig.visualFirstChunkTimeout.milliseconds
visual = ModelService(
baseUrl = PluginConfig.visualModelApi,
token = PluginConfig.visualModelToken,
timeout = timeout,
firstChunkTimeout = firstChunkTimeout,
timeout = maxOf(timeout, visualFirstChunk),
firstChunkTimeout = visualFirstChunk,
extraBody = parseExtraBody(PluginConfig.visualModelExtraBody)
)
}