返回 DeepSeek-Reasonix
compact_fold_input.go
根目录 / internal / agent / compact_fold_input.go
1 package agent
2
3 import (
4 "context"
5
6 "reasonix/internal/provider"
7 )
8
9 const minSummaryOutputTokens = 512
10
11 // summaryOutputBudget scales only shared/unknown-window summaries. Providers
12 // with an independent completion window keep the full digest cap; smaller
13 // shared windows reserve one quarter for a useful briefing without crowding
14 // every fold out of the prompt budget.
15 func (a *Agent) summaryOutputBudget() int {
16 if contextBudgetPolicyOf(a.svc.prov).WindowMode == provider.ContextWindowIndependent {
17 return summaryOutputMaxTokens
18 }
19 window := a.effectiveContextWindow()
20 if window <= 0 {
21 return summaryOutputMaxTokens
22 }
23 return min(summaryOutputMaxTokens, max(window/4, minSummaryOutputTokens))
24 }
25
26 // foldSummary is what compaction reports about turning a fold into a digest.
27 // It is populated even when the call fails, so telemetry still records how
28 // large the attempt was and that exactly one call was used.
29 type foldSummary struct {
30 Text string
31 Mode string
32 RequestID string
33 Usage *provider.Usage
34 FoldTokens int
35 Spans int
36 InputMode string
37 }
38
39 func summaryInputTokens(msgs []provider.Message) int {
40 return estimateMessagesTokens(msgs)
41 }
42
43 func (a *Agent) guardedSummaryInputTokens(msgs []provider.Message) int {
44 return a.estimatedVisibleRequestTokens(msgs)
45 }
46
47 func (a *Agent) summaryInputBudget(instructions string) int {
48 window := a.effectiveContextWindow()
49 if window <= 0 {
50 window = a.contextWindow
51 }
52 if window <= 0 {
53 return 0
54 }
55 return max(0, window-a.summaryOutputBudget()-estimateTextTokens(compactionInstruction)-estimateTextTokens(instructions)-protocolReserveTokens)
56 }
57
58 // foldToSummary turns a fold region into one digest with exactly one provider
59 // request. Pressure-time tool pruning is durable and happens before this call;
60 // the summary request never performs a private second transformation.
61 func (a *Agent) foldToSummary(ctx context.Context, fold []provider.Message, instructions string) (foldSummary, error) {
62 return a.foldToSummaryMode(ctx, fold, instructions, SummaryInputCachePrefix)
63 }
64
65 func (a *Agent) foldToSummaryMode(ctx context.Context, fold []provider.Message, instructions, inputMode string) (foldSummary, error) {
66 res := foldSummary{Mode: CompactionModeSummarized, Spans: 1, FoldTokens: summaryInputTokens(fold), InputMode: inputMode}
67 if inputMode == SummaryInputSlim {
68 summary, usage, err := a.summarizeTranscript(ctx, fold, instructions)
69 res.Text, res.Usage = summary, usage
70 return res, err
71 }
72 return a.singleCallSummary(ctx, res, fold, instructions)
73 }
74
75 func (a *Agent) singleCallSummary(ctx context.Context, res foldSummary, fold []provider.Message, instructions string) (foldSummary, error) {
76 summary, mode, usage, reqID, err := a.runCompactionSummary(ctx, fold, instructions)
77 res.Text, res.Mode, res.Usage, res.RequestID = summary, mode, usage, reqID
78 return res, err
79 }
80
81 func (a *Agent) foldSummaryWithTelemetry(ctx context.Context, trigger string, fold []provider.Message, instructions string, sourceTokens int, inputMode string) (foldSummary, CompactionTelemetry, error) {
82 res, err := a.foldToSummaryMode(ctx, fold, instructions, inputMode)
83 tele := compactionTelemetryFromSummary(trigger, a.CacheState(), sourceTokens, res)
84 if err != nil {
85 tele.Error = err.Error()
86 }
87 return res, tele, err
88 }
89
89 lines GO