dsh-context-compression-improved 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +1 -0
- package/CHANGELOG.ja.md +144 -83
- package/CHANGELOG.ko.md +143 -82
- package/CHANGELOG.md +278 -212
- package/CHANGELOG.zh.md +131 -77
- package/docs/installation.md +103 -103
- package/docs/installation.zh.md +100 -100
- package/package.json +1 -1
- package/packages/selector/cordis.patch.yml +5 -6
- package/packages/selector/lib/advisor-state.js +4 -231
- package/packages/selector/lib/client.d.ts +0 -24
- package/packages/selector/lib/client.js +6 -501
- package/packages/selector/lib/index.d.ts +4 -10
- package/packages/selector/lib/index.js +16 -234
- package/packages/selector/lib/pruner.d.ts +13 -248
- package/packages/selector/lib/pruner.js +148 -552
- package/packages/selector/src/client/EstimatorControls.tsx +0 -101
- package/packages/selector/src/client/index.ts +0 -17
- package/packages/selector/src/client/locales.ts +0 -38
- package/packages/selector/src/client/preset-options.ts +3 -2
- package/packages/selector/src/client/settings-section.tsx +8 -17
- package/packages/selector/src/index.ts +24 -271
- package/packages/selector/src/profiles.ts +4 -27
- package/packages/selector/src/pruner/state.ts +2 -25
- package/packages/selector/src/pruner.ts +75 -403
- package/packages/selector/src/runtime/audit.ts +27 -21
- package/packages/selector/src/runtime/config.ts +6 -32
- package/packages/selector/src/runtime/tokenpilot/advisor-prompt.ts +188 -188
- package/packages/selector/src/runtime/tokenpilot/advisor-state.ts +149 -133
- package/packages/selector/src/runtime/tokenpilot/advisor.ts +419 -419
- package/packages/selector/src/runtime/tokenpilot/benefit.ts +200 -0
- package/packages/selector/src/runtime/types.ts +0 -17
- package/packages/selector/tests/advisor-report.host.spec.ts +223 -223
- package/packages/selector/tests/preset-options-write.client.spec.ts +7 -23
- package/packages/selector/tests/public/package-contract.client.spec.ts +20 -0
- package/packages/selector/tests/runtime/advice-never-withholds.host.spec.ts +232 -0
- package/packages/selector/tests/runtime/advisor-invariant.spec.ts +272 -272
- package/packages/selector/tests/runtime/advisor.spec.ts +226 -226
- package/packages/selector/tests/runtime/audit.spec.ts +35 -21
- package/packages/selector/tests/runtime/char-basis.spec.ts +30 -30
- package/packages/selector/tests/runtime/deprecated-preset-options.spec.ts +96 -0
- package/packages/selector/tests/runtime/tokenpilot/benefit.spec.ts +217 -0
- package/packages/selector/tests/runtime/tokenpilot/profile-baseline.spec.ts +4 -5
- package/packages/selector/tests/settings-seat.client.spec.ts +45 -14
- package/scripts/toolclass-corpus-replay.mjs +281 -281
- package/packages/selector/src/client/ReviewOverlay.tsx +0 -320
- package/packages/selector/src/client/review-scope.ts +0 -16
- package/packages/selector/src/runtime/tokenpilot/proposal.ts +0 -267
- package/packages/selector/src/runtime/tokenpilot/review-queue.ts +0 -231
- package/packages/selector/src/runtime/tokenpilot/review-registry.ts +0 -117
- package/packages/selector/src/runtime/tokenpilot/review-storage.ts +0 -122
- package/packages/selector/tests/review-overlay.client.spec.tsx +0 -118
- package/packages/selector/tests/review-routes-registry.host.spec.ts +0 -142
- package/packages/selector/tests/review-routes.host.spec.ts +0 -290
- package/packages/selector/tests/runtime/tokenpilot/proposal.spec.ts +0 -393
- package/packages/selector/tests/runtime/tokenpilot/pruner-review.spec.ts +0 -382
- package/packages/selector/tests/runtime/tokenpilot/review-queue.spec.ts +0 -168
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TokenPilot-inspired benefit model — **advisory only**.
|
|
3
|
+
*
|
|
4
|
+
* This module prices one pass's planned replacements as ONE merged mutation and
|
|
5
|
+
* labels the batch with the band the model would have chosen. The label is
|
|
6
|
+
* ADVICE: nothing here suppresses, delays, or rewrites a reduction. The former
|
|
7
|
+
* human-gated review pipeline consumed these bands to withhold the batch from
|
|
8
|
+
* landing; that gate was retired because a reduction must never block automatic
|
|
9
|
+
* processing. The bands now feed the `reduction-advice` audit and the advisor
|
|
10
|
+
* report, and every planned replacement that the rule engine produced lands.
|
|
11
|
+
*
|
|
12
|
+
* Cache accounting (TokenPilot paper): one merged mutation pays a one-time tail
|
|
13
|
+
* KV-cache refill penalty of `(1−α)·tailTokens`, and every later turn recovers
|
|
14
|
+
* the reclaimed tokens at the cache-hit discount `α`:
|
|
15
|
+
*
|
|
16
|
+
* ```
|
|
17
|
+
* R = Σ(tokensBefore − tokensAfter) // net reclaimed tokens
|
|
18
|
+
* paybackTurns = (1−α)·tailTokens / (α·R) // one-time refill / per-turn saving
|
|
19
|
+
* expectedSaving = α·R·max(0, Ŝ − paybackTurns) // Ŝ = estimated remaining turns
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The refill penalty only models mutations of already-cached context. A
|
|
23
|
+
* fresh-stage batch (shaped before its first request) is exempt via
|
|
24
|
+
* `refillPenaltyExempt`: payback is 0 and every reclaimed token saves from
|
|
25
|
+
* the very first turn. Without that exemption every realistic fresh batch
|
|
26
|
+
* prices into the `not-worth-it` band, which makes the advice useless exactly
|
|
27
|
+
* where it is most often consulted.
|
|
28
|
+
*
|
|
29
|
+
* `expectedSaving` is only produced when Ŝ is known (the estimator answered
|
|
30
|
+
* with `expectedRemainingTurns`); it is never fabricated from a guess.
|
|
31
|
+
*
|
|
32
|
+
* Pure functions only: the classifier needs no I/O, no session state, and no
|
|
33
|
+
* host services, so every label is unit-testable and audit-replayable.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** The minimal per-candidate face the benefit model consumes. */
|
|
37
|
+
export interface BenefitCandidate {
|
|
38
|
+
readonly sourceSeq: number
|
|
39
|
+
readonly tokensBefore: number
|
|
40
|
+
readonly tokensAfter: number
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface BenefitInput {
|
|
44
|
+
/** Cache-hit discount rate α ∈ (0,1); validated upstream by config parsing. */
|
|
45
|
+
readonly alpha: number
|
|
46
|
+
/** Token mass of the protected tail that must be refilled after a mutation. */
|
|
47
|
+
readonly tailTokens: number
|
|
48
|
+
/** Estimated remaining turns Ŝ; `undefined` keeps expectedSaving out of the result. */
|
|
49
|
+
readonly remainingTurns?: number | undefined
|
|
50
|
+
/** True for fresh-stage batches: their content was never served, so it is
|
|
51
|
+
* not in the KV cache and shaping it causes no cache break — no refill
|
|
52
|
+
* penalty applies and the whole discounted recovery is pure gain. */
|
|
53
|
+
readonly refillPenaltyExempt?: boolean | undefined
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface BenefitEstimate {
|
|
57
|
+
/** Net reclaimed tokens across the batch; may be ≤ 0 when a batch is not worth it. */
|
|
58
|
+
readonly recoveredTokens: number
|
|
59
|
+
/** The one-time cache-refill penalty the merged mutation pays: (1−α)·tailTokens. */
|
|
60
|
+
readonly penaltyTokens: number
|
|
61
|
+
/** Turns of discounted recovery needed to recoup the penalty; `undefined` when α·R ≤ 0. */
|
|
62
|
+
readonly paybackTurns?: number
|
|
63
|
+
/** Discounted net benefit over the remaining session; omitted when Ŝ is unknown. */
|
|
64
|
+
readonly expectedSaving?: number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The band one priced batch falls into. Advisory vocabulary only — every band
|
|
69
|
+
* lands; the label says what the model thought of the landing, not whether it
|
|
70
|
+
* was allowed to happen.
|
|
71
|
+
*/
|
|
72
|
+
export type AdviceBand =
|
|
73
|
+
/** Payback ≤ 1 turn, or ≤ a quarter of the estimated remaining turns. */
|
|
74
|
+
| 'profitable'
|
|
75
|
+
/** At least one candidate reaches the high-impact threshold: the batch is
|
|
76
|
+
* large enough that a human would want to know it moved. */
|
|
77
|
+
| 'high-impact'
|
|
78
|
+
/** Ŝ known and payback ∈ (1, 3]: it does pay back, but slowly. */
|
|
79
|
+
| 'slow-payback'
|
|
80
|
+
/** α·R ≤ 0: the accounting has no discounted recovery to argue from. */
|
|
81
|
+
| 'unpriceable'
|
|
82
|
+
/** Ŝ known and payback > 3 turns: the model would not have spent the cache break. */
|
|
83
|
+
| 'not-worth-it'
|
|
84
|
+
|
|
85
|
+
export interface AdviceInput {
|
|
86
|
+
/** Cache-hit discount rate α ∈ (0,1); validated upstream by config parsing. */
|
|
87
|
+
readonly alpha: number
|
|
88
|
+
/** Token mass of the protected tail that must be refilled after a mutation. */
|
|
89
|
+
readonly tailTokens: number
|
|
90
|
+
/** Candidates at or above this token impact are labelled `high-impact`. */
|
|
91
|
+
readonly highImpactTokens: number
|
|
92
|
+
/** Estimated remaining turns Ŝ; `undefined` closes the slow-payback band. */
|
|
93
|
+
readonly remainingTurns?: number | undefined
|
|
94
|
+
/** Landing stage of the batch: `'fresh'` batches are priced without the
|
|
95
|
+
* tail-refill penalty (first-exposure shaping causes no cache break);
|
|
96
|
+
* `'history'` batches — already-served content — pay it in full. */
|
|
97
|
+
readonly stage?: 'fresh' | 'history' | undefined
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface AdviceResult {
|
|
101
|
+
readonly band: AdviceBand
|
|
102
|
+
/** The full benefit estimate the band was derived from. */
|
|
103
|
+
readonly benefit: BenefitEstimate
|
|
104
|
+
/** Number of candidates that carried a positive recovery and were priced. */
|
|
105
|
+
readonly priced: number
|
|
106
|
+
/** Largest single-candidate token mass in the batch (the high-impact evidence). */
|
|
107
|
+
readonly maxTokensBefore: number
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Shipped defaults of the advisory model. They are constants rather than
|
|
112
|
+
* settings keys because the machine no longer acts on them: after the review
|
|
113
|
+
* gate was retired these numbers only shape a label, so exposing them as
|
|
114
|
+
* tunable configuration would advertise a control that changes no behavior.
|
|
115
|
+
*/
|
|
116
|
+
export const DEFAULT_ADVICE_ALPHA = 0.1
|
|
117
|
+
export const DEFAULT_ADVICE_HIGH_IMPACT_TOKENS = 4_000
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Aggregate the batch-level benefit of a set of reduction candidates.
|
|
121
|
+
*
|
|
122
|
+
* Individual candidates whose replacement would grow the context contribute
|
|
123
|
+
* zero recovery (they never make a batch look better than dropping them).
|
|
124
|
+
*/
|
|
125
|
+
export function computeBenefit(candidates: readonly BenefitCandidate[], input: BenefitInput): BenefitEstimate {
|
|
126
|
+
const { alpha, tailTokens, remainingTurns } = input
|
|
127
|
+
let recoveredTokens = 0
|
|
128
|
+
for (const candidate of candidates) {
|
|
129
|
+
recoveredTokens += Math.max(0, candidate.tokensBefore - candidate.tokensAfter)
|
|
130
|
+
}
|
|
131
|
+
const penaltyTokens = input.refillPenaltyExempt === true ? 0 : (1 - alpha) * tailTokens
|
|
132
|
+
const perTurnSaving = alpha * recoveredTokens
|
|
133
|
+
if (perTurnSaving <= 0) {
|
|
134
|
+
return remainingTurns === undefined
|
|
135
|
+
? { recoveredTokens, penaltyTokens }
|
|
136
|
+
: { recoveredTokens, penaltyTokens, expectedSaving: -penaltyTokens }
|
|
137
|
+
}
|
|
138
|
+
const paybackTurns = penaltyTokens / perTurnSaving
|
|
139
|
+
if (remainingTurns === undefined) {
|
|
140
|
+
return { recoveredTokens, penaltyTokens, paybackTurns }
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
recoveredTokens,
|
|
144
|
+
penaltyTokens,
|
|
145
|
+
paybackTurns,
|
|
146
|
+
expectedSaving: perTurnSaving * Math.max(0, remainingTurns - paybackTurns),
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Label one batch of planned replacements.
|
|
152
|
+
*
|
|
153
|
+
* Pipeline: zero/negative-recovery candidates are priced out first (they never
|
|
154
|
+
* make a batch look better), the surviving batch is priced once through
|
|
155
|
+
* `computeBenefit`, and the band is a batch decision — the refill penalty is a
|
|
156
|
+
* property of the landing event, not of any single candidate, so pricing per
|
|
157
|
+
* candidate would overstate payback N-fold.
|
|
158
|
+
*
|
|
159
|
+
* Band precedence (identical thresholds to the retired triage model):
|
|
160
|
+
* - α too small to price a payback → `unpriceable`;
|
|
161
|
+
* - any candidate at `highImpactTokens` → `high-impact`;
|
|
162
|
+
* - `paybackTurns ≤ 1`, or Ŝ known and `paybackTurns ≤ 0.25·Ŝ` → `profitable`;
|
|
163
|
+
* - Ŝ known and `paybackTurns ∈ (1, 3]` → `slow-payback`;
|
|
164
|
+
* - everything else → `not-worth-it`.
|
|
165
|
+
*
|
|
166
|
+
* @param candidates - planned replacements of one pass, in any order.
|
|
167
|
+
* @param input - pricing inputs and the stage of the batch.
|
|
168
|
+
* @returns the advice, or `undefined` when nothing carried a positive recovery.
|
|
169
|
+
*/
|
|
170
|
+
export function adviseCandidates(
|
|
171
|
+
candidates: readonly BenefitCandidate[],
|
|
172
|
+
input: AdviceInput,
|
|
173
|
+
): AdviceResult | undefined {
|
|
174
|
+
const usable: BenefitCandidate[] = []
|
|
175
|
+
for (const candidate of candidates) {
|
|
176
|
+
if (Math.max(0, candidate.tokensBefore - candidate.tokensAfter) <= 0) continue
|
|
177
|
+
usable.push(candidate)
|
|
178
|
+
}
|
|
179
|
+
if (usable.length === 0) return undefined
|
|
180
|
+
|
|
181
|
+
const benefit = computeBenefit(usable, {
|
|
182
|
+
alpha: input.alpha,
|
|
183
|
+
tailTokens: input.tailTokens,
|
|
184
|
+
...input.remainingTurns !== undefined ? { remainingTurns: input.remainingTurns } : {},
|
|
185
|
+
refillPenaltyExempt: input.stage === 'fresh',
|
|
186
|
+
})
|
|
187
|
+
const payback = benefit.paybackTurns
|
|
188
|
+
const maxTokensBefore = usable.reduce((max, candidate) => Math.max(max, candidate.tokensBefore), 0)
|
|
189
|
+
const band: AdviceBand = payback === undefined
|
|
190
|
+
? 'unpriceable'
|
|
191
|
+
: maxTokensBefore >= input.highImpactTokens
|
|
192
|
+
? 'high-impact'
|
|
193
|
+
: payback <= 1
|
|
194
|
+
|| (input.remainingTurns !== undefined && payback <= 0.25 * input.remainingTurns)
|
|
195
|
+
? 'profitable'
|
|
196
|
+
: input.remainingTurns !== undefined && payback <= 3
|
|
197
|
+
? 'slow-payback'
|
|
198
|
+
: 'not-worth-it'
|
|
199
|
+
return { band, benefit, priced: usable.length, maxTokensBefore }
|
|
200
|
+
}
|
|
@@ -85,18 +85,6 @@ export interface PresetOptions {
|
|
|
85
85
|
readonly sampleLimit: number
|
|
86
86
|
readonly minTokens: number
|
|
87
87
|
}
|
|
88
|
-
/**
|
|
89
|
-
* Human-gated review pipeline (beta): edge/high-impact candidates queue for
|
|
90
|
-
* manual approval and execute in one merged batch at the next turn boundary
|
|
91
|
-
* instead of the automatic path (R4).
|
|
92
|
-
*/
|
|
93
|
-
readonly reviewMode: boolean
|
|
94
|
-
/** Turn-boundary patience: pending review proposals older than this many turns auto-expire (R4). */
|
|
95
|
-
readonly reviewTimeoutTurns: number
|
|
96
|
-
/** Cache-hit discount rate α in the benefit model; expectedSaving = α·R·Ŝ − (1−α)·tail. */
|
|
97
|
-
readonly cacheHitDiscountAlpha: number
|
|
98
|
-
/** Candidates whose tokenBefore reaches this threshold bypass payback triage and always enter review (R4). */
|
|
99
|
-
readonly reviewHighImpactTokens: number
|
|
100
88
|
}
|
|
101
89
|
|
|
102
90
|
/** Common user-authored Custom stages shared by persisted policy versions. */
|
|
@@ -154,11 +142,6 @@ export interface PresetOptionsSettings {
|
|
|
154
142
|
readonly prefixStabilizer?: boolean
|
|
155
143
|
readonly readState?: boolean
|
|
156
144
|
readonly estimatorMode?: '' | 'host' | 'direct'
|
|
157
|
-
/** Review-mode overrides (beta); see PresetOptions.reviewMode. */
|
|
158
|
-
readonly reviewMode?: boolean
|
|
159
|
-
readonly reviewTimeoutTurns?: number
|
|
160
|
-
readonly cacheHitDiscountAlpha?: number
|
|
161
|
-
readonly reviewHighImpactTokens?: number
|
|
162
145
|
/**
|
|
163
146
|
* Estimator endpoint fields. Persisted-settings only: they never enter the
|
|
164
147
|
* frozen CompressionPolicy, which is emitted verbatim by policy-resolved
|