From: Anderson A. Giacomolli Date: Fri, 6 Nov 2026 20:26:53 +0000 (-0300) Subject: Revert the block parts of the compaction view X-Git-Url: http://git.giacomolli.uk/onechat/commitdiff_plain/cc5d2d2d302e810c6d9b862035e9f8de91941390?ds=sidebyside Revert the block parts of the compaction view This reverts commits 4b9b226 and 56129a5. A compaction sends its view again as one input part, followed by the task and, on a retry, the note. The ChatGPT backend writes a cache entry only at the end of the latest message of a request, and a later request reads it only at one of its own message ends. Parts inside a message are not lookup boundaries, so the blocks gave no cache hit. The entry of a compaction ends after its task, which no later compaction begins with, so first tries miss with any split of the view. A warm-up call per prefix would write a usable entry, but it costs more than the misses, so the first-try misses stay. Issue: 8c5fd2a --- diff --git a/compactor.go b/compactor.go index 11497b8..16303b0 100644 --- a/compactor.go +++ b/compactor.go @@ -4,18 +4,12 @@ import ( "context" "errors" "fmt" - "slices" "strings" "unicode/utf8" ) -const ( - // compactionTries is the most calls for one node. - compactionTries = 5 - - // viewBlock is the number of view lines in one input part. - viewBlock = 4 -) +// compactionTries is the most calls for one node. +const compactionTries = 5 // ruler shows the model the size limit of a line. Models cannot count bytes, // and a sample line as the ruler gets its content copied. @@ -24,10 +18,7 @@ var ruler = strings.Repeat("-", nodeBytes) // Compactor builds the nodes of one agent with a model. A compaction is a call // like a turn, with the same system prompt and tools, so it reads them from the // prompt cache of the turns. The tools are never called. After them comes one -// user message with the compaction view up to the node and the task, in the -// parts that compactionParts gives. Only the last part holds the end of the -// view, so compactions whose views end at different lines begin with the same -// parts up to their last shared block. +// user message with the compaction view up to the node and the task. // // When the line is over nodeBytes, the next try sends the same view and task, // plus a note with the size of the newest line and its cut at the limit. A try @@ -56,18 +47,18 @@ func newCompactor(client *Client, name string, model ModelConfig) *Compactor { // Summarize returns the line of the node of task. func (c *Compactor) Summarize(ctx context.Context, task Task) (string, error) { + view := task.Context + "\n" text, err := compactionTask(task) if err != nil { return "", err } - first := compactionParts(task.Context, text) var lines []string note := "" for len(lines) < compactionTries { - parts := first + parts := []string{view, text} if note != "" { - parts = append(slices.Clip(first), note) + parts = append(parts, note) } var response Response @@ -104,22 +95,6 @@ func (c *Compactor) Summarize(ctx context.Context, task Task) (string, error) { return shortest(lines), nil } -// compactionParts returns the input parts of a first try for the compaction -// view context and the task text: the opening tag, one part for each whole -// block of viewBlock lines, and then one part with the rest of the lines, the -// closing tag, a newline, and the task. Joined, the parts are the view, a -// newline, and the task. -func compactionParts(context, task string) []string { - lines := strings.SplitAfter(strings.TrimPrefix(context, "\n"), "\n") - whole := len(lines) - 1 - (len(lines)-1)%viewBlock - parts := []string{"\n"} - for n := 0; n < whole; n += viewBlock { - parts = append(parts, strings.Join(lines[n:n+viewBlock], "")) - } - - return append(parts, strings.Join(lines[whole:], "")+"\n"+task) -} - // compactionTask returns the task of a build, with its input. func compactionTask(task Task) (string, error) { if task.Level == 0 && len(task.Input) == 1 { diff --git a/compactor_test.go b/compactor_test.go index 20862c7..35e09eb 100644 --- a/compactor_test.go +++ b/compactor_test.go @@ -20,7 +20,7 @@ func TestCompactorSendsThePromptToolsAndTask(t *testing.T) { line, err := compactor.Summarize(t.Context(), Task{ Level: 0, Index: 7, - Context: "\n0+4|a\n4+1|b\n5+1|c\n6+1|d\n7+1|e\n", + Context: "\n0+4|user: earlier\n", Input: []string{"user: " + strings.Repeat("x", 600)}, }) require.NoError(t, err) @@ -42,66 +42,14 @@ func TestCompactorSendsThePromptToolsAndTask(t *testing.T) { parts := inputParts(t, server.Call(0)) require.Equal(t, []string{ - "\n", - "0+4|a\n4+1|b\n5+1|c\n6+1|d\n", - "7+1|e\n\n" + - "Compaction: compress message 7 into one line of at most 512 bytes\n" + + "\n0+4|user: earlier\n\n", + "Compaction: compress message 7 into one line of at most 512 bytes\n" + "(about 70 words), the length of this ruler:\n" + strings.Repeat("-", 512) + "\n" + "\nuser: " + strings.Repeat("x", 600) + "\n", }, parts) } -func TestCompactionPartsEndWithTheRestAndTheTask(t *testing.T) { - testCases := []struct { - name string - context string - want []string - }{ - { - name: "empty view has the opening tag and the last part", - context: "\n", - want: []string{"\n", "\nTASK"}, - }, - { - name: "lines short of a block go into the last part", - context: "\n0+1|a\n1+1|b\n2+1|c\n", - want: []string{"\n", "0+1|a\n1+1|b\n2+1|c\n\nTASK"}, - }, - { - name: "one whole block", - context: "\n0+1|a\n1+1|b\n2+1|c\n3+1|d\n", - want: []string{"\n", "0+1|a\n1+1|b\n2+1|c\n3+1|d\n", "\nTASK"}, - }, - { - name: "two whole blocks and a rest", - context: "\n0+2|a\n2+1|b\n3+1|c\n4+1|d\n5+1|e\n6+1|f\n7+1|g\n8+1|h\n9+1|i\n", - want: []string{ - "\n", - "0+2|a\n2+1|b\n3+1|c\n4+1|d\n", - "5+1|e\n6+1|f\n7+1|g\n8+1|h\n", - "9+1|i\n\nTASK", - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - parts := compactionParts(tc.context, "TASK") - require.Equal(t, tc.want, parts) - require.Equal(t, tc.context+"\nTASK", strings.Join(parts, "")) - }) - } -} - -func TestCompactionPartsOfALongerViewBeginWithTheBlocksOfAShorterOne(t *testing.T) { - shorter := compactionParts("\n0+1|a\n1+1|b\n2+1|c\n3+1|d\n4+1|e\n", "task 5") - longer := compactionParts("\n0+1|a\n1+1|b\n2+1|c\n3+1|d\n4+1|e\n5+1|f\n6+1|g\n7+1|h\n", "task 8") - require.Len(t, shorter, 3) - require.Equal(t, shorter[:2], longer[:2]) - require.NotEqual(t, shorter[2], longer[2]) -} - func TestCompactorWritesTheMergeTask(t *testing.T) { text, err := compactionTask(Task{ Level: 2,