Skip to content

Commit e31029b

Browse files
authored
feat: support doubao seed 2.0 models (#12929)
### What this PR does Before this PR: - No support for Doubao Seed 2.0 models or their function-calling capabilities. - https://console.volcengine.com/ark/region:ark+cn-beijing/model/detail?Id=doubao-seed-2-0-pro After this PR: - Adds support for Doubao Seed 2.0 models. - Adds function-calling、vision support for Doubao Seed 2.0 models. Fixes # ### Why we need it and why it was done in this way The following tradeoffs were made: - Implemented explicit support to enable new model features while maintaining existing model paths. The following alternatives were considered: - Delay model-specific support until a unified model interface is available. Links to places where the discussion took place: <!-- optional: slack, other GH issue, mailinglist, ... --> ### Breaking changes - None anticipated. ### Special notes for your reviewer - Verify integration and function-calling behavior with Doubao Seed 2.0 endpoints. ### Checklist - [ ] PR: The PR description is expressive enough and will help future contributors - [ ] Code: Write code that humans can understand and keep it simple - [ ] Refactor: Left the code cleaner than found - [ ] Upgrade: Impact on upgrade flows considered if required - [ ] Documentation: User-guide update considered Release note ```release-note Add support for Doubao Seed 2.0 models and their function-calling capabilities. ```
1 parent b0659bc commit e31029b

File tree

7 files changed

+188
-4
lines changed

7 files changed

+188
-4
lines changed

src/renderer/src/config/models/__tests__/reasoning.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,3 +2499,58 @@ describe('Fireworks provider model name normalization', () => {
24992499
expect(isInterleavedThinkingModel(createModel({ id: 'accounts/fireworks/models/kimi-k2p5' }))).toBe(true)
25002500
})
25012501
})
2502+
2503+
describe('Doubao Seed 2.0 Models', () => {
2504+
it('should identify doubao-seed-2-0-pro-260215 as thinking model', () => {
2505+
const model: Model = {
2506+
id: 'doubao-seed-2-0-pro-260215',
2507+
name: 'doubao-seed-2-0-pro',
2508+
provider: 'doubao',
2509+
group: 'Doubao-Seed-2.0'
2510+
}
2511+
expect(isSupportedThinkingTokenDoubaoModel(model)).toBe(true)
2512+
expect(isDoubaoSeedAfter251015(model)).toBe(true)
2513+
expect(getThinkModelType(model)).toBe('doubao_after_251015')
2514+
})
2515+
2516+
it('should identify doubao-seed-2-0-lite-260215 as thinking model', () => {
2517+
const model: Model = {
2518+
id: 'doubao-seed-2-0-lite-260215',
2519+
name: 'doubao-seed-2-0-lite',
2520+
provider: 'doubao',
2521+
group: 'Doubao-Seed-2.0'
2522+
}
2523+
expect(isSupportedThinkingTokenDoubaoModel(model)).toBe(true)
2524+
})
2525+
2526+
it('should support minimal, low, medium, high reasoning effort', () => {
2527+
const model: Model = {
2528+
id: 'doubao-seed-2-0-lite-260215',
2529+
name: 'doubao-seed-2-0-lite',
2530+
provider: 'doubao',
2531+
group: 'Doubao-Seed-2.0'
2532+
}
2533+
const options = getModelSupportedReasoningEffortOptions(model)
2534+
expect(options).toEqual(['default', 'minimal', 'low', 'medium', 'high'])
2535+
})
2536+
2537+
it('should identify doubao-seed-2-0-code-preview-260215', () => {
2538+
const model: Model = {
2539+
id: 'doubao-seed-2-0-code-preview-260215',
2540+
name: 'doubao-seed-2-0-code-preview',
2541+
provider: 'doubao',
2542+
group: 'Doubao-Seed-2.0'
2543+
}
2544+
expect(isDoubaoSeedAfter251015(model)).toBe(true)
2545+
})
2546+
2547+
it('should identify doubao-seed-2-0-mini-260215', () => {
2548+
const model: Model = {
2549+
id: 'doubao-seed-2-0-mini-260215',
2550+
name: 'doubao-seed-2-0-mini',
2551+
provider: 'doubao',
2552+
group: 'Doubao-Seed-2.0'
2553+
}
2554+
expect(isDoubaoSeedAfter251015(model)).toBe(true)
2555+
})
2556+
})

