feat: revamp DeepSeek v4 model handling

- replace legacy DeepSeek ids with the new deepseek-v4 model family\n- move thinking control to request parameters and preserve assistant reasoning content\n- switch history split to IGNORE transcript injection and map upload auth failures to 401\n- update admin defaults, API docs, samples, and tests for the new model scheme
This commit is contained in:
CJACK
2026-04-26 00:02:14 +08:00
parent ed9efc5858
commit 131ca7d398
66 changed files with 949 additions and 697 deletions

View File

@@ -41,7 +41,7 @@ func (h *Handler) testSingleAccount(w http.ResponseWriter, r *http.Request) {
}
model, _ := req["model"].(string)
if model == "" {
model = "deepseek-chat"
model = "deepseek-v4-flash"
}
message, _ := req["message"].(string)
result := h.testAccount(r.Context(), acc, model, message)
@@ -53,7 +53,7 @@ func (h *Handler) testAllAccounts(w http.ResponseWriter, r *http.Request) {
_ = json.NewDecoder(r.Body).Decode(&req)
model, _ := req["model"].(string)
if model == "" {
model = "deepseek-chat"
model = "deepseek-v4-flash"
}
accounts := h.Store.Snapshot().Accounts
if len(accounts) == 0 {
@@ -211,7 +211,7 @@ func (h *Handler) testAPI(w http.ResponseWriter, r *http.Request) {
message, _ := req["message"].(string)
apiKey, _ := req["api_key"].(string)
if model == "" {
model = "deepseek-chat"
model = "deepseek-v4-flash"
}
if message == "" {
message = "你好"

View File

@@ -72,7 +72,7 @@ func TestTestAccount_BatchModeOnlyCreatesSession(t *testing.T) {
t.Fatal("expected test account")
}
result := h.testAccount(context.Background(), acc, "deepseek-chat", "")
result := h.testAccount(context.Background(), acc, "deepseek-v4-flash", "")
if ok, _ := result["success"].(bool); !ok {
t.Fatalf("expected success=true, got %#v", result)
@@ -177,7 +177,7 @@ func TestTestAccount_MessageModeUsesExpertModelTypeForExpertModel(t *testing.T)
t.Fatal("expected test account")
}
result := h.testAccount(context.Background(), acc, "deepseek-expert-chat", "hello")
result := h.testAccount(context.Background(), acc, "deepseek-v4-pro", "hello")
if ok, _ := result["success"].(bool); !ok {
t.Fatalf("expected success=true, got %#v", result)
@@ -200,7 +200,7 @@ func TestTestAccount_MessageModeUsesVisionModelTypeForVisionModel(t *testing.T)
t.Fatal("expected test account")
}
result := h.testAccount(context.Background(), acc, "deepseek-vision-chat", "hello")
result := h.testAccount(context.Background(), acc, "deepseek-v4-vision", "hello")
if ok, _ := result["success"].(bool); !ok {
t.Fatalf("expected success=true, got %#v", result)

View File

@@ -38,7 +38,7 @@ func TestGetChatHistoryAndUpdateSettings(t *testing.T) {
entry, err := historyStore.Start(chathistory.StartParams{
CallerID: "caller:test",
AccountID: "user@example.com",
Model: "deepseek-chat",
Model: "deepseek-v4-flash",
UserInput: "hello",
})
if err != nil {

View File

@@ -114,7 +114,7 @@ func prepareRawSampleCaptureRequest(store ConfigStore, req map[string]any) (map[
}
if model := strings.TrimSpace(fieldString(payload, "model")); model == "" {
payload["model"] = "deepseek-chat"
payload["model"] = "deepseek-v4-flash"
}
if _, ok := payload["stream"]; !ok {
payload["stream"] = true

View File

@@ -18,7 +18,7 @@ type stubOpenAIChatCaller struct{}
func (stubOpenAIChatCaller) ChatCompletions(w http.ResponseWriter, _ *http.Request) {
store := devcapture.Global()
session := store.Start("deepseek_completion", "https://chat.deepseek.com/api/v0/chat/completion", "acct-test", map[string]any{"model": "deepseek-chat"})
session := store.Start("deepseek_completion", "https://chat.deepseek.com/api/v0/chat/completion", "acct-test", map[string]any{"model": "deepseek-v4-flash"})
raw := io.NopCloser(strings.NewReader(
"data: {\"v\":\"hello [reference:1]\"}\n\n" +
"data: {\"v\":\"FINISHED\",\"p\":\"response/status\"}\n\n",
@@ -37,7 +37,7 @@ func (stubOpenAIChatCaller) ChatCompletions(w http.ResponseWriter, _ *http.Reque
type stubOpenAIChatCallerWithContinuations struct{}
func (stubOpenAIChatCallerWithContinuations) ChatCompletions(w http.ResponseWriter, _ *http.Request) {
recordCapturedResponse("deepseek_completion", "https://chat.deepseek.com/api/v0/chat/completion", http.StatusOK, map[string]any{"model": "deepseek-chat"}, "data: {\"v\":\"hello [reference:1]\"}\n\n"+"data: [DONE]\n\n")
recordCapturedResponse("deepseek_completion", "https://chat.deepseek.com/api/v0/chat/completion", http.StatusOK, map[string]any{"model": "deepseek-v4-flash"}, "data: {\"v\":\"hello [reference:1]\"}\n\n"+"data: [DONE]\n\n")
recordCapturedResponse("deepseek_continue", "https://chat.deepseek.com/api/v0/chat/continue", http.StatusOK, map[string]any{"chat_session_id": "session-1", "message_id": 2}, "data: {\"v\":\"continued\"}\n\n"+"data: [DONE]\n\n")
w.Header().Set("Content-Type", "text/event-stream")
@@ -73,7 +73,7 @@ func TestCaptureRawSampleWritesPersistentSample(t *testing.T) {
reqBody := `{
"sample_id":"My Sample 01",
"api_key":"local-key",
"model":"deepseek-chat",
"model":"deepseek-v4-flash",
"message":"广州天气",
"stream":true
}`
@@ -130,7 +130,7 @@ func TestCaptureRawSampleCombinesContinuationCaptures(t *testing.T) {
reqBody := `{
"sample_id":"My Sample 02",
"api_key":"local-key",
"model":"deepseek-chat",
"model":"deepseek-v4-flash",
"message":"广州天气",
"stream":true
}`
@@ -194,13 +194,13 @@ func TestCaptureRawSampleReturnsErrorWhenNoNewCaptureRecorded(t *testing.T) {
devcapture.Global().Clear()
defer devcapture.Global().Clear()
recordCapturedResponse("preexisting", "https://chat.deepseek.com/api/v0/chat/completion", http.StatusOK, map[string]any{"model": "deepseek-chat"}, "data: {\"v\":\"old\"}\n\n")
recordCapturedResponse("preexisting", "https://chat.deepseek.com/api/v0/chat/completion", http.StatusOK, map[string]any{"model": "deepseek-v4-flash"}, "data: {\"v\":\"old\"}\n\n")
h := &Handler{OpenAI: stubOpenAIChatCallerWithoutCapture{}}
reqBody := `{
"sample_id":"My Sample 03",
"api_key":"local-key",
"model":"deepseek-chat",
"model":"deepseek-v4-flash",
"message":"广州天气",
"stream":true
}`

View File

@@ -50,5 +50,5 @@ func settingsClaudeMapping(c config.Config) map[string]string {
if len(c.ClaudeModelMap) > 0 {
return c.ClaudeModelMap
}
return map[string]string{"fast": "deepseek-chat", "slow": "deepseek-reasoner"}
return map[string]string{"fast": "deepseek-v4-flash", "slow": "deepseek-v4-pro"}
}