From 47dc12169088c275be2a89611c88e7f74743879a Mon Sep 17 00:00:00 2001 From: CJACK Date: Sun, 5 Apr 2026 04:44:46 +0800 Subject: [PATCH] refactor: improve prompt construction by enforcing explicit newline boundaries between role markers and message content --- internal/admin/handler_accounts_testing.go | 2 +- internal/prompt/messages.go | 29 +++++++++++----------- internal/util/messages_test.go | 13 ++++++++-- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/internal/admin/handler_accounts_testing.go b/internal/admin/handler_accounts_testing.go index 2a8a447..a05d6cf 100644 --- a/internal/admin/handler_accounts_testing.go +++ b/internal/admin/handler_accounts_testing.go @@ -157,7 +157,7 @@ func (h *Handler) testAccount(ctx context.Context, acc config.Account, model, me result["message"] = "获取 PoW 失败: " + err.Error() return result } - payload := map[string]any{"chat_session_id": sessionID, "prompt": "<|User|>" + message, "ref_file_ids": []any{}, "thinking_enabled": thinking, "search_enabled": search} + payload := map[string]any{"chat_session_id": sessionID, "prompt": "<|User|>\n" + message, "ref_file_ids": []any{}, "thinking_enabled": thinking, "search_enabled": search} resp, err := h.DS.CallCompletion(ctx, authCtx, payload, pow, 1) if err != nil { result["message"] = "请求失败: " + err.Error() diff --git a/internal/prompt/messages.go b/internal/prompt/messages.go index 80333de..daf5b84 100644 --- a/internal/prompt/messages.go +++ b/internal/prompt/messages.go @@ -32,30 +32,31 @@ func MessagesPrepare(messages []map[string]any) string { merged = append(merged, msg) } parts := make([]string, 0, len(merged)) - for i, m := range merged { + for _, m := range merged { switch m.Role { case "assistant": - parts = append(parts, "<|Assistant|>"+m.Text+"<|end▁of▁sentence|>") + // Keep assistant turns on their own block so the model sees a clear + // boundary between prior answer text and the EOS marker. + parts = append(parts, "<|Assistant|>\n"+m.Text+"\n<|end▁of▁sentence|>") case "tool": - if i > 0 { - parts = append(parts, "<|Tool|>"+m.Text) - } else { - parts = append(parts, m.Text) + if strings.TrimSpace(m.Text) != "" { + parts = append(parts, "<|Tool|>\n"+m.Text) } case "system": - // Clear system boundary improves R1 and V3 context understanding significantly - if strings.TrimSpace(m.Text) != "" { - parts = append(parts, "\n"+strings.TrimSpace(m.Text)+"\n\n\n") + // Clear system boundary improves R1 and V3 context understanding significantly. + if text := strings.TrimSpace(m.Text); text != "" { + parts = append(parts, "\n"+text+"\n") } case "user": - // Always prepend <|User|> to user messages. DeepSeek R1 reasoning triggers best - // and aligns context perfectly when the user turn is explicitly marked. - parts = append(parts, "<|User|>"+m.Text) + // Put user turns on their own line so the role transition is explicit. + parts = append(parts, "<|User|>\n"+m.Text) default: - parts = append(parts, m.Text) + if strings.TrimSpace(m.Text) != "" { + parts = append(parts, m.Text) + } } } - out := strings.Join(parts, "") + out := strings.Join(parts, "\n\n") return markdownImagePattern.ReplaceAllString(out, `[${1}](${2})`) } diff --git a/internal/util/messages_test.go b/internal/util/messages_test.go index ab11b59..2ec3f50 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 != "<|User|>Hello" { + if got != "<|User|>\nHello" { t.Fatalf("unexpected prompt: %q", got) } } @@ -25,6 +25,15 @@ func TestMessagesPrepareRoles(t *testing.T) { {"role": "user", "content": "How are you"}, } got := MessagesPrepare(messages) + if !contains(got, "\nYou are helper\n\n\n<|User|>\nHi") { + t.Fatalf("expected system/user separation in %q", got) + } + if !contains(got, "<|User|>\nHi\n\n<|Assistant|>\nHello") { + t.Fatalf("expected user/assistant separation in %q", got) + } + if !contains(got, "<|Assistant|>\nHello\n<|end▁of▁sentence|>\n\n<|User|>\nHow are you") { + t.Fatalf("expected assistant/user separation in %q", got) + } if !contains(got, "<|Assistant|>") { t.Fatalf("expected assistant marker in %q", got) } @@ -55,7 +64,7 @@ func TestMessagesPrepareArrayTextVariants(t *testing.T) { }, } got := MessagesPrepare(messages) - if got != "<|User|>line1\nline2" { + if got != "<|User|>\nline1\nline2" { t.Fatalf("unexpected content from text variants: %q", got) } }