src/renderer/src/config/models/__tests__/tooluse.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,56 @@ describe('isFunctionCallingModel', () => {
145145
expect(isFunctionCallingModel(createModel({ id: 'deepseek-chat', provider: 'deepseek' }))).toBe(true)
146146
expect(isFunctionCallingModel(createModel({ id: 'deepseek-coder', provider: 'deepseek' }))).toBe(true)
147147
})
148+
149+
describe('Doubao Seed 2.0 Models', () => {
150+
it('should identify doubao-seed-2-0-pro-260215 as function calling model', () => {
151+
const model: Model = {
152+
id: 'doubao-seed-2-0-pro-260215',
153+
name: 'doubao-seed-2-0-pro',
154+
provider: 'doubao',
155+
group: 'Doubao-Seed-2.0'
156+
}
157+
expect(isFunctionCallingModel(model)).toBe(true)
158+
})
159+
160+
it('should identify doubao-seed-2-0-lite-260215 as function calling model', () => {
161+
const model: Model = {
162+
id: 'doubao-seed-2-0-lite-260215',
163+
name: 'doubao-seed-2-0-lite',
164+
provider: 'doubao',
165+
group: 'Doubao-Seed-2.0'
166+
}
167+
expect(isFunctionCallingModel(model)).toBe(true)
168+
})
169+
170+
it('should identify doubao-seed-2-0-code-preview-260215 as function calling model', () => {
171+
const model: Model = {
172+
id: 'doubao-seed-2-0-code-preview-260215',
173+
name: 'doubao-seed-2-0-code-preview',
174+
provider: 'doubao',
175+
group: 'Doubao-Seed-2.0'
176+
}
177+
expect(isFunctionCallingModel(model)).toBe(true)
178+
})
179+
180+
it('should identify doubao-seed-2-0-mini-260215 as function calling model', () => {
181+
const model: Model = {
182+
id: 'doubao-seed-2-0-mini-260215',
183+
name: 'doubao-seed-2-0-mini',
184+
provider: 'doubao',
185+
group: 'Doubao-Seed-2.0'
186+
}
187+
expect(isFunctionCallingModel(model)).toBe(true)
188+
})
189+
190+
it('should identify doubao-seed-2.0 models by name when provider is doubao', () => {
191+
const model: Model = {
192+
id: 'custom-id',
193+
name: 'doubao-seed-2.0-pro-260215',
194+
provider: 'doubao',
195+
group: 'Doubao-Seed-2.0'
196+
}
197+
expect(isFunctionCallingModel(model)).toBe(true)
198+
})
199+
})
148200
})

src/renderer/src/config/models/__tests__/vision.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,3 +320,55 @@ describe('isVisionModel', () => {
320320
})
321321
})
322322
})
323+
324+
describe('Doubao Seed 2.0 Models', () => {
325+
it('should identify doubao-seed-2-0-pro-260215 as vision model', () => {
326+
const model: Model = {
327+
id: 'doubao-seed-2-0-pro-260215',
328+
name: 'doubao-seed-2-0-pro',
329+
provider: 'doubao',
330+
group: 'Doubao-Seed-2.0'
331+
}
332+
expect(isVisionModel(model)).toBe(true)
333+
})
334+
335+
it('should identify doubao-seed-2-0-lite-260215 as vision model', () => {
336+
const model: Model = {
337+
id: 'doubao-seed-2-0-lite-260215',
338+
name: 'doubao-seed-2-0-lite',
339+
provider: 'doubao',
340+
group: 'Doubao-Seed-2.0'
341+
}
342+
expect(isVisionModel(model)).toBe(true)
343+
})
344+
345+
it('should identify doubao-seed-2-0-code-preview-260215 as vision model', () => {
346+
const model: Model = {
347+
id: 'doubao-seed-2-0-code-preview-260215',
348+
name: 'doubao-seed-2-0-code-preview',
349+
provider: 'doubao',
350+
group: 'Doubao-Seed-2.0'
351+
}
352+
expect(isVisionModel(model)).toBe(true)
353+
})
354+
355+
it('should identify doubao-seed-2-0-mini-260215 as vision model', () => {
356+
const model: Model = {
357+
id: 'doubao-seed-2-0-mini-260215',
358+
name: 'doubao-seed-2-0-mini',
359+
provider: 'doubao',
360+
group: 'Doubao-Seed-2.0'
361+
}
362+
expect(isVisionModel(model)).toBe(true)
363+
})
364+
365+
it('should identify doubao-seed-2.0 models by provider and name', () => {
366+
const model: Model = {
367+
id: 'custom-id',
368+
name: 'doubao-seed-2.0-pro-260215',
369+
provider: 'doubao',
370+
group: 'Doubao-Seed-2.0'
371+
}
372+
expect(isVisionModel(model)).toBe(true)
373+
})
374+
})

