@stabrise/scaledp 0.1.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/LICENSE +661 -0
- package/README.md +218 -0
- package/dist/box-DAfzwfhA.d.ts +119 -0
- package/dist/config-g6IrKlDC.d.ts +80 -0
- package/dist/data-to-image-DoZ4jQ3R.js +54 -0
- package/dist/data-to-image-DoZ4jQ3R.js.map +1 -0
- package/dist/detect/index.d.ts +71 -0
- package/dist/detect/index.js +2 -0
- package/dist/detect-q8AI_Jdj.js +274 -0
- package/dist/detect-q8AI_Jdj.js.map +1 -0
- package/dist/detector-output-C0Qt-jEq.d.ts +13 -0
- package/dist/detector-output-lyF1Mqb8.js +13 -0
- package/dist/detector-output-lyF1Mqb8.js.map +1 -0
- package/dist/display/index.d.ts +66 -0
- package/dist/display/index.js +237 -0
- package/dist/display/index.js.map +1 -0
- package/dist/document-B8I61TiY.d.ts +16 -0
- package/dist/entity-CedtRhU1.d.ts +22 -0
- package/dist/entity-D6Hxaugj.js +13 -0
- package/dist/entity-D6Hxaugj.js.map +1 -0
- package/dist/image-CAH2rLv9.js +511 -0
- package/dist/image-CAH2rLv9.js.map +1 -0
- package/dist/image-Dc5TSg46.d.ts +18 -0
- package/dist/image-DoZDJkcR.js +37 -0
- package/dist/image-DoZDJkcR.js.map +1 -0
- package/dist/image-draw-boxes-De0QbFv9.js +285 -0
- package/dist/image-draw-boxes-De0QbFv9.js.map +1 -0
- package/dist/index.d.ts +269 -0
- package/dist/index.js +11 -0
- package/dist/model-cache-BEaqqRZ9.js +182 -0
- package/dist/model-cache-BEaqqRZ9.js.map +1 -0
- package/dist/model-cache-BhFYpfZz.d.ts +36 -0
- package/dist/ner/index.d.ts +293 -0
- package/dist/ner/index.js +2 -0
- package/dist/ner-SsZLZ6ed.js +1028 -0
- package/dist/ner-SsZLZ6ed.js.map +1 -0
- package/dist/ocr/index.d.ts +440 -0
- package/dist/ocr/index.js +3 -0
- package/dist/ocr-OHX2WM3e.js +1294 -0
- package/dist/ocr-OHX2WM3e.js.map +1 -0
- package/dist/ort-CXDoPrtw.js +73 -0
- package/dist/ort-CXDoPrtw.js.map +1 -0
- package/dist/params-DapwK9Ns.js +37 -0
- package/dist/params-DapwK9Ns.js.map +1 -0
- package/dist/pdf/index.d.ts +123 -0
- package/dist/pdf/index.js +2 -0
- package/dist/pdf-BQl0dneD.js +417 -0
- package/dist/pdf-BQl0dneD.js.map +1 -0
- package/dist/pipeline-DACqGkpN.js +240 -0
- package/dist/pipeline-DACqGkpN.js.map +1 -0
- package/dist/pipeline-DeLO-OCE.d.ts +139 -0
- package/dist/registry/index.d.ts +169 -0
- package/dist/registry/index.js +1061 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/text-ahMLpxN9.js +109 -0
- package/dist/text-ahMLpxN9.js.map +1 -0
- package/dist/worker/index.d.ts +105 -0
- package/dist/worker/index.js +180 -0
- package/dist/worker/index.js.map +1 -0
- package/package.json +135 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
//#region src/core/config.ts
|
|
2
|
+
const DEFAULTS = {
|
|
3
|
+
modelHost: "https://huggingface.co",
|
|
4
|
+
cache: "indexeddb",
|
|
5
|
+
cacheDbName: "scaledp-models",
|
|
6
|
+
executionProviders: ["wasm"],
|
|
7
|
+
numThreads: 0,
|
|
8
|
+
pdf: {},
|
|
9
|
+
tesseract: {},
|
|
10
|
+
hf: {}
|
|
11
|
+
};
|
|
12
|
+
let current = { ...DEFAULTS };
|
|
13
|
+
/** Merge `patch` into the global config. Nested asset maps merge per key. */
|
|
14
|
+
function configure(patch) {
|
|
15
|
+
current = {
|
|
16
|
+
...current,
|
|
17
|
+
...patch,
|
|
18
|
+
pdf: {
|
|
19
|
+
...current.pdf,
|
|
20
|
+
...patch.pdf
|
|
21
|
+
},
|
|
22
|
+
tesseract: {
|
|
23
|
+
...current.tesseract,
|
|
24
|
+
...patch.tesseract
|
|
25
|
+
},
|
|
26
|
+
hf: {
|
|
27
|
+
...current.hf,
|
|
28
|
+
...patch.hf
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return current;
|
|
32
|
+
}
|
|
33
|
+
function getConfig() {
|
|
34
|
+
return current;
|
|
35
|
+
}
|
|
36
|
+
/** Restore defaults. Primarily for tests. */
|
|
37
|
+
function resetConfig() {
|
|
38
|
+
current = {
|
|
39
|
+
...DEFAULTS,
|
|
40
|
+
pdf: {},
|
|
41
|
+
tesseract: {},
|
|
42
|
+
hf: {}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Threads to request from onnxruntime-web.
|
|
47
|
+
*
|
|
48
|
+
* Leaves one core for the UI and caps at 4 -- past that, ORT's own
|
|
49
|
+
* synchronisation overhead outweighs the gain on these model sizes.
|
|
50
|
+
*/
|
|
51
|
+
function defaultNumThreads() {
|
|
52
|
+
const cores = typeof navigator !== "undefined" && typeof navigator.hardwareConcurrency === "number" ? navigator.hardwareConcurrency : 4;
|
|
53
|
+
return Math.max(1, Math.min(4, cores - 1));
|
|
54
|
+
}
|
|
55
|
+
function resolveNumThreads() {
|
|
56
|
+
const configured = getConfig().numThreads;
|
|
57
|
+
return configured > 0 ? configured : defaultNumThreads();
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/core/errors.ts
|
|
61
|
+
/**
|
|
62
|
+
* ScaleDP stages never throw by default: a failure is captured into the output
|
|
63
|
+
* schema's `exception` field so a pipeline always completes and partial results
|
|
64
|
+
* survive. `propagateError: true` opts a stage into throwing instead.
|
|
65
|
+
*/
|
|
66
|
+
var ScaleDpError = class extends Error {
|
|
67
|
+
stage;
|
|
68
|
+
cause;
|
|
69
|
+
constructor(message, stage, cause) {
|
|
70
|
+
super(message);
|
|
71
|
+
this.stage = stage;
|
|
72
|
+
this.cause = cause;
|
|
73
|
+
this.name = "ScaleDpError";
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
var ImageError = class extends ScaleDpError {
|
|
77
|
+
name = "ImageError";
|
|
78
|
+
};
|
|
79
|
+
var OcrError = class extends ScaleDpError {
|
|
80
|
+
name = "OcrError";
|
|
81
|
+
};
|
|
82
|
+
var DetectionError = class extends ScaleDpError {
|
|
83
|
+
name = "DetectionError";
|
|
84
|
+
};
|
|
85
|
+
var NerError = class extends ScaleDpError {
|
|
86
|
+
name = "NerError";
|
|
87
|
+
};
|
|
88
|
+
var ConfigError = class extends ScaleDpError {
|
|
89
|
+
name = "ConfigError";
|
|
90
|
+
};
|
|
91
|
+
/** Render a caught value the way Python writes a traceback into `exception`. */
|
|
92
|
+
function formatException(stage, error) {
|
|
93
|
+
if (error instanceof Error) return `${stage}: ${error.name}: ${error.message}${error.stack ? `\n${error.stack}` : ""}`;
|
|
94
|
+
return `${stage}: ${String(error)}`;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/core/pipeline.ts
|
|
98
|
+
/**
|
|
99
|
+
* The pipeline runner, modelled on `scaledp/pipeline/PandasPipeline.py` rather
|
|
100
|
+
* than on Spark.
|
|
101
|
+
*
|
|
102
|
+
* ScaleDP's Spark coupling is thin: every stage is a pure `Transformer` (there
|
|
103
|
+
* are no Estimators, so no fit/transform duality) and the only DataFrame surface
|
|
104
|
+
* stages use is withColumn / drop / select. That reduces to an array of plain
|
|
105
|
+
* row objects, which is what this file implements.
|
|
106
|
+
*/
|
|
107
|
+
const EXECUTION_TIME_COL = "execution_time";
|
|
108
|
+
const ROW_TIME_COL = "row_time";
|
|
109
|
+
/**
|
|
110
|
+
* Base class for every stage.
|
|
111
|
+
*
|
|
112
|
+
* Subclasses implement `apply`, which transforms a single row's input value.
|
|
113
|
+
* The base handles column wiring, error capture and the `keepInputData`
|
|
114
|
+
* contract, so those behave identically everywhere.
|
|
115
|
+
*/
|
|
116
|
+
var Stage = class {
|
|
117
|
+
params;
|
|
118
|
+
constructor(params) {
|
|
119
|
+
this.params = params;
|
|
120
|
+
}
|
|
121
|
+
/** Optional per-stage setup (model download, session creation). Called once. */
|
|
122
|
+
async init() {}
|
|
123
|
+
/** Release any held resources (ONNX sessions, workers). */
|
|
124
|
+
async dispose() {}
|
|
125
|
+
/**
|
|
126
|
+
* A stage may emit several rows per input row -- PDF page explosion, box
|
|
127
|
+
* cropping. Returning `null` means "use the single-row path".
|
|
128
|
+
*/
|
|
129
|
+
async expand(_input, _row, _ctx) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
async transform(rows, ctx) {
|
|
133
|
+
const { inputCol, outputCol, keepInputData, propagateError } = this.params;
|
|
134
|
+
const out = [];
|
|
135
|
+
for (const row of rows) {
|
|
136
|
+
ctx.signal?.throwIfAborted();
|
|
137
|
+
const input = row[inputCol];
|
|
138
|
+
let next;
|
|
139
|
+
const started = performance.now();
|
|
140
|
+
try {
|
|
141
|
+
next = await this.expand(input, row, ctx) ?? [{
|
|
142
|
+
...row,
|
|
143
|
+
[outputCol]: await this.apply(input, row, ctx)
|
|
144
|
+
}];
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (propagateError) throw error;
|
|
147
|
+
next = [{
|
|
148
|
+
...row,
|
|
149
|
+
[outputCol]: this.onError(formatException(this.name, error), row)
|
|
150
|
+
}];
|
|
151
|
+
}
|
|
152
|
+
const elapsed = performance.now() - started;
|
|
153
|
+
if (!keepInputData && inputCol !== outputCol) for (const r of next) delete r[inputCol];
|
|
154
|
+
for (const r of next) chargeRow(r, this.name, elapsed / next.length);
|
|
155
|
+
out.push(...next);
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Add a stage's cost to one row's running total.
|
|
162
|
+
*
|
|
163
|
+
* The row inherited its predecessor's timings by the spread that built it, so
|
|
164
|
+
* the record is copied before writing -- sibling rows from one expand would
|
|
165
|
+
* otherwise share it and every charge would land on all of them.
|
|
166
|
+
*/
|
|
167
|
+
function chargeRow(row, name, ms) {
|
|
168
|
+
const previous = row[ROW_TIME_COL];
|
|
169
|
+
const stages = { ...previous?.stages };
|
|
170
|
+
stages[name] = (stages[name] ?? 0) + ms;
|
|
171
|
+
row[ROW_TIME_COL] = {
|
|
172
|
+
stages,
|
|
173
|
+
total: (previous?.total ?? 0) + ms
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
var Pipeline = class {
|
|
177
|
+
stages;
|
|
178
|
+
constructor(stages) {
|
|
179
|
+
this.stages = stages;
|
|
180
|
+
}
|
|
181
|
+
/** Run every stage in order. Input is normalised into rows first. */
|
|
182
|
+
async transform(input, options = {}) {
|
|
183
|
+
let rows = await toRows(input);
|
|
184
|
+
const timings = {};
|
|
185
|
+
const started = performance.now();
|
|
186
|
+
for (const [index, stage] of this.stages.entries()) {
|
|
187
|
+
options.signal?.throwIfAborted();
|
|
188
|
+
const t0 = performance.now();
|
|
189
|
+
await stage.init();
|
|
190
|
+
rows = await stage.transform(rows, {
|
|
191
|
+
index,
|
|
192
|
+
signal: options.signal
|
|
193
|
+
});
|
|
194
|
+
const elapsed = performance.now() - t0;
|
|
195
|
+
const key = timings[stage.name] === void 0 ? stage.name : `${stage.name}#${index}`;
|
|
196
|
+
timings[key] = elapsed;
|
|
197
|
+
options.onStage?.(stage.name, elapsed, rows.length);
|
|
198
|
+
}
|
|
199
|
+
const executionTime = {
|
|
200
|
+
stages: timings,
|
|
201
|
+
total: performance.now() - started
|
|
202
|
+
};
|
|
203
|
+
return rows.map((row) => ({
|
|
204
|
+
...row,
|
|
205
|
+
[EXECUTION_TIME_COL]: executionTime
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
async dispose() {
|
|
209
|
+
await Promise.all(this.stages.map((s) => s.dispose()));
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
/** Normalise any accepted input into pipeline rows with `content` and `path`. */
|
|
213
|
+
async function toRows(input) {
|
|
214
|
+
if (Array.isArray(input)) return input.map((r) => ({ ...r }));
|
|
215
|
+
if (typeof input === "string") {
|
|
216
|
+
const response = await fetch(input);
|
|
217
|
+
if (!response.ok) throw new Error(`Failed to fetch ${input}: ${response.status} ${response.statusText}`);
|
|
218
|
+
return [{
|
|
219
|
+
content: new Uint8Array(await response.arrayBuffer()),
|
|
220
|
+
path: input
|
|
221
|
+
}];
|
|
222
|
+
}
|
|
223
|
+
if (input instanceof Uint8Array) return [{
|
|
224
|
+
content: input,
|
|
225
|
+
path: "memory"
|
|
226
|
+
}];
|
|
227
|
+
if (input instanceof ArrayBuffer) return [{
|
|
228
|
+
content: new Uint8Array(input),
|
|
229
|
+
path: "memory"
|
|
230
|
+
}];
|
|
231
|
+
if (typeof Blob !== "undefined" && input instanceof Blob) return [{
|
|
232
|
+
content: new Uint8Array(await input.arrayBuffer()),
|
|
233
|
+
path: "name" in input && typeof input.name === "string" ? input.name : "memory"
|
|
234
|
+
}];
|
|
235
|
+
return [{ ...input }];
|
|
236
|
+
}
|
|
237
|
+
//#endregion
|
|
238
|
+
export { resolveNumThreads as _, toRows as a, ImageError as c, ScaleDpError as d, formatException as f, resetConfig as g, getConfig as h, Stage as i, NerError as l, defaultNumThreads as m, Pipeline as n, ConfigError as o, configure as p, ROW_TIME_COL as r, DetectionError as s, EXECUTION_TIME_COL as t, OcrError as u };
|
|
239
|
+
|
|
240
|
+
//# sourceMappingURL=pipeline-DACqGkpN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-DACqGkpN.js","names":[],"sources":["../src/core/config.ts","../src/core/errors.ts","../src/core/pipeline.ts"],"sourcesContent":["/**\n * Global configuration. Everything an application owns -- asset URLs, model\n * hosts, auth -- is injected here rather than hardcoded, which is the main\n * structural difference from the pdftools prototype this library supersedes.\n */\n\nexport interface ModelProgress {\n repo: string\n file: string\n /** Bytes fetched so far across the request set. */\n loaded: number\n /** Total bytes expected; 0 when the server sent no content-length. */\n total: number\n phase: 'downloading' | 'initializing' | 'ready'\n}\n\nexport interface ScaleDpConfig {\n /** Base URL models resolve against. Point at an origin you control to self-host. */\n modelHost: string\n /** Where downloaded model files are kept between page loads. */\n cache: 'indexeddb' | 'none'\n /** IndexedDB database name, so consumers can isolate or purge their own store. */\n cacheDbName: string\n /**\n * Bearer token supplier for private model repos. Returning `undefined`\n * means \"fetch anonymously\".\n */\n auth?: (repo: string) => Promise<string | undefined> | string | undefined\n /** Reports download progress for every model file. */\n onProgress?: (progress: ModelProgress) => void\n /** Execution providers, in priority order, for ONNX sessions. */\n executionProviders: readonly string[]\n /**\n * WASM threads. `0` lets onnxruntime-web choose from hardwareConcurrency.\n * Threading only engages on a cross-origin-isolated page (COOP/COEP);\n * without that ORT silently falls back to the single-threaded build.\n */\n numThreads: number\n /**\n * Directory holding the onnxruntime-web `.wasm`/`.mjs` pair. The loader and\n * the binary must come from the same build variant AND the same version --\n * a mismatch fails at init with an opaque error. Leave unset to let\n * onnxruntime-web resolve its own default.\n */\n ortWasmPaths?: string\n /** pdf.js assets. All must be served by the consuming application. */\n pdf: {\n workerSrc?: string\n cMapUrl?: string\n standardFontDataUrl?: string\n wasmUrl?: string\n }\n /** Tesseract assets. */\n tesseract: {\n workerUrl?: string\n /** Base URL for `<lang>.traineddata` files. */\n dataUrl?: string\n }\n /** Hugging Face host overrides, for proxying gated repos through your origin. */\n hf: {\n remoteHost?: string\n /** e.g. 'api/hf-model/{model}/resolve/{revision}/' */\n remotePathTemplate?: string\n }\n}\n\nconst DEFAULTS: ScaleDpConfig = {\n modelHost: 'https://huggingface.co',\n cache: 'indexeddb',\n cacheDbName: 'scaledp-models',\n executionProviders: ['wasm'],\n numThreads: 0,\n pdf: {},\n tesseract: {},\n hf: {},\n}\n\nlet current: ScaleDpConfig = { ...DEFAULTS }\n\n/** Merge `patch` into the global config. Nested asset maps merge per key. */\nexport function configure(patch: Partial<ScaleDpConfig>): ScaleDpConfig {\n current = {\n ...current,\n ...patch,\n pdf: { ...current.pdf, ...patch.pdf },\n tesseract: { ...current.tesseract, ...patch.tesseract },\n hf: { ...current.hf, ...patch.hf },\n }\n return current\n}\n\nexport function getConfig(): Readonly<ScaleDpConfig> {\n return current\n}\n\n/** Restore defaults. Primarily for tests. */\nexport function resetConfig(): void {\n current = { ...DEFAULTS, pdf: {}, tesseract: {}, hf: {} }\n}\n\n/**\n * Threads to request from onnxruntime-web.\n *\n * Leaves one core for the UI and caps at 4 -- past that, ORT's own\n * synchronisation overhead outweighs the gain on these model sizes.\n */\nexport function defaultNumThreads(): number {\n const cores =\n typeof navigator !== 'undefined' && typeof navigator.hardwareConcurrency === 'number'\n ? navigator.hardwareConcurrency\n : 4\n return Math.max(1, Math.min(4, cores - 1))\n}\n\nexport function resolveNumThreads(): number {\n const configured = getConfig().numThreads\n return configured > 0 ? configured : defaultNumThreads()\n}\n","/**\n * ScaleDP stages never throw by default: a failure is captured into the output\n * schema's `exception` field so a pipeline always completes and partial results\n * survive. `propagateError: true` opts a stage into throwing instead.\n */\n\nexport class ScaleDpError extends Error {\n constructor(\n message: string,\n readonly stage: string,\n override readonly cause?: unknown\n ) {\n super(message)\n this.name = 'ScaleDpError'\n }\n}\n\nexport class ImageError extends ScaleDpError {\n override readonly name = 'ImageError'\n}\nexport class OcrError extends ScaleDpError {\n override readonly name = 'OcrError'\n}\nexport class DetectionError extends ScaleDpError {\n override readonly name = 'DetectionError'\n}\nexport class NerError extends ScaleDpError {\n override readonly name = 'NerError'\n}\nexport class ConfigError extends ScaleDpError {\n override readonly name = 'ConfigError'\n}\n\n/** Render a caught value the way Python writes a traceback into `exception`. */\nexport function formatException(stage: string, error: unknown): string {\n if (error instanceof Error) {\n return `${stage}: ${error.name}: ${error.message}${error.stack ? `\\n${error.stack}` : ''}`\n }\n return `${stage}: ${String(error)}`\n}\n","/**\n * The pipeline runner, modelled on `scaledp/pipeline/PandasPipeline.py` rather\n * than on Spark.\n *\n * ScaleDP's Spark coupling is thin: every stage is a pure `Transformer` (there\n * are no Estimators, so no fit/transform duality) and the only DataFrame surface\n * stages use is withColumn / drop / select. That reduces to an array of plain\n * row objects, which is what this file implements.\n */\n\nimport { formatException } from './errors.js'\nimport type { BaseStageParams } from './params.js'\n\n/** One record flowing through the pipeline. Stages read and write named fields. */\nexport type Row = Record<string, unknown>\n\n/** Per-stage wall-clock timings, mirroring PandasPipeline's `execution_time` column. */\nexport interface ExecutionTime {\n stages: Record<string, number>\n total: number\n}\n\nexport const EXECUTION_TIME_COL = 'execution_time'\n\n/**\n * Per-row timings, accumulated as a row travels the pipeline.\n *\n * `execution_time` is per *run* -- one number per stage, the same on every row,\n * which is what Python records. That cannot answer \"how long did page 7 take\",\n * because a stage's number covers every page at once. This column can: each row\n * carries the time spent on it alone.\n *\n * A stage that expands produces several rows from one call, so its cost is\n * split evenly between them. The parts still sum to the call, but no finer\n * attribution is available from outside the stage.\n */\nexport interface RowTime {\n stages: Record<string, number>\n total: number\n}\n\nexport const ROW_TIME_COL = 'row_time'\n\n/** Anything a pipeline can be fed directly. */\nexport type PipelineInput = Uint8Array | ArrayBuffer | Blob | File | string | Row | Row[]\n\n/**\n * A stage described well enough to reconstruct it from plain data.\n *\n * This is the serialised form of a pipeline: `StageDescriptor[]` is JSON, so it\n * crosses the worker boundary (see `@stabrise/scaledp/worker`) and survives a\n * round trip through storage. `@stabrise/scaledp/registry` turns it back into\n * live stages.\n */\nexport interface StageDescriptor {\n /** Exported class name, e.g. 'PdfToImage'. */\n type: string\n /** Constructor options. Must be structured-cloneable. */\n options?: Record<string, unknown>\n}\n\nexport interface StageContext {\n /** Zero-based index of this stage in the pipeline. */\n index: number\n signal?: AbortSignal\n}\n\n/**\n * Base class for every stage.\n *\n * Subclasses implement `apply`, which transforms a single row's input value.\n * The base handles column wiring, error capture and the `keepInputData`\n * contract, so those behave identically everywhere.\n */\nexport abstract class Stage<P extends BaseStageParams = BaseStageParams> {\n abstract readonly name: string\n\n constructor(readonly params: P) {}\n\n /**\n * Transform one row's input value into this stage's output value.\n *\n * Throwing is fine and expected -- `transform` converts it into the output\n * schema's `exception` field unless `propagateError` is set.\n */\n protected abstract apply(input: unknown, row: Row, ctx: StageContext): Promise<unknown>\n\n /**\n * Value written to `outputCol` when `apply` throws. Subclasses return an\n * empty instance of their output schema carrying the message, so downstream\n * stages see a well-formed value rather than `undefined`.\n */\n protected abstract onError(message: string, row: Row): unknown\n\n /** Optional per-stage setup (model download, session creation). Called once. */\n async init(): Promise<void> {}\n\n /** Release any held resources (ONNX sessions, workers). */\n async dispose(): Promise<void> {}\n\n /**\n * A stage may emit several rows per input row -- PDF page explosion, box\n * cropping. Returning `null` means \"use the single-row path\".\n */\n protected async expand(_input: unknown, _row: Row, _ctx: StageContext): Promise<Row[] | null> {\n return null\n }\n\n async transform(rows: Row[], ctx: StageContext): Promise<Row[]> {\n const { inputCol, outputCol, keepInputData, propagateError } = this.params\n const out: Row[] = []\n\n for (const row of rows) {\n ctx.signal?.throwIfAborted()\n const input = row[inputCol]\n let next: Row[]\n\n const started = performance.now()\n try {\n const expanded = await this.expand(input, row, ctx)\n next = expanded ?? [{ ...row, [outputCol]: await this.apply(input, row, ctx) }]\n } catch (error) {\n if (propagateError) throw error\n next = [{ ...row, [outputCol]: this.onError(formatException(this.name, error), row) }]\n }\n // Failures are timed too: a stage that spent nine seconds before\n // throwing still cost nine seconds.\n const elapsed = performance.now() - started\n\n if (!keepInputData && inputCol !== outputCol) {\n for (const r of next) delete r[inputCol]\n }\n for (const r of next) chargeRow(r, this.name, elapsed / next.length)\n out.push(...next)\n }\n return out\n }\n}\n\n/**\n * Add a stage's cost to one row's running total.\n *\n * The row inherited its predecessor's timings by the spread that built it, so\n * the record is copied before writing -- sibling rows from one expand would\n * otherwise share it and every charge would land on all of them.\n */\nfunction chargeRow(row: Row, name: string, ms: number): void {\n const previous = row[ROW_TIME_COL] as RowTime | undefined\n const stages = { ...previous?.stages }\n stages[name] = (stages[name] ?? 0) + ms\n row[ROW_TIME_COL] = { stages, total: (previous?.total ?? 0) + ms }\n}\n\nexport interface PipelineOptions {\n signal?: AbortSignal\n /** Called after each stage with its name and elapsed milliseconds. */\n onStage?: (name: string, ms: number, rows: number) => void\n}\n\nexport class Pipeline {\n constructor(readonly stages: Stage[]) {}\n\n /** Run every stage in order. Input is normalised into rows first. */\n async transform(input: PipelineInput, options: PipelineOptions = {}): Promise<Row[]> {\n let rows = await toRows(input)\n const timings: Record<string, number> = {}\n const started = performance.now()\n\n for (const [index, stage] of this.stages.entries()) {\n options.signal?.throwIfAborted()\n const t0 = performance.now()\n await stage.init()\n rows = await stage.transform(rows, { index, signal: options.signal })\n const elapsed = performance.now() - t0\n\n // Two stages of the same class in one pipeline must not overwrite\n // each other's timing, so disambiguate by position.\n const key = timings[stage.name] === undefined ? stage.name : `${stage.name}#${index}`\n timings[key] = elapsed\n options.onStage?.(stage.name, elapsed, rows.length)\n }\n\n const executionTime: ExecutionTime = { stages: timings, total: performance.now() - started }\n return rows.map((row) => ({ ...row, [EXECUTION_TIME_COL]: executionTime }))\n }\n\n async dispose(): Promise<void> {\n await Promise.all(this.stages.map((s) => s.dispose()))\n }\n}\n\n/** Normalise any accepted input into pipeline rows with `content` and `path`. */\nexport async function toRows(input: PipelineInput): Promise<Row[]> {\n if (Array.isArray(input)) return input.map((r) => ({ ...r }))\n\n if (typeof input === 'string') {\n const response = await fetch(input)\n if (!response.ok) {\n throw new Error(`Failed to fetch ${input}: ${response.status} ${response.statusText}`)\n }\n const data = new Uint8Array(await response.arrayBuffer())\n return [{ content: data, path: input }]\n }\n\n if (input instanceof Uint8Array) return [{ content: input, path: 'memory' }]\n if (input instanceof ArrayBuffer) return [{ content: new Uint8Array(input), path: 'memory' }]\n\n if (typeof Blob !== 'undefined' && input instanceof Blob) {\n const data = new Uint8Array(await input.arrayBuffer())\n const path = 'name' in input && typeof input.name === 'string' ? input.name : 'memory'\n return [{ content: data, path }]\n }\n\n return [{ ...(input as Row) }]\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
//#region src/core/params.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The TS analogue of `scaledp/params.py`.
|
|
4
|
+
*
|
|
5
|
+
* Python builds params from a frozen `defaultParams` map plus a coercion pass
|
|
6
|
+
* (`HasDefaultEnum._set`) that unwraps enums, normalises `lang`, and runs any
|
|
7
|
+
* `validate<Param>` hook. TypeScript needs neither a metaclass nor Param
|
|
8
|
+
* objects -- an options object merged over a frozen default, with optional
|
|
9
|
+
* per-key validators, covers the same ground with real types.
|
|
10
|
+
*/
|
|
11
|
+
type Validator<T> = { [K in keyof T]?: (value: T[K], all: T) => void; };
|
|
12
|
+
/** Params every stage accepts, mirroring the Python mixins. */
|
|
13
|
+
interface BaseStageParams {
|
|
14
|
+
/** Row field this stage reads. */
|
|
15
|
+
inputCol: string;
|
|
16
|
+
/** Row field this stage writes. */
|
|
17
|
+
outputCol: string;
|
|
18
|
+
/** Row field holding the source path; used to populate output `path`. */
|
|
19
|
+
pathCol: string;
|
|
20
|
+
/** Row field holding the page index for multi-page inputs. */
|
|
21
|
+
pageCol: string;
|
|
22
|
+
/** Keep `inputCol` in the output rows instead of dropping it. */
|
|
23
|
+
keepInputData: boolean;
|
|
24
|
+
/** Throw on failure instead of recording it in the output's `exception`. */
|
|
25
|
+
propagateError: boolean;
|
|
26
|
+
}
|
|
27
|
+
declare const BASE_STAGE_DEFAULTS: BaseStageParams;
|
|
28
|
+
/**
|
|
29
|
+
* Merge user options over defaults and run validators.
|
|
30
|
+
*
|
|
31
|
+
* `undefined` values are ignored so `{ scoreThreshold: undefined }` falls back
|
|
32
|
+
* to the default rather than erasing it -- callers spreading optional config
|
|
33
|
+
* would otherwise silently lose defaults.
|
|
34
|
+
*/
|
|
35
|
+
declare function resolveParams<T extends object>(defaults: Readonly<T>, options?: Partial<T>, validators?: Validator<T>): T;
|
|
36
|
+
/** Throw unless `value` lies within [min, max]. */
|
|
37
|
+
declare function assertInRange(name: string, value: number, min: number, max: number): void;
|
|
38
|
+
/** Throw unless `value` is a positive integer. */
|
|
39
|
+
declare function assertPositiveInt(name: string, value: number): void;
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/core/pipeline.d.ts
|
|
42
|
+
/** One record flowing through the pipeline. Stages read and write named fields. */
|
|
43
|
+
type Row = Record<string, unknown>;
|
|
44
|
+
/** Per-stage wall-clock timings, mirroring PandasPipeline's `execution_time` column. */
|
|
45
|
+
interface ExecutionTime {
|
|
46
|
+
stages: Record<string, number>;
|
|
47
|
+
total: number;
|
|
48
|
+
}
|
|
49
|
+
declare const EXECUTION_TIME_COL = "execution_time";
|
|
50
|
+
/**
|
|
51
|
+
* Per-row timings, accumulated as a row travels the pipeline.
|
|
52
|
+
*
|
|
53
|
+
* `execution_time` is per *run* -- one number per stage, the same on every row,
|
|
54
|
+
* which is what Python records. That cannot answer "how long did page 7 take",
|
|
55
|
+
* because a stage's number covers every page at once. This column can: each row
|
|
56
|
+
* carries the time spent on it alone.
|
|
57
|
+
*
|
|
58
|
+
* A stage that expands produces several rows from one call, so its cost is
|
|
59
|
+
* split evenly between them. The parts still sum to the call, but no finer
|
|
60
|
+
* attribution is available from outside the stage.
|
|
61
|
+
*/
|
|
62
|
+
interface RowTime {
|
|
63
|
+
stages: Record<string, number>;
|
|
64
|
+
total: number;
|
|
65
|
+
}
|
|
66
|
+
declare const ROW_TIME_COL = "row_time";
|
|
67
|
+
/** Anything a pipeline can be fed directly. */
|
|
68
|
+
type PipelineInput = Uint8Array | ArrayBuffer | Blob | File | string | Row | Row[];
|
|
69
|
+
/**
|
|
70
|
+
* A stage described well enough to reconstruct it from plain data.
|
|
71
|
+
*
|
|
72
|
+
* This is the serialised form of a pipeline: `StageDescriptor[]` is JSON, so it
|
|
73
|
+
* crosses the worker boundary (see `@stabrise/scaledp/worker`) and survives a
|
|
74
|
+
* round trip through storage. `@stabrise/scaledp/registry` turns it back into
|
|
75
|
+
* live stages.
|
|
76
|
+
*/
|
|
77
|
+
interface StageDescriptor {
|
|
78
|
+
/** Exported class name, e.g. 'PdfToImage'. */
|
|
79
|
+
type: string;
|
|
80
|
+
/** Constructor options. Must be structured-cloneable. */
|
|
81
|
+
options?: Record<string, unknown>;
|
|
82
|
+
}
|
|
83
|
+
interface StageContext {
|
|
84
|
+
/** Zero-based index of this stage in the pipeline. */
|
|
85
|
+
index: number;
|
|
86
|
+
signal?: AbortSignal;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Base class for every stage.
|
|
90
|
+
*
|
|
91
|
+
* Subclasses implement `apply`, which transforms a single row's input value.
|
|
92
|
+
* The base handles column wiring, error capture and the `keepInputData`
|
|
93
|
+
* contract, so those behave identically everywhere.
|
|
94
|
+
*/
|
|
95
|
+
declare abstract class Stage<P extends BaseStageParams = BaseStageParams> {
|
|
96
|
+
readonly params: P;
|
|
97
|
+
abstract readonly name: string;
|
|
98
|
+
constructor(params: P);
|
|
99
|
+
/**
|
|
100
|
+
* Transform one row's input value into this stage's output value.
|
|
101
|
+
*
|
|
102
|
+
* Throwing is fine and expected -- `transform` converts it into the output
|
|
103
|
+
* schema's `exception` field unless `propagateError` is set.
|
|
104
|
+
*/
|
|
105
|
+
protected abstract apply(input: unknown, row: Row, ctx: StageContext): Promise<unknown>;
|
|
106
|
+
/**
|
|
107
|
+
* Value written to `outputCol` when `apply` throws. Subclasses return an
|
|
108
|
+
* empty instance of their output schema carrying the message, so downstream
|
|
109
|
+
* stages see a well-formed value rather than `undefined`.
|
|
110
|
+
*/
|
|
111
|
+
protected abstract onError(message: string, row: Row): unknown;
|
|
112
|
+
/** Optional per-stage setup (model download, session creation). Called once. */
|
|
113
|
+
init(): Promise<void>;
|
|
114
|
+
/** Release any held resources (ONNX sessions, workers). */
|
|
115
|
+
dispose(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* A stage may emit several rows per input row -- PDF page explosion, box
|
|
118
|
+
* cropping. Returning `null` means "use the single-row path".
|
|
119
|
+
*/
|
|
120
|
+
protected expand(_input: unknown, _row: Row, _ctx: StageContext): Promise<Row[] | null>;
|
|
121
|
+
transform(rows: Row[], ctx: StageContext): Promise<Row[]>;
|
|
122
|
+
}
|
|
123
|
+
interface PipelineOptions {
|
|
124
|
+
signal?: AbortSignal;
|
|
125
|
+
/** Called after each stage with its name and elapsed milliseconds. */
|
|
126
|
+
onStage?: (name: string, ms: number, rows: number) => void;
|
|
127
|
+
}
|
|
128
|
+
declare class Pipeline {
|
|
129
|
+
readonly stages: Stage[];
|
|
130
|
+
constructor(stages: Stage[]);
|
|
131
|
+
/** Run every stage in order. Input is normalised into rows first. */
|
|
132
|
+
transform(input: PipelineInput, options?: PipelineOptions): Promise<Row[]>;
|
|
133
|
+
dispose(): Promise<void>;
|
|
134
|
+
}
|
|
135
|
+
/** Normalise any accepted input into pipeline rows with `content` and `path`. */
|
|
136
|
+
declare function toRows(input: PipelineInput): Promise<Row[]>;
|
|
137
|
+
//#endregion
|
|
138
|
+
export { assertPositiveInt as _, PipelineOptions as a, RowTime as c, StageDescriptor as d, toRows as f, assertInRange as g, Validator as h, PipelineInput as i, Stage as l, BaseStageParams as m, ExecutionTime as n, ROW_TIME_COL as o, BASE_STAGE_DEFAULTS as p, Pipeline as r, Row as s, EXECUTION_TIME_COL as t, StageContext as u, resolveParams as v };
|
|
139
|
+
//# sourceMappingURL=pipeline-DeLO-OCE.d.ts.map
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { d as StageDescriptor, l as Stage, r as Pipeline } from "../pipeline-DeLO-OCE.js";
|
|
2
|
+
//#region src/registry/types.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Runtime metadata describing every stage's parameters.
|
|
5
|
+
*
|
|
6
|
+
* Params in this library are a TypeScript interface plus a frozen defaults
|
|
7
|
+
* object (see `src/core/params.ts`). Types, enums and ranges live in the `.d.ts`
|
|
8
|
+
* and in validator closures -- neither readable at runtime, which is what a
|
|
9
|
+
* parameter form needs. This file declares the shape of that missing metadata;
|
|
10
|
+
* `catalog.ts` fills it in.
|
|
11
|
+
*
|
|
12
|
+
* The defaults themselves are never restated here. Every spec points at the
|
|
13
|
+
* stage's own `*_DEFAULTS` constant, so a changed default cannot drift out of
|
|
14
|
+
* the catalogue -- and `test/unit/registry.test.ts` fails when a *new* param is
|
|
15
|
+
* added to a stage without a matching entry.
|
|
16
|
+
*/
|
|
17
|
+
/** What a column holds, well enough to check that a stage can read it. */
|
|
18
|
+
type ColumnKind = 'bytes' | 'image' | 'boxes' | 'document' | 'ner' | 'orientations' | 'box';
|
|
19
|
+
/** Which widget a parameter wants. */
|
|
20
|
+
type StageParamKind = 'string' | 'number' | 'boolean' | 'enum' |
|
|
21
|
+
/** An array of strings edited as a list: labels, lang, displayDataList. */
|
|
22
|
+
'stringList' |
|
|
23
|
+
/** A single row field name: inputCol, outputCol, orientationCol, boxCol. */
|
|
24
|
+
'column' |
|
|
25
|
+
/** A fixed-length list of row field names: inputCols. */
|
|
26
|
+
'columns' |
|
|
27
|
+
/** A CSS colour, or null for "choose one per group". */
|
|
28
|
+
'color';
|
|
29
|
+
interface StageParamOption {
|
|
30
|
+
value: string;
|
|
31
|
+
label: string;
|
|
32
|
+
/** Longer description, for a tooltip. */
|
|
33
|
+
title?: string;
|
|
34
|
+
/** Selectable but not usable as configured -- private repos, say. */
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
}
|
|
37
|
+
interface StageParamSpec {
|
|
38
|
+
/** Key in the stage's params object. */
|
|
39
|
+
key: string;
|
|
40
|
+
kind: StageParamKind;
|
|
41
|
+
label: string;
|
|
42
|
+
/** One line explaining what the parameter does. */
|
|
43
|
+
help?: string;
|
|
44
|
+
min?: number;
|
|
45
|
+
max?: number;
|
|
46
|
+
step?: number;
|
|
47
|
+
/** `columns` only: how many entries the list must have, when it is fixed. */
|
|
48
|
+
arity?: number;
|
|
49
|
+
/**
|
|
50
|
+
* `columns` only: the fewest entries a variable-length list may have.
|
|
51
|
+
*
|
|
52
|
+
* `ImageDrawBoxes` takes an image and at least one box column, so its list
|
|
53
|
+
* grows but never shrinks below two. Without this the constraint lives only
|
|
54
|
+
* inside the stage's constructor validator, where a form cannot see it.
|
|
55
|
+
*/
|
|
56
|
+
minArity?: number;
|
|
57
|
+
/** `columns`/`column` only: what each position must hold. */
|
|
58
|
+
accepts?: ColumnKind[];
|
|
59
|
+
/**
|
|
60
|
+
* Values worth offering.
|
|
61
|
+
*
|
|
62
|
+
* On an `enum` these are the only values. On a `stringList` they are the
|
|
63
|
+
* ones a UI should let you pick from -- the list stays open, but the field
|
|
64
|
+
* names that actually render are not guessable, so leaving it entirely free
|
|
65
|
+
* text hides them.
|
|
66
|
+
*/
|
|
67
|
+
options?: readonly StageParamOption[];
|
|
68
|
+
/** `enum` only: also accept a value outside `options`. */
|
|
69
|
+
allowCustom?: boolean;
|
|
70
|
+
/** Wiring and plumbing rather than behaviour; collapse it by default. */
|
|
71
|
+
advanced?: boolean;
|
|
72
|
+
/** Reject the value in the UI before the constructor throws. */
|
|
73
|
+
required?: boolean;
|
|
74
|
+
}
|
|
75
|
+
/** Where a stage's weights come from, so a UI can report cache state. */
|
|
76
|
+
type StageCacheSpec =
|
|
77
|
+
/** The param names a PaddleOCR preset id. */
|
|
78
|
+
{
|
|
79
|
+
kind: 'paddle-preset';
|
|
80
|
+
param: string;
|
|
81
|
+
} |
|
|
82
|
+
/** The param names a Hugging Face repo id or URL. */
|
|
83
|
+
{
|
|
84
|
+
kind: 'hf-repo';
|
|
85
|
+
param: string;
|
|
86
|
+
approxBytes?: number;
|
|
87
|
+
} |
|
|
88
|
+
/** The param names an id in `NER_MODELS`. */
|
|
89
|
+
{
|
|
90
|
+
kind: 'ner-id';
|
|
91
|
+
param: string;
|
|
92
|
+
};
|
|
93
|
+
interface StageSpec {
|
|
94
|
+
/** Exported class name. Also the `StageDescriptor.type` and the stage's `name`. */
|
|
95
|
+
type: string;
|
|
96
|
+
label: string;
|
|
97
|
+
group: 'Read' | 'Detect' | 'Recognise' | 'Understand' | 'Transform';
|
|
98
|
+
/** Import specifier the class lives behind, shown on the stage card. */
|
|
99
|
+
subpath: string;
|
|
100
|
+
summary: string;
|
|
101
|
+
/** Column kinds this stage reads, in `inputCols` order where it has one. */
|
|
102
|
+
consumes: readonly ColumnKind[];
|
|
103
|
+
/** Column kind written to `outputCol`. */
|
|
104
|
+
produces: ColumnKind;
|
|
105
|
+
/** Extra columns written by stages that emit more than one. */
|
|
106
|
+
alsoProduces?: readonly {
|
|
107
|
+
param: string;
|
|
108
|
+
kind: ColumnKind;
|
|
109
|
+
}[];
|
|
110
|
+
/** Optional peer dependency the stage needs at run time. */
|
|
111
|
+
peer?: string;
|
|
112
|
+
cache?: StageCacheSpec;
|
|
113
|
+
/** One row per input row, or several? PDF page explosion and box cropping. */
|
|
114
|
+
expands?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* The output is for looking at, not for feeding onward.
|
|
117
|
+
*
|
|
118
|
+
* An annotated page is still an image, so a UI choosing "the most recent
|
|
119
|
+
* image column" would hand it to the next detector -- which would then read
|
|
120
|
+
* text through the boxes drawn over it. Chaining annotation passes is a real
|
|
121
|
+
* idiom, so this marks the column rather than forbidding it.
|
|
122
|
+
*/
|
|
123
|
+
terminal?: boolean;
|
|
124
|
+
/** The stage's own frozen `*_DEFAULTS` object. */
|
|
125
|
+
defaults: Readonly<Record<string, unknown>>;
|
|
126
|
+
params: readonly StageParamSpec[];
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/registry/catalog.d.ts
|
|
130
|
+
declare const STAGE_SPECS: readonly StageSpec[];
|
|
131
|
+
/** Name → constructor, for building a stage from a `StageDescriptor`. */
|
|
132
|
+
declare const STAGE_CLASSES: Readonly<Record<string, new (options?: never) => Stage>>;
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/registry/codegen.d.ts
|
|
135
|
+
interface PipelineCodeOptions {
|
|
136
|
+
/** Name bound to the pipeline. */
|
|
137
|
+
variable?: string;
|
|
138
|
+
/** Emit the import block above it. */
|
|
139
|
+
imports?: boolean;
|
|
140
|
+
/** Spaces per indent level. */
|
|
141
|
+
indent?: number;
|
|
142
|
+
}
|
|
143
|
+
declare function pipelineCode(descriptors: readonly StageDescriptor[], options?: PipelineCodeOptions): string;
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/registry/index.d.ts
|
|
146
|
+
/** Metadata for one stage, by exported class name. */
|
|
147
|
+
declare function getStageSpec(type: string): (typeof STAGE_SPECS)[number] | undefined;
|
|
148
|
+
/**
|
|
149
|
+
* Build one stage from its serialised form.
|
|
150
|
+
*
|
|
151
|
+
* Throws on an unknown type, and lets the stage's own constructor validators
|
|
152
|
+
* throw on a bad param -- an unknown OCR preset should fail here, where the
|
|
153
|
+
* message can name the offending field, rather than several stages later.
|
|
154
|
+
*/
|
|
155
|
+
declare function createStage(descriptor: StageDescriptor): Stage;
|
|
156
|
+
/** Build a whole pipeline from its serialised form. */
|
|
157
|
+
declare function pipelineFromDescriptors(descriptors: readonly StageDescriptor[]): Pipeline;
|
|
158
|
+
/**
|
|
159
|
+
* The serialised form of a live stage.
|
|
160
|
+
*
|
|
161
|
+
* `stage.params` is fully resolved -- defaults merged in -- so this round-trips
|
|
162
|
+
* exactly but is more verbose than the options originally passed.
|
|
163
|
+
*/
|
|
164
|
+
declare function describeStage(stage: Stage): StageDescriptor;
|
|
165
|
+
/** The serialised form of a live pipeline. */
|
|
166
|
+
declare function describePipeline(pipeline: Pipeline): StageDescriptor[];
|
|
167
|
+
//#endregion
|
|
168
|
+
export { type ColumnKind, type PipelineCodeOptions, STAGE_CLASSES, STAGE_SPECS, type StageCacheSpec, type StageDescriptor, type StageParamKind, type StageParamOption, type StageParamSpec, type StageSpec, createStage, describePipeline, describeStage, getStageSpec, pipelineCode, pipelineFromDescriptors };
|
|
169
|
+
//# sourceMappingURL=index.d.ts.map
|