From 6688e0ba35000c9c783f0ef6a36c521286573a03 Mon Sep 17 00:00:00 2001 From: CJACK Date: Sun, 19 Apr 2026 17:47:45 +0800 Subject: [PATCH] refactor: remove unnecessary whitespace and end-of-sentence markers to align with official DeepSeek chat template encoding --- internal/prompt/messages.go | 10 ++++++---- internal/prompt/messages_test.go | 8 ++++---- internal/util/messages_test.go | 12 ++++++------ internal/util/util_edge_test.go | 12 +++++++----- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/internal/prompt/messages.go b/internal/prompt/messages.go index 91a3b84..bb563dd 100644 --- a/internal/prompt/messages.go +++ b/internal/prompt/messages.go @@ -65,7 +65,7 @@ func MessagesPrepareWithThinking(messages []map[string]any, thinkingEnabled bool parts = append(parts, formatRoleBlock(systemMarker, text, endInstructionsMarker)) } case "user": - parts = append(parts, formatRoleBlock(userMarker, m.Text, endSentenceMarker)) + parts = append(parts, formatRoleBlock(userMarker, m.Text, "")) default: if strings.TrimSpace(m.Text) != "" { parts = append(parts, m.Text) @@ -79,13 +79,15 @@ func MessagesPrepareWithThinking(messages []map[string]any, thinkingEnabled bool } parts = append(parts, assistantMarker+thinkPrefix) } - out := strings.Join(parts, "\n\n") + out := strings.Join(parts, "") return markdownImagePattern.ReplaceAllString(out, `[${1}](${2})`) } -// DeepSeek-style turn suffixes stay attached to the same block as the role content. +// formatRoleBlock produces a single concatenated block: marker + text + endMarker. +// No whitespace is inserted between marker and text to match the official +// DeepSeek V3.2 chat template encoding. func formatRoleBlock(marker, text, endMarker string) string { - out := marker + "\n" + text + out := marker + text if strings.TrimSpace(endMarker) != "" { out += endMarker } diff --git a/internal/prompt/messages_test.go b/internal/prompt/messages_test.go index a86f9db..b61c6a1 100644 --- a/internal/prompt/messages_test.go +++ b/internal/prompt/messages_test.go @@ -35,13 +35,13 @@ func TestMessagesPrepareUsesTurnSuffixes(t *testing.T) { if !strings.HasPrefix(got, "<|begin▁of▁sentence|>") { t.Fatalf("expected begin-of-sentence marker, got %q", got) } - if !strings.Contains(got, "<|System|>\nSystem rule<|end▁of▁instructions|>") { + if !strings.Contains(got, "<|System|>System rule<|end▁of▁instructions|>") { t.Fatalf("expected system instructions suffix, got %q", got) } - if !strings.Contains(got, "<|User|>\nQuestion<|end▁of▁sentence|>") { - t.Fatalf("expected user sentence suffix, got %q", got) + if !strings.Contains(got, "<|User|>Question") { + t.Fatalf("expected user question, got %q", got) } - if !strings.Contains(got, "<|Assistant|>\nAnswer<|end▁of▁sentence|>") { + if !strings.Contains(got, "<|Assistant|>Answer<|end▁of▁sentence|>") { t.Fatalf("expected assistant sentence suffix, got %q", got) } } diff --git a/internal/util/messages_test.go b/internal/util/messages_test.go index 9a09a26..092ff28 100644 --- a/internal/util/messages_test.go +++ b/internal/util/messages_test.go @@ -12,7 +12,7 @@ func TestMessagesPrepareBasic(t *testing.T) { if got == "" { t.Fatal("expected non-empty prompt") } - if got != "<|begin▁of▁sentence|>\n\n<|User|>\nHello<|end▁of▁sentence|>\n\n<|Assistant|>" { + if got != "<|begin▁of▁sentence|><|User|>Hello<|Assistant|>" { t.Fatalf("unexpected prompt: %q", got) } } @@ -26,19 +26,19 @@ func TestMessagesPrepareRoles(t *testing.T) { {"role": "user", "content": "How are you"}, } got := MessagesPrepare(messages) - if !contains(got, "<|System|>\nYou are helper<|end▁of▁instructions|>\n\n<|User|>\nHi<|end▁of▁sentence|>") { + if !contains(got, "<|System|>You are helper<|end▁of▁instructions|><|User|>Hi") { t.Fatalf("expected system/user separation in %q", got) } if !contains(got, "<|begin▁of▁sentence|>") { t.Fatalf("expected begin marker in %q", got) } - if !contains(got, "<|User|>\nHi<|end▁of▁sentence|>\n\n<|Assistant|>\nHello<|end▁of▁sentence|>") { + if !contains(got, "<|User|>Hi<|Assistant|>Hello<|end▁of▁sentence|>") { t.Fatalf("expected user/assistant separation in %q", got) } - if !contains(got, "<|Assistant|>\nHello<|end▁of▁sentence|>\n\n<|Tool|>\nSearch results<|end▁of▁toolresults|>") { + if !contains(got, "<|Assistant|>Hello<|end▁of▁sentence|><|Tool|>Search results<|end▁of▁toolresults|>") { t.Fatalf("expected assistant/tool separation in %q", got) } - if !contains(got, "<|Tool|>\nSearch results<|end▁of▁toolresults|>\n\n<|User|>\nHow are you<|end▁of▁sentence|>") { + if !contains(got, "<|Tool|>Search results<|end▁of▁toolresults|><|User|>How are you") { t.Fatalf("expected tool/user separation in %q", got) } if !contains(got, "<|Assistant|>") { @@ -77,7 +77,7 @@ func TestMessagesPrepareArrayTextVariants(t *testing.T) { }, } got := MessagesPrepare(messages) - if got != "<|begin▁of▁sentence|>\n\n<|User|>\nline1\nline2<|end▁of▁sentence|>\n\n<|Assistant|>" { + if got != "<|begin▁of▁sentence|><|User|>line1\nline2<|Assistant|>" { t.Fatalf("unexpected content from text variants: %q", got) } } diff --git a/internal/util/util_edge_test.go b/internal/util/util_edge_test.go index 4b0dda5..0d19679 100644 --- a/internal/util/util_edge_test.go +++ b/internal/util/util_edge_test.go @@ -173,8 +173,10 @@ func TestMessagesPrepareMergesConsecutiveSameRole(t *testing.T) { if count != 1 { t.Fatalf("expected one User marker for the merged pair, got %d occurrences", count) } - if count := strings.Count(got, "<|end▁of▁sentence|>"); count != 1 { - t.Fatalf("expected one sentence terminator for the merged pair, got %d occurrences", count) + // User messages no longer have end_of_sentence markers in the official format. + // The merged pair should have zero end_of_sentence markers (user turn only). + if count := strings.Count(got, "<|end▁of▁sentence|>"); count != 0 { + t.Fatalf("expected zero sentence terminators for user-only merge, got %d occurrences", count) } } @@ -190,10 +192,10 @@ func TestMessagesPrepareAssistantMarkers(t *testing.T) { if !strings.Contains(got, "<|end▁of▁sentence|>") { t.Fatalf("expected end of sentence marker, got %q", got) } - if strings.Count(got, "<|end▁of▁sentence|>") != 2 { - t.Fatalf("expected both turns to be terminated, got %q", got) + if strings.Count(got, "<|end▁of▁sentence|>") != 1 { + t.Fatalf("expected one end_of_sentence (assistant only), got %q", got) } - if !strings.Contains(got, "<|Assistant|>\nHello!<|end▁of▁sentence|>") { + if !strings.Contains(got, "<|Assistant|>Hello!<|end▁of▁sentence|>") { t.Fatalf("expected assistant EOS suffix, got %q", got) } if strings.Contains(got, "") {