src/renderer/src/config/models/default.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,30 @@ export const SYSTEM_MODELS: Record<SystemProviderId | 'defaultModel', Model[]> =
948948
provider: 'doubao',
949949
name: 'Doubao-vision-lite-32k',
950950
group: 'Doubao-vision-lite-32k'
951+
},
952+
{
953+
id: 'doubao-seed-2-0-pro-260215',
954+
provider: 'doubao',
955+
name: 'Doubao-Seed-2.0-Pro',
956+
group: 'Doubao-Seed-2.0'
957+
},
958+
{
959+
id: 'doubao-seed-2-0-lite-260215',
960+
provider: 'doubao',
961+
name: 'Doubao-Seed-2.0-Lite',
962+
group: 'Doubao-Seed-2.0'
963+
},
964+
{
965+
id: 'doubao-seed-2-0-code-preview-260215',
966+
provider: 'doubao',
967+
name: 'Doubao-Seed-2.0-Code-Preview',
968+
group: 'Doubao-Seed-2.0'
969+
},
970+
{
971+
id: 'doubao-seed-2-0-mini-260215',
972+
provider: 'doubao',
973+
name: 'Doubao-Seed-2.0-Mini',
974+
group: 'Doubao-Seed-2.0'
951975
}
952976
],
953977
minimax: [

src/renderer/src/config/models/reasoning.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ export function isQwenAlwaysThinkModel(model?: Model): boolean {
467467

468468
// Doubao 支持思考模式的模型正则
469469
export const DOUBAO_THINKING_MODEL_REGEX =
470-
/doubao-(?:1[.-]5-thinking-vision-pro|1[.-]5-thinking-pro-m|seed-1[.-][68](?:-flash)?(?!-(?:thinking)(?:-|$))|seed-code(?:-preview)?(?:-\d+)?)(?:-[\w-]+)*/i
470+
/doubao-(?:1[.-]5-thinking-vision-pro|1[.-]5-thinking-pro-m|seed-1[.-][68](?:-flash)?(?!-(?:thinking)(?:-|$))|seed-code(?:-preview)?(?:-\d+)?|seed-2[.-]0(?:-[\w-]+)?)(?:-[\w-]+)*/i
471471

472472
// 支持 auto 的 Doubao 模型 doubao-seed-1.6-xxx doubao-seed-1-6-xxx doubao-1-5-thinking-pro-m-xxx
473473
// 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
@@ -480,9 +480,8 @@ export function isDoubaoThinkingAutoModel(model: Model): boolean {
480480
}
481481

482482
export function isDoubaoSeedAfter251015(model: Model): boolean {
483-
const pattern = new RegExp(/doubao-seed-1-6-(?:lite-)?251015/i)
484-
const result = pattern.test(model.id)
485-
return result
483+
const pattern = /doubao-seed-1-6-(?:lite-)?251015|doubao-seed-2[.-]0/i
484+
return pattern.test(model.id) || pattern.test(model.name)
486485
}
487486

488487
export function isDoubaoSeed18Model(model: Model): boolean {

src/renderer/src/config/models/tooluse.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const FUNCTION_CALLING_MODELS = [
2727
'gemini(?:-[\\w-]+)?', // 提前排除了gemini的嵌入模型
2828
'grok-3(?:-[\\w-]+)?',
2929
'doubao-seed-1[.-][68](?:-[\\w-]+)?',
30+
'doubao-seed-2[.-]0(?:-[\\w-]+)?',
3031
'doubao-seed-code(?:-[\\w-]+)?',
3132
'kimi-k2(?:-[\\w-]+)?',
3233
'ling-\\w+(?:-[\\w-]+)?',

src/renderer/src/config/models/vision.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const visionAllowedModels = [
4747
'kimi-latest',
4848
'gemma-3(?:-[\\w-]+)',
4949
'doubao-seed-1[.-][68](?:-[\\w-]+)?',
50+
'doubao-seed-2[.-]0(?:-[\\w-]+)?',
5051
'doubao-seed-code(?:-[\\w-]+)?',
5152
'kimi-thinking-preview',
5253
`gemma3(?:[-:\\w]+)?`,

0 commit comments

Comments
 (0)