@whyparabola/cabar 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +312 -2
- package/dist/cabar-B-R-rHby.d.cts +202 -0
- package/dist/cabar-B-R-rHby.d.ts +202 -0
- package/dist/chunk-UE4FTY7E.js +388 -0
- package/dist/index.cjs +681 -0
- package/dist/index.d.cts +255 -0
- package/dist/index.d.ts +255 -0
- package/dist/index.js +289 -0
- package/dist/langchain.cjs +358 -0
- package/dist/langchain.d.cts +35 -0
- package/dist/langchain.d.ts +35 -0
- package/dist/langchain.js +50 -0
- package/package.json +84 -4
- package/src/cabar.ts +485 -0
- package/src/context.ts +67 -0
- package/src/index.ts +20 -0
- package/src/langchain.ts +75 -0
- package/src/normalize.ts +40 -0
- package/src/prism.ts +482 -0
- package/src/renderings.ts +170 -0
- package/src/shared.ts +85 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { T as TokenCounter, S as Similarity, C as CabarSelectResult, a as CabarUnit, b as CabarSelectOptions } from './cabar-B-R-rHby.cjs';
|
|
2
|
+
export { A as ADAPTIVE_DEFAULTS, c as CHAR4_COUNTER, d as CabarDecision, e as CabarSelector, f as CabarStats, D as DEFAULTS, g as DEFAULT_RECENCY_DECAY_DAYS, h as cosineSimilarity, i as embeddingSimilarity, j as estimateTokens, r as recencyDecay } from './cabar-B-R-rHby.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PrismSelector: CABAR-2 multi-fidelity budgeted selection.
|
|
6
|
+
*
|
|
7
|
+
* Where CabarSelector answers "which units do we spend verbatim budget
|
|
8
|
+
* on, and summarize the rest", Prism answers the finer question "at WHICH
|
|
9
|
+
* FIDELITY do we render each unit". It solves a Multiple-Choice Knapsack
|
|
10
|
+
* Problem (MCKP): each unit offers a small menu of renderings — verbatim /
|
|
11
|
+
* extract / claims / mention — with distinct (cost, utility) points, and the
|
|
12
|
+
* selector greedily packs marginal-utility-per-token, allowed to UPGRADE an
|
|
13
|
+
* already-selected unit to a costlier fidelity when that upgrade is the densest
|
|
14
|
+
* feasible move. All-or-nothing (CABAR-1) is the special case of a two-point
|
|
15
|
+
* menu {verbatim, absent}; Prism dominates it under tight budgets by trading a
|
|
16
|
+
* verbatim unit for several cheaper-fidelity units that together carry more.
|
|
17
|
+
*
|
|
18
|
+
* Design invariants (same purity contract as CabarSelector):
|
|
19
|
+
* - PURE + deterministic: no LLM, no I/O, no Date.now — the caller supplies
|
|
20
|
+
* `now`; `claims` are pre-fetched onto the units by the caller.
|
|
21
|
+
* - Provider-agnostic token cost: the injectable `TokenCounter` defaults to
|
|
22
|
+
* the shared char/4 estimator (prod), and benchmarks inject a real BPE
|
|
23
|
+
* counter. Selection logic never assumes a specific vocabulary.
|
|
24
|
+
* - Cache-stable OUTPUT ORDERING: selected units are emitted by
|
|
25
|
+
* (timestamp asc, id asc), NOT by score, so the same units land in the same
|
|
26
|
+
* prompt slots turn-over-turn (KV-cache friendly).
|
|
27
|
+
* - β-hysteresis: an optional per-unit bonus for re-selecting a unit at
|
|
28
|
+
* ≥ its previous fidelity (keeps prompts stable turn-over-turn). Defaults
|
|
29
|
+
* to 0, a no-op.
|
|
30
|
+
* - Answer-lossless FLOOR: every unit at or above `tauFloor` that misses the
|
|
31
|
+
* budget still gets a mention line in the tail, so nothing recallable is
|
|
32
|
+
* silently dropped.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/** The four rendering fidelities, most→least faithful. */
|
|
36
|
+
type Fidelity = 'verbatim' | 'extract' | 'claims' | 'mention';
|
|
37
|
+
/** A retrieved unit plus its caller-pre-fetched claims (the CabarUnit + claims). */
|
|
38
|
+
interface PrismUnit {
|
|
39
|
+
id: string;
|
|
40
|
+
content: string;
|
|
41
|
+
/** Relevance from your retriever, normalized to [0,1] (top item ideally 1.0). */
|
|
42
|
+
score: number;
|
|
43
|
+
timestamp?: Date;
|
|
44
|
+
/** Pre-resolved claim strings; enables the CLAIMS fidelity. Selector never fetches these. */
|
|
45
|
+
claims?: string[];
|
|
46
|
+
/** Optional vector for `similarity: embeddingSimilarity`. */
|
|
47
|
+
embedding?: ArrayLike<number>;
|
|
48
|
+
}
|
|
49
|
+
/** Per-fidelity multipliers φ(f) — how much utility a fidelity retains vs verbatim. */
|
|
50
|
+
type FidelityFactors = Record<Fidelity, number>;
|
|
51
|
+
interface PrismSelectOptions {
|
|
52
|
+
/** Token budget for the guaranteed block + selected renderings. The tail is capped separately by tailBudgetTokens. */
|
|
53
|
+
budgetTokens?: number;
|
|
54
|
+
/** Hard cap on DISTINCT units selected (upgrades do not count against it). */
|
|
55
|
+
maxUnits?: number;
|
|
56
|
+
/** Hard token cap for the mention-line tail (separate from budgetTokens). */
|
|
57
|
+
tailBudgetTokens?: number;
|
|
58
|
+
/** Minimum score for a unit to earn a tail mention line (below this: dropped). */
|
|
59
|
+
tauFloor?: number;
|
|
60
|
+
/** ρ = recencyLambda·decay + (1−recencyLambda). 0 ⇒ ρ≡1 (multi-session safe). */
|
|
61
|
+
recencyLambda?: number;
|
|
62
|
+
/** Recency scale in days for the exponential decay e^(-age/days). Default 365. */
|
|
63
|
+
recencyDecayDays?: number;
|
|
64
|
+
/** Blend on the novelty term: effectiveNovelty = 1 − noveltyWeight·(1 − novelty). */
|
|
65
|
+
noveltyWeight?: number;
|
|
66
|
+
/** Tokens pre-charged against budgetTokens before selection (e.g. resolved-claims block). */
|
|
67
|
+
guaranteedTokens?: number;
|
|
68
|
+
/** Deterministic "current time" for recency. Defaults to `new Date()`. */
|
|
69
|
+
now?: Date;
|
|
70
|
+
/** Injectable token cost model. Defaults to the shared char/4 estimator. */
|
|
71
|
+
tokenCounter?: TokenCounter;
|
|
72
|
+
/**
|
|
73
|
+
* Unit-level similarity used for novelty, in [0, 1]. Defaults to word-set
|
|
74
|
+
* Jaccard between the renderings. Pass `embeddingSimilarity` to catch paraphrases.
|
|
75
|
+
*/
|
|
76
|
+
similarity?: Similarity<PrismUnit>;
|
|
77
|
+
/** Per-fidelity utility multipliers φ. Merged over defaults. */
|
|
78
|
+
fidelityFactors?: Partial<FidelityFactors>;
|
|
79
|
+
/** β — multiplicative bonus ×(1+β) for re-selecting a unit at ≥ prev fidelity. */
|
|
80
|
+
hysteresisBonus?: number;
|
|
81
|
+
/** Prior turn's selection (unit → fidelity) for the β-hysteresis predicate. */
|
|
82
|
+
prevSelected?: Array<{
|
|
83
|
+
unitId: string;
|
|
84
|
+
fidelity: Fidelity;
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Adaptive stopping mode. When true, ADD-move admission
|
|
88
|
+
* (a unit newly entering the selection) is gated: past `minKeep` distinct
|
|
89
|
+
* units, a unit may only be ADD-admitted if its relevance fraction (score /
|
|
90
|
+
* top-candidate score) is >= `relFloor` AND the candidate rendering's
|
|
91
|
+
* novelty vs the already-chosen renderings is >= `novFloor`. UPGRADE moves
|
|
92
|
+
* and the mention-tail are unaffected. `maxCeilingTokens` replaces
|
|
93
|
+
* `budgetTokens` as the only hard token bound (`maxUnits` is ignored).
|
|
94
|
+
* Default false: behavior is byte-identical to the fixed-budget path.
|
|
95
|
+
*/
|
|
96
|
+
adaptive?: boolean;
|
|
97
|
+
/** Adaptive mode: distinct units ADD-admitted before the relFloor/novFloor gate applies. Default 3. */
|
|
98
|
+
minKeep?: number;
|
|
99
|
+
/** Adaptive mode: below this fraction of the top candidate's score, ADD admission stops. Default 0.4. */
|
|
100
|
+
relFloor?: number;
|
|
101
|
+
/** Adaptive mode: below this novelty vs chosen renderings, ADD admission stops. Default 0.2. */
|
|
102
|
+
novFloor?: number;
|
|
103
|
+
/** Adaptive mode: hard token ceiling — replaces budgetTokens as the bound. Default 4000. */
|
|
104
|
+
maxCeilingTokens?: number;
|
|
105
|
+
}
|
|
106
|
+
interface PrismSelectedUnit {
|
|
107
|
+
unit: PrismUnit;
|
|
108
|
+
fidelity: Fidelity;
|
|
109
|
+
rendered: string;
|
|
110
|
+
tokens: number;
|
|
111
|
+
}
|
|
112
|
+
interface PrismStats {
|
|
113
|
+
/** Sum of every candidate unit's VERBATIM cost (the pre-selection ceiling). */
|
|
114
|
+
candidateTokens: number;
|
|
115
|
+
selectedTokens: number;
|
|
116
|
+
tailTokens: number;
|
|
117
|
+
budgetTokens: number;
|
|
118
|
+
/** guaranteedTokens + selectedTokens + tailTokens — actual spend vs budgetTokens. */
|
|
119
|
+
utilizedTokens: number;
|
|
120
|
+
fidelityHistogram: Record<Fidelity, number>;
|
|
121
|
+
/** Number of greedy moves applied (adds + upgrades). */
|
|
122
|
+
moves: number;
|
|
123
|
+
}
|
|
124
|
+
interface PrismSelectResult {
|
|
125
|
+
selected: PrismSelectedUnit[];
|
|
126
|
+
/** Unselected units at or above tauFloor — floored into the mention tail. */
|
|
127
|
+
tail: PrismUnit[];
|
|
128
|
+
/** The rendered tail block (mention lines, or verbatim on the tiny-pool guard). */
|
|
129
|
+
tailBlock: string;
|
|
130
|
+
stats: PrismStats;
|
|
131
|
+
}
|
|
132
|
+
declare class PrismSelector {
|
|
133
|
+
/**
|
|
134
|
+
* MCKP-greedy multi-fidelity selection: build each unit's rendering menu,
|
|
135
|
+
* greedily apply the densest feasible ADD/UPGRADE move, run the KMN
|
|
136
|
+
* best-single swap, then floor the remainder into a mention tail.
|
|
137
|
+
*/
|
|
138
|
+
static select(units: PrismUnit[], query: string, opts?: PrismSelectOptions): PrismSelectResult;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Prism renderings: deterministic multi-fidelity renderings of a retrieved
|
|
143
|
+
* unit (the CABAR-2 "Prism" extension of CABAR's all-or-nothing selection).
|
|
144
|
+
*
|
|
145
|
+
* CABAR-1 spent budget on a unit at a single fidelity (verbatim, or nothing —
|
|
146
|
+
* with an extractive tail for the rest). Prism turns that binary into a ladder:
|
|
147
|
+
* a unit can be rendered at VERBATIM (full content), EXTRACT (query-aware
|
|
148
|
+
* sentence extract, ≤~40% of verbatim tokens), CLAIMS (its pre-resolved claim
|
|
149
|
+
* bullets), or MENTION (a one-line dereferenceable pointer). The MCKP selector
|
|
150
|
+
* (PrismSelector) then picks per-unit fidelities to maximize utility under the
|
|
151
|
+
* token budget instead of dropping units wholesale.
|
|
152
|
+
*
|
|
153
|
+
* Every rendering here is PURE and deterministic: no LLM, no I/O, no clock.
|
|
154
|
+
* Costs are measured through an injected `TokenCounter` (char/4 by default,
|
|
155
|
+
* real BPE when you inject one) so the same code costs the same
|
|
156
|
+
* text the caller will bill for. Claims are pre-fetched by the caller and live
|
|
157
|
+
* on the unit — this module never fetches them.
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
/** Lowercased word (3+ chars) token set — same family as CabarSelector.tokenize. */
|
|
161
|
+
declare function tokenize(text: string): Set<string>;
|
|
162
|
+
declare function jaccard(a: Set<string>, b: Set<string>): number;
|
|
163
|
+
/** Sentence split — same regex family as CabarSelector.buildTailSummary. */
|
|
164
|
+
declare function splitSentences(text: string): string[];
|
|
165
|
+
/**
|
|
166
|
+
* Word-boundary truncation to a token budget, appending an ellipsis only when
|
|
167
|
+
* the text is actually cut. Uses the injected counter so the cut respects the
|
|
168
|
+
* caller's tokenization (char/4 or BPE). Always keeps at least the first word.
|
|
169
|
+
*/
|
|
170
|
+
declare function truncateToTokens(text: string, maxTokens: number, counter: TokenCounter): string;
|
|
171
|
+
/** VERBATIM — the unit's full content, unchanged. */
|
|
172
|
+
declare function verbatim(u: PrismUnit): string;
|
|
173
|
+
/**
|
|
174
|
+
* EXTRACT — query-aware sentence extraction targeting ≤~40% of verbatim tokens.
|
|
175
|
+
*
|
|
176
|
+
* Sentences are scored by query-term overlap plus a first-sentence positional
|
|
177
|
+
* prior, deduped on normalized text, then greedily packed (highest score first,
|
|
178
|
+
* stable on original order) up to the ~40% token target. Selected sentences are
|
|
179
|
+
* emitted in ORIGINAL narrative order (unlike the score-ordered tail) so the
|
|
180
|
+
* extract reads coherently. Never returns empty for non-empty content: if the
|
|
181
|
+
* target is too small for any sentence, the single top-scored sentence is kept
|
|
182
|
+
* (a single-sentence unit thus extracts to itself, and is dropped later by the
|
|
183
|
+
* selector's cost-dominance guard rather than duplicating verbatim).
|
|
184
|
+
*/
|
|
185
|
+
declare function extract(u: PrismUnit, query: string, counter: TokenCounter): string;
|
|
186
|
+
/**
|
|
187
|
+
* CLAIMS — the unit's pre-resolved claims as '- <claim>' bullet lines.
|
|
188
|
+
* UNAVAILABLE (null) when the caller pre-fetched no claims for this unit.
|
|
189
|
+
*/
|
|
190
|
+
declare function claimsRendering(u: PrismUnit): string | null;
|
|
191
|
+
/**
|
|
192
|
+
* MENTION — a one-line dereferenceable pointer:
|
|
193
|
+
* [<id>@<yyyy-mm-dd if timestamp>] <first sentence, ≤25 tokens>
|
|
194
|
+
* This is the answer-lossless floor: even a unit that loses the budget contest
|
|
195
|
+
* still leaves a citable trace the caller can dereference back to the full unit.
|
|
196
|
+
*/
|
|
197
|
+
declare function mention(u: PrismUnit, counter: TokenCounter): string;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Score normalization. The selectors expect relevance in [0, 1] with the top
|
|
201
|
+
* candidate at (or near) 1.0: `tauFloor` and the adaptive relevance cliff are
|
|
202
|
+
* fractions of that scale. Raw retriever scores rarely are: cosine
|
|
203
|
+
* similarities bunch up in 0.7–0.85, BM25 and reranker logits are unbounded,
|
|
204
|
+
* and vector-store distances run the wrong way.
|
|
205
|
+
*/
|
|
206
|
+
interface NormalizeOptions {
|
|
207
|
+
/**
|
|
208
|
+
* - `minmax` (default): best → 1, worst → 0. Spreads bunched-up scores
|
|
209
|
+
* (cosine similarities) across the full range.
|
|
210
|
+
* - `max`: divide by the best score. Keeps ratios between scores; only for
|
|
211
|
+
* non-negative scores.
|
|
212
|
+
*/
|
|
213
|
+
method?: 'minmax' | 'max';
|
|
214
|
+
/** Set to false for distances (lower = more relevant). Default true. */
|
|
215
|
+
higherIsBetter?: boolean;
|
|
216
|
+
}
|
|
217
|
+
/** Returns copies of the units with `score` mapped to [0, 1]. Input order is kept. */
|
|
218
|
+
declare function normalizeScores<T extends {
|
|
219
|
+
score: number;
|
|
220
|
+
}>(units: T[], opts?: NormalizeOptions): T[];
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Helpers around a selection result: turn it into prompt text, and compare it
|
|
224
|
+
* with what you send today (shadow mode).
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
interface ToContextOptions {
|
|
228
|
+
/** Separator between selected units. Default: a blank line. */
|
|
229
|
+
separator?: string;
|
|
230
|
+
/** Heading put above the tail. Default: "Other possibly relevant notes:". Pass '' for none. */
|
|
231
|
+
tailHeading?: string;
|
|
232
|
+
/** Wraps each selected unit, e.g. to add ids or XML tags. Default: the text as is. */
|
|
233
|
+
format?: (text: string, id: string) => string;
|
|
234
|
+
}
|
|
235
|
+
/** Joins a CABAR or Prism result into one string to put in the prompt. */
|
|
236
|
+
declare function toContext(result: CabarSelectResult | PrismSelectResult, opts?: ToContextOptions): string;
|
|
237
|
+
interface ShadowReport {
|
|
238
|
+
/** Tokens of every unit you passed in (what "send everything" costs). */
|
|
239
|
+
sendAllTokens: number;
|
|
240
|
+
/** Tokens CABAR would send: selected + tail. */
|
|
241
|
+
cabarTokens: number;
|
|
242
|
+
/** 1 − cabarTokens / sendAllTokens. */
|
|
243
|
+
savedFraction: number;
|
|
244
|
+
selectedIds: string[];
|
|
245
|
+
tailIds: string[];
|
|
246
|
+
droppedIds: string[];
|
|
247
|
+
result: CabarSelectResult;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Shadow mode: run CABAR next to your current pipeline without changing what
|
|
251
|
+
* you send. Log the report, compare answers, then switch when you trust it.
|
|
252
|
+
*/
|
|
253
|
+
declare function shadowReport(units: CabarUnit[], query: string, opts?: CabarSelectOptions): ShadowReport;
|
|
254
|
+
|
|
255
|
+
export { CabarSelectOptions, CabarSelectResult, CabarUnit, type Fidelity, type FidelityFactors, type NormalizeOptions, type PrismSelectOptions, type PrismSelectResult, type PrismSelectedUnit, PrismSelector, type PrismStats, type PrismUnit, type ShadowReport, Similarity, type ToContextOptions, TokenCounter, claimsRendering, extract, jaccard, mention, normalizeScores, shadowReport, splitSentences, toContext, tokenize, truncateToTokens, verbatim };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { T as TokenCounter, S as Similarity, C as CabarSelectResult, a as CabarUnit, b as CabarSelectOptions } from './cabar-B-R-rHby.js';
|
|
2
|
+
export { A as ADAPTIVE_DEFAULTS, c as CHAR4_COUNTER, d as CabarDecision, e as CabarSelector, f as CabarStats, D as DEFAULTS, g as DEFAULT_RECENCY_DECAY_DAYS, h as cosineSimilarity, i as embeddingSimilarity, j as estimateTokens, r as recencyDecay } from './cabar-B-R-rHby.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PrismSelector: CABAR-2 multi-fidelity budgeted selection.
|
|
6
|
+
*
|
|
7
|
+
* Where CabarSelector answers "which units do we spend verbatim budget
|
|
8
|
+
* on, and summarize the rest", Prism answers the finer question "at WHICH
|
|
9
|
+
* FIDELITY do we render each unit". It solves a Multiple-Choice Knapsack
|
|
10
|
+
* Problem (MCKP): each unit offers a small menu of renderings — verbatim /
|
|
11
|
+
* extract / claims / mention — with distinct (cost, utility) points, and the
|
|
12
|
+
* selector greedily packs marginal-utility-per-token, allowed to UPGRADE an
|
|
13
|
+
* already-selected unit to a costlier fidelity when that upgrade is the densest
|
|
14
|
+
* feasible move. All-or-nothing (CABAR-1) is the special case of a two-point
|
|
15
|
+
* menu {verbatim, absent}; Prism dominates it under tight budgets by trading a
|
|
16
|
+
* verbatim unit for several cheaper-fidelity units that together carry more.
|
|
17
|
+
*
|
|
18
|
+
* Design invariants (same purity contract as CabarSelector):
|
|
19
|
+
* - PURE + deterministic: no LLM, no I/O, no Date.now — the caller supplies
|
|
20
|
+
* `now`; `claims` are pre-fetched onto the units by the caller.
|
|
21
|
+
* - Provider-agnostic token cost: the injectable `TokenCounter` defaults to
|
|
22
|
+
* the shared char/4 estimator (prod), and benchmarks inject a real BPE
|
|
23
|
+
* counter. Selection logic never assumes a specific vocabulary.
|
|
24
|
+
* - Cache-stable OUTPUT ORDERING: selected units are emitted by
|
|
25
|
+
* (timestamp asc, id asc), NOT by score, so the same units land in the same
|
|
26
|
+
* prompt slots turn-over-turn (KV-cache friendly).
|
|
27
|
+
* - β-hysteresis: an optional per-unit bonus for re-selecting a unit at
|
|
28
|
+
* ≥ its previous fidelity (keeps prompts stable turn-over-turn). Defaults
|
|
29
|
+
* to 0, a no-op.
|
|
30
|
+
* - Answer-lossless FLOOR: every unit at or above `tauFloor` that misses the
|
|
31
|
+
* budget still gets a mention line in the tail, so nothing recallable is
|
|
32
|
+
* silently dropped.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/** The four rendering fidelities, most→least faithful. */
|
|
36
|
+
type Fidelity = 'verbatim' | 'extract' | 'claims' | 'mention';
|
|
37
|
+
/** A retrieved unit plus its caller-pre-fetched claims (the CabarUnit + claims). */
|
|
38
|
+
interface PrismUnit {
|
|
39
|
+
id: string;
|
|
40
|
+
content: string;
|
|
41
|
+
/** Relevance from your retriever, normalized to [0,1] (top item ideally 1.0). */
|
|
42
|
+
score: number;
|
|
43
|
+
timestamp?: Date;
|
|
44
|
+
/** Pre-resolved claim strings; enables the CLAIMS fidelity. Selector never fetches these. */
|
|
45
|
+
claims?: string[];
|
|
46
|
+
/** Optional vector for `similarity: embeddingSimilarity`. */
|
|
47
|
+
embedding?: ArrayLike<number>;
|
|
48
|
+
}
|
|
49
|
+
/** Per-fidelity multipliers φ(f) — how much utility a fidelity retains vs verbatim. */
|
|
50
|
+
type FidelityFactors = Record<Fidelity, number>;
|
|
51
|
+
interface PrismSelectOptions {
|
|
52
|
+
/** Token budget for the guaranteed block + selected renderings. The tail is capped separately by tailBudgetTokens. */
|
|
53
|
+
budgetTokens?: number;
|
|
54
|
+
/** Hard cap on DISTINCT units selected (upgrades do not count against it). */
|
|
55
|
+
maxUnits?: number;
|
|
56
|
+
/** Hard token cap for the mention-line tail (separate from budgetTokens). */
|
|
57
|
+
tailBudgetTokens?: number;
|
|
58
|
+
/** Minimum score for a unit to earn a tail mention line (below this: dropped). */
|
|
59
|
+
tauFloor?: number;
|
|
60
|
+
/** ρ = recencyLambda·decay + (1−recencyLambda). 0 ⇒ ρ≡1 (multi-session safe). */
|
|
61
|
+
recencyLambda?: number;
|
|
62
|
+
/** Recency scale in days for the exponential decay e^(-age/days). Default 365. */
|
|
63
|
+
recencyDecayDays?: number;
|
|
64
|
+
/** Blend on the novelty term: effectiveNovelty = 1 − noveltyWeight·(1 − novelty). */
|
|
65
|
+
noveltyWeight?: number;
|
|
66
|
+
/** Tokens pre-charged against budgetTokens before selection (e.g. resolved-claims block). */
|
|
67
|
+
guaranteedTokens?: number;
|
|
68
|
+
/** Deterministic "current time" for recency. Defaults to `new Date()`. */
|
|
69
|
+
now?: Date;
|
|
70
|
+
/** Injectable token cost model. Defaults to the shared char/4 estimator. */
|
|
71
|
+
tokenCounter?: TokenCounter;
|
|
72
|
+
/**
|
|
73
|
+
* Unit-level similarity used for novelty, in [0, 1]. Defaults to word-set
|
|
74
|
+
* Jaccard between the renderings. Pass `embeddingSimilarity` to catch paraphrases.
|
|
75
|
+
*/
|
|
76
|
+
similarity?: Similarity<PrismUnit>;
|
|
77
|
+
/** Per-fidelity utility multipliers φ. Merged over defaults. */
|
|
78
|
+
fidelityFactors?: Partial<FidelityFactors>;
|
|
79
|
+
/** β — multiplicative bonus ×(1+β) for re-selecting a unit at ≥ prev fidelity. */
|
|
80
|
+
hysteresisBonus?: number;
|
|
81
|
+
/** Prior turn's selection (unit → fidelity) for the β-hysteresis predicate. */
|
|
82
|
+
prevSelected?: Array<{
|
|
83
|
+
unitId: string;
|
|
84
|
+
fidelity: Fidelity;
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Adaptive stopping mode. When true, ADD-move admission
|
|
88
|
+
* (a unit newly entering the selection) is gated: past `minKeep` distinct
|
|
89
|
+
* units, a unit may only be ADD-admitted if its relevance fraction (score /
|
|
90
|
+
* top-candidate score) is >= `relFloor` AND the candidate rendering's
|
|
91
|
+
* novelty vs the already-chosen renderings is >= `novFloor`. UPGRADE moves
|
|
92
|
+
* and the mention-tail are unaffected. `maxCeilingTokens` replaces
|
|
93
|
+
* `budgetTokens` as the only hard token bound (`maxUnits` is ignored).
|
|
94
|
+
* Default false: behavior is byte-identical to the fixed-budget path.
|
|
95
|
+
*/
|
|
96
|
+
adaptive?: boolean;
|
|
97
|
+
/** Adaptive mode: distinct units ADD-admitted before the relFloor/novFloor gate applies. Default 3. */
|
|
98
|
+
minKeep?: number;
|
|
99
|
+
/** Adaptive mode: below this fraction of the top candidate's score, ADD admission stops. Default 0.4. */
|
|
100
|
+
relFloor?: number;
|
|
101
|
+
/** Adaptive mode: below this novelty vs chosen renderings, ADD admission stops. Default 0.2. */
|
|
102
|
+
novFloor?: number;
|
|
103
|
+
/** Adaptive mode: hard token ceiling — replaces budgetTokens as the bound. Default 4000. */
|
|
104
|
+
maxCeilingTokens?: number;
|
|
105
|
+
}
|
|
106
|
+
interface PrismSelectedUnit {
|
|
107
|
+
unit: PrismUnit;
|
|
108
|
+
fidelity: Fidelity;
|
|
109
|
+
rendered: string;
|
|
110
|
+
tokens: number;
|
|
111
|
+
}
|
|
112
|
+
interface PrismStats {
|
|
113
|
+
/** Sum of every candidate unit's VERBATIM cost (the pre-selection ceiling). */
|
|
114
|
+
candidateTokens: number;
|
|
115
|
+
selectedTokens: number;
|
|
116
|
+
tailTokens: number;
|
|
117
|
+
budgetTokens: number;
|
|
118
|
+
/** guaranteedTokens + selectedTokens + tailTokens — actual spend vs budgetTokens. */
|
|
119
|
+
utilizedTokens: number;
|
|
120
|
+
fidelityHistogram: Record<Fidelity, number>;
|
|
121
|
+
/** Number of greedy moves applied (adds + upgrades). */
|
|
122
|
+
moves: number;
|
|
123
|
+
}
|
|
124
|
+
interface PrismSelectResult {
|
|
125
|
+
selected: PrismSelectedUnit[];
|
|
126
|
+
/** Unselected units at or above tauFloor — floored into the mention tail. */
|
|
127
|
+
tail: PrismUnit[];
|
|
128
|
+
/** The rendered tail block (mention lines, or verbatim on the tiny-pool guard). */
|
|
129
|
+
tailBlock: string;
|
|
130
|
+
stats: PrismStats;
|
|
131
|
+
}
|
|
132
|
+
declare class PrismSelector {
|
|
133
|
+
/**
|
|
134
|
+
* MCKP-greedy multi-fidelity selection: build each unit's rendering menu,
|
|
135
|
+
* greedily apply the densest feasible ADD/UPGRADE move, run the KMN
|
|
136
|
+
* best-single swap, then floor the remainder into a mention tail.
|
|
137
|
+
*/
|
|
138
|
+
static select(units: PrismUnit[], query: string, opts?: PrismSelectOptions): PrismSelectResult;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Prism renderings: deterministic multi-fidelity renderings of a retrieved
|
|
143
|
+
* unit (the CABAR-2 "Prism" extension of CABAR's all-or-nothing selection).
|
|
144
|
+
*
|
|
145
|
+
* CABAR-1 spent budget on a unit at a single fidelity (verbatim, or nothing —
|
|
146
|
+
* with an extractive tail for the rest). Prism turns that binary into a ladder:
|
|
147
|
+
* a unit can be rendered at VERBATIM (full content), EXTRACT (query-aware
|
|
148
|
+
* sentence extract, ≤~40% of verbatim tokens), CLAIMS (its pre-resolved claim
|
|
149
|
+
* bullets), or MENTION (a one-line dereferenceable pointer). The MCKP selector
|
|
150
|
+
* (PrismSelector) then picks per-unit fidelities to maximize utility under the
|
|
151
|
+
* token budget instead of dropping units wholesale.
|
|
152
|
+
*
|
|
153
|
+
* Every rendering here is PURE and deterministic: no LLM, no I/O, no clock.
|
|
154
|
+
* Costs are measured through an injected `TokenCounter` (char/4 by default,
|
|
155
|
+
* real BPE when you inject one) so the same code costs the same
|
|
156
|
+
* text the caller will bill for. Claims are pre-fetched by the caller and live
|
|
157
|
+
* on the unit — this module never fetches them.
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
/** Lowercased word (3+ chars) token set — same family as CabarSelector.tokenize. */
|
|
161
|
+
declare function tokenize(text: string): Set<string>;
|
|
162
|
+
declare function jaccard(a: Set<string>, b: Set<string>): number;
|
|
163
|
+
/** Sentence split — same regex family as CabarSelector.buildTailSummary. */
|
|
164
|
+
declare function splitSentences(text: string): string[];
|
|
165
|
+
/**
|
|
166
|
+
* Word-boundary truncation to a token budget, appending an ellipsis only when
|
|
167
|
+
* the text is actually cut. Uses the injected counter so the cut respects the
|
|
168
|
+
* caller's tokenization (char/4 or BPE). Always keeps at least the first word.
|
|
169
|
+
*/
|
|
170
|
+
declare function truncateToTokens(text: string, maxTokens: number, counter: TokenCounter): string;
|
|
171
|
+
/** VERBATIM — the unit's full content, unchanged. */
|
|
172
|
+
declare function verbatim(u: PrismUnit): string;
|
|
173
|
+
/**
|
|
174
|
+
* EXTRACT — query-aware sentence extraction targeting ≤~40% of verbatim tokens.
|
|
175
|
+
*
|
|
176
|
+
* Sentences are scored by query-term overlap plus a first-sentence positional
|
|
177
|
+
* prior, deduped on normalized text, then greedily packed (highest score first,
|
|
178
|
+
* stable on original order) up to the ~40% token target. Selected sentences are
|
|
179
|
+
* emitted in ORIGINAL narrative order (unlike the score-ordered tail) so the
|
|
180
|
+
* extract reads coherently. Never returns empty for non-empty content: if the
|
|
181
|
+
* target is too small for any sentence, the single top-scored sentence is kept
|
|
182
|
+
* (a single-sentence unit thus extracts to itself, and is dropped later by the
|
|
183
|
+
* selector's cost-dominance guard rather than duplicating verbatim).
|
|
184
|
+
*/
|
|
185
|
+
declare function extract(u: PrismUnit, query: string, counter: TokenCounter): string;
|
|
186
|
+
/**
|
|
187
|
+
* CLAIMS — the unit's pre-resolved claims as '- <claim>' bullet lines.
|
|
188
|
+
* UNAVAILABLE (null) when the caller pre-fetched no claims for this unit.
|
|
189
|
+
*/
|
|
190
|
+
declare function claimsRendering(u: PrismUnit): string | null;
|
|
191
|
+
/**
|
|
192
|
+
* MENTION — a one-line dereferenceable pointer:
|
|
193
|
+
* [<id>@<yyyy-mm-dd if timestamp>] <first sentence, ≤25 tokens>
|
|
194
|
+
* This is the answer-lossless floor: even a unit that loses the budget contest
|
|
195
|
+
* still leaves a citable trace the caller can dereference back to the full unit.
|
|
196
|
+
*/
|
|
197
|
+
declare function mention(u: PrismUnit, counter: TokenCounter): string;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Score normalization. The selectors expect relevance in [0, 1] with the top
|
|
201
|
+
* candidate at (or near) 1.0: `tauFloor` and the adaptive relevance cliff are
|
|
202
|
+
* fractions of that scale. Raw retriever scores rarely are: cosine
|
|
203
|
+
* similarities bunch up in 0.7–0.85, BM25 and reranker logits are unbounded,
|
|
204
|
+
* and vector-store distances run the wrong way.
|
|
205
|
+
*/
|
|
206
|
+
interface NormalizeOptions {
|
|
207
|
+
/**
|
|
208
|
+
* - `minmax` (default): best → 1, worst → 0. Spreads bunched-up scores
|
|
209
|
+
* (cosine similarities) across the full range.
|
|
210
|
+
* - `max`: divide by the best score. Keeps ratios between scores; only for
|
|
211
|
+
* non-negative scores.
|
|
212
|
+
*/
|
|
213
|
+
method?: 'minmax' | 'max';
|
|
214
|
+
/** Set to false for distances (lower = more relevant). Default true. */
|
|
215
|
+
higherIsBetter?: boolean;
|
|
216
|
+
}
|
|
217
|
+
/** Returns copies of the units with `score` mapped to [0, 1]. Input order is kept. */
|
|
218
|
+
declare function normalizeScores<T extends {
|
|
219
|
+
score: number;
|
|
220
|
+
}>(units: T[], opts?: NormalizeOptions): T[];
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Helpers around a selection result: turn it into prompt text, and compare it
|
|
224
|
+
* with what you send today (shadow mode).
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
interface ToContextOptions {
|
|
228
|
+
/** Separator between selected units. Default: a blank line. */
|
|
229
|
+
separator?: string;
|
|
230
|
+
/** Heading put above the tail. Default: "Other possibly relevant notes:". Pass '' for none. */
|
|
231
|
+
tailHeading?: string;
|
|
232
|
+
/** Wraps each selected unit, e.g. to add ids or XML tags. Default: the text as is. */
|
|
233
|
+
format?: (text: string, id: string) => string;
|
|
234
|
+
}
|
|
235
|
+
/** Joins a CABAR or Prism result into one string to put in the prompt. */
|
|
236
|
+
declare function toContext(result: CabarSelectResult | PrismSelectResult, opts?: ToContextOptions): string;
|
|
237
|
+
interface ShadowReport {
|
|
238
|
+
/** Tokens of every unit you passed in (what "send everything" costs). */
|
|
239
|
+
sendAllTokens: number;
|
|
240
|
+
/** Tokens CABAR would send: selected + tail. */
|
|
241
|
+
cabarTokens: number;
|
|
242
|
+
/** 1 − cabarTokens / sendAllTokens. */
|
|
243
|
+
savedFraction: number;
|
|
244
|
+
selectedIds: string[];
|
|
245
|
+
tailIds: string[];
|
|
246
|
+
droppedIds: string[];
|
|
247
|
+
result: CabarSelectResult;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Shadow mode: run CABAR next to your current pipeline without changing what
|
|
251
|
+
* you send. Log the report, compare answers, then switch when you trust it.
|
|
252
|
+
*/
|
|
253
|
+
declare function shadowReport(units: CabarUnit[], query: string, opts?: CabarSelectOptions): ShadowReport;
|
|
254
|
+
|
|
255
|
+
export { CabarSelectOptions, CabarSelectResult, CabarUnit, type Fidelity, type FidelityFactors, type NormalizeOptions, type PrismSelectOptions, type PrismSelectResult, type PrismSelectedUnit, PrismSelector, type PrismStats, type PrismUnit, type ShadowReport, Similarity, type ToContextOptions, TokenCounter, claimsRendering, extract, jaccard, mention, normalizeScores, shadowReport, splitSentences, toContext, tokenize, truncateToTokens, verbatim };
|