mirror of
https://github.com/jie65535/JChatGPT.git
synced 2026-09-15 02:56:10 +08:00
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:
@@ -146,22 +146,28 @@ object LargeLanguageModels {
|
|||||||
|
|
||||||
// 初始化推理模型
|
// 初始化推理模型
|
||||||
if (PluginConfig.reasoningModelApi.isNotBlank() && PluginConfig.reasoningModelToken.isNotBlank()) {
|
if (PluginConfig.reasoningModelApi.isNotBlank() && PluginConfig.reasoningModelToken.isNotBlank()) {
|
||||||
|
// 推理模型出首块前常有思考预热,比对话慢,使用单独放宽的首块超时;
|
||||||
|
// socket 超时(两次读间隔,等首块时也归它管)不能小于首块预算,否则首块超时形同虚设
|
||||||
|
val reasoningFirstChunk = PluginConfig.reasoningFirstChunkTimeout.milliseconds
|
||||||
reasoning = ModelService(
|
reasoning = ModelService(
|
||||||
baseUrl = PluginConfig.reasoningModelApi,
|
baseUrl = PluginConfig.reasoningModelApi,
|
||||||
token = PluginConfig.reasoningModelToken,
|
token = PluginConfig.reasoningModelToken,
|
||||||
timeout = timeout,
|
timeout = maxOf(timeout, reasoningFirstChunk),
|
||||||
firstChunkTimeout = firstChunkTimeout,
|
firstChunkTimeout = reasoningFirstChunk,
|
||||||
extraBody = parseExtraBody(PluginConfig.reasoningModelExtraBody)
|
extraBody = parseExtraBody(PluginConfig.reasoningModelExtraBody)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化视觉模型
|
// 初始化视觉模型
|
||||||
if (PluginConfig.visualModelApi.isNotBlank() && PluginConfig.visualModelToken.isNotBlank()) {
|
if (PluginConfig.visualModelApi.isNotBlank() && PluginConfig.visualModelToken.isNotBlank()) {
|
||||||
|
// 视觉模型需服务端先下载图片再出首块,比对话天然慢,使用单独放宽的首块超时;
|
||||||
|
// socket 超时(两次读间隔,等首块时也归它管)不能小于首块预算,否则首块超时形同虚设
|
||||||
|
val visualFirstChunk = PluginConfig.visualFirstChunkTimeout.milliseconds
|
||||||
visual = ModelService(
|
visual = ModelService(
|
||||||
baseUrl = PluginConfig.visualModelApi,
|
baseUrl = PluginConfig.visualModelApi,
|
||||||
token = PluginConfig.visualModelToken,
|
token = PluginConfig.visualModelToken,
|
||||||
timeout = timeout,
|
timeout = maxOf(timeout, visualFirstChunk),
|
||||||
firstChunkTimeout = firstChunkTimeout,
|
firstChunkTimeout = visualFirstChunk,
|
||||||
extraBody = parseExtraBody(PluginConfig.visualModelExtraBody)
|
extraBody = parseExtraBody(PluginConfig.visualModelExtraBody)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ object PluginConfig : AutoSavePluginConfig("Config") {
|
|||||||
@ValueDescription("首块响应超时时间,单位毫秒,默认10秒。若连接建立后在此时间内没收到首块data:则中断走重试")
|
@ValueDescription("首块响应超时时间,单位毫秒,默认10秒。若连接建立后在此时间内没收到首块data:则中断走重试")
|
||||||
val firstChunkTimeout: Long by value(10000L)
|
val firstChunkTimeout: Long by value(10000L)
|
||||||
|
|
||||||
|
@ValueDescription("视觉模型首块响应超时时间,单位毫秒,默认120秒。视觉模型需先下载图片再出首块,比对话天然慢,故单独放宽")
|
||||||
|
val visualFirstChunkTimeout: Long by value(120000L)
|
||||||
|
|
||||||
|
@ValueDescription("推理模型首块响应超时时间,单位毫秒,默认90秒。推理模型出首块前常有思考预热,比对话慢,故单独放宽")
|
||||||
|
val reasoningFirstChunkTimeout: Long by value(90000L)
|
||||||
|
|
||||||
@Deprecated("使用外部文件而不是在配置文件内保存提示词")
|
@Deprecated("使用外部文件而不是在配置文件内保存提示词")
|
||||||
@ValueDescription("系统提示词,该字段已弃用,使用提示词文件而不是在这里修改")
|
@ValueDescription("系统提示词,该字段已弃用,使用提示词文件而不是在这里修改")
|
||||||
var prompt: String by value("你是一个乐于助人的助手")
|
var prompt: String by value("你是一个乐于助人的助手")
|
||||||
|
|||||||
Reference in New Issue
Block a user