模型支持协议扩展参数,用于关闭思考模式
DeepSeek 现役的 v4 系列全部默认开启思考模式,没有单独的非思考型模型
可换;官方给的关闭方式是在请求里带 thinking={"type":"disabled"}。
ai_models 表早有 extra_json 字段但从未接线,这里接通:模型配置里的
JSON 对象会合并进每次调用的请求体,因此任何协议级参数都能在管理端
配置,不必改代码。合并不会覆盖 model/messages/max_tokens/temperature/
stream —— 预算和结构由代码掌握,重试逻辑才不会被配置绕过。
写入前校验 JSON,避免非法值存进 JSON 列后每次调用才报错。
线上模型已配置为关闭思考:同一会话下由 10133 ms / 1024 输出 tokens、
回复被截断,变为 669 ms / 10 tokens、回复完整。max_tokens 相应回调至 512。
管理端模型表单新增「协议参数」输入框(该目录尚未纳入版本库,仅已发布)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
812d8032e1
commit
151834caac
@@ -320,3 +320,51 @@ func TestTruncatedAnswerIsRetriedAndKeptIfItSurvives(t *testing.T) {
|
||||
t.Fatalf("text = %q", result.Text)
|
||||
}
|
||||
}
|
||||
|
||||
// A model that reasons by default is told not to through its stored protocol
|
||||
// fields, without a code change and without a second model row.
|
||||
func TestModelExtraFieldsReachTheProviderWithoutOverridingTheCall(t *testing.T) {
|
||||
server, body, _ := captureAIRequest(t, `{"id":"c","choices":[{"message":{"content":"在的"},"finish_reason":"stop"}],"usage":{}}`, 200)
|
||||
model := testModel("openai", server.URL)
|
||||
model.Extra = map[string]any{
|
||||
"thinking": map[string]any{"type": "disabled"},
|
||||
// Structural fields and the budget stay under this code's control.
|
||||
"model": "someone-elses-model",
|
||||
"max_tokens": 999999,
|
||||
"stream": true,
|
||||
}
|
||||
provider, err := newAIProvider(model, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = provider.Chat(context.Background(), aiChatRequest{Messages: []aiChatMessage{{Role: "user", Text: "在吗"}}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
thinking, ok := (*body)["thinking"].(map[string]any)
|
||||
if !ok || thinking["type"] != "disabled" {
|
||||
t.Fatalf("thinking = %v", (*body)["thinking"])
|
||||
}
|
||||
if (*body)["model"] != "demo-model" || (*body)["max_tokens"] != float64(128) || (*body)["stream"] != false {
|
||||
t.Fatalf("扩展参数不得覆盖调用本身: %v", *body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAIModelExtraIsValidatedBeforeItIsStored(t *testing.T) {
|
||||
keep := "{\"thinking\":{\"type\":\"disabled\"}}"
|
||||
value, err := aiModelExtra(&keep, nil)
|
||||
if err != nil || value != keep {
|
||||
t.Fatalf("value = %v err = %v", value, err)
|
||||
}
|
||||
blank := " "
|
||||
if value, err = aiModelExtra(&blank, "old"); err != nil || value != nil {
|
||||
t.Fatalf("留空应清除扩展参数: %v %v", value, err)
|
||||
}
|
||||
broken := "{not json"
|
||||
if _, err = aiModelExtra(&broken, nil); err == nil {
|
||||
t.Fatal("非法 JSON 必须在写库前被拒绝")
|
||||
}
|
||||
// Omitted entirely: the stored value survives an edit that does not mention it.
|
||||
if value, err = aiModelExtra(nil, "old"); err != nil || value != "old" {
|
||||
t.Fatalf("value = %v err = %v", value, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user