fix: user custom params should always overwrite other params (#8907)

* fix(aws-bedrock): 未支持自定义参数

* refactor(AnthropicAPIClient): 简化消息创建参数逻辑

移除不必要的MessageCreateParams类型,直接在commonParams中设置stream参数

* refactor(openai): 简化API客户端参数处理逻辑

移除冗余的stream参数分支逻辑,直接在commonParams中设置stream相关参数

* docs(aiCore): 添加注释说明用户自定义参数应覆盖其他参数

* feat(openai): 添加流式输出选项支持

当流式输出启用且提供者支持时,包含stream_options以包含使用情况信息

* fix(openai): 移除冗余的逻辑判断
This commit is contained in:
Phantom 2025-08-08 16:58:31 +08:00 committed by GitHub
parent da5372637b
commit 97a63ea5b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 26 additions and 43 deletions

View File

@ -11,7 +11,6 @@ import {
import {
ContentBlock,
ContentBlockParam,
MessageCreateParams,
MessageCreateParamsBase,
RedactedThinkingBlockParam,
ServerToolUseBlockParam,
@ -495,22 +494,14 @@ export class AnthropicAPIClient extends BaseApiClient<
system: systemMessage ? [systemMessage] : undefined,
thinking: this.getBudgetToken(assistant, model),
tools: tools.length > 0 ? tools : undefined,
stream: streamOutput,
// 只在对话场景下应用自定义参数,避免影响翻译、总结等其他业务逻辑
// 注意:用户自定义参数总是应该覆盖其他参数
...(coreRequest.callType === 'chat' ? this.getCustomParameters(assistant) : {})
}
const finalParams: MessageCreateParams = streamOutput
? {
...commonParams,
stream: true
}
: {
...commonParams,
stream: false
}
const timeout = this.getTimeout(model)
return { payload: finalParams, messages: sdkMessages, metadata: { timeout } }
return { payload: commonParams, messages: sdkMessages, metadata: { timeout } }
}
}
}

View File

@ -418,7 +418,10 @@ export class AwsBedrockAPIClient extends BaseApiClient<
temperature: this.getTemperature(assistant, model),
topP: this.getTopP(assistant, model),
stream: streamOutput !== false,
tools: tools.length > 0 ? tools : undefined
tools: tools.length > 0 ? tools : undefined,
// 只在对话场景下应用自定义参数,避免影响翻译、总结等其他业务逻辑
// 注意:用户自定义参数总是应该覆盖其他参数
...(coreRequest.callType === 'chat' ? this.getCustomParameters(assistant) : {})
}
const timeout = this.getTimeout(model)

View File

@ -532,6 +532,7 @@ export class GeminiAPIClient extends BaseApiClient<
...(enableGenerateImage ? this.getGenerateImageParameter() : {}),
...this.getBudgetToken(assistant, model),
// 只在对话场景下应用自定义参数,避免影响翻译、总结等其他业务逻辑
// 注意:用户自定义参数总是应该覆盖其他参数
...(coreRequest.callType === 'chat' ? this.getCustomParameters(assistant) : {})
}

View File

@ -564,6 +564,10 @@ export class OpenAIAPIClient extends OpenAIBaseClient<
reqMessages = processReqMessages(model, reqMessages)
// 5. 创建通用参数
// Create the appropriate parameters object based on whether streaming is enabled
// Note: Some providers like Mistral don't support stream_options
const shouldIncludeStreamOptions = streamOutput && isSupportStreamOptionsProvider(this.provider)
const commonParams: OpenAISdkParams = {
model: model.id,
messages:
@ -574,36 +578,24 @@ export class OpenAIAPIClient extends OpenAIBaseClient<
top_p: this.getTopP(assistant, model),
max_tokens: maxTokens,
tools: tools.length > 0 ? tools : undefined,
stream: streamOutput,
...(shouldIncludeStreamOptions ? { stream_options: { include_usage: true } } : {}),
// groq 有不同的 service tier 配置,不符合 openai 接口类型
service_tier: this.getServiceTier(model) as OpenAIServiceTier,
...this.getProviderSpecificParameters(assistant, model),
...this.getReasoningEffort(assistant, model),
...getOpenAIWebSearchParams(model, enableWebSearch),
// 只在对话场景下应用自定义参数,避免影响翻译、总结等其他业务逻辑
...(coreRequest.callType === 'chat' ? this.getCustomParameters(assistant) : {}),
// OpenRouter usage tracking
...(this.provider.id === 'openrouter' ? { usage: { include: true } } : {}),
...(isQwenMTModel(model) ? extra_body : {})
...(isQwenMTModel(model) ? extra_body : {}),
// 只在对话场景下应用自定义参数,避免影响翻译、总结等其他业务逻辑
// 注意:用户自定义参数总是应该覆盖其他参数
...(coreRequest.callType === 'chat' ? this.getCustomParameters(assistant) : {})
}
// Create the appropriate parameters object based on whether streaming is enabled
// Note: Some providers like Mistral don't support stream_options
const shouldIncludeStreamOptions = streamOutput && isSupportStreamOptionsProvider(this.provider)
const sdkParams: OpenAISdkParams = streamOutput
? {
...commonParams,
stream: true,
...(shouldIncludeStreamOptions ? { stream_options: { include_usage: true } } : {})
}
: {
...commonParams,
stream: false
}
const timeout = this.getTimeout(model)
return { payload: sdkParams, messages: reqMessages, metadata: { timeout } }
return { payload: commonParams, messages: reqMessages, metadata: { timeout } }
}
}
}

View File

@ -7,7 +7,7 @@ import {
isSupportedReasoningEffortOpenAIModel,
isVisionModel
} from '@renderer/config/models'
import { isSupportDeveloperRoleProvider } from '@renderer/config/providers'
import { isSupportDeveloperRoleProvider, isSupportStreamOptionsProvider } from '@renderer/config/providers'
import { estimateTextTokens } from '@renderer/services/TokenService'
import {
FileMetadata,
@ -441,6 +441,9 @@ export class OpenAIResponseAPIClient extends OpenAIBaseClient<
}
tools = tools.concat(extraTools)
const shouldIncludeStreamOptions = streamOutput && isSupportStreamOptionsProvider(this.provider)
const commonParams: OpenAIResponseSdkParams = {
model: model.id,
input:
@ -451,24 +454,17 @@ export class OpenAIResponseAPIClient extends OpenAIBaseClient<
top_p: this.getTopP(assistant, model),
max_output_tokens: maxTokens,
stream: streamOutput,
...(shouldIncludeStreamOptions ? { stream_options: { include_usage: true } } : {}),
tools: !isEmpty(tools) ? tools : undefined,
// groq 有不同的 service tier 配置,不符合 openai 接口类型
service_tier: this.getServiceTier(model) as OpenAIServiceTier,
...(this.getReasoningEffort(assistant, model) as OpenAI.Reasoning),
// 只在对话场景下应用自定义参数,避免影响翻译、总结等其他业务逻辑
// 注意:用户自定义参数总是应该覆盖其他参数
...(coreRequest.callType === 'chat' ? this.getCustomParameters(assistant) : {})
}
const sdkParams: OpenAIResponseSdkParams = streamOutput
? {
...commonParams,
stream: true
}
: {
...commonParams,
stream: false
}
const timeout = this.getTimeout(model)
return { payload: sdkParams, messages: reqMessages, metadata: { timeout } }
return { payload: commonParams, messages: reqMessages, metadata: { timeout } }
}
}
}