pikelet-wasm 0.7.0
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/CHANGELOG.md +868 -0
- package/LICENSE +191 -0
- package/README.md +590 -0
- package/complete/builder.d.ts +82 -0
- package/complete/builder.mjs +527 -0
- package/complete/encoder-kernels/encoder.mjs +2 -0
- package/complete/encoder-kernels/encoder.node.mjs +2 -0
- package/complete/encoder-kernels/encoder.node.wasm +0 -0
- package/complete/encoder-kernels/encoder.wasm +0 -0
- package/complete/format.mjs +8 -0
- package/complete/index.d.ts +289 -0
- package/complete/index.mjs +1124 -0
- package/complete/inline-transformer.mjs +205 -0
- package/complete/lexical.mjs +264 -0
- package/complete/retrieval-abstention.mjs +119 -0
- package/complete/sources.mjs +186 -0
- package/complete/student-abstention.mjs +102 -0
- package/complete/student-embedder.mjs +231 -0
- package/complete/wordpiece.mjs +68 -0
- package/dist/engine.js +2 -0
- package/dist/engine.scalar.js +2 -0
- package/dist/engine.scalar.wasm +0 -0
- package/dist/engine.wasm +0 -0
- package/package.json +168 -0
- package/pancake-artifact-common.js +561 -0
- package/pancake-artifact-range.js +799 -0
- package/pancake-artifact-sketch.js +1040 -0
- package/pancake-artifact.d.ts +109 -0
- package/pancake-artifact.js +31 -0
- package/pancake-core.js +1268 -0
- package/pancake-errors.js +40 -0
- package/pancake-loader.js +66 -0
- package/pancake.d.ts +691 -0
- package/pancake.js +254 -0
- package/pancake.node.mjs +259 -0
- package/pancake.web.d.ts +50 -0
- package/pancake.web.mjs +88 -0
- package/pancake.workerd.mjs +72 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pikelet-wasm/complete — reader for complete .pancake artifacts
|
|
3
|
+
* (spec/COMPLETE_PROFILE.md, profile pancake-complete-v1). Opens any kind
|
|
4
|
+
* (1 student-inline, 2 declared-external, 3 inline-transformer) from a file
|
|
5
|
+
* path in Node or a range source anywhere.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** A byte-range source: local file, HTTP, memory, or anything else. */
|
|
9
|
+
export interface CompleteRangeSource {
|
|
10
|
+
/** Total bytes, when known. Verified against the header when present. */
|
|
11
|
+
size?: number;
|
|
12
|
+
preferredParallelism?: number;
|
|
13
|
+
preferredGapBytes?: number;
|
|
14
|
+
read(offset: number, length: number): Promise<Uint8Array | ArrayBufferLike>;
|
|
15
|
+
close?(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface HttpRangeSourceStats {
|
|
19
|
+
requests: number;
|
|
20
|
+
bytes: number;
|
|
21
|
+
acceptRanges: string | null;
|
|
22
|
+
etag: string | null;
|
|
23
|
+
fullFallback: boolean;
|
|
24
|
+
/** Transient-status (429/502/503/504) retries issued, across all reads. */
|
|
25
|
+
retries: number;
|
|
26
|
+
/**
|
|
27
|
+
* Redirect hops resolved while pinning the final URL. A redirecting host
|
|
28
|
+
* (GitHub release assets) is resolved once and range reads go straight
|
|
29
|
+
* to the target, so its rate-limited front door is charged per mount,
|
|
30
|
+
* not per read; expired signed URLs (401/403) re-resolve automatically.
|
|
31
|
+
*/
|
|
32
|
+
redirects: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface HttpRangeSource extends CompleteRangeSource {
|
|
36
|
+
stats: HttpRangeSourceStats;
|
|
37
|
+
init(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export declare function httpRangeSource(url: string, options?: {
|
|
41
|
+
preferredParallelism?: number;
|
|
42
|
+
preferredGapBytes?: number;
|
|
43
|
+
/** Cap on the one-time full download when a host ignores Range, enforced on received bytes. Default 64 MiB. */
|
|
44
|
+
maxFullFallbackBytes?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Query parameter appended per range read so each read gets its own HTTP
|
|
47
|
+
* cache key (defeats Chromium's same-URL cache-entry lock). Default 'r';
|
|
48
|
+
* pass null for hosts that sign the full query string (presigned URLs) —
|
|
49
|
+
* range reads then share the unmodified URL.
|
|
50
|
+
*/
|
|
51
|
+
cacheKeyParam?: string | null | false;
|
|
52
|
+
/**
|
|
53
|
+
* Retries per read for transient statuses (429/502/503/504), with capped
|
|
54
|
+
* exponential backoff (Retry-After honored when sane). Default 6; 0
|
|
55
|
+
* disables. CDNs rate-limit the parallel range bursts a query issues.
|
|
56
|
+
*/
|
|
57
|
+
maxRetries?: number;
|
|
58
|
+
}): HttpRangeSource;
|
|
59
|
+
|
|
60
|
+
export interface CompleteQueryResult {
|
|
61
|
+
matchQuality: 'strong' | 'weak' | 'none' | 'unscored';
|
|
62
|
+
confidence?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Each result is the hydrated corpus record plus the search's `id` and
|
|
65
|
+
* `distance`. Those two names are reserved: they always come from the
|
|
66
|
+
* search, and a record field of the same name is overwritten, never the
|
|
67
|
+
* other way round.
|
|
68
|
+
*/
|
|
69
|
+
results: Array<{ id: number; distance: number } & Record<string, unknown>>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface CompleteSearch {
|
|
73
|
+
info(): {
|
|
74
|
+
identity: string;
|
|
75
|
+
/** Container header formatVersion (1 or 2). */
|
|
76
|
+
formatVersion: number;
|
|
77
|
+
/** Manifest profile: 'pancake-complete-v1' | 'pancake-complete-v2'. */
|
|
78
|
+
profile: string;
|
|
79
|
+
/**
|
|
80
|
+
* Human-readable pack name from the identity-verified manifest
|
|
81
|
+
* (compile records it under corpus.provenance.name); null when the
|
|
82
|
+
* builder recorded none.
|
|
83
|
+
*/
|
|
84
|
+
name: string | null;
|
|
85
|
+
/**
|
|
86
|
+
* Content license recorded at compile (SPDX id or free text) under
|
|
87
|
+
* corpus.provenance.license; null when the builder recorded none.
|
|
88
|
+
*/
|
|
89
|
+
license: string | null;
|
|
90
|
+
records: number;
|
|
91
|
+
dim: number;
|
|
92
|
+
metric: string | number;
|
|
93
|
+
encoder: Record<string, unknown>;
|
|
94
|
+
/**
|
|
95
|
+
* Kind 2: true when the host encoder passed the declaration's verification
|
|
96
|
+
* vectors, false when served unverified (verifyEncoder:false or
|
|
97
|
+
* allowUnverifiedEncoder), null when no host encoder was supplied.
|
|
98
|
+
* Kind 3: whether the inline encoder verified against its own vectors —
|
|
99
|
+
* null while a lazily-opened encoder has not arrived yet (unknown, not
|
|
100
|
+
* unverified; it resolves before the first query completes). While
|
|
101
|
+
* deferred, `encoder` serves the identity-verified manifest declaration
|
|
102
|
+
* with `deferred: true`, replaced by the full declaration on arrival.
|
|
103
|
+
* Kind 1: null (inline student encoder, nothing external to verify).
|
|
104
|
+
*/
|
|
105
|
+
encoderVerified: boolean | null;
|
|
106
|
+
/**
|
|
107
|
+
* 'per-record-sha256' on format 2 (each hydrated record verified on its
|
|
108
|
+
* own range read); 'segment-sha256' on format 1 (whole-segment digests
|
|
109
|
+
* only, lazy record reads not independently verifiable).
|
|
110
|
+
*/
|
|
111
|
+
corpusIntegrity: string;
|
|
112
|
+
fileBytes: number;
|
|
113
|
+
residentBytes: number;
|
|
114
|
+
residentVerified: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* True only after a full vectors pass (verifyIndexVectors at open, or
|
|
117
|
+
* verifyVectors() later). Until then, lazily fetched rerank rows are
|
|
118
|
+
* committed via the identity-anchored vectorsSha256 but not verified
|
|
119
|
+
* per read.
|
|
120
|
+
*/
|
|
121
|
+
vectorsVerified: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Present when the artifact carries a lexical index segment (kind 5):
|
|
124
|
+
* queries run hybrid (BM25 candidates join the exact rerank; result
|
|
125
|
+
* order fuses distance and BM25 rankings by reciprocal rank). Null on
|
|
126
|
+
* vector-only artifacts.
|
|
127
|
+
*/
|
|
128
|
+
lexical: { terms: number; docCount: number; lazy?: true } | null;
|
|
129
|
+
/**
|
|
130
|
+
* 'engine' once a WASM scan kernel serves the resident scan
|
|
131
|
+
* (auto-staged or injected via options.sketchScanner); 'js' before
|
|
132
|
+
* background staging resolves and forever if it fails or was disabled.
|
|
133
|
+
*/
|
|
134
|
+
residentScan: 'engine' | 'js';
|
|
135
|
+
sampleQueries: string[];
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Verify the index's lazy vector rows against the identity-anchored
|
|
139
|
+
* vectorsSha256 (streamed where a streaming hash exists). Resolves true
|
|
140
|
+
* on match; throws on mismatch.
|
|
141
|
+
*/
|
|
142
|
+
verifyVectors(options?: { chunkBytes?: number }): Promise<true>;
|
|
143
|
+
query(text: string, options?: {
|
|
144
|
+
k?: number;
|
|
145
|
+
/**
|
|
146
|
+
* Retrieval mode on artifacts carrying a lexical segment: 'hybrid'
|
|
147
|
+
* (default — BM25 candidates join the rerank, RRF result order),
|
|
148
|
+
* 'vector' (ignore the lexical index), 'lexical' (BM25 ranking only),
|
|
149
|
+
* 'augmented' (BM25 candidates join the exact rerank but results stay
|
|
150
|
+
* in pure distance order — the mode for workloads scored against
|
|
151
|
+
* exact nearest neighbors, where RRF's reordering reads as loss by
|
|
152
|
+
* definition; measured on the 456k wiki eval it lifts recall@10 from
|
|
153
|
+
* 82.8% to 85.3% while RRF-ordered hybrid scores 45.9% on that
|
|
154
|
+
* metric). Abstention scores identically in every mode.
|
|
155
|
+
*/
|
|
156
|
+
retrieval?: 'hybrid' | 'vector' | 'lexical' | 'augmented';
|
|
157
|
+
rerank?: number;
|
|
158
|
+
parallelism?: number;
|
|
159
|
+
gap?: number;
|
|
160
|
+
maxRangeBytes?: number;
|
|
161
|
+
}): Promise<CompleteQueryResult>;
|
|
162
|
+
/** Hydrate one corpus record by id (verified per record on format 2). */
|
|
163
|
+
record(id: number): Promise<Record<string, unknown>>;
|
|
164
|
+
/** The evaluation segment's JSON object, or null when the artifact carries none. */
|
|
165
|
+
evaluation(): Promise<Record<string, unknown> | null>;
|
|
166
|
+
close(): Promise<void>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export declare function openPancakeFile(
|
|
170
|
+
input: string | CompleteRangeSource,
|
|
171
|
+
options?: {
|
|
172
|
+
/**
|
|
173
|
+
* Required to serve kind-2 (declared external encoder) artifacts. It is
|
|
174
|
+
* run against the declaration's verification vectors at open and the
|
|
175
|
+
* open fails if any disagree beyond the declared tolerance.
|
|
176
|
+
*/
|
|
177
|
+
encodeQuery?: (text: string) => Promise<Float32Array | number[]> | Float32Array | number[];
|
|
178
|
+
/** Skip encoder verification (kind 2 host vectors, kind 3 inline vectors). Default true. */
|
|
179
|
+
verifyEncoder?: boolean;
|
|
180
|
+
/** Serve a kind-2 declaration that carries no verification vectors, marked unverified. Default false. */
|
|
181
|
+
allowUnverifiedEncoder?: boolean;
|
|
182
|
+
/** Verify each hydrated record against its digest on format 2. Default true. */
|
|
183
|
+
verifyRecords?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Pin the expected manifest identity (sha256 hex). Checked against the
|
|
186
|
+
* header one 64-byte read in — a mismatched artifact is refused before
|
|
187
|
+
* anything else is fetched; the manifest-hash verification then binds
|
|
188
|
+
* the header's claim to the manifest bytes as always.
|
|
189
|
+
*/
|
|
190
|
+
expectedIdentity?: string;
|
|
191
|
+
/**
|
|
192
|
+
* Kind-3 artifacts open lazily: the ~25 MiB inline-encoder region is not
|
|
193
|
+
* read at open, and by default starts downloading in the background the
|
|
194
|
+
* moment open resolves (the first query awaits it; the whole segment is
|
|
195
|
+
* digest-verified on arrival, and the header/calibration slices used at
|
|
196
|
+
* open are byte-compared against it before any result is returned).
|
|
197
|
+
* Set false to defer the transfer entirely to the first query. Default
|
|
198
|
+
* true.
|
|
199
|
+
*/
|
|
200
|
+
prefetchEncoder?: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* Fully verify the index's lazy vector rows at open (one streamed pass
|
|
203
|
+
* against the identity-anchored vectorsSha256). Default false: without
|
|
204
|
+
* it, rows that feed reranking are covered by the whole-segment
|
|
205
|
+
* commitment but not verified per read until verifyVectors() runs —
|
|
206
|
+
* the documented transitional stance (spec section 6).
|
|
207
|
+
*/
|
|
208
|
+
verifyIndexVectors?: boolean;
|
|
209
|
+
/**
|
|
210
|
+
* Budget for any single open-path read (manifest, segment table,
|
|
211
|
+
* query-interp, corpus tables, evaluation, digest pages), honored
|
|
212
|
+
* strictly. Default 256 MiB; Infinity defers to the 2 GiB backstop.
|
|
213
|
+
*/
|
|
214
|
+
maxReadBytes?: number;
|
|
215
|
+
/** Budget for a single corpus record read. Default 16 MiB. */
|
|
216
|
+
maxRecordBytes?: number;
|
|
217
|
+
/** Override the kind-3 wasm kernel loader. */
|
|
218
|
+
createEncoder?: () => Promise<unknown> | unknown;
|
|
219
|
+
/**
|
|
220
|
+
* Resident-scan acceleration. Default (undefined): in Node, when the
|
|
221
|
+
* corpus is large enough that the pure-JS sketch scan dominates query
|
|
222
|
+
* time (~16M sketch cells), the engine's SIMD scan kernel is staged in
|
|
223
|
+
* the background and serves queries once ready — the JS scan answers
|
|
224
|
+
* identically until then and permanently if staging fails. Pass false
|
|
225
|
+
* to force the JS scan; a ready scanner object (createSketchScanner's
|
|
226
|
+
* shape — caller-owned, not disposed by close()); or an async factory
|
|
227
|
+
* (sketchArtifact) => scanner, invoked once the sketch is fully
|
|
228
|
+
* resident (the injection point for browser bundles, which cannot load
|
|
229
|
+
* the Node engine entrypoint).
|
|
230
|
+
*/
|
|
231
|
+
sketchScanner?: false | { scan: (pooledQuery: unknown, c: number) => unknown }
|
|
232
|
+
| ((sketch: unknown) => unknown | Promise<unknown>);
|
|
233
|
+
rerankParallelism?: number;
|
|
234
|
+
rerankGap?: number;
|
|
235
|
+
rerankMaxRangeBytes?: number;
|
|
236
|
+
}
|
|
237
|
+
): Promise<CompleteSearch>;
|
|
238
|
+
|
|
239
|
+
/** Header formatVersion -> manifest profile accepted by this reader. */
|
|
240
|
+
export declare const SUPPORTED_PROFILES: Readonly<Record<number, string>>;
|
|
241
|
+
export declare const CORPUS_LAYOUT_V2: 'records-v2';
|
|
242
|
+
/**
|
|
243
|
+
* Check a host encoder against a kind-2 declaration's verification vectors
|
|
244
|
+
* (contract 4.4 mode 2) without opening an artifact. Throws on dimension
|
|
245
|
+
* or tolerance disagreement; resolves with the number of vectors checked.
|
|
246
|
+
*/
|
|
247
|
+
export declare function verifyHostEncoder(
|
|
248
|
+
declaration: Record<string, unknown>,
|
|
249
|
+
encodeQuery: (text: string) => Promise<Float32Array | number[]> | Float32Array | number[],
|
|
250
|
+
dim: number
|
|
251
|
+
): Promise<{ checked: number }>;
|
|
252
|
+
|
|
253
|
+
/** Kernel layout compiled into the kind-3 encoder (mirrors encoder.cpp). */
|
|
254
|
+
export declare const KERNEL_LAYOUT: Record<'V' | 'P' | 'T' | 'D' | 'F' | 'L' | 'B' | 'H', number>;
|
|
255
|
+
export declare function expectedBlobBytes(layout?: Record<string, number>): number;
|
|
256
|
+
export declare function parseInlineTransformerEncoder(encoderBytes: Uint8Array): {
|
|
257
|
+
declaration: Record<string, unknown>;
|
|
258
|
+
vocabText: string;
|
|
259
|
+
blob: Uint8Array;
|
|
260
|
+
};
|
|
261
|
+
export declare function createInlineTransformerEmbedder(input: {
|
|
262
|
+
declaration: Record<string, unknown>;
|
|
263
|
+
vocabText: string;
|
|
264
|
+
blob: Uint8Array;
|
|
265
|
+
createEncoder: () => Promise<unknown> | unknown;
|
|
266
|
+
verify?: boolean;
|
|
267
|
+
}): Promise<{
|
|
268
|
+
declaration: Record<string, unknown>;
|
|
269
|
+
dim: number;
|
|
270
|
+
maxSeq: number;
|
|
271
|
+
embed(text: string): Promise<{ vector: Float32Array; text: string; windows: number }>;
|
|
272
|
+
dispose(): void;
|
|
273
|
+
}>;
|
|
274
|
+
/**
|
|
275
|
+
* Assert an expected verification-vector embedding is exactly dim finite
|
|
276
|
+
* numbers; throws otherwise. Malformed expectations would otherwise make
|
|
277
|
+
* every comparison NaN and "pass".
|
|
278
|
+
*/
|
|
279
|
+
export declare function validateExpectedEmbedding(values: unknown, dim: number, label: string): void;
|
|
280
|
+
/** Validate (or default to 1e-3) a verification vector's tolerance. */
|
|
281
|
+
export declare function validateTestVectorTolerance(tolerance: unknown, label: string): number;
|
|
282
|
+
export declare const INLINE_TEST_VECTOR_TEXTS: string[];
|
|
283
|
+
export declare function buildInlineTestVectors(embedder: unknown, texts?: string[]): Promise<Array<{
|
|
284
|
+
text: string; windows: number; embedding: number[]; tolerance: number;
|
|
285
|
+
}>>;
|
|
286
|
+
export declare function verifyInlineTestVectors(embedder: unknown): Promise<{ checked: number }>;
|
|
287
|
+
|
|
288
|
+
/** Documented alias for openPancakeFile — the project renamed to Pikelet; the reader's original export stays for compatibility. */
|
|
289
|
+
export declare const openPikeletFile: typeof openPancakeFile;
|