mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-08 06:19:05 +08:00
fix: convert 'developer' role to 'system' for unsupported providers (#12325)
AI SDK v5 uses 'developer' role for reasoning models, but some providers like Azure DeepSeek R1 only support 'system', 'user', 'assistant', 'tool' roles, causing HTTP 422 errors. This fix adds a custom fetch wrapper that converts 'developer' role back to 'system' for providers that don't support it. Fixes #12321 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
116ee6f94b
commit
6b0bb64795
@ -1,5 +1,5 @@
|
||||
import { formatPrivateKey, hasProviderConfig, ProviderConfigFactory } from '@cherrystudio/ai-core/provider'
|
||||
import { isOpenAIChatCompletionOnlyModel } from '@renderer/config/models'
|
||||
import { isOpenAIChatCompletionOnlyModel, isOpenAIReasoningModel } from '@renderer/config/models'
|
||||
import {
|
||||
getAwsBedrockAccessKeyId,
|
||||
getAwsBedrockApiKey,
|
||||
@ -29,6 +29,7 @@ import {
|
||||
isNewApiProvider,
|
||||
isOllamaProvider,
|
||||
isPerplexityProvider,
|
||||
isSupportDeveloperRoleProvider,
|
||||
isSupportStreamOptionsProvider,
|
||||
isVertexProvider
|
||||
} from '@renderer/utils/provider'
|
||||
@ -264,6 +265,14 @@ export function providerToAiSdkConfig(actualProvider: Provider, model: Model): A
|
||||
}
|
||||
}
|
||||
|
||||
// Apply developer-to-system role conversion for providers that don't support developer role
|
||||
// bug: https://github.com/vercel/ai/issues/10982
|
||||
// fixPR: https://github.com/vercel/ai/pull/11127
|
||||
// TODO: but the PR don't backport to v5, the code will be removed when upgrading to v6
|
||||
if (!isSupportDeveloperRoleProvider(actualProvider) || !isOpenAIReasoningModel(model)) {
|
||||
extraOptions.fetch = createDeveloperToSystemFetch(extraOptions.fetch)
|
||||
}
|
||||
|
||||
if (hasProviderConfig(aiSdkProviderId) && aiSdkProviderId !== 'openai-compatible') {
|
||||
const options = ProviderConfigFactory.fromProvider(aiSdkProviderId, baseConfig, extraOptions)
|
||||
return {
|
||||
@ -302,6 +311,44 @@ export function isModernSdkSupported(provider: Provider): boolean {
|
||||
return hasProviderConfig(aiSdkProviderId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom fetch wrapper that converts 'developer' role to 'system' role in request body.
|
||||
* This is needed for providers that don't support the 'developer' role (e.g., Azure DeepSeek R1).
|
||||
*
|
||||
* @param originalFetch - Optional original fetch function to wrap
|
||||
* @returns A fetch function that transforms the request body
|
||||
*/
|
||||
function createDeveloperToSystemFetch(originalFetch?: typeof fetch): typeof fetch {
|
||||
const baseFetch = originalFetch ?? fetch
|
||||
return async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
let options = init
|
||||
if (options?.body && typeof options.body === 'string') {
|
||||
try {
|
||||
const body = JSON.parse(options.body)
|
||||
if (body.messages && Array.isArray(body.messages)) {
|
||||
let hasChanges = false
|
||||
body.messages = body.messages.map((msg: { role: string }) => {
|
||||
if (msg.role === 'developer') {
|
||||
hasChanges = true
|
||||
return { ...msg, role: 'system' }
|
||||
}
|
||||
return msg
|
||||
})
|
||||
if (hasChanges) {
|
||||
options = {
|
||||
...options,
|
||||
body: JSON.stringify(body)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// If parsing fails, just use original body
|
||||
}
|
||||
}
|
||||
return baseFetch(input, options)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 准备特殊provider的配置,主要用于异步处理的配置
|
||||
*/
|
||||
@ -360,5 +407,6 @@ export async function prepareSpecialProviderConfig(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user