mirror of
https://git.openapi.site/https://github.com/desirecore/config-center.git
synced 2026-10-21 06:24:14 +08:00
feat(compute): 官方 Anthropic 模型声明接受不含 thinking 的工具轮 (#99)
新增 extra.thinkingToolTurnValidation(requires-thinking / accepts-thinkless),与 thinkingRoundTrip 并列(后者 additionalProperties:false,不能往里加字段)。 anthropic.json 与 anthropic-claude.json 的 Fable 5.1 / Opus 5 / Sonnet 5 声明 accepts-thinkless:官方 adaptive thinking 不要求工具轮以 thinking 开头,模型跳过思考的 工具轮原样回放即合法(mini 真机六轮验证全部 200)。客户端据此不再对这类响应重试、 不再降级为关闭思考。旧客户端忽略该字段,行为不变。 model-spec schema 的 spec.extra 同步禁止 thinkingRoundTrip 与 thinkingToolTurnValidation, 与客户端 Schema 一致,避免写错后新客户端整份拒收规格。 presetDataVersion 113 → 114。
This commit is contained in:
@@ -777,6 +777,28 @@ describe('provider schema 反例(防 PR #1 重演)', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('校验 Provider model 的工具轮 thinking 校验口径', () => {
|
||||||
|
for (const value of ['requires-thinking', 'accepts-thinkless']) {
|
||||||
|
const valid = makeValidProvider()
|
||||||
|
valid.models[0].extra = {
|
||||||
|
thinkingRoundTrip: {
|
||||||
|
enabled: true,
|
||||||
|
protocol: 'anthropic-messages',
|
||||||
|
allowEmptySignature: false,
|
||||||
|
scope: 'active-tool-turn',
|
||||||
|
},
|
||||||
|
thinkingToolTurnValidation: value,
|
||||||
|
}
|
||||||
|
assert.equal(validate(valid), true, JSON.stringify(validate.errors))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const broken of ['accept', true, null]) {
|
||||||
|
const invalid = makeValidProvider()
|
||||||
|
invalid.models[0].extra = { thinkingToolTurnValidation: broken }
|
||||||
|
assert.equal(validate(invalid), false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('拒绝 Ultra 与重复 reasoning effort', () => {
|
it('拒绝 Ultra 与重复 reasoning effort', () => {
|
||||||
const ultra = makeValidProvider()
|
const ultra = makeValidProvider()
|
||||||
ultra.models[0].extra = {
|
ultra.models[0].extra = {
|
||||||
@@ -868,6 +890,22 @@ describe('model-spec schema 接入面边界', () => {
|
|||||||
assert.equal(validate(data), false)
|
assert.equal(validate(data), false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('拒绝在模型内在规格中声明接入面的 thinking 回放能力与工具轮校验口径', () => {
|
||||||
|
for (const extra of [
|
||||||
|
{
|
||||||
|
thinkingRoundTrip: {
|
||||||
|
enabled: true,
|
||||||
|
protocol: 'anthropic-messages',
|
||||||
|
allowEmptySignature: false,
|
||||||
|
scope: 'active-tool-turn',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ thinkingToolTurnValidation: 'accepts-thinkless' },
|
||||||
|
]) {
|
||||||
|
assert.equal(validate({ specs: [{ id: 'claude-test', spec: { extra } }] }), false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('仍允许模型内在扩展参数', () => {
|
it('仍允许模型内在扩展参数', () => {
|
||||||
const data = {
|
const data = {
|
||||||
specs: [{ id: 'gpt-test', spec: { extra: { intrinsicBudgetHint: 8192 } } }],
|
specs: [{ id: 'gpt-test', spec: { extra: { intrinsicBudgetHint: 8192 } } }],
|
||||||
|
|||||||
@@ -62,7 +62,8 @@
|
|||||||
"protocol": "anthropic-messages",
|
"protocol": "anthropic-messages",
|
||||||
"allowEmptySignature": false,
|
"allowEmptySignature": false,
|
||||||
"scope": "active-tool-turn"
|
"scope": "active-tool-turn"
|
||||||
}
|
},
|
||||||
|
"thinkingToolTurnValidation": "accepts-thinkless"
|
||||||
},
|
},
|
||||||
"source": "preset"
|
"source": "preset"
|
||||||
},
|
},
|
||||||
@@ -102,7 +103,8 @@
|
|||||||
"protocol": "anthropic-messages",
|
"protocol": "anthropic-messages",
|
||||||
"allowEmptySignature": false,
|
"allowEmptySignature": false,
|
||||||
"scope": "active-tool-turn"
|
"scope": "active-tool-turn"
|
||||||
}
|
},
|
||||||
|
"thinkingToolTurnValidation": "accepts-thinkless"
|
||||||
},
|
},
|
||||||
"source": "preset"
|
"source": "preset"
|
||||||
},
|
},
|
||||||
@@ -141,7 +143,8 @@
|
|||||||
"protocol": "anthropic-messages",
|
"protocol": "anthropic-messages",
|
||||||
"allowEmptySignature": false,
|
"allowEmptySignature": false,
|
||||||
"scope": "active-tool-turn"
|
"scope": "active-tool-turn"
|
||||||
}
|
},
|
||||||
|
"thinkingToolTurnValidation": "accepts-thinkless"
|
||||||
},
|
},
|
||||||
"source": "preset"
|
"source": "preset"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"allowEmptySignature": false,
|
"allowEmptySignature": false,
|
||||||
"scope": "active-tool-turn"
|
"scope": "active-tool-turn"
|
||||||
},
|
},
|
||||||
|
"thinkingToolTurnValidation": "accepts-thinkless",
|
||||||
"serverSideWebSearch": {
|
"serverSideWebSearch": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"dialect": "anthropic-messages",
|
"dialect": "anthropic-messages",
|
||||||
@@ -97,6 +98,7 @@
|
|||||||
"allowEmptySignature": false,
|
"allowEmptySignature": false,
|
||||||
"scope": "active-tool-turn"
|
"scope": "active-tool-turn"
|
||||||
},
|
},
|
||||||
|
"thinkingToolTurnValidation": "accepts-thinkless",
|
||||||
"serverSideWebSearch": {
|
"serverSideWebSearch": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"dialect": "anthropic-messages",
|
"dialect": "anthropic-messages",
|
||||||
@@ -156,6 +158,7 @@
|
|||||||
"allowEmptySignature": false,
|
"allowEmptySignature": false,
|
||||||
"scope": "active-tool-turn"
|
"scope": "active-tool-turn"
|
||||||
},
|
},
|
||||||
|
"thinkingToolTurnValidation": "accepts-thinkless",
|
||||||
"serverSideWebSearch": {
|
"serverSideWebSearch": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"dialect": "anthropic-messages",
|
"dialect": "anthropic-messages",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"presetDataVersion": 113,
|
"presetDataVersion": 114,
|
||||||
"updatedAt": "2026-09-13",
|
"updatedAt": "2026-09-13",
|
||||||
"description": "DesireCore 官方配置中心"
|
"description": "DesireCore 官方配置中心"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,8 +259,12 @@
|
|||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "模型内在开放扩展:modelOrigin 描述真实原厂身份,speech 描述可跨小版本复用的语音协议;不含价格,也不得声明 Provider/接入面的 reasoning effort 能力。",
|
"description": "模型内在开放扩展:modelOrigin 描述真实原厂身份,speech 描述可跨小版本复用的语音协议;不含价格,也不得声明 Provider/接入面的 reasoning effort、thinking 回放能力(thinkingRoundTrip)或工具轮 thinking 校验口径(thinkingToolTurnValidation)——这些只能写在 provider model 的 extra 中,客户端 Schema 会拒收整份规格。",
|
||||||
"not": { "required": ["reasoning"] },
|
"allOf": [
|
||||||
|
{ "not": { "required": ["reasoning"] } },
|
||||||
|
{ "not": { "required": ["thinkingRoundTrip"] } },
|
||||||
|
{ "not": { "required": ["thinkingToolTurnValidation"] } }
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"modelOrigin": { "$ref": "#/definitions/modelOrigin" },
|
"modelOrigin": { "$ref": "#/definitions/modelOrigin" },
|
||||||
"speech": { "$ref": "#/definitions/speechModelProfile" },
|
"speech": { "$ref": "#/definitions/speechModelProfile" },
|
||||||
|
|||||||
@@ -252,7 +252,7 @@
|
|||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "接入面特定配置:如 TTS 模型音色列表、ASR 支持格式、reasoning effort 与 native thinking 回放能力。这里是兼容扩展面:旧客户端会安全保留并忽略未知子字段。",
|
"description": "接入面特定配置:如 TTS 模型音色列表、ASR 支持格式、reasoning effort、native thinking 回放能力与工具轮 thinking 校验口径。这里是兼容扩展面:旧客户端会安全保留并忽略未知子字段。",
|
||||||
"properties": {
|
"properties": {
|
||||||
"thinkingRoundTrip": {
|
"thinkingRoundTrip": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -280,6 +280,11 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
"thinkingToolTurnValidation": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["requires-thinking", "accepts-thinkless"],
|
||||||
|
"description": "接入面对 thinking 工具轨迹中不含 thinking 的工具轮的校验口径,仅在同一模型声明了 thinkingRoundTrip 时生效;缺省视为 requires-thinking。requires-thinking:接入面要求每个工具轮都带可回放 thinking(例如只在首轮返回 thinking、之后会拒绝整条会话的兼容网关),客户端在执行工具前把这类响应判为上游失败并重试,同一会话再次违规时关闭思考。accepts-thinkless:接入面按 Anthropic adaptive thinking 规则校验,模型自行跳过思考的工具轮本身就是合法历史,客户端原样接受,不重试也不降级。只有官方文档或真机回放证明接受此类历史的接入面才能声明 accepts-thinkless;不得由 Provider 名称或 URL 推断。旧客户端忽略该字段并保持 requires-thinking 行为。"
|
||||||
|
},
|
||||||
"reasoning": {
|
"reasoning": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "当前 Provider 接入面接受哪些 reasoning effort 值——精确档位矩阵。只能写在 provider model 的 extra 里:同一模型经不同网关支持的集合可能不同,因此 model-spec 的 spec.extra 里写本键会被客户端 applySpec 主动丢弃。想表达「这个模型根本关不掉思考」的用 model-spec 的 spec.extra.thinkingOnly,那只回答 off 能否使用、不声明任何深度档位。",
|
"description": "当前 Provider 接入面接受哪些 reasoning effort 值——精确档位矩阵。只能写在 provider model 的 extra 里:同一模型经不同网关支持的集合可能不同,因此 model-spec 的 spec.extra 里写本键会被客户端 applySpec 主动丢弃。想表达「这个模型根本关不掉思考」的用 model-spec 的 spec.extra.thinkingOnly,那只回答 off 能否使用、不声明任何深度档位。",
|
||||||
|
|||||||
Reference in New Issue
Block a user