mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-05 04:19:02 +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
This commit is contained in:
parent
b4810bb487
commit
06b1ae0cb8
@ -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
|
||||
|
||||
@ -89,6 +89,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