gpu-sankhya 0.1.2 → 0.3.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/README.md +147 -59
- package/dist/charset.d.ts +17 -1
- package/dist/core.d.ts +5 -0
- package/dist/index.d.ts +25 -3
- package/dist/index.js +8 -5
- package/dist/lang-hi-deva.d.ts +2 -0
- package/dist/types.d.ts +119 -1
- package/dist/weights.d.ts +15 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# gpu-sankhya
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/gpu-sankhya)
|
|
4
|
-
[](https://www.npmjs.com/package/gpu-sankhya?activeTab=code)
|
|
5
5
|
[](./LICENSE)
|
|
6
6
|
[](https://athrvk.github.io/gpu-sankhya/)
|
|
7
7
|
|
|
8
8
|
Parses Indian informal number/currency shorthand — Hinglish (romanised
|
|
9
|
-
Hindi) and Indian-English amount phrases like `sava
|
|
10
|
-
`2.5L`, `20k`, `2-3 lakh` —
|
|
11
|
-
unit, currency, and confidence
|
|
9
|
+
Hindi), Devanagari Hindi, and Indian-English amount phrases like `sava
|
|
10
|
+
lakh`, `dedh crore`, `डेढ़ लाख`, `सवा करोड़`, `2.5L`, `20k`, `2-3 lakh` —
|
|
11
|
+
into a clean numeric value, with the span, unit, currency, and confidence
|
|
12
|
+
that produced it. Mixed-script input (Latin and Devanagari in the same
|
|
13
|
+
string, e.g. `"budget 2 लाख hai"`) is supported: currency and unit
|
|
14
|
+
detection scan both scripts' marker lists.
|
|
12
15
|
|
|
13
16
|
A small char-level CNN tags each character of the input with a BIO span
|
|
14
17
|
label and a semantic token class (digit, prefix word like "sava"/"dedh",
|
|
@@ -18,9 +21,10 @@ never predicts the value directly, so the arithmetic can't drift from the
|
|
|
18
21
|
grammar (prefix semantics, additive descending units, multiplicative
|
|
19
22
|
ascending units like `das hazaar crore` = 10,000 × 1 crore = 1e11, etc).
|
|
20
23
|
|
|
21
|
-
Ships with a small (
|
|
22
|
-
in the package — `import { parse }
|
|
23
|
-
network fetch. Zero runtime
|
|
24
|
+
Ships with a small (47.2 KB gzipped, 80.8 KB raw `dist/index.js`)
|
|
25
|
+
int8-quantized default model inlined in the package — `import { parse }
|
|
26
|
+
from "gpu-sankhya"` works with no network fetch. Zero runtime
|
|
27
|
+
dependencies.
|
|
24
28
|
|
|
25
29
|
Model training lives in `python/` (a separate, actively-trained
|
|
26
30
|
component); this package is the runtime that loads its exported weights.
|
|
@@ -65,6 +69,22 @@ parse("sawaa laakh ka budget hai");
|
|
|
65
69
|
// variance ("sawaa"/"sava", "laakh"/"lakh") is part of the training data,
|
|
66
70
|
// not special-cased.
|
|
67
71
|
|
|
72
|
+
// Devanagari input follows the same grammar/arithmetic as Hinglish (the
|
|
73
|
+
// core is language-independent -- see How it works); the expected output
|
|
74
|
+
// shape is identical, e.g.:
|
|
75
|
+
parse("डेढ़ लाख");
|
|
76
|
+
// [{ span: "डेढ़ लाख", value: 150000, unit: "lakh", ... }]
|
|
77
|
+
|
|
78
|
+
parse("सवा दो करोड़ का फ्लैट");
|
|
79
|
+
// [{ span: "सवा दो करोड़", value: 22500000, unit: "crore", ... }]
|
|
80
|
+
|
|
81
|
+
parse("बजट साढ़े तीन लाख है");
|
|
82
|
+
// [{ span: "साढ़े तीन लाख", value: 350000, unit: "lakh", ... }]
|
|
83
|
+
// NOTE: the correctness of these Devanagari examples depends on the
|
|
84
|
+
// bundled weights being trained on the hi_deva pack (see python/README.md);
|
|
85
|
+
// the runtime-side normalization/decoding/currency support is in place
|
|
86
|
+
// independent of which weights are loaded (createParser({ weights })).
|
|
87
|
+
|
|
68
88
|
// batch (uses WebGPU automatically for large batches in a browser, else CPU)
|
|
69
89
|
const results = await parseBatch(["sava lakh", "dedh crore", "..."]);
|
|
70
90
|
|
|
@@ -110,6 +130,29 @@ interface Sankhya {
|
|
|
110
130
|
actually obtained. Result is cached, so repeated calls only probe once.
|
|
111
131
|
`parseBatch`'s `"auto"` backend uses this (not `isWebGPUAvailable()`)
|
|
112
132
|
to decide whether to try the GPU path.
|
|
133
|
+
- **`inspect(text) => Inspection`** — synchronous CPU inspection of the
|
|
134
|
+
raw model output before decode/repair: `{ text, chars: [{ch, bio,
|
|
135
|
+
bioProb, cls, clsId}], spans, ms }`, one entry per character with its
|
|
136
|
+
argmax BIO tag, BIO softmax probability, and predicted class. Useful
|
|
137
|
+
for debugging misclassifications or building a "what did the model
|
|
138
|
+
actually see" view (this is what powers the demo's per-character
|
|
139
|
+
panel); `parse()`'s decoded spans are the thing to use for normal
|
|
140
|
+
consumption.
|
|
141
|
+
- **`modelInfo() => ModelInfo`** — info about the currently loaded
|
|
142
|
+
default model: `{ version, params, channels, embedDim, vocab, classes,
|
|
143
|
+
layers: [{k, dilation, residual}] }`.
|
|
144
|
+
- **`CLASSES`** — the exported array of semantic token class names (the
|
|
145
|
+
same strings that appear in `Sankhya.classes` and `Inspection.chars[].cls`).
|
|
146
|
+
- **`normalizeText(text) => string`** — the exact normalization
|
|
147
|
+
`parse`/`parseBatch` apply before char-encoding (Unicode NFC, then
|
|
148
|
+
Devanagari digits U+0966-U+096F mapped 1:1 to ASCII `"0"`-`"9"`, then
|
|
149
|
+
lowercasing), exposed so callers can reproduce the same offsets. `parse`
|
|
150
|
+
returns `start`/`end` as indices into `normalizeText(text)`, not the raw
|
|
151
|
+
input — for the overwhelming majority of input, which already arrives in
|
|
152
|
+
NFC form, normalization never changes the string's length, so offsets
|
|
153
|
+
are unaffected; call `normalizeText` yourself first if you need to be
|
|
154
|
+
sure for non-NFC input. The `span` field is a substring of your original
|
|
155
|
+
input when lengths match, and of the normalized string otherwise.
|
|
113
156
|
|
|
114
157
|
## Backends
|
|
115
158
|
|
|
@@ -127,61 +170,91 @@ interface Sankhya {
|
|
|
127
170
|
|
|
128
171
|
### Why CPU by default
|
|
129
172
|
|
|
130
|
-
One inference is small —
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
173
|
+
One inference is small — a 5-layer, 48-channel dilated/residual char
|
|
174
|
+
CNN, 39,579 parameters — and `parse()` runs in about 3.6 ms p50 (60-char
|
|
175
|
+
input) in plain JS; `parseBatch` on CPU averages about 4.0 ms/string over
|
|
176
|
+
500 strings. A WebGPU dispatch has fixed overhead of a few milliseconds
|
|
177
|
+
(device/pipeline setup, buffer upload, queue submit, readback), which
|
|
178
|
+
dwarfs that per-string cost. So the GPU only pays off once you're
|
|
179
|
+
amortizing that overhead over a batch — hundreds of strings at once —
|
|
180
|
+
which is exactly what `parseBatch` does with `backend: "auto"`/`"webgpu"`;
|
|
181
|
+
`parse()` stays CPU-only and synchronous on purpose.
|
|
182
|
+
|
|
183
|
+
The WebGPU path's plain (non-residual) conv layers have been verified on
|
|
184
|
+
a real GPU in desktop Chrome, matching the CPU backend span-for-span on
|
|
185
|
+
the demo page's batch benchmark. The current shipped model (arch `v2`)
|
|
186
|
+
adds a residual connection (`y = relu(conv(x)) + x`) on four of its five
|
|
187
|
+
layers; the WGSL shader's residual path is covered by unit tests that
|
|
188
|
+
check its structure but has not yet been re-verified against a real GPU
|
|
189
|
+
adapter in a browser — run the demo's batch benchmark yourself and check
|
|
190
|
+
for a 0 mismatch count before relying on it. The demo's benchmark re-runs
|
|
191
|
+
the CPU/WebGPU comparison on every click, so any regression shows up as a
|
|
192
|
+
mismatch count rather than a silent wrong answer.
|
|
144
193
|
|
|
145
194
|
## Accuracy
|
|
146
195
|
|
|
147
|
-
The bundled default model:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
196
|
+
The bundled default model (arch `v2`): 39,579 parameters, 5 conv layers
|
|
197
|
+
over 16-dim char embeddings — a plain kernel-5 layer, then four residual
|
|
198
|
+
kernel-3 layers with dilations 1/2/4/8 (`y = relu(conv(x)) + x`), 48
|
|
199
|
+
channels, ±17-character receptive field — over a 114-character vocab
|
|
200
|
+
(union of the `hi_latn` and `hi_deva` packs), 120 output classes. Trained
|
|
201
|
+
20 epochs on 200,000 synthetic examples generated from both language
|
|
202
|
+
packs' grammars, mixed 0.55/0.45 with a 10% cross-pack share, plus
|
|
203
|
+
out-of-vocab "unk noise" augmentation so the model has actually seen
|
|
204
|
+
`<unk>` characters (emoji, CJK, Cyrillic, other symbols) during training
|
|
205
|
+
(see `python/README.md`). An older `v1` preset (the previously shipped
|
|
206
|
+
4-layer, non-residual, 32-channel stack) is still loadable by both the
|
|
207
|
+
Python and JS runtimes for anyone using older exported weights.
|
|
152
208
|
|
|
153
209
|
On synthetic validation data (drawn from the same generator/templates as
|
|
154
|
-
training): 0.
|
|
210
|
+
training): 0.932 value accuracy. This number is optimistic — it's testing
|
|
155
211
|
the model on its own distribution.
|
|
156
212
|
|
|
157
|
-
On
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
| value accuracy |
|
|
163
|
-
|
|
|
164
|
-
|
|
|
165
|
-
|
|
|
166
|
-
|
|
167
|
-
|
|
213
|
+
On two hand-written gold sets, written independently of the generator —
|
|
214
|
+
`python/tests/gold.jsonl` (romanised Hindi, 184 sentences / 168 spans)
|
|
215
|
+
and `python/tests/gold_deva.jsonl` (Devanagari Hindi, 169 sentences / 141
|
|
216
|
+
spans) — evaluated against the shipped int8-quantized weights:
|
|
217
|
+
|
|
218
|
+
| gold set | examples | spans | value accuracy | span precision | span recall | span F1 |
|
|
219
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
220
|
+
| gold.jsonl (romanised) | 184 | 168 | 0.9515 | 0.8971 | 0.9515 | 0.9235 |
|
|
221
|
+
| gold_deva.jsonl (Devanagari) | 169 | 141 | 0.9861 | 0.9662 | 0.9931 | 0.9795 |
|
|
222
|
+
| combined | 353 | 309 | 0.9676 | 0.9288 | 0.9709 | 0.9494 |
|
|
223
|
+
|
|
224
|
+
Negatives (zero-gold-span examples, 55 total): 4 false positives (7.3%).
|
|
225
|
+
Per-category value accuracy: digits 0.977, words 0.964, prefix 0.948,
|
|
226
|
+
range 0.917, currency 0.979, multi_unit 1.0, symbol_unit 1.0,
|
|
227
|
+
mixed_script 1.0, long 0.75.
|
|
228
|
+
|
|
229
|
+
Compared to the previously shipped `v1` model (0.9441 / 0.9645 / 0.9536
|
|
230
|
+
combined value acc, F1 0.9510, 2/55 negatives false positives): this
|
|
231
|
+
model gains about 1.4 points of value accuracy and is materially more
|
|
232
|
+
robust to input containing characters outside its training vocabulary,
|
|
233
|
+
at the cost of slightly lower span precision — it produces a few more
|
|
234
|
+
spurious spans on unfamiliar words. That's a known, measured trade-off,
|
|
235
|
+
not an oversight.
|
|
236
|
+
|
|
237
|
+
**The gold numbers are the ones to trust.** Known miss categories, in rough
|
|
168
238
|
order of frequency:
|
|
169
239
|
|
|
170
240
|
- unusual typos the noise model doesn't cover (e.g. "croer" for "crore")
|
|
171
241
|
- possessive apostrophes ("do lakh's")
|
|
172
|
-
- long multi-term
|
|
242
|
+
- long multi-term/mixed-numeral constructs ("three n half lakh", "50M")
|
|
243
|
+
- multi-number range phrases ("तीस पैंतीस हज़ार", "paanch se sadhe saat lakh")
|
|
173
244
|
- occasional spurious spans triggered by unfamiliar words near number-ish
|
|
174
245
|
context
|
|
175
246
|
|
|
176
247
|
Reproduce these numbers yourself with
|
|
177
|
-
`python -m sankhya.eval_gold --gold tests/gold.jsonl --weights-json src/data/default-weights.json --int8`
|
|
248
|
+
`python -m sankhya.eval_gold --gold tests/gold.jsonl tests/gold_deva.jsonl --weights-json src/data/default-weights.json --int8`
|
|
178
249
|
from `python/` (see `python/README.md`).
|
|
179
250
|
|
|
180
251
|
## How it works
|
|
181
252
|
|
|
182
|
-
1. The input string is
|
|
183
|
-
|
|
184
|
-
|
|
253
|
+
1. The input string is normalized (`normalizeText`: Unicode NFC, then
|
|
254
|
+
Devanagari digits U+0966-U+096F mapped to ASCII `"0"`-`"9"`, then
|
|
255
|
+
lowercased — byte-identical to the Python reference) and char-encoded
|
|
256
|
+
against the model's vocab (unknown chars map to `<unk>`).
|
|
257
|
+
2. A dilated/residual conv1d stack (see Accuracy above) produces, per
|
|
185
258
|
character, a 3-way BIO logit (O/B/I) and a class logit over the
|
|
186
259
|
semantic token vocabulary (prefix words, cardinals, units, digits,
|
|
187
260
|
separators, misc).
|
|
@@ -216,9 +289,9 @@ Raw per-character BIO/class predictions are cleaned up before evaluation:
|
|
|
216
289
|
on the resulting token sequence.
|
|
217
290
|
|
|
218
291
|
One more detail that matters more than it looks like it should: the
|
|
219
|
-
runtime right-pads the character-id array with
|
|
292
|
+
runtime right-pads the character-id array with 24 pad tokens before
|
|
220
293
|
running the forward pass (mirroring `python/sankhya/np_infer.py`'s
|
|
221
|
-
`pad_ids`/`PAD_TAIL=
|
|
294
|
+
`pad_ids`/`PAD_TAIL=24`), because training always right-pads every
|
|
222
295
|
example to the model's max length the same way. Running a short, tightly
|
|
223
296
|
cropped input (e.g. the bare 4 characters of `"2.5L"`) without that
|
|
224
297
|
padding measurably corrupts predictions — the model was never trained on
|
|
@@ -227,11 +300,20 @@ outputs are discarded; only the real characters' predictions are used.
|
|
|
227
300
|
|
|
228
301
|
## Limitations
|
|
229
302
|
|
|
230
|
-
- **
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
303
|
+
- **Hinglish and Devanagari Hindi.** Romanised Hindi / Indian-English
|
|
304
|
+
amount phrases and Devanagari-script Hindi (`डेढ़ लाख`, `सवा करोड़`) are
|
|
305
|
+
both supported, including mixed-script input in the same string.
|
|
306
|
+
Currency and unit detection scan the Latin (`hi_latn`) and Devanagari
|
|
307
|
+
(`hi_deva`) marker lists together. Other Indian languages (Marathi,
|
|
308
|
+
Gujarati, Bengali, Tamil/Telugu/Kannada) are planned via additional
|
|
309
|
+
language packs (the arithmetic core is already language-independent;
|
|
310
|
+
only the class vocabulary and currency-marker lists are per-language) —
|
|
311
|
+
see Roadmap. Devanagari accuracy depends on the bundled weights being
|
|
312
|
+
trained on the `hi_deva` pack; see Devanagari gold-set numbers above.
|
|
313
|
+
- **Offsets are into the normalized string.** `parse()`'s `start`/`end`
|
|
314
|
+
index `normalizeText(text)`, not the raw input, in the rare case NFC
|
|
315
|
+
normalization changes the string's length (see `normalizeText` in the
|
|
316
|
+
API section above).
|
|
235
317
|
- Text longer than 128 characters is processed with a sliding window
|
|
236
318
|
(128-char windows, 16-char overlap) and results are merged/deduplicated
|
|
237
319
|
by span; extremely long inputs may still miss a span that straddles a
|
|
@@ -253,7 +335,10 @@ outputs are discarded; only the real characters' predictions are used.
|
|
|
253
335
|
(`test/fixtures/parity.jsonl`, `decoded.jsonl` — see
|
|
254
336
|
`python/README.md`'s "Ship to the npm package" section).
|
|
255
337
|
- `bench/` — `parse()`/`parseBatch()` latency benchmarks.
|
|
256
|
-
- `demo/` —
|
|
338
|
+
- `demo/` — an interactive demo: live parse as you type, a per-character
|
|
339
|
+
model-internals view (`inspect()`), batch benchmark controls (CPU vs
|
|
340
|
+
WebGPU), a raw-JSON view of results, a theme toggle, and shareable
|
|
341
|
+
state via URL hash.
|
|
257
342
|
- `python/sankhya/` — `classes.py` (shared class vocabulary), `core.py`
|
|
258
343
|
(the deterministic arithmetic core), `langs/` (language packs, e.g.
|
|
259
344
|
`hi_latn.py`), `noise_latn.py` (typo/spelling-variance injection),
|
|
@@ -271,11 +356,12 @@ outputs are discarded; only the real characters' predictions are used.
|
|
|
271
356
|
Everything here is scoped to Indian languages — there's no plan to
|
|
272
357
|
support non-Indian numbering/currency shorthand.
|
|
273
358
|
|
|
274
|
-
1.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
359
|
+
1. ~~**Devanagari Hindi pack** (डेढ़ लाख).~~ **Done.** The `hi_deva`
|
|
360
|
+
language pack, Devanagari currency markers, Unicode-aware (`\p{L}`/
|
|
361
|
+
`\p{M}`) letters-run repair for matras/nukta/virama, and input
|
|
362
|
+
normalization (NFC + Devanagari-digit mapping) are all in place, and
|
|
363
|
+
mixed Latin/Devanagari input is supported. See `python/README.md` for
|
|
364
|
+
the training-side status and gold-set numbers.
|
|
279
365
|
2. **Other Indian languages as packs**: Marathi (साडे, सव्वा), Gujarati
|
|
280
366
|
(સવા, દોઢ), Bengali (দেড়, আড়াই), and Tamil/Telugu/Kannada number
|
|
281
367
|
words. Same shape as (1) — a new pack, a new noise function, a charset
|
|
@@ -293,9 +379,11 @@ npm run bench # parse() and parseBatch() latency
|
|
|
293
379
|
npm run size # gzipped dist/index.js size
|
|
294
380
|
```
|
|
295
381
|
|
|
296
|
-
See `demo/index.html` for
|
|
297
|
-
|
|
298
|
-
|
|
382
|
+
See `demo/index.html` for the full interactive demo (live parse,
|
|
383
|
+
per-character model view, benchmark controls, JSON view, theme toggle,
|
|
384
|
+
shareable hash) — it imports `dist/index.js` directly (no build step
|
|
385
|
+
needed beyond `npm run build`). Live at
|
|
386
|
+
https://athrvk.github.io/gpu-sankhya/.
|
|
299
387
|
|
|
300
388
|
## Releasing
|
|
301
389
|
|
package/dist/charset.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const MAX_LEN = 128;
|
|
2
2
|
export declare const WINDOW_OVERLAP = 16;
|
|
3
|
-
export declare const PAD_TAIL =
|
|
3
|
+
export declare const PAD_TAIL = 24;
|
|
4
4
|
/** Total (padded) inference length for a window/text of `realLen` real
|
|
5
5
|
* characters: realLen + at least PAD_TAIL pad chars, rounded up to a
|
|
6
6
|
* multiple of 8. */
|
|
@@ -8,6 +8,22 @@ export declare function paddedLength(realLen: number): number;
|
|
|
8
8
|
/** Upper bound on paddedLength() for any single window (window text is
|
|
9
9
|
* capped at MAX_LEN chars) -- the size Scratch buffers are allocated to. */
|
|
10
10
|
export declare const PADDED_MAX: number;
|
|
11
|
+
/** Normalize input text exactly as the Python side does, before char
|
|
12
|
+
* encoding: (1) Unicode NFC normalization, (2) Devanagari digits U+0966-
|
|
13
|
+
* U+096F mapped 1:1 to ASCII "0"-"9", (3) lowercasing. Must stay byte-
|
|
14
|
+
* identical to Python's `s.normalize("NFC")` + digit map + `.lower()`.
|
|
15
|
+
*
|
|
16
|
+
* NFC normalization can change string length (e.g. composing a base +
|
|
17
|
+
* combining mark into fewer code units, or occasionally more). `parse()`
|
|
18
|
+
* returns spans/offsets into `normalizeText(input)`, not the original
|
|
19
|
+
* input string -- for the overwhelming majority of real-world inputs,
|
|
20
|
+
* which already arrive in NFC form, normalization is a no-op on length
|
|
21
|
+
* and offsets, and the `span` field is safe to treat as a substring of
|
|
22
|
+
* the original input too (this is guaranteed to be true when the two
|
|
23
|
+
* strings have equal length). Callers who need to map offsets back onto
|
|
24
|
+
* the original input for non-NFC input should first call
|
|
25
|
+
* `normalizeText()` themselves and index into its result. */
|
|
26
|
+
export declare function normalizeText(s: string): string;
|
|
11
27
|
export declare function buildCharToId(charset: string[]): Map<string, number>;
|
|
12
28
|
/** Encode `text` into char ids, right-padded with pad id 0 up to `padLen`
|
|
13
29
|
* total entries (default: no padding, i.e. exactly text.length). If `out`
|
package/dist/core.d.ts
CHANGED
|
@@ -11,5 +11,10 @@ export interface LangPack {
|
|
|
11
11
|
}
|
|
12
12
|
type Tok = [string, string];
|
|
13
13
|
export declare function evaluate(rawTokens: Tok[]): Result;
|
|
14
|
+
/** Merge one or more LangPacks' marker lists into a single pack, de-duped,
|
|
15
|
+
* sorted longest-first so `detectCurrency` tries the longest (most
|
|
16
|
+
* specific) marker before a shorter one that might be its prefix (e.g.
|
|
17
|
+
* "Rs." before "Rs", "रुपये" before a shorter overlapping marker). */
|
|
18
|
+
export declare function mergeLangPacks(...packs: LangPack[]): LangPack;
|
|
14
19
|
export declare function detectCurrency(text: string, start: number, end: number, pack: LangPack): "INR" | null;
|
|
15
20
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { Sankhya, ParseOptions, WeightsJson } from "./types.js";
|
|
2
|
-
export type { Sankhya, ParseOptions } from "./types.js";
|
|
1
|
+
import type { Sankhya, ParseOptions, WeightsJson, Inspection, ModelInfo } from "./types.js";
|
|
2
|
+
export type { Sankhya, ParseOptions, CharTag, Inspection, ModelInfo } from "./types.js";
|
|
3
3
|
export { isWebGPUAvailable, probeWebGPU } from "./infer-webgpu.js";
|
|
4
|
+
export { normalizeText } from "./charset.js";
|
|
5
|
+
export { CLASSES } from "./classes.js";
|
|
4
6
|
export interface CreateParserOptions {
|
|
5
7
|
weights?: WeightsJson;
|
|
6
8
|
backend?: "cpu" | "webgpu" | "auto";
|
|
@@ -16,13 +18,29 @@ export declare class Parser {
|
|
|
16
18
|
private clsIdsScratch;
|
|
17
19
|
private bioProbsScratch;
|
|
18
20
|
constructor(opts?: CreateParserOptions);
|
|
19
|
-
/** Synchronous CPU parse of a single string.
|
|
21
|
+
/** Synchronous CPU parse of a single string.
|
|
22
|
+
*
|
|
23
|
+
* The returned spans/offsets (`start`, `end`, and `span` when the
|
|
24
|
+
* normalized string's length differs from the input's) are indices into
|
|
25
|
+
* `normalizeText(text)`, not the raw `text` argument -- see
|
|
26
|
+
* normalizeText() in charset.ts. For the overwhelming majority of real
|
|
27
|
+
* input, which already arrives in NFC form, normalization never changes
|
|
28
|
+
* string length, so offsets and `span` are identical either way. */
|
|
20
29
|
parse(text: string, opts?: ParseOptions): Sankhya[];
|
|
21
30
|
/** `fw` may cover a padded length (PAD_TAIL right-padding, see charset.ts);
|
|
22
31
|
* `realLen` (defaults to fw.length, i.e. no padding) bounds decoding to the
|
|
23
32
|
* actual text -- the padded tail's logits are only used to give the real
|
|
24
33
|
* tokens correct right-context during the conv stack, never decoded. */
|
|
25
34
|
private decodeForward;
|
|
35
|
+
/** Synchronous CPU inspection: raw argmax BIO/class tags for every
|
|
36
|
+
* character of the normalized text (before decode repair), plus the same
|
|
37
|
+
* spans `parse()` would return. Uses the same window/padding logic as
|
|
38
|
+
* parse(): for texts longer than MAX_LEN, each character is filled from
|
|
39
|
+
* the first window that covers it. */
|
|
40
|
+
inspect(text: string): Inspection;
|
|
41
|
+
/** Static info about the loaded model: architecture, parameter count and
|
|
42
|
+
* vocab/class sizes. */
|
|
43
|
+
modelInfo(): ModelInfo;
|
|
26
44
|
/** Batched parse. Uses WebGPU when requested/available and the batch is
|
|
27
45
|
* large enough to be worthwhile; falls back to CPU otherwise. */
|
|
28
46
|
parseBatch(texts: string[], opts?: ParseOptions): Promise<Sankhya[][]>;
|
|
@@ -34,4 +52,8 @@ export declare function parse(text: string, opts?: ParseOptions): Sankhya[];
|
|
|
34
52
|
* when `opts.backend === "auto"` and WebGPU is available and the batch is
|
|
35
53
|
* large (>=32); otherwise runs on CPU. Defaults to CPU. */
|
|
36
54
|
export declare function parseBatch(texts: string[], opts?: ParseOptions): Promise<Sankhya[][]>;
|
|
55
|
+
/** Inspect a single string on the default parser -- see Parser.inspect(). */
|
|
56
|
+
export declare function inspect(text: string): Inspection;
|
|
57
|
+
/** Info about the default parser's loaded model -- see Parser.modelInfo(). */
|
|
58
|
+
export declare function modelInfo(): ModelInfo;
|
|
37
59
|
export declare function createParser(opts?: CreateParserOptions): Parser;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function hA(A){return A.quantized!==void 0}function dA(A){let e=atob(A),n=new Int8Array(e.length);for(let t=0;t<e.length;t++)n[t]=e.charCodeAt(t)<<24>>24;return n}function eA(A){let e=dA(A.data_b64),n=new Float32Array(e.length);for(let t=0;t<e.length;t++)n[t]=e[t]*A.scale;return{shape:A.shape,data:n}}function nA(A){return{shape:A.shape,data:Float32Array.from(A.data)}}function tA(A){let e=A.layers??3,n=A.dilation??2,t=["conv1","conv2","conv3",...e===4?["conv4"]:[]];if(hA(A)){let r={layers:e,dilation:n,charset:A.charset,classes:A.classes,embed:eA(A.embed),conv1:void 0,conv2:void 0,conv3:void 0,bio:void 0,cls:void 0};for(let o of[...t,"bio","cls"]){let u=A[o];r[o]={w:eA(u.w),b:Float32Array.from(u.b)}}return r}let a=A,s={layers:e,dilation:n,charset:a.charset,classes:a.classes,embed:nA(a.embed),conv1:void 0,conv2:void 0,conv3:void 0,bio:void 0,cls:void 0};for(let r of[...t,"bio","cls"]){let o=a[r];s[r]={w:nA(o.w),b:Float32Array.from(o.b.data)}}return s}function IA(A){return Math.ceil(A/8)*8}function x(A){return IA(A+16)}var H=x(128);function rA(A){let e=new Map;for(let n=0;n<A.length;n++)e.set(A[n],n);return e}function U(A,e,n,t){let a=A.toLowerCase(),s=e.get("<unk>")??1,r=e.get("<pad>")??0,o=t??a.length,u=n?n.subarray(0,o):new Int32Array(o);for(let f=0;f<a.length;f++)u[f]=e.get(a[f])??s;for(let f=a.length;f<o;f++)u[f]=r;return u}function sA(A){if(A<=128)return[{offset:0,length:A}];let e=[],n=112,t=0;for(;t<A;){let a=Math.min(128,A-t);if(e.push({offset:t,length:a}),t+a>=A)break;t+=n}return e}var O=class{buffers;padded;bioBuf;clsBuf;constructor(e){let n=[e.conv1,e.conv2,e.conv3,...e.layers===4&&e.conv4?[e.conv4]:[]],t=Math.max(e.embed.shape[1],...n.map(s=>s.w.shape[0]));this.buffers=[new Float32Array(t*H),new Float32Array(t*H)];let a=8;this.padded=new Float32Array(t*(H+2*a)),this.bioBuf=new Float32Array(e.bio.w.shape[0]*H),this.clsBuf=new Float32Array(e.cls.w.shape[0]*H)}buf(e){return this.buffers[e%2]}paddedBuf(){return this.padded}};function m(A,e,n,t,a,s,r,o){let[u,f,B]=t.w.shape;if(f!==e)throw new Error(`channel mismatch: expected ${e}, got ${f}`);let w=t.w.data,g=t.b,c=n+2*a;for(let C=0;C<e;C++)o.fill(0,C*c,C*c+a),o.set(A.subarray(C*n,C*n+n),C*c+a),o.fill(0,C*c+a+n,C*c+c);for(let C=0;C<u;C++){let i=C*n,D=g[C],h=C*e*B;if(B===3){for(let P=0;P<n;P++)r[i+P]=D;for(let P=0;P<e;P++){let d=P*c,b=h+P*3,I=w[b],l=w[b+1],v=w[b+2];for(let Q=0;Q<n;Q++){let E=d+Q;r[i+Q]+=I*o[E]+l*o[E+s]+v*o[E+2*s]}}}else if(B===5){for(let P=0;P<n;P++)r[i+P]=D;for(let P=0;P<e;P++){let d=P*c,b=h+P*5,I=w[b],l=w[b+1],v=w[b+2],Q=w[b+3],E=w[b+4];for(let p=0;p<n;p++){let R=d+p;r[i+p]+=I*o[R]+l*o[R+1]+v*o[R+2]+Q*o[R+3]+E*o[R+4]}}}else{for(let P=0;P<n;P++)r[i+P]=D;for(let P=0;P<e;P++){let d=P*c,b=h+P*B;for(let I=0;I<B;I++){let l=w[b+I],v=I*s,Q=d+v;for(let E=0;E<n;E++)r[i+E]+=l*o[Q+E]}}}for(let P=0;P<n;P++){let d=r[i+P];r[i+P]=d>0?d:0}}return u}function oA(A,e,n,t,a){let[s,r]=t.w.shape;if(r!==e)throw new Error(`head channel mismatch: expected ${e}, got ${r}`);let o=t.w.data,u=t.b,f=e-e%4;for(let B=0;B<n;B++){let w=B*s;for(let g=0;g<s;g++){let c=u[g],C=g*e,i=0;for(;i<f;i+=4)c+=o[C+i]*A[i*n+B]+o[C+i+1]*A[(i+1)*n+B]+o[C+i+2]*A[(i+2)*n+B]+o[C+i+3]*A[(i+3)*n+B];for(;i<e;i++)c+=o[C+i]*A[i*n+B];a[w+g]=c}}return s}function j(A,e,n){let t=e.length,a=A.embed,s=a.shape[1],r=n.buf(0);for(let c=0;c<t;c++){let i=e[c]*s;for(let D=0;D<s;D++)r[D*t+c]=a.data[i+D]}let o=s,u=n.paddedBuf(),f=n.buf(1);o=m(r,o,t,A.conv1,1,1,f,u),r=f,f=n.buf(2),o=m(r,o,t,A.conv2,2,1,f,u),r=f;let B=A.dilation,w=Math.floor(B*2/2);if(f=n.buf(3),o=m(r,o,t,A.conv3,w,B,f,u),r=f,A.layers===4&&A.conv4){let C=Math.floor(4);f=n.buf(4),o=m(r,o,t,A.conv4,C,4,f,u),r=f}oA(r,o,t,A.bio,n.bioBuf);let g=oA(r,o,t,A.cls,n.clsBuf);return{bioLogits:n.bioBuf,clsLogits:n.clsBuf,length:t,nCls:g}}function fA(A,e,n,t){let a=-1/0;for(let r=0;r<n;r++)a=Math.max(a,A[e+r]);let s=0;for(let r=0;r<n;r++){let o=Math.exp(A[e+r]-a);t[r]=o,s+=o}for(let r=0;r<n;r++)t[r]/=s;return t}function Y(A,e,n){let t=0,a=-1/0;for(let s=0;s<n;s++){let r=A[e+s];r>a&&(a=r,t=s)}return t}var pA=["PFX_PAAV","PFX_AADHA","PFX_PAUNE","PFX_SAVA","PFX_DEDH","PFX_DHAI","PFX_SAADHE"],RA=Array.from({length:99},(A,e)=>`CARD_${e+1}`),yA=["UNIT_SAU","UNIT_HAZAAR","UNIT_LAKH","UNIT_MILLION","UNIT_CRORE","UNIT_BILLION","UNIT_ARAB","UNIT_KHARAB"],HA=["O","SEP","RANGE","DIGITS","DOT","COMMA"],L=["O",...HA.filter(A=>A!=="O"),...pA,...RA,...yA],M=Object.fromEntries(L.map((A,e)=>[A,e])),aA={UNIT_SAU:100,UNIT_HAZAAR:1e3,UNIT_LAKH:1e5,UNIT_MILLION:1e6,UNIT_CRORE:1e7,UNIT_BILLION:1e9,UNIT_ARAB:1e9,UNIT_KHARAB:1e11},J={UNIT_SAU:"sau",UNIT_HAZAAR:"hazaar",UNIT_LAKH:"lakh",UNIT_MILLION:"million",UNIT_CRORE:"crore",UNIT_BILLION:"billion",UNIT_ARAB:"arab",UNIT_KHARAB:"kharab"},K={PFX_PAAV:{standalone:.25,op:null},PFX_AADHA:{standalone:.5,op:null},PFX_PAUNE:{standalone:.75,op:"sub25",min_n:2},PFX_SAVA:{standalone:1.25,op:"add25",min_n:2},PFX_DEDH:{standalone:1.5,op:null},PFX_DHAI:{standalone:2.5,op:null},PFX_SAADHE:{standalone:.5,op:"add5",min_n:3}};function uA(A){return A in K}function BA(A){return A.startsWith("CARD_")}function cA(A){return A in aA}function gA(A){return parseInt(A.split("_",2)[1],10)}function T(A){return aA[A]}var iA=new Set(["SEP","RANGE","DOT","COMMA"]),MA=["PFX_","CARD_","UNIT_"],xA=["PFX_","CARD_","UNIT_"];function FA(A){return MA.some(e=>A.startsWith(e))||A==="DIGITS"}function UA(A){return xA.some(e=>A.startsWith(e))}var mA=M.O,G=M.SEP,W=M.RANGE,OA=M.DIGITS,TA=M.DOT,GA=M.COMMA;function CA(A){return/[a-z]/i.test(A)?"letter":/[0-9]/.test(A)?"digit":/\s/.test(A)?"space":"punct"}function zA(A){let e=[],n=0,t=A.length;for(;n<t;){let a=CA(A[n]),s=n+1;for(;s<t&&CA(A[s])===a;)s++;e.push({type:a,start:n,end:s}),n=s}return e}function kA(A,e,n){let t=new Map;for(let f=e;f<n;f++){let B=A[f];UA(L[B])&&t.set(B,(t.get(B)??0)+1)}if(t.size===0)return mA;let a=-1;for(let f of t.values())f>a&&(a=f);let s=[...t.entries()].filter(([,f])=>f===a).map(([f])=>f);if(s.length===1)return s[0];let r=-1,o=1/0,u=s[0];for(let f of s){let B=0,w=0,g=1/0;for(let c=e;c<n;c++)A[c]===f?(g===1/0&&(g=c),B++,B>w&&(w=B)):B=0;(w>r||w===r&&g<o)&&(r=w,o=g,u=f)}return u}function NA(A,e,n){let t=[],a=e;for(;a<n;){let o=a+1;for(;o<n&&A[o]===A[a];)o++;t.push({start:a,end:o,cls:A[a]}),a=o}let s=kA(A,e,n),r=[];for(let o=0;o<t.length;o++){let u=t[o];if(u.end-u.start>=3){r.push([u.start,u.end,u.cls]);continue}let B=o>0?t[o-1]:null,w=o<t.length-1?t[o+1]:null,g=B!==null&&B.end-B.start>=3,c=w!==null&&w.end-w.start>=3,C;if(g&&c){let i=B.end-B.start;C=w.end-w.start>i?w.cls:B.cls}else g?C=B.cls:c?C=w.cls:C=s;r.push([u.start,u.end,C])}return r}function XA(A,e){let n=A.length,t=new Array(n),a=zA(A);for(let s=0;s<a.length;s++){let r=a[s],{type:o,start:u,end:f}=r;if(o==="digit"){for(let c=u;c<f;c++)t[c]=OA;continue}if(o==="space"){let c=!1;for(let i=u;i<f;i++)if(e[i]===W){c=!0;break}let C=c?W:G;for(let i=u;i<f;i++)t[i]=C;continue}if(o==="letter"){for(let[c,C,i]of NA(e,u,f))for(let D=c;D<C;D++)t[D]=i;continue}let B=s>0?a[s-1].type:null,w=s<a.length-1?a[s+1].type:null,g=G;if(f-u===1){let c=A[u];(c==="."||c===",")&&B==="digit"&&w==="digit"?g=c==="."?TA:GA:(c==="-"||c==="\u2013"||c==="/")&&B==="digit"&&w==="digit"?g=W:g=G}for(let c=u;c<f;c++)t[c]=g}return t}function SA(A,e){let n=Array.from({length:e},(t,a)=>A[a]);for(let t=1;t<e-1;t++)A[t]===0&&(A[t-1]===1||A[t-1]===2)&&A[t+1]===2&&(n[t]=2);return n}function wA(A){return A!==void 0&&A>="0"&&A<="9"}function _A(A,e,n){if(n<=e||!wA(A[n-1]))return n;let t=n;for(;t<A.length&&wA(A[t]);)t++;return t}function PA(A,e,n,t){let a=A.length,s=SA(e,a),r=[],o=null;for(let f=0;f<a;f++){let B=s[f];B===1?(o!==null&&r.push([o,f]),o=f):B===2||o!==null&&(r.push([o,f]),o=null)}o!==null&&r.push([o,a]);for(let f=0;f<r.length;f++)r[f]=[r[f][0],_A(A,r[f][0],r[f][1])];let u=[];for(let[f,B]of r){let w=A.slice(f,B),g=Array.from({length:B-f},(l,v)=>n[f+v]),c=XA(w,g),C=f,i=[];for(let l=f+1;l<=B;l++)(l===B||c[l-f]!==c[C-f])&&(i.push([c[C-f],C,l]),C=l);let D=0,h=i.length;for(;D<h&&iA.has(L[i[D][0]]);)D++;for(;h>D&&iA.has(L[i[h-1][0]]);)h--;let P=i.slice(D,h);if(P.length===0)continue;let d=P[0][1],b=P[P.length-1][2];if(!P.some(([l])=>FA(L[l])))continue;let I=null;if(t){let l=[];for(let v=d;v<b;v++)l.push(Math.max(...t[v]));if(I=l.length?l.reduce((v,Q)=>v+Q,0)/l.length:0,I<.5)continue}u.push({start:d,end:b,text:A.slice(d,b),tokens:P.map(([l,v,Q])=>[l,A.slice(v,Q)]),confidence:I})}return u}function jA(A){let e=[],n="",t=!1,a=()=>{if(t){let s=n.replace(/,/g,""),r=parseFloat(s);e.push(["NUM",Number.isNaN(r)?0:r])}n="",t=!1};for(let[s,r]of A)s!=="SEP"&&(s==="DIGITS"||s==="DOT"||s==="COMMA"?(n+=r,t=!0):(a(),e.push([s,r])));return a(),e}function YA(A,e){if(e!==null){let n=K[e];if(n===void 0)return A!==null?A:1;if(A!==null&&n.op){if(n.op==="sub25")return A-.25;if(n.op==="add25")return A+.25;if(n.op==="add5")return A+.5}return n.standalone}return A!==null?A:1}function JA(A){let e=jA(A),n=0,t=null,a=null,s=null,r=null;function o(u){let f=YA(s,r);if(u===null)n+=f*1;else{let B=T(u);t!==null&&B>t?n=n*B:n=n+f*B,t=B,(a===null||B>T(a))&&(a=u)}s=null,r=null}for(let[u,f]of e)if(u==="NUM")s!==null&&o(null),s=f;else if(BA(u)){s!==null&&o(null);try{s=gA(u)}catch{}}else if(uA(u))r!==null&&o(null),r=u;else if(cA(u))o(u);else continue;return(s!==null||r!==null)&&o(null),[n,a]}function z(A){let e=Math.round(A),n=Math.max(1e-6,Math.abs(A)*1e-9);return Math.abs(A-e)<n?e:Math.round(A*1e6)/1e6}function KA(A){let e=[],n=0;for(;n<A.length;){let[t,a]=A[n];if(t.startsWith("PFX_")){let s=a,r=n+1;for(;;){let o=r;if(o<A.length&&A[o][0]==="SEP"&&o++,o<A.length&&A[o][0]===t){for(let u=r;u<=o;u++)s+=A[u][1];r=o+1;continue}break}e.push([t,s]),n=r}else e.push(A[n]),n++}return e}function DA(A){try{let e=A.map(g=>g[0]),n=KA(A),t=[[]];for(let[g,c]of n){if(g==="RANGE"){t.length<2&&t.push([]);continue}t[t.length-1].push([g,c])}let a=t.filter(g=>g.length>0).map(g=>JA(g));if(a.length===0)return{value:0,range:null,unit:null,classes:e,currency:null};if(a.length===1){let[g,c]=a[0];return{value:z(g),range:null,unit:c?J[c]??null:null,classes:e,currency:null}}let[s,r]=a[0],[o,u]=a[1],f;r===null&&u!==null?(s=s*T(u),f=u):f=r!==null?r:u;let[B,w]=s<=o?[s,o]:[o,s];return{value:z(B),range:[z(B),z(w)],unit:f?J[f]??null:null,classes:e,currency:null}}catch{return{value:0,range:null,unit:null,classes:A.map(e=>e[0]),currency:null}}}function vA(A,e,n,t){let a=A.slice(Math.max(0,e-4),e),s=A.slice(n,n+6),r=a.replace(/\s+$/,"");for(let u of t.currency_markers_before??[]){let f=u.replace(/\.+$/,"").toLowerCase(),B=r.toLowerCase();if(B.endsWith(u.toLowerCase())||B.endsWith(f))return"INR"}let o=s.replace(/^\s+/,"");for(let u of t.currency_words_after??[]){let f=u.toLowerCase();if(o.toLowerCase().startsWith(f))return"INR"}return null}var lA={currency_markers_before:["\u20B9","Rs","Rs.","rs","INR","Re"],currency_words_after:["rupaye","rupay","rupees","rupiya","rupya","/-"]};var WA=`
|
|
1
|
+
function LA(A){return A.version===2&&Array.isArray(A.conv)}function dA(A){return A.quantized!==void 0}function FA(A){let B=atob(A),n=new Int8Array(B.length);for(let e=0;e<B.length;e++)n[e]=B.charCodeAt(e)<<24>>24;return n}function T(A){let B=FA(A.data_b64),n=new Float32Array(B.length);for(let e=0;e<B.length;e++)n[e]=B[e]*A.scale;return{shape:A.shape,data:n}}function U(A){return{shape:A.shape,data:Float32Array.from(A.data)}}function tA(A,B){return A*(B-1)/2}function Y(A){return{w:U(A.w),b:Float32Array.from(A.b.data)}}function m(A){return{w:T(A.w),b:Float32Array.from(A.b)}}function gA(A){let B=dA(A);if(LA(A)){let g=A.conv.map(f=>{let w=tA(f.dilation,f.k);if(B){let P=f;return{k:f.k,dilation:f.dilation,residual:f.residual,padding:w,w:T(P.w),b:Float32Array.from(P.b)}}let s=f;return{k:f.k,dilation:f.dilation,residual:f.residual,padding:w,w:U(s.w),b:Float32Array.from(s.b.data)}});return{version:2,charset:A.charset,classes:A.classes,embed:B?T(A.embed):U(A.embed),conv:g,bio:B?m(A.bio):Y(A.bio),cls:B?m(A.cls):Y(A.cls)}}let n=A.layers??3,e=A.dilation??2,t=[{name:"conv1",k:3,dilation:1},{name:"conv2",k:5,dilation:1},{name:"conv3",k:3,dilation:e}];n===4&&t.push({name:"conv4",k:3,dilation:4});let r=t.map(g=>{let f=tA(g.dilation,g.k);if(B){let u=A[g.name];if(!u)throw new Error(`missing ${g.name} in weights JSON`);return{k:g.k,dilation:g.dilation,residual:!1,padding:f,w:T(u.w),b:Float32Array.from(u.b)}}let s=A[g.name];if(!s)throw new Error(`missing ${g.name} in weights JSON`);return{k:g.k,dilation:g.dilation,residual:!1,padding:f,w:U(s.w),b:Float32Array.from(s.b.data)}});return{version:A.version??1,charset:A.charset,classes:A.classes,embed:B?T(A.embed):U(A.embed),conv:r,bio:B?m(A.bio):Y(A.bio),cls:B?m(A.cls):Y(A.cls)}}function MA(A){return Math.ceil(A/8)*8}function x(A){return MA(A+24)}var R=x(128),RA=/[०-९]/g;function k(A){return A.normalize("NFC").replace(RA,B=>String(B.charCodeAt(0)-2406)).toLowerCase()}function sA(A){let B=new Map;for(let n=0;n<A.length;n++)B.set(A[n],n);return B}function p(A,B,n,e){let t=B.get("<unk>")??1,r=B.get("<pad>")??0,g=e??A.length,f=n?n.subarray(0,g):new Int32Array(g);for(let w=0;w<A.length;w++)f[w]=B.get(A[w])??t;for(let w=A.length;w<g;w++)f[w]=r;return f}function Z(A){if(A<=128)return[{offset:0,length:A}];let B=[],n=112,e=0;for(;e<A;){let t=Math.min(128,A-e);if(B.push({offset:e,length:t}),e+t>=A)break;e+=n}return B}var X=class{buffers;padded;bioBuf;clsBuf;constructor(B){let n=B.conv,e=Math.max(B.embed.shape[1],...n.map(r=>r.w.shape[0]));this.buffers=[new Float32Array(e*R),new Float32Array(e*R)];let t=n.length?Math.max(...n.map(r=>r.padding)):0;this.padded=new Float32Array(e*(R+2*t)),this.bioBuf=new Float32Array(B.bio.w.shape[0]*R),this.clsBuf=new Float32Array(B.cls.w.shape[0]*R)}buf(B){return this.buffers[B%2]}paddedBuf(){return this.padded}};function OA(A,B,n,e,t,r){let[g,f,w]=e.w.shape;if(f!==B)throw new Error(`channel mismatch: expected ${B}, got ${f}`);let s=e.w.data,P=e.b,u=e.padding,o=e.dilation,C=n+2*u;for(let D=0;D<B;D++)r.fill(0,D*C,D*C+u),r.set(A.subarray(D*n,D*n+n),D*C+u),r.fill(0,D*C+u+n,D*C+C);for(let D=0;D<g;D++){let Q=D*n,i=P[D],I=D*B*w;if(w===3){for(let v=0;v<n;v++)t[Q+v]=i;for(let v=0;v<B;v++){let h=v*C,b=I+v*3,L=s[b],H=s[b+1],E=s[b+2];for(let c=0;c<n;c++){let a=h+c;t[Q+c]+=L*r[a]+H*r[a+o]+E*r[a+2*o]}}}else if(w===5){for(let v=0;v<n;v++)t[Q+v]=i;for(let v=0;v<B;v++){let h=v*C,b=I+v*5,L=s[b],H=s[b+1],E=s[b+2],c=s[b+3],a=s[b+4];for(let d=0;d<n;d++){let F=h+d;t[Q+d]+=L*r[F]+H*r[F+1]+E*r[F+2]+c*r[F+3]+a*r[F+4]}}}else{for(let v=0;v<n;v++)t[Q+v]=i;for(let v=0;v<B;v++){let h=v*C,b=I+v*w;for(let L=0;L<w;L++){let H=s[b+L],E=L*o,c=h+E;for(let a=0;a<n;a++)t[Q+a]+=H*r[c+a]}}}if(e.residual)for(let v=0;v<n;v++){let h=t[Q+v];t[Q+v]=(h>0?h:0)+A[Q+v]}else for(let v=0;v<n;v++){let h=t[Q+v];t[Q+v]=h>0?h:0}}return g}function wA(A,B,n,e,t){let[r,g]=e.w.shape;if(g!==B)throw new Error(`head channel mismatch: expected ${B}, got ${g}`);let f=e.w.data,w=e.b,s=B-B%4;for(let P=0;P<n;P++){let u=P*r;for(let o=0;o<r;o++){let C=w[o],D=o*B,Q=0;for(;Q<s;Q+=4)C+=f[D+Q]*A[Q*n+P]+f[D+Q+1]*A[(Q+1)*n+P]+f[D+Q+2]*A[(Q+2)*n+P]+f[D+Q+3]*A[(Q+3)*n+P];for(;Q<B;Q++)C+=f[D+Q]*A[Q*n+P];t[u+o]=C}}return r}function j(A,B,n){let e=B.length,t=A.embed,r=t.shape[1],g=n.buf(0);for(let u=0;u<e;u++){let C=B[u]*r;for(let D=0;D<r;D++)g[D*e+u]=t.data[C+D]}let f=r,w=n.paddedBuf(),s=1;for(let u of A.conv){let o=n.buf(s);f=OA(g,f,e,u,o,w),g=o,s++}wA(g,f,e,A.bio,n.bioBuf);let P=wA(g,f,e,A.cls,n.clsBuf);return{bioLogits:n.bioBuf,clsLogits:n.clsBuf,length:e,nCls:P}}function $(A,B,n,e){let t=-1/0;for(let g=0;g<n;g++)t=Math.max(t,A[B+g]);let r=0;for(let g=0;g<n;g++){let f=Math.exp(A[B+g]-t);e[g]=f,r+=f}for(let g=0;g<n;g++)e[g]/=r;return e}function G(A,B,n){let e=0,t=-1/0;for(let r=0;r<n;r++){let g=A[B+r];g>t&&(t=g,e=r)}return e}var xA=["PFX_PAAV","PFX_AADHA","PFX_PAUNE","PFX_SAVA","PFX_DEDH","PFX_DHAI","PFX_SAADHE"],zA=Array.from({length:99},(A,B)=>`CARD_${B+1}`),TA=["UNIT_SAU","UNIT_HAZAAR","UNIT_LAKH","UNIT_MILLION","UNIT_CRORE","UNIT_BILLION","UNIT_ARAB","UNIT_KHARAB"],UA=["O","SEP","RANGE","DIGITS","DOT","COMMA"],M=["O",...UA.filter(A=>A!=="O"),...xA,...zA,...TA],O=Object.fromEntries(M.map((A,B)=>[A,B])),PA={UNIT_SAU:100,UNIT_HAZAAR:1e3,UNIT_LAKH:1e5,UNIT_MILLION:1e6,UNIT_CRORE:1e7,UNIT_BILLION:1e9,UNIT_ARAB:1e9,UNIT_KHARAB:1e11},AA={UNIT_SAU:"sau",UNIT_HAZAAR:"hazaar",UNIT_LAKH:"lakh",UNIT_MILLION:"million",UNIT_CRORE:"crore",UNIT_BILLION:"billion",UNIT_ARAB:"arab",UNIT_KHARAB:"kharab"},BA={PFX_PAAV:{standalone:.25,op:null},PFX_AADHA:{standalone:.5,op:null},PFX_PAUNE:{standalone:.75,op:"sub25",min_n:2},PFX_SAVA:{standalone:1.25,op:"add25",min_n:2},PFX_DEDH:{standalone:1.5,op:null},PFX_DHAI:{standalone:2.5,op:null},PFX_SAADHE:{standalone:.5,op:"add5",min_n:3}};function CA(A){return A in BA}function oA(A){return A.startsWith("CARD_")}function vA(A){return A in PA}function DA(A){return parseInt(A.split("_",2)[1],10)}function N(A){return PA[A]}var QA=new Set(["SEP","RANGE","DOT","COMMA"]),pA=["PFX_","CARD_","UNIT_"],GA=["PFX_","CARD_","UNIT_"];function yA(A){return pA.some(B=>A.startsWith(B))||A==="DIGITS"}function YA(A){return GA.some(B=>A.startsWith(B))}var mA=O.O,J=O.SEP,eA=O.RANGE,XA=O.DIGITS,jA=O.DOT,NA=O.COMMA,JA=/\p{L}|\p{M}/u;function uA(A){return JA.test(A)?"letter":/[0-9]/.test(A)?"digit":/\s/.test(A)?"space":"punct"}function SA(A){let B=[],n=0,e=A.length;for(;n<e;){let t=uA(A[n]),r=n+1;for(;r<e&&uA(A[r])===t;)r++;B.push({type:t,start:n,end:r}),n=r}return B}function KA(A,B,n){let e=new Map;for(let s=B;s<n;s++){let P=A[s];YA(M[P])&&e.set(P,(e.get(P)??0)+1)}if(e.size===0)return mA;let t=-1;for(let s of e.values())s>t&&(t=s);let r=[...e.entries()].filter(([,s])=>s===t).map(([s])=>s);if(r.length===1)return r[0];let g=-1,f=1/0,w=r[0];for(let s of r){let P=0,u=0,o=1/0;for(let C=B;C<n;C++)A[C]===s?(o===1/0&&(o=C),P++,P>u&&(u=P)):P=0;(u>g||u===g&&o<f)&&(g=u,f=o,w=s)}return w}function _A(A,B,n){let e=[],t=B;for(;t<n;){let f=t+1;for(;f<n&&A[f]===A[t];)f++;e.push({start:t,end:f,cls:A[t]}),t=f}let r=KA(A,B,n),g=[];for(let f=0;f<e.length;f++){let w=e[f];if(w.end-w.start>=3){g.push([w.start,w.end,w.cls]);continue}let P=f>0?e[f-1]:null,u=f<e.length-1?e[f+1]:null,o=P!==null&&P.end-P.start>=3,C=u!==null&&u.end-u.start>=3,D;if(o&&C){let Q=P.end-P.start;D=u.end-u.start>Q?u.cls:P.cls}else o?D=P.cls:C?D=u.cls:D=r;g.push([w.start,w.end,D])}return g}function WA(A,B){let n=A.length,e=new Array(n),t=SA(A);for(let r=0;r<t.length;r++){let g=t[r],{type:f,start:w,end:s}=g;if(f==="digit"){for(let C=w;C<s;C++)e[C]=XA;continue}if(f==="space"){let C=!1;for(let Q=w;Q<s;Q++)if(B[Q]===eA){C=!0;break}let D=C?eA:J;for(let Q=w;Q<s;Q++)e[Q]=D;continue}if(f==="letter"){for(let[C,D,Q]of _A(B,w,s))for(let i=C;i<D;i++)e[i]=Q;continue}let P=r>0?t[r-1].type:null,u=r<t.length-1?t[r+1].type:null,o=J;if(s-w===1){let C=A[w];(C==="."||C===",")&&P==="digit"&&u==="digit"?o=C==="."?jA:NA:(C==="-"||C==="\u2013"||C==="/")&&P==="digit"&&u==="digit"?o=eA:o=J}for(let C=w;C<s;C++)e[C]=o}return e}function VA(A,B){let n=Array.from({length:B},(e,t)=>A[t]);for(let e=1;e<B-1;e++)A[e]===0&&(A[e-1]===1||A[e-1]===2)&&A[e+1]===2&&(n[e]=2);return n}function EA(A){return A!==void 0&&A>="0"&&A<="9"}function qA(A,B,n){if(n<=B||!EA(A[n-1]))return n;let e=n;for(;e<A.length&&EA(A[e]);)e++;return e}function cA(A,B,n,e){let t=A.length,r=VA(B,t),g=[],f=null;for(let s=0;s<t;s++){let P=r[s];P===1?(f!==null&&g.push([f,s]),f=s):P===2||f!==null&&(g.push([f,s]),f=null)}f!==null&&g.push([f,t]);for(let s=0;s<g.length;s++)g[s]=[g[s][0],qA(A,g[s][0],g[s][1])];let w=[];for(let[s,P]of g){let u=A.slice(s,P),o=Array.from({length:P-s},(H,E)=>n[s+E]),C=WA(u,o),D=s,Q=[];for(let H=s+1;H<=P;H++)(H===P||C[H-s]!==C[D-s])&&(Q.push([C[D-s],D,H]),D=H);let i=0,I=Q.length;for(;i<I&&QA.has(M[Q[i][0]]);)i++;for(;I>i&&QA.has(M[Q[I-1][0]]);)I--;let v=Q.slice(i,I);if(v.length===0)continue;let h=v[0][1],b=v[v.length-1][2];if(!v.some(([H])=>yA(M[H])))continue;let L=null;if(e){let H=[];for(let E=h;E<b;E++)H.push(Math.max(...e[E]));if(L=H.length?H.reduce((E,c)=>E+c,0)/H.length:0,L<.5)continue}w.push({start:h,end:b,text:A.slice(h,b),tokens:v.map(([H,E,c])=>[H,A.slice(E,c)]),confidence:L})}return w}function ZA(A){let B=[],n="",e=!1,t=()=>{if(e){let r=n.replace(/,/g,""),g=parseFloat(r);B.push(["NUM",Number.isNaN(g)?0:g])}n="",e=!1};for(let[r,g]of A)r!=="SEP"&&(r==="DIGITS"||r==="DOT"||r==="COMMA"?(n+=g,e=!0):(t(),B.push([r,g])));return t(),B}function $A(A,B){if(B!==null){let n=BA[B];if(n===void 0)return A!==null?A:1;if(A!==null&&n.op){if(n.op==="sub25")return A-.25;if(n.op==="add25")return A+.25;if(n.op==="add5")return A+.5}return n.standalone}return A!==null?A:1}function AB(A){let B=ZA(A),n=0,e=null,t=null,r=null,g=null;function f(w){let s=$A(r,g);if(w===null)n+=s*1;else{let P=N(w);e!==null&&P>e?n=n*P:n=n+s*P,e=P,(t===null||P>N(t))&&(t=w)}r=null,g=null}for(let[w,s]of B)if(w==="NUM")r!==null&&f(null),r=s;else if(oA(w)){r!==null&&f(null);try{r=DA(w)}catch{}}else if(CA(w))g!==null&&f(null),g=w;else if(vA(w))f(w);else continue;return(r!==null||g!==null)&&f(null),[n,t]}function S(A){let B=Math.round(A),n=Math.max(1e-6,Math.abs(A)*1e-9);return Math.abs(A-B)<n?B:Math.round(A*1e6)/1e6}function BB(A){let B=[],n=0;for(;n<A.length;){let[e,t]=A[n];if(e.startsWith("PFX_")){let r=t,g=n+1;for(;;){let f=g;if(f<A.length&&A[f][0]==="SEP"&&f++,f<A.length&&A[f][0]===e){for(let w=g;w<=f;w++)r+=A[w][1];g=f+1;continue}break}B.push([e,r]),n=g}else B.push(A[n]),n++}return B}function aA(A){try{let B=A.map(o=>o[0]),n=BB(A),e=[[]];for(let[o,C]of n){if(o==="RANGE"){e.length<2&&e.push([]);continue}e[e.length-1].push([o,C])}let t=e.filter(o=>o.length>0).map(o=>AB(o));if(t.length===0)return{value:0,range:null,unit:null,classes:B,currency:null};if(t.length===1){let[o,C]=t[0];return{value:S(o),range:null,unit:C?AA[C]??null:null,classes:B,currency:null}}let[r,g]=t[0],[f,w]=t[1],s;g===null&&w!==null?(r=r*N(w),s=w):s=g!==null?g:w;let[P,u]=r<=f?[r,f]:[f,r];return{value:S(P),range:[S(P),S(u)],unit:s?AA[s]??null:null,classes:B,currency:null}}catch{return{value:0,range:null,unit:null,classes:A.map(B=>B[0]),currency:null}}}function iA(...A){let B=(e,t)=>t.length-e.length,n=e=>[...new Set(e.flat())].sort(B);return{currency_markers_before:n(A.map(e=>e.currency_markers_before??[])),currency_words_after:n(A.map(e=>e.currency_words_after??[]))}}function IA(A,B,n,e){let t=A.slice(Math.max(0,B-4),B),r=A.slice(n,n+6),f=t.replace(/\s+$/,"").toLowerCase(),w=[...e.currency_markers_before??[]].sort((o,C)=>C.length-o.length);for(let o of w){let C=o.replace(/\.+$/,"").toLowerCase();if(f.endsWith(o.toLowerCase())||f.endsWith(C))return"INR"}let P=r.replace(/^\s+/,"").toLowerCase(),u=[...e.currency_words_after??[]].sort((o,C)=>C.length-o.length);for(let o of u){let C=o.toLowerCase();if(P.startsWith(C))return"INR"}return null}var HA={currency_markers_before:["\u20B9","Rs","Rs.","rs","INR","Re"],currency_words_after:["rupaye","rupay","rupees","rupiya","rupya","/-"]};var bA={currency_markers_before:["\u20B9","\u0930\u0941","\u0930\u0941.","Rs","Rs.","INR"],currency_words_after:["\u0930\u0941\u092A\u092F\u0947","\u0930\u0941\u092A\u090F","\u0930\u0942\u092A\u092F\u0947","\u0930\u0941\u092A\u092F\u093E","/-"]};var eB=`
|
|
2
2
|
struct Params { batch: u32, length: u32, embedDim: u32, vocab: u32, stride: u32 };
|
|
3
3
|
@group(0) @binding(0) var<uniform> p: Params;
|
|
4
4
|
@group(0) @binding(1) var<storage, read> charIds: array<i32>;
|
|
@@ -17,8 +17,8 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
17
17
|
xOut[(b * p.embedDim + c) * p.length + t] = embed[cid * p.embedDim + c];
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
`,
|
|
21
|
-
struct Params { batch: u32, length: u32, cIn: u32, cOut: u32, k: u32, padding: u32, dilation: u32, relu: u32, stride: u32 };
|
|
20
|
+
`,nB=`
|
|
21
|
+
struct Params { batch: u32, length: u32, cIn: u32, cOut: u32, k: u32, padding: u32, dilation: u32, relu: u32, residual: u32, stride: u32 };
|
|
22
22
|
@group(0) @binding(0) var<uniform> p: Params;
|
|
23
23
|
@group(0) @binding(1) var<storage, read> x: array<f32>; // (batch, cIn, L)
|
|
24
24
|
@group(0) @binding(2) var<storage, read> w: array<f32>; // (cOut, cIn, k)
|
|
@@ -47,9 +47,12 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
if (p.relu != 0u && acc < 0.0) { acc = 0.0; }
|
|
50
|
+
if (p.residual != 0u) {
|
|
51
|
+
acc = acc + x[(b * p.cIn + oc) * p.length + t];
|
|
52
|
+
}
|
|
50
53
|
out[(b * p.cOut + oc) * p.length + t] = acc;
|
|
51
54
|
}
|
|
52
|
-
`,
|
|
55
|
+
`,rB=`
|
|
53
56
|
struct Params { batch: u32, length: u32, cIn: u32, nOut: u32, stride: u32 };
|
|
54
57
|
@group(0) @binding(0) var<uniform> p: Params;
|
|
55
58
|
@group(0) @binding(1) var<storage, read> x: array<f32>; // (batch, cIn, L)
|
|
@@ -73,4 +76,4 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
73
76
|
}
|
|
74
77
|
out[(b * p.length + t) * p.nOut + o] = acc;
|
|
75
78
|
}
|
|
76
|
-
`;function V(){return typeof navigator<"u"&&!!navigator.gpu}var k=null;function q(){return k||(k=(async()=>{if(!V())return!1;try{return await navigator.gpu.requestAdapter()!==null}catch{return!1}})(),k)}var N=class{weights;state=null;constructor(e){this.weights=e}async init(){if(this.state)return this.state;if(!V())throw new Error("WebGPU is not available in this environment");let e=await navigator.gpu.requestAdapter();if(!e)throw new Error("No WebGPU adapter available");let n=await e.requestDevice(),t=(u,f)=>{let B=n.createBuffer({size:Math.max(4,u.byteLength),usage:f,mappedAtCreation:!0});return new Float32Array(B.getMappedRange()).set(u),B.unmap(),B},a=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,s=this.weights,o=[s.conv1,s.conv2,s.conv3,...s.layers===4&&s.conv4?[s.conv4]:[]].map(u=>({w:t(u.w.data,a),b:t(u.b,a)}));return this.state={device:n,embedModule:n.createShaderModule({code:WA}),convModule:n.createShaderModule({code:VA}),headModule:n.createShaderModule({code:qA}),embedBuf:t(s.embed.data,a),convBufs:o,bioBuf:{w:t(s.bio.w.data,a),b:t(s.bio.b,a)},clsBuf:{w:t(s.cls.w.data,a),b:t(s.cls.b,a)}},this.state}async run(e,n,t){let a=await this.init(),{device:s}=a,r=this.weights,o=r.embed.shape[1],u=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC,f=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,B=s.createBuffer({size:e.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Int32Array(B.getMappedRange()).set(e),B.unmap();let w=v=>{let Q=s.createBuffer({size:v.byteLength,usage:f,mappedAtCreation:!0});return new Uint32Array(Q.getMappedRange()).set(v),Q.unmap(),Q},g=s.limits?.maxComputeWorkgroupsPerDimension??65535,c=v=>{let Q=Math.max(1,Math.ceil(v/64)),E=Math.min(Q,g),p=Math.ceil(Q/E);return{x:E,y:p,stride:E*64}},C=(v,Q,E)=>{let p=s.createBindGroup({layout:v.getBindGroupLayout(0),entries:Q}),R=s.createCommandEncoder(),y=R.beginComputePass();y.setPipeline(v),y.setBindGroup(0,p),y.dispatchWorkgroups(E.x,E.y),y.end(),s.queue.submit([R.finish()])},i=s.createBuffer({size:n*o*t*4,usage:u});{let v=c(n*t),Q=w(new Uint32Array([n,t,o,r.embed.shape[0],v.stride])),E=s.createComputePipeline({layout:"auto",compute:{module:a.embedModule,entryPoint:"main"}});C(E,[{binding:0,resource:{buffer:Q}},{binding:1,resource:{buffer:B}},{binding:2,resource:{buffer:a.embedBuf}},{binding:3,resource:{buffer:i}}],v)}let D=o,h=[r.conv1,r.conv2,r.conv3,...r.layers===4&&r.conv4?[r.conv4]:[]],P=s.createComputePipeline({layout:"auto",compute:{module:a.convModule,entryPoint:"main"}});for(let v=0;v<h.length;v++){let Q=h[v],[E,,p]=Q.w.shape,R=v===2,y=v===3,F=y?4:R?r.dilation:1,_=y?Math.floor(8/2):R?Math.floor(r.dilation*2/2):v===0?1:2,$=s.createBuffer({size:n*E*t*4,usage:u}),AA=c(n*E*t),bA=w(new Uint32Array([n,t,D,E,p,_,F,1,AA.stride]));C(P,[{binding:0,resource:{buffer:bA}},{binding:1,resource:{buffer:i}},{binding:2,resource:{buffer:a.convBufs[v].w}},{binding:3,resource:{buffer:a.convBufs[v].b}},{binding:4,resource:{buffer:$}}],AA),i=$,D=E}let d=s.createComputePipeline({layout:"auto",compute:{module:a.headModule,entryPoint:"main"}}),b=async(v,Q)=>{let E=s.createBuffer({size:n*t*Q*4,usage:u}),p=c(n*t*Q),R=w(new Uint32Array([n,t,D,Q,p.stride]));C(d,[{binding:0,resource:{buffer:R}},{binding:1,resource:{buffer:i}},{binding:2,resource:{buffer:v.w}},{binding:3,resource:{buffer:v.b}},{binding:4,resource:{buffer:E}}],p);let y=s.createBuffer({size:n*t*Q*4,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),F=s.createCommandEncoder();F.copyBufferToBuffer(E,0,y,0,n*t*Q*4),s.queue.submit([F.finish()]),await y.mapAsync(GPUMapMode.READ);let _=new Float32Array(y.getMappedRange().slice(0));return y.unmap(),_},I=await b(a.bioBuf,r.bio.w.shape[0]),l=await b(a.clsBuf,r.cls.w.shape[0]);return{bio:I,cls:l}}};var QA={version:1,quantized:"int8_symmetric_per_tensor",layers:4,charset:["<pad>","<unk>"," ","!",'"',"#","%","'","(",")","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":","?","@","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","~","\u20B9"],classes:["O","SEP","RANGE","DIGITS","DOT","COMMA","PFX_PAAV","PFX_AADHA","PFX_PAUNE","PFX_SAVA","PFX_DEDH","PFX_DHAI","PFX_SAADHE","CARD_1","CARD_2","CARD_3","CARD_4","CARD_5","CARD_6","CARD_7","CARD_8","CARD_9","CARD_10","CARD_11","CARD_12","CARD_13","CARD_14","CARD_15","CARD_16","CARD_17","CARD_18","CARD_19","CARD_20","CARD_21","CARD_22","CARD_23","CARD_24","CARD_25","CARD_26","CARD_27","CARD_28","CARD_29","CARD_30","CARD_31","CARD_32","CARD_33","CARD_34","CARD_35","CARD_36","CARD_37","CARD_38","CARD_39","CARD_40","CARD_41","CARD_42","CARD_43","CARD_44","CARD_45","CARD_46","CARD_47","CARD_48","CARD_49","CARD_50","CARD_51","CARD_52","CARD_53","CARD_54","CARD_55","CARD_56","CARD_57","CARD_58","CARD_59","CARD_60","CARD_61","CARD_62","CARD_63","CARD_64","CARD_65","CARD_66","CARD_67","CARD_68","CARD_69","CARD_70","CARD_71","CARD_72","CARD_73","CARD_74","CARD_75","CARD_76","CARD_77","CARD_78","CARD_79","CARD_80","CARD_81","CARD_82","CARD_83","CARD_84","CARD_85","CARD_86","CARD_87","CARD_88","CARD_89","CARD_90","CARD_91","CARD_92","CARD_93","CARD_94","CARD_95","CARD_96","CARD_97","CARD_98","CARD_99","UNIT_SAU","UNIT_HAZAAR","UNIT_LAKH","UNIT_MILLION","UNIT_CRORE","UNIT_BILLION","UNIT_ARAB","UNIT_KHARAB"],embed:{shape:[56,16],scale:.03634775057435036,data_b64:"AAAAAAAAAAAAAAAAAAAAAAfSJgP/6wYvDdn2DikdGePzEOgLCAYRAv4YAwMPRtO3+B4L/v76H//xITRCCwv3ufAZHyPXR/MJ0/Hz8uMf/Bb9E+kAF/UdCvk/zP/j5gEULdsJDrjR+ggHAgkNDegV5/q9/v8aCuf+7/M19QMgGSbo9OoQEQ024/4D8N795PcH+QMHIAgL+v0F68wE7QkECzLh8w3F/hoy5PAz8M3u/NIVBtr3ACEM/+wSXSX9G9Pn8i4T/RwKBRTmAAfy+jXmmQju+TPcH+elFEcKACYa2Pv8PxjxKADx6wAK/fbuEvub3+QiGj0HBMMTNBTL6uo9+uEfFSYD6e3y/kcb1wHmNgnoFhknDfTZ3vs4ENED4jL/+CUfJx3+6uUPPAfOAOcy/P8aHisc+uDnDjv+yA7uMQL2ICAwJff81g46E9AC4jP3+RoWJiH77eUUOwfJ/uk4AvwgIyoo/fXFDzEX0f7jMPb0HyApJPTq2A85Dsz57DD69BkdHxX89d4aPA7MBOs9/OP+Bucw7yfyFfkSJQIbIQ/6IQcYAAYlEOMKIE4qIfK4PiLzDCUM8vsIAwrrBvkr+ekCJOpI8O4l/PgZI/8Y/ycE3AT6DfwG3twb4S4BkDCe8er/veoxIMjwHQzU7RLoHxYEyuHz3soM/wvTtwPTLMfx6ekfC/8U3u8O2xgUDv8l2Abmn/Xq+OcfDX/dQhQSDwkR/enVzO0SFBHkAO43Aw8a/SUZ8CjlGP7s9tQMLxEA7v7V8AwJ+xQBAOq92PsBGAjmKxHw99oZ8UwpGeQlzjfv5g7s2yHhKOb7/fU58t8U9ODx4Pc6Jwjl+cASCQEy6AXp983MLhoQOCPhPuQVKBHmTuUb5xg2AvryHe0K0AwUGhzk1AEYyQnmJQsV4uAUFBcgCNoh4w/01xLTCEi3AA/yEPft4+X69PUXBwn56gYeGeXiEurfHxm4EiT1Be4w/AkWHvTv5CnH2frpD/YxLAO2DBwc7B/iAOK/+fvnGhD4GPshBisW1N/kEfsN/cLd+Af55AMmHMO9Ce08+vogAR/54NsMFCShxvoDVhPxJPgT8tMACeMTA84NMPEn0hHyNdgA/+oG5PsoD/vky97z7wPx+C8V6AHH+elF8hjpCNEVYdn97Oc8Fv3xA/EI5QAaFwJCyCzYHS8ECOgN+PEF5Ns="},conv1:{w:{shape:[32,16,3],scale:.006139184348285198,data_b64:"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"},b:[.45622,.23405,.22881,.099713,.22726,.17001,.048671,-.17105,.11404,.33485,.15626,-.46358,-.013018,.099381,-.010189,.020385,-.14867,-.17133,-.030829,.10267,-.13208,-.38272,.064075,-.042051,-.15628,.20139,.15375,-.013163,.098084,.047966,.22716,-.074847]},conv2:{w:{shape:[32,32,5],scale:.009565402753651142,data_b64:"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"},b:[.25476,.026761,.091159,.2577,.011283,-.31972,.73302,-.021524,-.20232,.049772,-.091728,.11994,-.40917,.061952,-.055094,-34595e-9,.1525,.17977,.025422,.47911,.2569,-.067177,.086829,-.011742,.12641,.13773,.33299,-.2564,-.067883,.021229,.84651,.89692]},conv3:{w:{shape:[32,32,3],scale:.011997192166745663,data_b64:"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"},b:[.95696,.38779,-.019267,.15136,1.357,.8184,.18205,.47105,.10438,.032386,-.26726,1.2156,.86512,-.053118,.57925,-.21673,1.2695,.64724,.11427,.29962,.64951,-.061881,.019131,.1549,1.2697,.042946,.61255,-.57353,-.13114,1.0174,.11395,.26929]},conv4:{w:{shape:[32,32,3],scale:.01576780155301094,data_b64:"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"},b:[.89296,.26698,.91654,.46187,-.081608,-.53949,.55512,.21752,1.0169,.47651,.34679,.29588,1.5106,.60742,-.1133,-.028405,.037585,-.23182,1.2854,.27839,.24252,.69016,-.17436,.5821,-.059923,.050272,1.2284,.32915,.25613,.31951,.25337,.76967]},bio:{w:{shape:[3,32],scale:.008006345480680466,data_b64:"/QLWCQR//MgHBaD4EfoD8/ryCAcCAgLuCwQV9wcD+frzA/sGEyMXffcE/vwF/gH2/vf0CAH7D/YJCAj/Cgf9+u8DNwfmtyEF6AZeA/3/B/YA9+gK/vQM9QgI/gILCf36"},b:[.87751,-.81366,-.26467]},cls:{w:{shape:[120,32],scale:.009712129831314087,data_b64:"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"},b:[1.5043,.16996,-.14971,.29736,-.50758,.11862,.029212,.1628,-.14132,-.091054,-.60198,-.25317,-.13608,.068661,-.12722,-.36333,-.16175,-.27111,-.14709,-.23161,.064164,-.46374,-.52342,-.047273,-.12203,-.25037,-.5412,-.33762,-.01589,-.37118,.019277,-.44845,-.27225,-.70827,-.15251,-.32633,-.4003,-.38486,-.18858,-.20396,-.32059,-.34326,-.50492,-.42893,-.53269,-.39711,-.1355,-.26617,-.36554,-.46165,-.1886,-.22946,-.20626,-.3812,-.17224,-.22552,-.30371,-.17449,-.087149,-.33845,-.4778,-.21339,-.29264,-.56332,-.28292,-.33691,-.48023,-.25778,-.27241,-.39297,-.31795,-.44322,-.24301,-.22345,-.32524,.084856,-.17181,-.34565,-.19354,-.13021,.0022854,-.58743,.034923,-.45897,-.51305,-.31592,-.3854,-.37011,-.19354,-.46266,-.29652,-.21346,-.17185,-.48329,-.49975,-.41428,-.45629,-.16367,-.29652,-.48026,-.54081,-.55343,-.46746,-.3885,-.29678,-.45206,-.37856,-.124,-.061739,.043541,-.046948,-.14789,-.36611,.21359,.29946,-.6239,.19281,-.41082,-.34077,-.22366]}};var S=class{weights;charToId;gpu=null;defaultBackend;scratch;idsScratch=new Int32Array(H);bioIdsScratch=new Int32Array(128);clsIdsScratch=new Int32Array(128);bioProbsScratch=Array.from({length:128},()=>new Float32Array(3));constructor(e={}){this.weights=tA(e.weights??QA),this.charToId=rA(this.weights.charset),this.defaultBackend=e.backend??"cpu",this.scratch=new O(this.weights)}parse(e,n={}){let t=sA(e.length);if(t.length===1&&t[0].length===e.length){let r=x(e.length),o=U(e,this.charToId,this.idsScratch,r),u=j(this.weights,o,this.scratch);return this.decodeForward(e,u,0,e.length)}let a=[],s=new Set;for(let r of t){let o=e.slice(r.offset,r.offset+r.length),u=x(o.length),f=U(o,this.charToId,this.idsScratch,u),B=j(this.weights,f,this.scratch),w=this.decodeForward(o,B,r.offset,o.length);for(let g of w){let c=`${g.start}:${g.end}`;s.has(c)||(s.add(c),a.push(g))}}return a.sort((r,o)=>r.start-o.start),a}decodeForward(e,n,t,a=n.length){let s=a,r=s<=128,o=r?this.bioIdsScratch:new Int32Array(s),u=r?this.clsIdsScratch:new Int32Array(s),f=r?this.bioProbsScratch:Array.from({length:s},()=>new Float32Array(3));for(let g=0;g<s;g++)o[g]=Y(n.bioLogits,g*3,3),u[g]=Y(n.clsLogits,g*n.nCls,n.nCls),fA(n.bioLogits,g*3,3,f[g]);let B=PA(e,o.subarray(0,s),u.subarray(0,s),f),w=[];for(let g of B){let c=g.tokens.map(([D,h])=>[L[D],h]),C=DA(c),i=vA(e,g.start,g.end,lA);w.push({span:g.text,start:g.start+t,end:g.end+t,value:C.value,...C.range?{range:C.range}:{},unit:C.unit??null,currency:i,confidence:g.confidence??0,classes:C.classes})}return w}async parseBatch(e,n={}){let t=n.backend??this.defaultBackend;if(!(t==="webgpu"||t==="auto"&&e.length>=32&&await q()))return e.map(u=>this.parse(u,{backend:"cpu"}));let s=new Array(e.length),r=[],o=[];for(let u=0;u<e.length;u++)e[u].length<=128?r.push(u):o.push(u);for(let u of o)s[u]=this.parse(e[u],{backend:"cpu"});if(r.length>0){this.gpu||(this.gpu=new N(this.weights));let u=Math.max(...r.map(D=>e[D].length),1),f=x(u),B=r.length,w=new Int32Array(B*f),g=this.charToId.get("<pad>")??0;w.fill(g);for(let D=0;D<B;D++){let h=e[r[D]],P=U(h,this.charToId);w.set(P,D*f)}let{bio:c,cls:C}=await this.gpu.run(w,B,f),i=this.weights.cls.w.shape[0];for(let D=0;D<B;D++){let h=e[r[D]],P=h.length,d=new Float32Array(P*3),b=new Float32Array(P*i);for(let l=0;l<P;l++)d.set(c.subarray((D*f+l)*3,(D*f+l)*3+3),l*3),b.set(C.subarray((D*f+l)*i,(D*f+l)*i+i),l*i);let I={bioLogits:d,clsLogits:b,length:P,nCls:i};s[r[D]]=this.decodeForward(h,I,0,P)}}return s}},Z=null;function EA(){return Z||(Z=new S),Z}function ve(A,e={}){return EA().parse(A,e)}function le(A,e={}){return EA().parseBatch(A,e)}function Qe(A={}){return new S(A)}export{S as Parser,Qe as createParser,V as isWebGPUAvailable,ve as parse,le as parseBatch,q as probeWebGPU};
|
|
79
|
+
`;function nA(){return typeof navigator<"u"&&!!navigator.gpu}var K=null;function rA(){return K||(K=(async()=>{if(!nA())return!1;try{return await navigator.gpu.requestAdapter()!==null}catch{return!1}})(),K)}var _=class{weights;state=null;constructor(B){this.weights=B}async init(){if(this.state)return this.state;if(!nA())throw new Error("WebGPU is not available in this environment");let B=await navigator.gpu.requestAdapter();if(!B)throw new Error("No WebGPU adapter available");let n=await B.requestDevice(),e=(f,w)=>{let s=n.createBuffer({size:Math.max(4,f.byteLength),usage:w,mappedAtCreation:!0});return new Float32Array(s.getMappedRange()).set(f),s.unmap(),s},t=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,r=this.weights,g=r.conv.map(f=>({w:e(f.w.data,t),b:e(f.b,t)}));return this.state={device:n,embedModule:n.createShaderModule({code:eB}),convModule:n.createShaderModule({code:nB}),headModule:n.createShaderModule({code:rB}),embedBuf:e(r.embed.data,t),convBufs:g,bioBuf:{w:e(r.bio.w.data,t),b:e(r.bio.b,t)},clsBuf:{w:e(r.cls.w.data,t),b:e(r.cls.b,t)}},this.state}async run(B,n,e){let t=await this.init(),{device:r}=t,g=this.weights,f=g.embed.shape[1],w=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC,s=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,P=r.createBuffer({size:B.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Int32Array(P.getMappedRange()).set(B),P.unmap();let u=E=>{let c=r.createBuffer({size:E.byteLength,usage:s,mappedAtCreation:!0});return new Uint32Array(c.getMappedRange()).set(E),c.unmap(),c},o=r.limits?.maxComputeWorkgroupsPerDimension??65535,C=E=>{let c=Math.max(1,Math.ceil(E/64)),a=Math.min(c,o),d=Math.ceil(c/a);return{x:a,y:d,stride:a*64}},D=(E,c,a)=>{let d=r.createBindGroup({layout:E.getBindGroupLayout(0),entries:c}),F=r.createCommandEncoder(),l=F.beginComputePass();l.setPipeline(E),l.setBindGroup(0,d),l.dispatchWorkgroups(a.x,a.y),l.end(),r.queue.submit([F.finish()])},Q=r.createBuffer({size:n*f*e*4,usage:w});{let E=C(n*e),c=u(new Uint32Array([n,e,f,g.embed.shape[0],E.stride])),a=r.createComputePipeline({layout:"auto",compute:{module:t.embedModule,entryPoint:"main"}});D(a,[{binding:0,resource:{buffer:c}},{binding:1,resource:{buffer:P}},{binding:2,resource:{buffer:t.embedBuf}},{binding:3,resource:{buffer:Q}}],E)}let i=f,I=g.conv,v=r.createComputePipeline({layout:"auto",compute:{module:t.convModule,entryPoint:"main"}});for(let E=0;E<I.length;E++){let c=I[E],[a,,d]=c.w.shape,F=c.dilation,l=c.padding,z=r.createBuffer({size:n*a*e*4,usage:w}),y=C(n*a*e),hA=u(new Uint32Array([n,e,i,a,d,l,F,1,c.residual?1:0,y.stride]));D(v,[{binding:0,resource:{buffer:hA}},{binding:1,resource:{buffer:Q}},{binding:2,resource:{buffer:t.convBufs[E].w}},{binding:3,resource:{buffer:t.convBufs[E].b}},{binding:4,resource:{buffer:z}}],y),Q=z,i=a}let h=r.createComputePipeline({layout:"auto",compute:{module:t.headModule,entryPoint:"main"}}),b=async(E,c)=>{let a=r.createBuffer({size:n*e*c*4,usage:w}),d=C(n*e*c),F=u(new Uint32Array([n,e,i,c,d.stride]));D(h,[{binding:0,resource:{buffer:F}},{binding:1,resource:{buffer:Q}},{binding:2,resource:{buffer:E.w}},{binding:3,resource:{buffer:E.b}},{binding:4,resource:{buffer:a}}],d);let l=r.createBuffer({size:n*e*c*4,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),z=r.createCommandEncoder();z.copyBufferToBuffer(a,0,l,0,n*e*c*4),r.queue.submit([z.finish()]),await l.mapAsync(GPUMapMode.READ);let y=new Float32Array(l.getMappedRange().slice(0));return l.unmap(),y},L=await b(t.bioBuf,g.bio.w.shape[0]),H=await b(t.clsBuf,g.cls.w.shape[0]);return{bio:L,cls:H}}};var lA={version:2,quantized:"int8_symmetric_per_tensor",charset:["<pad>","<unk>"," ","!",'"',"#","%","'","(",")","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":","=","?","@","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","}","~","\u0901","\u0902","\u0903","\u0905","\u0906","\u0907","\u0908","\u0909","\u090A","\u090F","\u0911","\u0913","\u0915","\u0916","\u0917","\u0918","\u091A","\u091B","\u091C","\u091D","\u091F","\u0920","\u0921","\u0922","\u0923","\u0924","\u0925","\u0926","\u0927","\u0928","\u092A","\u092B","\u092C","\u092D","\u092E","\u092F","\u0930","\u0932","\u0935","\u0936","\u0937","\u0938","\u0939","\u093C","\u093E","\u093F","\u0940","\u0941","\u0942","\u0947","\u0948","\u0949","\u094B","\u094C","\u094D","\u20B9"],classes:["O","SEP","RANGE","DIGITS","DOT","COMMA","PFX_PAAV","PFX_AADHA","PFX_PAUNE","PFX_SAVA","PFX_DEDH","PFX_DHAI","PFX_SAADHE","CARD_1","CARD_2","CARD_3","CARD_4","CARD_5","CARD_6","CARD_7","CARD_8","CARD_9","CARD_10","CARD_11","CARD_12","CARD_13","CARD_14","CARD_15","CARD_16","CARD_17","CARD_18","CARD_19","CARD_20","CARD_21","CARD_22","CARD_23","CARD_24","CARD_25","CARD_26","CARD_27","CARD_28","CARD_29","CARD_30","CARD_31","CARD_32","CARD_33","CARD_34","CARD_35","CARD_36","CARD_37","CARD_38","CARD_39","CARD_40","CARD_41","CARD_42","CARD_43","CARD_44","CARD_45","CARD_46","CARD_47","CARD_48","CARD_49","CARD_50","CARD_51","CARD_52","CARD_53","CARD_54","CARD_55","CARD_56","CARD_57","CARD_58","CARD_59","CARD_60","CARD_61","CARD_62","CARD_63","CARD_64","CARD_65","CARD_66","CARD_67","CARD_68","CARD_69","CARD_70","CARD_71","CARD_72","CARD_73","CARD_74","CARD_75","CARD_76","CARD_77","CARD_78","CARD_79","CARD_80","CARD_81","CARD_82","CARD_83","CARD_84","CARD_85","CARD_86","CARD_87","CARD_88","CARD_89","CARD_90","CARD_91","CARD_92","CARD_93","CARD_94","CARD_95","CARD_96","CARD_97","CARD_98","CARD_99","UNIT_SAU","UNIT_HAZAAR","UNIT_LAKH","UNIT_MILLION","UNIT_CRORE","UNIT_BILLION","UNIT_ARAB","UNIT_KHARAB"],embed_dim:16,channels:48,embed:{shape:[114,16],scale:.026793908327817917,data_b64:"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"},conv:[{k:5,dilation:1,residual:!1,w:{shape:[48,16,5],scale:.006297729909420013,data_b64:"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"},b:[-.41403,-.37083,-.17471,-.10723,-.217,-.12782,-.13307,-.17872,.14632,.22011,-.51505,-.49735,-.37585,-.09941,-.28281,-.019124,-.42833,.035917,-.10015,-.15915,-.25731,-.26232,-.0039441,-.27283,-.15598,-.25122,-.0023473,-.22346,-.29785,-.20515,-.19531,-.4258,-.18466,-.01237,.29463,-.2259,-.34927,.099886,-.44475,.075165,-.23074,-.3804,-.36044,-.20509,-.13041,-.65456,-.15375,-.27194]},{k:3,dilation:1,residual:!0,w:{shape:[48,48,3],scale:.011268280446529388,data_b64:"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"},b:[-.11524,-.18613,.1175,-.24892,.044796,.036463,.162,.1028,.29527,.66518,.22132,.018315,.021825,-.035526,-.079711,.003407,.027631,.018111,.091177,.19069,-.014315,.14228,.56057,.094511,-.2393,.14826,.15474,.080275,.10113,-.0066077,.18899,.37924,.22151,.15665,.025146,.12335,.039528,.020341,.17161,.30304,.089673,.7569,-.26167,-.43312,-.10887,-.15408,.089991,.14783]},{k:3,dilation:2,residual:!0,w:{shape:[48,48,3],scale:.01531923096626997,data_b64:"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"},b:[.32767,.15526,.082936,-.049189,-.054941,-.15,.26939,.011199,82305e-8,1.0392,.2586,-.35586,.59987,.199,.1843,.024139,-.021032,.021746,.068581,.1081,-.066881,.28893,.89474,.89374,.0083983,.010518,.63441,.033195,.63983,.12939,.35362,.14388,1.1091,.2411,-.18525,.38478,-.054586,.68936,-.039841,.35021,.042444,1.2556,-.077732,-.63378,-.12078,.63872,-.024576,.76438]},{k:3,dilation:4,residual:!0,w:{shape:[48,48,3],scale:.017100131139159203,data_b64:"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"},b:[1.3777,.085752,.28277,-.0026793,-.36331,.26844,.23482,.45244,-1.3456,.32375,.62031,-.2426,.0069488,.28055,1.2795,.49334,.092458,.021483,.35107,.12564,.094297,.33727,1.1613,.91248,.33595,-.31547,1.0323,.48746,-.51575,.62476,.13256,.57825,1.5317,.17567,.028722,.71635,-.029699,-.071299,.67362,.67226,.57821,1.9162,.22972,-.058133,-.21721,1.7296,-.063783,1.2866]},{k:3,dilation:8,residual:!0,w:{shape:[48,48,3],scale:.01713515631854534,data_b64:"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"},b:[.17334,.95171,.39722,.81052,.1426,.24649,.26206,-1.6457,.60351,.68078,.32679,-.072643,-1.4102,-.10251,-.77406,.49564,-.033894,.076563,.036676,-.66481,-.080242,.22412,.46619,1.2746,.53776,.49293,.26188,.56415,-.41336,-.037646,.33929,.76413,.56441,.18243,.5228,-95438e-10,-.11429,.43393,.4121,-.025991,.0081522,1.6035,.041022,.06896,.15759,1.8212,-.1321,.81853]}],bio:{w:{shape:[3,48],scale:.004121375735849142,data_b64:"KP707AkH9PmB9RL0dgJFDxD4ASj2ADr27AgHFQIH9PgXzeMA/QHvLQ4FAP76/wb52gD+7gwJ9/IM9xDu9wT4ERP3/FX7/yD67Q0FEwT09fYMFtL68wTsVgAB/gIGuAb62gH67AoK+vA/9hEAiwTwEBr48+X7Adbt7BEFEgL29fcLFkQIBwXuwCH//gIE9Qb7"},b:[.33826,-.72342,.082475]},cls:{w:{shape:[120,48],scale:.006543000228703022,data_b64:"Pgj9AQEFAQ2BBgEAdAU5/gAHBAIHCy4IAvr9AgMPCQYcuvMECgEDGAMQAwfxNgIC7f0B6wgFuNg78fv3t/b1FQoH+w78/ur3+BID4AT99wYS+y4JF+sKIhX4/vnzJuz+CzTx/AQQD/Ad898U4Pjv6w//vPwaFNoK+vQC9dz+Lfnc3iEM7AIHEwnuAh/vKAf//PMIAQMGEAgrBvYEvhPr7/n46fwhAvAF/eL0/AAK6ugOMxHo9QYJ9eoKAA/z7vXn9vv6/PcDB/kKAAb9/wj59/wL8+v7BOz0CgQFAfwHFQcl+fAbRAQL9QLsCgUkEADu/wvvEgIFAfrvAwoCDQ8W+/0K7wkEBycHCBX8AAMA+gMd+/oK9g0J9vUEBAwj5/j6+hAA7Ab4BOXy8C4P+RIECfUNA/X99Pn+Bf7dAxP/9wsEFA8KAfgEGe8HBQH0CiD/+gD4FhL7FCz/AQT16Bfh9vn7M+/lAOwXAfz3Cg8L0SQHDBP1+uIABgcCEgIR7OYNBhvs/d0F8/IaEuAJ8v/kAiAIEwAK8BL6/Q4F8gjl9/ojI/EO8PkC7vDhBvH5+wUkBwPqAfzyCRz7EhcB5Bvq+ecWEPoB/PruDf75Gvb6Gg3HFh4AEPf+GQ8HBggP9974+PoX/CgBChr3+QP99gj57AkH9vfz4P8JEur3Ef74DRzj7xchCRUIDPoM/fsC+hH//wX3C8n9GREL/O4M5gTm+gXv7fP//fMo+u/sBxT66xzyIgwcAwP//gnyARQM7wMs9fAIBwUSDR0U7AAF5f77/iIGH/4JAf0E9/TyAuLxMeER5hgC5uEKBfUG+PAA+Psm4wD3Av8HCxsKEvz//A4F6gEPGfr++QvmAvkHAxER6SgZAPfdACT68PcP9QP2/+fwCAzcHB/2BRDx/gEKEgXtD/8F/ggO9Q0SEQr6AAP7IiIOE+bsAwL77gTrFArx5vn38f8JCQMVCwYID+gH/fUNCAUB7gUJIvgD/P0V+/nuDPEV+PPzBhjt6Ab/Dv7t9/sR7grq//z1FgEHCBoO5//0FgT34AgVFvUZAAEG/Qn8/wsLFATz++/o9vodFxX44/MA6hb+BgwQERYB/PXrAhEIEQwMHAP/9QX2H/kABvjx+AQZAvcnG/jp+fPtCPPnA+/u7PgADfoOFwIBBPbu//ABFQkIKhQO+AgB/vsDAv8SARUIAvwk6fUH+QUFAgbt9Pzc+P0LAf8N/fUCDx8IDfcGFf8VDQUHEgX5BBgYBAT+G/8Z9e/pC/sD7//7+fbu7PLk8AwTAv4Y9xIMD/MH9wjnEAX7Aw/z+wz9B/McB/0G7QD6AgsV+QQDAfYl/u385fj3+/wN7BoOCO/7DgUEBfoJAQ8OCQEC+Pn7CfssBgbr+Q0A+f/gEfX9+QH+AuL1/hMG+gfzA/YM8RIJ+A8TAgoCFPcD//YOBQD9+f7s/f0FEf0Q/fcNCSf48vwPAgQD8f737wgu9O8K9vT8A+wDBQ3/7vP89/8AFvv8EPwMB/vl9O/mBA0MGwP7FfzyB/8FFQoQ/gMP+u0OBu/6/gsB+g77Iv4DAQQU9gMF/gcFCwcI9QX4+Az4CAHwBwcG9gMU9hD+7gUgDwv4+wfu9gPvABIAB+skDA4QBwgBEwP6EgD2GvT0EPoQBPz5AgDy9/3x+BH6Av0ECxj0C/Lt9QoKEuz9B/Ai/wwHFgLwEQURDvv0DhPh9QT0DPv/DwvwARcNBvvx+BEd9SQM8/kNBA0W/O4HCvAC9fH2A/P58gkB/gz0+/z6+vn2+/kM8wwFA/kKCvoK7wESLvUR+SAB+Nz3+gbgAfUAFQ4CEAQPEfAGA/b8CwT3CgIA/f78Bv/hEv0H/QHx+gclAuEC+A8ADvAQ+h0BBOr67APwGQEE+Pz5/BICDQv/EgDq+f39AP4LCwP7+wP98P0h+OQG8wMBBv4GA+YOBgMjAff9Awrl+fgCAwn89/f7AQsbAgj/CwX/6vsQGfv7CP0DAP4L/BYZ5/4R8xP9EAPyBgL/BfDq+fsg/O/+/wzr6gji/QXuAgf+BAAXGO8D//8J/Pn1AgkIBPL9+ALwHQ7/+gH8BP3qEffoAQLx/f/59BEHDA8TGPLxCf/5EwES/gsR+gfz8vcIA/Pz/vn7BBL8AQH++wr0BwoB/BT3CSvrD/ng9gAI/QP2EwD3Cv8HDAf5+xIO+gACCfv5/wUCEwoCAf8S9gD/+gD8Bf//EAz78//o/Psc/wcE+e0KABALAQIG+f//9/P7Du0BARANBPMWBP0DBwT0/gAEAgjwAffu/wH5BxsR/wYBCuMP+xAM/AgE/f3sBfv8/P/8BR7//goQ/AUA/wT8DQbzBgT2DBsBDfX6BPwa/vXy8gX3AgX96Q0a9/kRCxcPGe8D+gH37PoJHgUM+fH6/fYCDAwJ+gXq8/nsDgQe+w0K7PgHBfn0/v4A/PwBFAv3APL+AhsL/f72DAoHAfQE//b69vf5CAoAA/4PAv4FCQH1HQEDFQrq/AD8/QUVBPr3/vEIBBcNAfoHDQDz+QkDCQH+/RH3AgcED/38AgUSAfX3DOf+AQnu7/v2AQwKCQz1Dfj5Ae0GBf4pFQIO/AEGCPn5BQfzEvv+DvzzBAcM/gH0//H/AwfqDQX3Awn6/wv/CvwFAgL3Cvca/PsB/QAFAQcMDgv5AgfzAf/tBQQR/An66QEI9fkO8wAO7vf8Cv//EhcB+wQPA/cI/fr+Ce4D8gMLAgkF8v34/AL8ChYL9wkUDAgS8QDy+gMA/wzx/gn7EA/5BO0HAPoM/v8HCQAA+gHo+Qr2FAMDDvQH+v8U+wj9HPwA/wEIBAr3CwwMCxX7APn8BQP+BOkMBAUEAvYC+P3z/+kFDAT/+/0H8/wZAwb9Bh3+Av7zCAn/CgLzDA/yB/X2/wsA8+YQ/AEEEvkCAgEPBAP1BArzBAT/Dfn9Bg33FRUHAPwG8AsGDQsJ/yT9+v4FASr06fID+wHzFPgGEP4LCfICBwULEf8OAPkGBvP09/j0CPD8BAL5Bg/8/Q3/EOwMC+r+9v//6wb/DQz/DfgOAAblDwv0BfziCvsXAQH+CQYDBPISBAjyBBTx/Av8Dff7Bwb79hsRA/wHBAj5BwUE/QH/DwIR8wEQAAIZBf/8B/gAAPX3Bw0DAwj++ggAAvMB/x7x9PXn9Pf/DusN+f/4/gIBBgH3CP/qAgIbBQv6FwMFBAYZAQ8YAwMM9fr+D/UBCPgC9f0a+f/7EwMIBAX4BwDvEQUCAfXtCQAi+wL29Pvu/QwN/Ajz/hMK/SQICgoF+wz5/P0RA/wP8f3w9Pn2BfMNAwIL9f4Y8gQA+wUO6vIZA/cK+gj+Dwbx7RkFCPb8APLw+voQ+/obDwbw/v34BPoOHB4K7QLn8gAdBf4A7BgCC/358/8NAQAMChXxDg77B+8OBPETDQgNCgD+B/kJAwb1Dg36AvvoDQTn+gICFv3/9AbwAAv++woUAAT9F/D+CAL/+AP4BP8P8An9CwYVCv/9AhYA7/8PEAEB+f4DA/sP8wD08AT3A/36DBz8FAMB7w8E/t4WBvQNDfkC9vrqARkE/PsRDQQC/wvr9wUMEAT98f4LAQT8AgIW/QAG+f0QDwwKAP3y/AkCGAHy/f8I9/gCChUJ8fbyAAf+/v4FAggEDvfx7P/uCAf4+hz/DgQT/gDt+gIG9PsVAg0TGfr3AxTlBPwMDwDqDAz2+u/1BPgU9fcO/w8PAvnz9QUB+gMMDBD4Au8GBgEXAQHz/QEC/gEFCR0E7/4GBQLwAQEHBRX6AQf59QUA/AEhBRIIBQAR8x7/AezmBvoLDuYP9/QD/AEC/+8E/wT0BQ3t+AIMGuYG9wkGAg0VAP4nAvwLBvMK//QMAOkaCgH/Cf/v9P0RBP4DBhAA6f4IAv/19AcN8QLy+wf7/PftBgL1Agn/9Q0P+BT6F/L7BAAGDvkRAgPu+g/5DPkIG/sEAfz+AQX2FvYLBPkD7xcICucJAyYEFv8D9BL//+UB9f0BL+4J8f30//0E/ewVDfr5BfwD+QINCwgA9O8H7gYS+PwgBxACEhkG+gMG+/gG+/vtDP/3AAH+CAT/6vwJCwH9BQf6+v8M8/j6/OkOAf0D9QIZBf4LIfT79u4EGO4GCQb3Cvf89P4G/Qr2APjxDfgMCAD98xUIE+wF+fgFAgsKAfn/AA8I8xoM9gL/9wID4fwDD/T+/wAPCPj0EQj5AQELCvrs+gYA+xX/+/kU9/8G//j2Bgf9HPT7AfsH+v8JAAjxHf8DCfsA+hDsAw/9H/EDCwL9+AXxGP72A/j5+RcTBgEG+Sj/AAPz+CLz7PkHAAwHAvYKC/QKEPb5BwvuBPf1EwL++PYG/fsP7hQB9/cBA/sTCRAE8hv78QgDAP0GGwQHEewBAv0UB+4AAPYA9ggiDgXs//z/BvoN/QTs8gQF8gwYAQgFFwD+AvsG9hEEAgcH/P4EA/78Agr6IAIDFekCBAMD7wUC/OjwAQD77v8MAv0TCyf1/gD39QkA9f/67Aj2DPMLBOT2//v3BPcDIQUY+voAEfj4DvMJGgwFDP/5+gUC//QE9fsGBO4IGvcEAwYN9/z7+/4J+Q34HBHt+/oK/voB/gX8DwcCAxPwAQoKFAT08RP97RbpBwLyCh0JBwD/+g0CCwnuCBIDERH8Cvf1+PcT/wHx+PsH9/gF7QQCDQL6Bxvy+wsACwrw9QL5/Qn/CgMMGv37AvT6BAULDAEXDv4EDfH1ExoCAvTr+wLzDgoVBwb++vwACfD6EfcI/wkFBwn7DgD2Bv0DCgEE+AATAQICCPv3+RoE/vbw8g0OAPEBBgH6C/r+AwkB+e0Q+Pj5/AcGBwYHCBgI9hAHDgQtCfcAAvz99Bb4+/br/AUIAvoDA/j4/+3+/BT4/gD69gIFF/QOC/0QBwgABvv9BAwPBgEDDvnyDP3/ABj69wIBC/0EBAH78vsABgT/9vkRBwkLAgwHGvwHCwfwART4+QDpFAoAAu3w9xwE/Q7x6wcGA/sI/woN/wQA+wn0Aw36EPoNBwH8BAL0ARIQ9P4Z9Qck/Q/vAvb/+gH0A/X7+wYPAwUR9O8H9vb+CQD0AOcNH/0OAf/9/wz4CA0PGQ339/X0CwsN+g4C8xn0BALx+gMTAvga/O4JBvEKAvABAfkAAvLyHPcE+wYE+wcE9/AI9AsZAQQbCwTy/gH7E/v3+Qn4AgT2AQ8C7hQL+yfrARMJAPoL7gQCCgXuDwIE+A4GBgPvBgn9Af0B7BgN+PUFAwgNBPYQBfYG+BoJ/yAABwvw/wr3DfgW/Qvx//L+BQQFAPDhCAIV8wQCBg3+6gT6/QEQ8fofAeYQAfwS/OIMEQn9/QH7F+/38P8O7+z7Cff18Qr2+gIDCAcEHgb8FAHt+QoG/P4pDAkEAvkC/xYA/gL+CQIHAvAG+PwNBuMK9/n86gb/CQ38AAcL+xIM/f7r+AIBC/QHE/v99QcCAgwGB/AdDwr1EAAFDAT1/P3uAAIHCPgTFAfs+vv0Ehzw9Prp+ggMA/0VAf8EAgEC/RP8AxoYAwP5GAP4DQgGEPvz/PQB+APuDw4AAvv47fH/9fYIAwD++/389f4P/wYS9vwABiL78PcME/kK+P39AA33A/779QnQ+w8LAgP//vsXAwcX/wkI/fzu/f8DAA4L/xXuCykCBAEHAv8FCwgDAgPs/vr/BQMDEAfu/wP3Ge0F8voO+wXzAvkJDwkLDPYG/Ab+CBrtAP/9AAEQ/v339Rf58QsJC/nwAAfu8QL9GAr88fEIAwL1CAf2AxQH/AH9Auj8ByQZBAADAgf2Avj3/AD0Bg/7+gDuAQr1/wv4BxYGBe0M/Qj7+xH++wgFAf79/A/++vr6APkM+f/6AP0GChj8AgvyEPoCBQH49gwC+/YA//of/AL++hH+9vwBBR4RBvv19QYJ+vkD/AP7DA0KEvz0Avv++v4NEgkh+/sE6/QW8foO/wf9BQ8IAPz87xgDCPz6BxH39wgTCAIFDgD0AfnyEwIDAfn4Cf7+AgL3DQX3AAUX+w4ABxMS/QcAAO71CAz18QgHBQMQ/Qb0Ef35Eu/2Bfn89/4SDgcRBf706Af5A/8V9gsD//8KCf/6CRT4/hH9+PoTAQQN//seAwr/DwLz/vL/FPQPEf8B8Av++wEJ5AUQ8ALvBvwGA/T79AL1CA4E/woU/gkfCwsKEwD+Afv1FgUMDfcLDQLzAPvt+Qz5CATx4vrxCwMAA/oHCwfz9/38++YPEgIdJfwODQf8Cw/1C+wACfbpFwwJ8AH4AgYG7fb89wz6AA779AAF/g/7BRnx+wbzBf8j/PoF+wr8AvkRDgEN9vYQ+wIT+wMA/gAL/gX/AwDw/g8XDPH+9hUBAwsI+/L6AwABA/cE/Q4VAgkIBgj++/r5CAUD9goFDQYS9vzs6wX6BREUChn+EAf0/+D/8/wTCfoNBPcB+vsSCQIP/wID/gMH+gAC/AoF/AwE/u/xBwEFCw4M/v8E5/z8BPv/BfcLEwr1GfvtBfr7AvrrEv/mDvQJCgP6ABHvDAPpCvYWAAUMBvgHDvv79/4CCw79/wwFBQgFCwL5BwoJBPX69wQe8fj8FvgNAgD29Bv5DPkG6g8WB/n7/QkFFgD7+/Hz+fgX/wALFgn3BALyCQMB+gcE/gPvAQkB/gIG8ynt9/EL/fvt/gb7BfP/EgoCAPn6HPcNFwUX/QUJ/Q3y/woABAQN//X6CwgB8gwIDRUK6gD2/Q0A/wr1/AcCCv4FBQr9BPcB6gQKBwf8BALw//b0HQYODPInBvEA+QQIBxbv+fUN8gLz9Bv9BQD5GAYIBBn//An78f8HBfsIC/0ACvrw/fQBDv4ODQcI/f4CDvAU8gAG9AIEBBES+/YD/fTpAv4OAvgQIQgNEvj9AP79//z6DP799O7wCxMG8wH2Df8J/Rrx7AYf9g4Q9gsPF/nyAxIA9foNKv/3Avni/gQDBvYN+gH/8PcgCQ8G9gQJ+ff2BPHv8wn8+fv6AwgBIPX0ARAA8RAI+/8a/wMNBQMHBwkAEhAGAvXpCAgE7f8D+w8A6QX49AUF+v/+AhUCD/T1+fX/ARP98P8U9vcE+O0F/+4FAAr/+QwV7vwGB/0ABhESChP7AP359wkEAgEDBQYSABQS8dgDAgAOCfj/9fv4/foD/gj97//tAhAJ/QUW/SEXCQn/+fnzIAcFEforDQsE6f//DPEO7QIAFQPs/dH89vvt+v772QYPBPgJ+hPT/vr2FgkM+gz9KAwM89Ii0+QM2fv3AgcKCez/7uDX7BgCDfT/BgvbBgQWDvgK/Poq/hQEFAoX+/bw5QEE+sMs5wUUzQsADfwS4Ov3A/feHgf49wDiFQcRDg0qxfsC8yMoBAYQAQzx+PwABAkP++sQ2BYK/ATsAv0LCgcQC+AaART29fj6A/TqBPze3ygCCAbT/w8NLQ3uBAASsgsPEdYgCv/93vLoFO8P/gn1CDO6whUK+g45/wfD8hMK5vcU/w8r+/4LBgkG/AoLAAX+Dff3M/P+7fr09u4W8/f8C+0bEyMHCBTw+/4FCRMH9PQWC/LhBPr/Cf7sB/nu8wcEJ+j79gAC5/sqBhUS7PX7Cfj1DwX7AgjTAfruCxMDAff2B/3bCfrwEv0bCQfu7/oJDgv+ChIM//0bBAMJBuAgBugI8CwEB/4JD/8R6wTwBQv59QQA/RIE/ujv"},b:[2.1537,.47451,.029461,.89724,-.12645,-1.3064,-.42351,-.070797,.34355,.20397,-.43014,-.063977,-.11719,-.34141,-.37835,-.64427,-.53819,-.47944,-.56216,-.12763,-.48014,-.56977,.050473,-.33839,-.65921,-.31452,-.33799,.10971,.078488,-.45741,-.15056,-.018883,-.27828,-.17847,-.81039,-.28268,-.14222,-.29722,-.77616,-.47762,-.3697,-.46026,-.13087,-.49869,-.28312,-.69974,-.41188,-.92325,-.58822,-.39002,-.77904,-.36065,-.11276,-.51998,-.6679,-.38287,-.65133,-.40006,-.26539,-.30836,-.44642,-.63607,-.34191,-.47544,-.56102,-.12988,-.55126,-.47222,-.1993,-.83675,-.95856,-.1607,-.10582,-.52014,-.43954,-.43493,-.62038,-.5219,-.36894,-.45107,-.21352,-.24609,-.35412,-.22215,-.3239,.0019337,-.40894,-.61599,-.35282,-.37185,-.41393,-.5583,-.21046,-.82141,-.49686,-.81666,-.62528,-.17747,-.33321,-.42288,-.37428,-.17428,-1.1207,-.22147,-.65601,-.58428,-.5439,-.10838,-.0096173,-.40622,-.38756,-1.0267,.49986,.42088,.80243,-.025016,.4964,-.71379,.045631,-.52001]}};var V=class{weights;charToId;gpu=null;defaultBackend;scratch;idsScratch=new Int32Array(R);bioIdsScratch=new Int32Array(128);clsIdsScratch=new Int32Array(128);bioProbsScratch=Array.from({length:128},()=>new Float32Array(3));constructor(B={}){this.weights=gA(B.weights??lA),this.charToId=sA(this.weights.charset),this.defaultBackend=B.backend??"cpu",this.scratch=new X(this.weights)}parse(B,n={}){let e=B;B=k(B);let t=e.length===B.length,r,g=Z(B.length);if(g.length===1&&g[0].length===B.length){let f=x(B.length),w=p(B,this.charToId,this.idsScratch,f),s=j(this.weights,w,this.scratch);r=this.decodeForward(B,s,0,B.length)}else{let f=[],w=new Set;for(let s of g){let P=B.slice(s.offset,s.offset+s.length),u=x(P.length),o=p(P,this.charToId,this.idsScratch,u),C=j(this.weights,o,this.scratch),D=this.decodeForward(P,C,s.offset,P.length);for(let Q of D){let i=`${Q.start}:${Q.end}`;w.has(i)||(w.add(i),f.push(Q))}}f.sort((s,P)=>s.start-P.start),r=f}if(t)for(let f of r)f.span=e.slice(f.start,f.end);return r}decodeForward(B,n,e,t=n.length){let r=t,g=r<=128,f=g?this.bioIdsScratch:new Int32Array(r),w=g?this.clsIdsScratch:new Int32Array(r),s=g?this.bioProbsScratch:Array.from({length:r},()=>new Float32Array(3));for(let o=0;o<r;o++)f[o]=G(n.bioLogits,o*3,3),w[o]=G(n.clsLogits,o*n.nCls,n.nCls),$(n.bioLogits,o*3,3,s[o]);let P=cA(B,f.subarray(0,r),w.subarray(0,r),s),u=[];for(let o of P){let C=o.tokens.map(([i,I])=>[M[i],I]),D=aA(C),Q=IA(B,o.start,o.end,tB);u.push({span:o.text,start:o.start+e,end:o.end+e,value:D.value,...D.range?{range:D.range}:{},unit:D.unit??null,currency:Q,confidence:o.confidence??0,classes:D.classes})}return u}inspect(B){let n=performance.now(),e=k(B),t=Z(e.length),r=new Array(e.length),g=new Array(e.length).fill(!1);for(let s of t){let P=e.slice(s.offset,s.offset+s.length),u=x(P.length),o=p(P,this.charToId,this.idsScratch,u),C=j(this.weights,o,this.scratch);for(let D=0;D<P.length;D++){let Q=s.offset+D;if(g[Q])continue;g[Q]=!0;let i=G(C.bioLogits,D*3,3),I=new Float32Array(3);$(C.bioLogits,D*3,3,I);let v=G(C.clsLogits,D*C.nCls,C.nCls);r[Q]={ch:P[D],bio:i,bioProb:[I[0],I[1],I[2]],cls:M[v],clsId:v}}}let f=this.parse(B),w=performance.now()-n;return{text:e,chars:r,spans:f,ms:w}}modelInfo(){let B=this.weights,n=B.embed.data.length;for(let t of B.conv)n+=t.w.data.length+t.b.length;n+=B.bio.w.data.length+B.bio.b.length,n+=B.cls.w.data.length+B.cls.b.length;let e=B.conv.length?Math.max(...B.conv.map(t=>t.w.shape[0])):B.embed.shape[1];return{version:B.version,params:n,channels:e,embedDim:B.embed.shape[1],vocab:B.embed.shape[0],classes:B.classes.length,layers:B.conv.map(t=>({k:t.k,dilation:t.dilation,residual:t.residual}))}}async parseBatch(B,n={}){let e=n.backend??this.defaultBackend;if(!(e==="webgpu"||e==="auto"&&B.length>=32&&await rA()))return B.map(P=>this.parse(P,{backend:"cpu"}));let r=B,g=B.map(k),f=new Array(B.length),w=[],s=[];for(let P=0;P<g.length;P++)g[P].length<=128?w.push(P):s.push(P);for(let P of s)f[P]=this.parse(r[P],{backend:"cpu"});if(w.length>0){this.gpu||(this.gpu=new _(this.weights));let P=Math.max(...w.map(v=>g[v].length),1),u=x(P),o=w.length,C=new Int32Array(o*u),D=this.charToId.get("<pad>")??0;C.fill(D);for(let v=0;v<o;v++){let h=g[w[v]],b=p(h,this.charToId);C.set(b,v*u)}let{bio:Q,cls:i}=await this.gpu.run(C,o,u),I=this.weights.cls.w.shape[0];for(let v=0;v<o;v++){let h=w[v],b=g[h],L=r[h],H=L.length===b.length,E=b.length,c=new Float32Array(E*3),a=new Float32Array(E*I);for(let l=0;l<E;l++)c.set(Q.subarray((v*u+l)*3,(v*u+l)*3+3),l*3),a.set(i.subarray((v*u+l)*I,(v*u+l)*I+I),l*I);let d={bioLogits:c,clsLogits:a,length:E,nCls:I},F=this.decodeForward(b,d,0,E);if(H)for(let l of F)l.span=L.slice(l.start,l.end);f[h]=F}}return f}},fA=null;function q(){return fA||(fA=new V),fA}function FB(A,B={}){return q().parse(A,B)}function MB(A,B={}){return q().parseBatch(A,B)}function RB(A){return q().inspect(A)}function OB(){return q().modelInfo()}function xB(A={}){return new V(A)}var tB=iA(HA,bA);export{M as CLASSES,V as Parser,xB as createParser,RB as inspect,nA as isWebGPUAvailable,OB as modelInfo,k as normalizeText,FB as parse,MB as parseBatch,rA as probeWebGPU};
|
package/dist/types.d.ts
CHANGED
|
@@ -146,4 +146,122 @@ export interface WeightsJsonInt8 {
|
|
|
146
146
|
b: number[];
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
-
|
|
149
|
+
/** v2 conv layer entry, float form. */
|
|
150
|
+
export interface ConvLayerJsonFloat {
|
|
151
|
+
k: number;
|
|
152
|
+
dilation: number;
|
|
153
|
+
residual: boolean;
|
|
154
|
+
w: {
|
|
155
|
+
shape: number[];
|
|
156
|
+
data: number[];
|
|
157
|
+
};
|
|
158
|
+
b: {
|
|
159
|
+
shape: number[];
|
|
160
|
+
data: number[];
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/** v2 conv layer entry, int8 form. */
|
|
164
|
+
export interface ConvLayerJsonInt8 {
|
|
165
|
+
k: number;
|
|
166
|
+
dilation: number;
|
|
167
|
+
residual: boolean;
|
|
168
|
+
w: {
|
|
169
|
+
shape: number[];
|
|
170
|
+
scale: number;
|
|
171
|
+
data_b64: string;
|
|
172
|
+
};
|
|
173
|
+
b: number[];
|
|
174
|
+
}
|
|
175
|
+
/** Weights JSON version 2, float form: an explicit ordered `conv` layer list
|
|
176
|
+
* instead of the hard-coded conv1..conv4 fields. See CONTRACT.md section 2. */
|
|
177
|
+
export interface WeightsJsonV2Float {
|
|
178
|
+
version: 2;
|
|
179
|
+
charset: string[];
|
|
180
|
+
classes: string[];
|
|
181
|
+
embed_dim?: number;
|
|
182
|
+
channels?: number;
|
|
183
|
+
embed: {
|
|
184
|
+
shape: number[];
|
|
185
|
+
data: number[];
|
|
186
|
+
};
|
|
187
|
+
conv: ConvLayerJsonFloat[];
|
|
188
|
+
bio: {
|
|
189
|
+
w: {
|
|
190
|
+
shape: number[];
|
|
191
|
+
data: number[];
|
|
192
|
+
};
|
|
193
|
+
b: {
|
|
194
|
+
shape: number[];
|
|
195
|
+
data: number[];
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
cls: {
|
|
199
|
+
w: {
|
|
200
|
+
shape: number[];
|
|
201
|
+
data: number[];
|
|
202
|
+
};
|
|
203
|
+
b: {
|
|
204
|
+
shape: number[];
|
|
205
|
+
data: number[];
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/** Weights JSON version 2, int8 form. */
|
|
210
|
+
export interface WeightsJsonV2Int8 {
|
|
211
|
+
version: 2;
|
|
212
|
+
quantized: string;
|
|
213
|
+
charset: string[];
|
|
214
|
+
classes: string[];
|
|
215
|
+
embed_dim?: number;
|
|
216
|
+
channels?: number;
|
|
217
|
+
embed: {
|
|
218
|
+
shape: number[];
|
|
219
|
+
scale: number;
|
|
220
|
+
data_b64: string;
|
|
221
|
+
};
|
|
222
|
+
conv: ConvLayerJsonInt8[];
|
|
223
|
+
bio: {
|
|
224
|
+
w: {
|
|
225
|
+
shape: number[];
|
|
226
|
+
scale: number;
|
|
227
|
+
data_b64: string;
|
|
228
|
+
};
|
|
229
|
+
b: number[];
|
|
230
|
+
};
|
|
231
|
+
cls: {
|
|
232
|
+
w: {
|
|
233
|
+
shape: number[];
|
|
234
|
+
scale: number;
|
|
235
|
+
data_b64: string;
|
|
236
|
+
};
|
|
237
|
+
b: number[];
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
export type WeightsJson = WeightsJsonFloat | WeightsJsonInt8 | WeightsJsonV2Float | WeightsJsonV2Int8;
|
|
241
|
+
export interface CharTag {
|
|
242
|
+
ch: string;
|
|
243
|
+
bio: 0 | 1 | 2;
|
|
244
|
+
bioProb: [number, number, number];
|
|
245
|
+
cls: string;
|
|
246
|
+
clsId: number;
|
|
247
|
+
}
|
|
248
|
+
export interface Inspection {
|
|
249
|
+
/** normalized text (see normalizeText()) */
|
|
250
|
+
text: string;
|
|
251
|
+
chars: CharTag[];
|
|
252
|
+
spans: Sankhya[];
|
|
253
|
+
ms: number;
|
|
254
|
+
}
|
|
255
|
+
export interface ModelInfo {
|
|
256
|
+
version: number;
|
|
257
|
+
params: number;
|
|
258
|
+
channels: number;
|
|
259
|
+
embedDim: number;
|
|
260
|
+
vocab: number;
|
|
261
|
+
classes: number;
|
|
262
|
+
layers: Array<{
|
|
263
|
+
k: number;
|
|
264
|
+
dilation: number;
|
|
265
|
+
residual: boolean;
|
|
266
|
+
}>;
|
|
267
|
+
}
|
package/dist/weights.d.ts
CHANGED
|
@@ -4,22 +4,27 @@ export interface Tensor {
|
|
|
4
4
|
data: Float32Array;
|
|
5
5
|
}
|
|
6
6
|
export interface ConvLayer {
|
|
7
|
+
k: number;
|
|
8
|
+
dilation: number;
|
|
9
|
+
residual: boolean;
|
|
10
|
+
padding: number;
|
|
11
|
+
w: Tensor;
|
|
12
|
+
b: Float32Array;
|
|
13
|
+
}
|
|
14
|
+
export interface HeadLayer {
|
|
7
15
|
w: Tensor;
|
|
8
16
|
b: Float32Array;
|
|
9
17
|
}
|
|
10
18
|
export interface LoadedWeights {
|
|
11
|
-
|
|
12
|
-
dilation: number;
|
|
19
|
+
version: number;
|
|
13
20
|
charset: string[];
|
|
14
21
|
classes: string[];
|
|
15
22
|
embed: Tensor;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
conv4?: ConvLayer;
|
|
20
|
-
bio: ConvLayer;
|
|
21
|
-
cls: ConvLayer;
|
|
23
|
+
conv: ConvLayer[];
|
|
24
|
+
bio: HeadLayer;
|
|
25
|
+
cls: HeadLayer;
|
|
22
26
|
}
|
|
23
|
-
/** Load
|
|
24
|
-
* python/sankhya/export.py) into
|
|
27
|
+
/** Load a v1 or v2, float or int8, weights JSON (as written by
|
|
28
|
+
* python/sankhya/export.py) into a normalised LoadedWeights with an ordered
|
|
29
|
+
* `conv` layer list. See CONTRACT.md section 2. */
|
|
25
30
|
export declare function loadWeights(json: WeightsJson): LoadedWeights;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gpu-sankhya",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Fast char-CNN extraction of Hinglish
|
|
5
|
+
"description": "Fast char-CNN extraction of Hinglish and Devanagari Hindi numeric quantities, with CPU and WebGPU backends.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|