mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 04:31:27 +08:00
feat(models): add doubao_after_251015 reasoning model type and support (#10826)
* feat(models): add doubao_after_251015 model type and support
Add new model type 'doubao_after_251015' with reasoning effort levels and update regex patterns to handle version 251015 and later
* fix(sdk): add warning for reasoning_effort field and update reasoning logic
Add warning comment about reasoning_effort field being overwritten for openai-compatible providers
Update reasoning effort logic to handle Doubao seed models after 251015 and standardize field naming
* fix(reasoning): update Doubao model regex patterns and tests
Update regex patterns for Doubao model validation to correctly handle version constraints
Add comprehensive test cases for model validation functions
(cherry picked from commit 06b1ae0cb8)
This commit is contained in:
parent
0d86e16e28
commit
ab78ef71d9
@ -5,6 +5,7 @@ import {
|
||||
GEMINI_FLASH_MODEL_REGEX,
|
||||
getThinkModelType,
|
||||
isDeepSeekHybridInferenceModel,
|
||||
isDoubaoSeedAfter251015,
|
||||
isDoubaoThinkingAutoModel,
|
||||
isGrok4FastReasoningModel,
|
||||
isGrokReasoningModel,
|
||||
@ -170,6 +171,10 @@ export function getReasoningEffort(assistant: Assistant, model: Model): Reasonin
|
||||
|
||||
// Doubao 思考模式支持
|
||||
if (isSupportedThinkingTokenDoubaoModel(model)) {
|
||||
if (isDoubaoSeedAfter251015(model)) {
|
||||
return { reasoningEffort }
|
||||
}
|
||||
// Comment below this line seems weird. reasoning is high instead of null/undefined. Who wrote this?
|
||||
// reasoningEffort 为空,默认开启 enabled
|
||||
if (reasoningEffort === 'high') {
|
||||
return { thinking: { type: 'enabled' } }
|
||||
@ -226,12 +231,12 @@ export function getReasoningEffort(assistant: Assistant, model: Model): Reasonin
|
||||
const supportedOptions = MODEL_SUPPORTED_REASONING_EFFORT[modelType]
|
||||
if (supportedOptions.includes(reasoningEffort)) {
|
||||
return {
|
||||
reasoning_effort: reasoningEffort
|
||||
reasoningEffort
|
||||
}
|
||||
} else {
|
||||
// 如果不支持,fallback到第一个支持的值
|
||||
return {
|
||||
reasoning_effort: supportedOptions[0]
|
||||
reasoningEffort: supportedOptions[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
166
src/renderer/src/config/__test__/reasoning.test.ts
Normal file
166
src/renderer/src/config/__test__/reasoning.test.ts
Normal file
@ -0,0 +1,166 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { isDoubaoSeedAfter251015, isDoubaoThinkingAutoModel } from '../models/reasoning'
|
||||
|
||||
// FIXME: Idk why it's imported. Maybe circular dependency somewhere
|
||||
vi.mock('@renderer/services/AssistantService.ts', () => ({
|
||||
getDefaultAssistant: () => {
|
||||
return {
|
||||
id: 'default',
|
||||
name: 'default',
|
||||
emoji: '😀',
|
||||
prompt: '',
|
||||
topics: [],
|
||||
messages: [],
|
||||
type: 'assistant',
|
||||
regularPhrases: [],
|
||||
settings: {}
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
describe('Doubao Models', () => {
|
||||
describe('isDoubaoThinkingAutoModel', () => {
|
||||
it('should return false for invalid models', () => {
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-seed-1-6-251015',
|
||||
name: 'doubao-seed-1-6-251015',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-seed-1-6-lite-251015',
|
||||
name: 'doubao-seed-1-6-lite-251015',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-seed-1-6-thinking-250715',
|
||||
name: 'doubao-seed-1-6-thinking-250715',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-seed-1-6-flash',
|
||||
name: 'doubao-seed-1-6-flash',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-seed-1-6-thinking',
|
||||
name: 'doubao-seed-1-6-thinking',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('should return true for valid models', () => {
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-seed-1-6-250615',
|
||||
name: 'doubao-seed-1-6-250615',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'Doubao-Seed-1.6',
|
||||
name: 'Doubao-Seed-1.6',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-1-5-thinking-pro-m',
|
||||
name: 'doubao-1-5-thinking-pro-m',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-seed-1.6-lite',
|
||||
name: 'doubao-seed-1.6-lite',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
isDoubaoThinkingAutoModel({
|
||||
id: 'doubao-1-5-thinking-pro-m-12345',
|
||||
name: 'doubao-1-5-thinking-pro-m-12345',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('isDoubaoSeedAfter251015', () => {
|
||||
it('should return true for models matching the pattern', () => {
|
||||
expect(
|
||||
isDoubaoSeedAfter251015({
|
||||
id: 'doubao-seed-1-6-251015',
|
||||
name: '',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
isDoubaoSeedAfter251015({
|
||||
id: 'doubao-seed-1-6-lite-251015',
|
||||
name: '',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('should return false for models not matching the pattern', () => {
|
||||
expect(
|
||||
isDoubaoSeedAfter251015({
|
||||
id: 'doubao-seed-1-6-250615',
|
||||
name: '',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isDoubaoSeedAfter251015({
|
||||
id: 'Doubao-Seed-1.6',
|
||||
name: '',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isDoubaoSeedAfter251015({
|
||||
id: 'doubao-1-5-thinking-pro-m',
|
||||
name: '',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
isDoubaoSeedAfter251015({
|
||||
id: 'doubao-seed-1-6-lite-251016',
|
||||
name: '',
|
||||
provider: '',
|
||||
group: ''
|
||||
})
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -31,6 +31,7 @@ export const MODEL_SUPPORTED_REASONING_EFFORT: ReasoningEffortConfig = {
|
||||
qwen_thinking: ['low', 'medium', 'high'] as const,
|
||||
doubao: ['auto', 'high'] as const,
|
||||
doubao_no_auto: ['high'] as const,
|
||||
doubao_after_251015: ['minimal', 'low', 'medium', 'high'] as const,
|
||||
hunyuan: ['auto'] as const,
|
||||
zhipu: ['auto'] as const,
|
||||
perplexity: ['low', 'medium', 'high'] as const,
|
||||
@ -51,6 +52,7 @@ export const MODEL_SUPPORTED_OPTIONS: ThinkingOptionConfig = {
|
||||
qwen_thinking: MODEL_SUPPORTED_REASONING_EFFORT.qwen_thinking,
|
||||
doubao: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.doubao] as const,
|
||||
doubao_no_auto: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.doubao_no_auto] as const,
|
||||
doubao_after_251015: MODEL_SUPPORTED_REASONING_EFFORT.doubao_after_251015,
|
||||
hunyuan: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.hunyuan] as const,
|
||||
zhipu: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.zhipu] as const,
|
||||
perplexity: MODEL_SUPPORTED_REASONING_EFFORT.perplexity,
|
||||
@ -85,6 +87,8 @@ export const getThinkModelType = (model: Model): ThinkingModelType => {
|
||||
} else if (isSupportedThinkingTokenDoubaoModel(model)) {
|
||||
if (isDoubaoThinkingAutoModel(model)) {
|
||||
thinkingModelType = 'doubao'
|
||||
} else if (isDoubaoSeedAfter251015(model)) {
|
||||
thinkingModelType = 'doubao_after_251015'
|
||||
} else {
|
||||
thinkingModelType = 'doubao_no_auto'
|
||||
}
|
||||
@ -308,14 +312,21 @@ export const DOUBAO_THINKING_MODEL_REGEX =
|
||||
/doubao-(?:1[.-]5-thinking-vision-pro|1[.-]5-thinking-pro-m|seed-1[.-]6(?:-flash)?(?!-(?:thinking)(?:-|$)))(?:-[\w-]+)*/i
|
||||
|
||||
// 支持 auto 的 Doubao 模型 doubao-seed-1.6-xxx doubao-seed-1-6-xxx doubao-1-5-thinking-pro-m-xxx
|
||||
// Auto thinking is no longer supported after version 251015, see https://console.volcengine.com/ark/region:ark+cn-beijing/model/detail?Id=doubao-seed-1-6
|
||||
export const DOUBAO_THINKING_AUTO_MODEL_REGEX =
|
||||
/doubao-(1-5-thinking-pro-m|seed-1[.-]6)(?!-(?:flash|thinking)(?:-|$))(?:-[\w-]+)*/i
|
||||
/doubao-(1-5-thinking-pro-m|seed-1[.-]6)(?!-(?:flash|thinking)(?:-|$))(?:-lite)?(?!-251015)(?:-\d+)?$/i
|
||||
|
||||
export function isDoubaoThinkingAutoModel(model: Model): boolean {
|
||||
const modelId = getLowerBaseModelName(model.id)
|
||||
return DOUBAO_THINKING_AUTO_MODEL_REGEX.test(modelId) || DOUBAO_THINKING_AUTO_MODEL_REGEX.test(model.name)
|
||||
}
|
||||
|
||||
export function isDoubaoSeedAfter251015(model: Model): boolean {
|
||||
const pattern = new RegExp(/doubao-seed-1-6-(?:lite-)?251015/i)
|
||||
const result = pattern.test(model.id)
|
||||
return result
|
||||
}
|
||||
|
||||
export function isSupportedThinkingTokenDoubaoModel(model?: Model): boolean {
|
||||
if (!model) {
|
||||
return false
|
||||
|
||||
@ -85,6 +85,7 @@ const ThinkModelTypes = [
|
||||
'qwen_thinking',
|
||||
'doubao',
|
||||
'doubao_no_auto',
|
||||
'doubao_after_251015',
|
||||
'hunyuan',
|
||||
'zhipu',
|
||||
'perplexity',
|
||||
|
||||
@ -78,6 +78,7 @@ export type ReasoningEffortOptionalParams = {
|
||||
thinking?: { type: 'disabled' | 'enabled' | 'auto'; budget_tokens?: number }
|
||||
reasoning?: { max_tokens?: number; exclude?: boolean; effort?: string; enabled?: boolean } | OpenAI.Reasoning
|
||||
reasoningEffort?: OpenAI.Chat.Completions.ChatCompletionCreateParams['reasoning_effort'] | 'none' | 'auto'
|
||||
// WARN: This field will be overwrite to undefined by aisdk if the provider is openai-compatible. Use reasoningEffort instead.
|
||||
reasoning_effort?: OpenAI.Chat.Completions.ChatCompletionCreateParams['reasoning_effort'] | 'none' | 'auto'
|
||||
enable_thinking?: boolean
|
||||
thinking_budget?: number
|
||||
|
||||
Loading…
Reference in New Issue
Block a user