refactor: remove unnecessary whitespace and end-of-sentence markers to align with official DeepSeek chat template encoding

This commit is contained in:
CJACK
2026-04-19 17:47:45 +08:00
parent c945f49fc4
commit 6688e0ba35
4 changed files with 23 additions and 19 deletions

View File

@@ -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
}

View File

@@ -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>\n</think>Answer<end▁of▁sentence>") {
if !strings.Contains(got, "<Assistant></think>Answer<end▁of▁sentence>") {
t.Fatalf("expected assistant sentence suffix, got %q", got)
}
}

View File

@@ -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></think>" {
if got != "<begin▁of▁sentence><User>Hello<Assistant></think>" {
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>\n</think>Hello<end▁of▁sentence>") {
if !contains(got, "<User>Hi<Assistant></think>Hello<end▁of▁sentence>") {
t.Fatalf("expected user/assistant separation in %q", got)
}
if !contains(got, "<Assistant>\n</think>Hello<end▁of▁sentence>\n\n<Tool>\nSearch results<end▁of▁toolresults>") {
if !contains(got, "<Assistant></think>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></think>" {
if got != "<begin▁of▁sentence><User>line1\nline2<Assistant></think>" {
t.Fatalf("unexpected content from text variants: %q", got)
}
}

View File

@@ -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, "<endofsentence>"); 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>\n</think>Hello!<end▁of▁sentence>") {
if !strings.Contains(got, "<Assistant></think>Hello!<end▁of▁sentence>") {
t.Fatalf("expected assistant EOS suffix, got %q", got)
}
if strings.Contains(got, "<system_instructions>") {