diff --git a/docs/context-engine-strategies.md b/docs/context-engine-strategies.md index bb7ed1325..a4150e315 100644 --- a/docs/context-engine-strategies.md +++ b/docs/context-engine-strategies.md @@ -16,7 +16,7 @@ Context Engine 的目标不是伪装网页聊天记录,而是把 API 会话编 | strategy | 输出形态 | 默认使用 | 适用场景 | 回滚价值 | |---|---|---:|---|---| -| `raw_transcript` | 旧式 `# DS2API_HISTORY.txt` + `=== N. ROLE ===` transcript | 否 | 调试、回归、兼容旧行为 | 最高,保留旧形态 | +| `raw_transcript` | 中性标题 + `=== N. ROLE ===` transcript | 否 | 调试、回归、兼容旧行为 | 较高,保留旧式轮次形态 | | `natural_context` | `# Conversation Context` + 全量自然化轮次 | 否 | 需要完整历史但不想暴露实现术语 | 从压缩策略回退到全文 | | `context_capsule` | 当前任务 + 约束 + 早期摘要,不回放最近完整轮次 | 否 | 普通问答、长历史摘要 | 降低上下文体积 | | `hybrid_recent` | 当前任务 + 约束 + 早期摘要 + 最近精确上下文 | 是 | Agent 长任务、编程、调试 | 默认生产策略 | diff --git a/internal/httpapi/openai/history_split_test.go b/internal/httpapi/openai/history_split_test.go index f6c72869e..0a41be786 100644 --- a/internal/httpapi/openai/history_split_test.go +++ b/internal/httpapi/openai/history_split_test.go @@ -95,7 +95,7 @@ func TestBuildOpenAICurrentInputContextTranscriptUsesNaturalContextSections(t *t func TestBuildOpenAICurrentInputContextTranscriptRawStrategy(t *testing.T) { transcript := promptcompat.BuildOpenAICurrentInputContextTranscriptWithStrategy(historySplitTestMessages(), "raw_transcript") for _, want := range []string{ - "# DS2API_HISTORY.txt", + "# Conversation Transcript", "=== 1. SYSTEM ===", "=== 5. USER ===", } { diff --git a/internal/promptcompat/history_transcript.go b/internal/promptcompat/history_transcript.go index 95c8e24f8..ea05605cc 100644 --- a/internal/promptcompat/history_transcript.go +++ b/internal/promptcompat/history_transcript.go @@ -7,7 +7,7 @@ import ( const CurrentInputContextFilename = "DS2API_HISTORY.txt" -const historyTranscriptTitle = "# DS2API_HISTORY.txt" +const historyTranscriptTitle = "# Conversation Transcript" const historyTranscriptSummary = "Prior conversation history and tool progress." const naturalContextTitle = "# Conversation Context" const naturalContextSummary = "This note captures the working conversation state for the current request." diff --git a/internal/promptcompat/history_transcript_test.go b/internal/promptcompat/history_transcript_test.go index c3a3948d5..ea215e814 100644 --- a/internal/promptcompat/history_transcript_test.go +++ b/internal/promptcompat/history_transcript_test.go @@ -2,6 +2,8 @@ package promptcompat import ( "fmt" + "os" + "path/filepath" "strings" "testing" ) @@ -46,9 +48,12 @@ func TestBuildOpenAICurrentInputContextTranscriptStrategyShapes(t *testing.T) { } raw := BuildOpenAICurrentInputContextTranscriptWithStrategy(messages, "raw_transcript") - if !strings.Contains(raw, "# DS2API_HISTORY.txt") || !strings.Contains(raw, "=== 1. SYSTEM ===") { + if !strings.Contains(raw, "# Conversation Transcript") || !strings.Contains(raw, "=== 1. SYSTEM ===") { t.Fatalf("expected raw transcript shape, got %q", raw) } + if strings.Contains(raw, "DS2API") { + t.Fatalf("raw transcript should not expose implementation terms, got %q", raw) + } natural := BuildOpenAICurrentInputContextTranscriptWithStrategy(messages, "natural_context") if !strings.Contains(natural, "## Conversation") || strings.Contains(natural, "Earlier Context Summary") { @@ -60,3 +65,26 @@ func TestBuildOpenAICurrentInputContextTranscriptStrategyShapes(t *testing.T) { t.Fatalf("expected context capsule without recent exact section, got %q", capsule) } } + +func TestBuildOpenAICurrentInputContextTranscriptStrategyGoldens(t *testing.T) { + messages := []any{ + map[string]any{"role": "system", "content": "system rule"}, + map[string]any{"role": "user", "content": "first turn"}, + map[string]any{"role": "assistant", "content": "first answer"}, + map[string]any{"role": "user", "content": "latest request"}, + } + for _, strategy := range []string{"raw_transcript", "natural_context", "context_capsule", "hybrid_recent"} { + t.Run(strategy, func(t *testing.T) { + got := BuildOpenAICurrentInputContextTranscriptWithStrategy(messages, strategy) + path := filepath.Join("testdata", "context_strategy", strategy+".golden") + want, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read golden: %v", err) + } + wantText := strings.ReplaceAll(string(want), "\r\n", "\n") + if got != wantText { + t.Fatalf("golden mismatch for %s\n--- got ---\n%s\n--- want ---\n%s", strategy, got, wantText) + } + }) + } +} diff --git a/internal/promptcompat/testdata/context_strategy/context_capsule.golden b/internal/promptcompat/testdata/context_strategy/context_capsule.golden new file mode 100644 index 000000000..e7b9f8bac --- /dev/null +++ b/internal/promptcompat/testdata/context_strategy/context_capsule.golden @@ -0,0 +1,15 @@ +# Conversation Context +This note summarizes earlier context and preserves the most recent turns needed for the current reply. + +## Current Task +latest request + +## Non-Negotiable Instructions + +- system rule + +## Earlier Context Summary + +- User: first turn +- Assistant: first answer +- User: latest request diff --git a/internal/promptcompat/testdata/context_strategy/hybrid_recent.golden b/internal/promptcompat/testdata/context_strategy/hybrid_recent.golden new file mode 100644 index 000000000..010ded09c --- /dev/null +++ b/internal/promptcompat/testdata/context_strategy/hybrid_recent.golden @@ -0,0 +1,23 @@ +# Conversation Context +This note summarizes earlier context and preserves the most recent turns needed for the current reply. + +## Current Task +latest request + +## Non-Negotiable Instructions + +- system rule + +## Recent Exact Context + +1. System guidance: +system rule + +2. User: +first turn + +3. Assistant: +first answer + +4. User: +latest request diff --git a/internal/promptcompat/testdata/context_strategy/natural_context.golden b/internal/promptcompat/testdata/context_strategy/natural_context.golden new file mode 100644 index 000000000..969d7b2b8 --- /dev/null +++ b/internal/promptcompat/testdata/context_strategy/natural_context.golden @@ -0,0 +1,16 @@ +# Conversation Context +This note captures the working conversation state for the current request. + +## Conversation + +1. System guidance: +system rule + +2. User: +first turn + +3. Assistant: +first answer + +4. User: +latest request diff --git a/internal/promptcompat/testdata/context_strategy/raw_transcript.golden b/internal/promptcompat/testdata/context_strategy/raw_transcript.golden new file mode 100644 index 000000000..637f6feca --- /dev/null +++ b/internal/promptcompat/testdata/context_strategy/raw_transcript.golden @@ -0,0 +1,14 @@ +# Conversation Transcript +Prior conversation history and tool progress. + +=== 1. SYSTEM === +system rule + +=== 2. USER === +first turn + +=== 3. ASSISTANT === +first answer + +=== 4. USER === +latest request