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.
```
This commit is contained in:
George·Dong
2026-02-14 22:40:46 +08:00
committed by GitHub
parent b0659bc149
commit e31029b0e9
7 changed files with 188 additions and 4 deletions

View File

@@ -2499,3 +2499,58 @@ describe('Fireworks provider model name normalization', () => {
expect(isInterleavedThinkingModel(createModel({ id: 'accounts/fireworks/models/kimi-k2p5' }))).toBe(true)
})
})
describe('Doubao Seed 2.0 Models', () => {
it('should identify doubao-seed-2-0-pro-260215 as thinking model', () => {
const model: Model = {
id: 'doubao-seed-2-0-pro-260215',
name: 'doubao-seed-2-0-pro',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isSupportedThinkingTokenDoubaoModel(model)).toBe(true)
expect(isDoubaoSeedAfter251015(model)).toBe(true)
expect(getThinkModelType(model)).toBe('doubao_after_251015')
})
it('should identify doubao-seed-2-0-lite-260215 as thinking model', () => {
const model: Model = {
id: 'doubao-seed-2-0-lite-260215',
name: 'doubao-seed-2-0-lite',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isSupportedThinkingTokenDoubaoModel(model)).toBe(true)
})
it('should support minimal, low, medium, high reasoning effort', () => {
const model: Model = {
id: 'doubao-seed-2-0-lite-260215',
name: 'doubao-seed-2-0-lite',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
const options = getModelSupportedReasoningEffortOptions(model)
expect(options).toEqual(['default', 'minimal', 'low', 'medium', 'high'])
})
it('should identify doubao-seed-2-0-code-preview-260215', () => {
const model: Model = {
id: 'doubao-seed-2-0-code-preview-260215',
name: 'doubao-seed-2-0-code-preview',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isDoubaoSeedAfter251015(model)).toBe(true)
})
it('should identify doubao-seed-2-0-mini-260215', () => {
const model: Model = {
id: 'doubao-seed-2-0-mini-260215',
name: 'doubao-seed-2-0-mini',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isDoubaoSeedAfter251015(model)).toBe(true)
})
})

View File

@@ -145,4 +145,56 @@ describe('isFunctionCallingModel', () => {
expect(isFunctionCallingModel(createModel({ id: 'deepseek-chat', provider: 'deepseek' }))).toBe(true)
expect(isFunctionCallingModel(createModel({ id: 'deepseek-coder', provider: 'deepseek' }))).toBe(true)
})
describe('Doubao Seed 2.0 Models', () => {
it('should identify doubao-seed-2-0-pro-260215 as function calling model', () => {
const model: Model = {
id: 'doubao-seed-2-0-pro-260215',
name: 'doubao-seed-2-0-pro',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isFunctionCallingModel(model)).toBe(true)
})
it('should identify doubao-seed-2-0-lite-260215 as function calling model', () => {
const model: Model = {
id: 'doubao-seed-2-0-lite-260215',
name: 'doubao-seed-2-0-lite',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isFunctionCallingModel(model)).toBe(true)
})
it('should identify doubao-seed-2-0-code-preview-260215 as function calling model', () => {
const model: Model = {
id: 'doubao-seed-2-0-code-preview-260215',
name: 'doubao-seed-2-0-code-preview',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isFunctionCallingModel(model)).toBe(true)
})
it('should identify doubao-seed-2-0-mini-260215 as function calling model', () => {
const model: Model = {
id: 'doubao-seed-2-0-mini-260215',
name: 'doubao-seed-2-0-mini',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isFunctionCallingModel(model)).toBe(true)
})
it('should identify doubao-seed-2.0 models by name when provider is doubao', () => {
const model: Model = {
id: 'custom-id',
name: 'doubao-seed-2.0-pro-260215',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isFunctionCallingModel(model)).toBe(true)
})
})
})

View File

@@ -320,3 +320,55 @@ describe('isVisionModel', () => {
})
})
})
describe('Doubao Seed 2.0 Models', () => {
it('should identify doubao-seed-2-0-pro-260215 as vision model', () => {
const model: Model = {
id: 'doubao-seed-2-0-pro-260215',
name: 'doubao-seed-2-0-pro',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isVisionModel(model)).toBe(true)
})
it('should identify doubao-seed-2-0-lite-260215 as vision model', () => {
const model: Model = {
id: 'doubao-seed-2-0-lite-260215',
name: 'doubao-seed-2-0-lite',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isVisionModel(model)).toBe(true)
})
it('should identify doubao-seed-2-0-code-preview-260215 as vision model', () => {
const model: Model = {
id: 'doubao-seed-2-0-code-preview-260215',
name: 'doubao-seed-2-0-code-preview',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isVisionModel(model)).toBe(true)
})
it('should identify doubao-seed-2-0-mini-260215 as vision model', () => {
const model: Model = {
id: 'doubao-seed-2-0-mini-260215',
name: 'doubao-seed-2-0-mini',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isVisionModel(model)).toBe(true)
})
it('should identify doubao-seed-2.0 models by provider and name', () => {
const model: Model = {
id: 'custom-id',
name: 'doubao-seed-2.0-pro-260215',
provider: 'doubao',
group: 'Doubao-Seed-2.0'
}
expect(isVisionModel(model)).toBe(true)
})
})

View File

@@ -948,6 +948,30 @@ export const SYSTEM_MODELS: Record<SystemProviderId | 'defaultModel', Model[]> =
provider: 'doubao',
name: 'Doubao-vision-lite-32k',
group: 'Doubao-vision-lite-32k'
},
{
id: 'doubao-seed-2-0-pro-260215',
provider: 'doubao',
name: 'Doubao-Seed-2.0-Pro',
group: 'Doubao-Seed-2.0'
},
{
id: 'doubao-seed-2-0-lite-260215',
provider: 'doubao',
name: 'Doubao-Seed-2.0-Lite',
group: 'Doubao-Seed-2.0'
},
{
id: 'doubao-seed-2-0-code-preview-260215',
provider: 'doubao',
name: 'Doubao-Seed-2.0-Code-Preview',
group: 'Doubao-Seed-2.0'
},
{
id: 'doubao-seed-2-0-mini-260215',
provider: 'doubao',
name: 'Doubao-Seed-2.0-Mini',
group: 'Doubao-Seed-2.0'
}
],
minimax: [

View File

@@ -467,7 +467,7 @@ export function isQwenAlwaysThinkModel(model?: Model): boolean {
// Doubao 支持思考模式的模型正则
export const DOUBAO_THINKING_MODEL_REGEX =
/doubao-(?:1[.-]5-thinking-vision-pro|1[.-]5-thinking-pro-m|seed-1[.-][68](?:-flash)?(?!-(?:thinking)(?:-|$))|seed-code(?:-preview)?(?:-\d+)?)(?:-[\w-]+)*/i
/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
// 支持 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
@@ -480,9 +480,8 @@ export function isDoubaoThinkingAutoModel(model: Model): boolean {
}
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
const pattern = /doubao-seed-1-6-(?:lite-)?251015|doubao-seed-2[.-]0/i
return pattern.test(model.id) || pattern.test(model.name)
}
export function isDoubaoSeed18Model(model: Model): boolean {

View File

@@ -27,6 +27,7 @@ export const FUNCTION_CALLING_MODELS = [
'gemini(?:-[\\w-]+)?', // 提前排除了gemini的嵌入模型
'grok-3(?:-[\\w-]+)?',
'doubao-seed-1[.-][68](?:-[\\w-]+)?',
'doubao-seed-2[.-]0(?:-[\\w-]+)?',
'doubao-seed-code(?:-[\\w-]+)?',
'kimi-k2(?:-[\\w-]+)?',
'ling-\\w+(?:-[\\w-]+)?',

View File

@@ -47,6 +47,7 @@ const visionAllowedModels = [
'kimi-latest',
'gemma-3(?:-[\\w-]+)',
'doubao-seed-1[.-][68](?:-[\\w-]+)?',
'doubao-seed-2[.-]0(?:-[\\w-]+)?',
'doubao-seed-code(?:-[\\w-]+)?',
'kimi-thinking-preview',
`gemma3(?:[-:\\w]+)?`,