hama-js 1.3.12 → 1.4.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.
Files changed (35) hide show
  1. package/dist/browser/assets/{asr_waveform_fp16.onnx → asr_waveform.hama} +0 -0
  2. package/dist/{node/assets/decoder_step.onnx → browser/assets/decoder_step.hama} +0 -0
  3. package/dist/{node/assets/encoder.onnx → browser/assets/encoder.hama} +0 -0
  4. package/dist/browser/assets/hama.wasm +0 -0
  5. package/dist/browser/browser.js +49 -196
  6. package/dist/browser/browser.js.map +1 -1
  7. package/dist/browser/engine.browser.js +12 -0
  8. package/dist/browser/engine.browser.js.map +1 -0
  9. package/dist/browser/engine.js +146 -0
  10. package/dist/browser/engine.js.map +1 -0
  11. package/dist/browser/pronunciation.js +195 -8
  12. package/dist/browser/pronunciation.js.map +1 -1
  13. package/dist/node/asr.js +18 -67
  14. package/dist/node/asr.js.map +1 -1
  15. package/dist/node/assets/{asr_waveform_fp16.onnx → asr_waveform.hama} +0 -0
  16. package/dist/{browser/assets/decoder_step.onnx → node/assets/decoder_step.hama} +0 -0
  17. package/dist/{browser/assets/encoder.onnx → node/assets/encoder.hama} +0 -0
  18. package/dist/node/assets/hama.wasm +0 -0
  19. package/dist/node/engine.browser.js +12 -0
  20. package/dist/node/engine.browser.js.map +1 -0
  21. package/dist/node/engine.js +146 -0
  22. package/dist/node/engine.js.map +1 -0
  23. package/dist/node/engine.node.js +26 -0
  24. package/dist/node/engine.node.js.map +1 -0
  25. package/dist/node/index.js +35 -162
  26. package/dist/node/index.js.map +1 -1
  27. package/dist/node/pronunciation.js +195 -8
  28. package/dist/node/pronunciation.js.map +1 -1
  29. package/dist/types/asr.d.ts +2 -5
  30. package/dist/types/browser.d.ts +5 -8
  31. package/dist/types/engine.browser.d.ts +2 -0
  32. package/dist/types/engine.d.ts +40 -0
  33. package/dist/types/engine.node.d.ts +4 -0
  34. package/dist/types/index.d.ts +3 -3
  35. package/package.json +10 -10
@@ -1,37 +1,19 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import { InferenceSession, Tensor } from "onnxruntime-node";
1
+ import { HamaEngine } from "./engine.js";
2
+ import { loadWasm, resolveModelBytes } from "./engine.node.js";
5
3
  import { buildDisplayIpa, decodeIdsToResult, decoderIds, encodeText, prepareTextForPrediction, } from "./tokenizer.js";
6
4
  import { pronunciationReplaceWithModel, pronunciationScanWithModel, } from "./pronunciation.js";
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- const defaultModelPath = path.join(__dirname, "assets", "g2p_fp16.onnx");
9
- const defaultEncoderModelPath = path.join(__dirname, "assets", "encoder.onnx");
10
- const defaultDecoderStepModelPath = path.join(__dirname, "assets", "decoder_step.onnx");
11
5
  let defaultPronunciationModelPromise = null;
12
- const resolveName = (available, primary, ...fallbacks) => {
13
- if (available.includes(primary))
14
- return primary;
15
- for (const fallback of fallbacks) {
16
- if (available.includes(fallback))
17
- return fallback;
18
- }
19
- const matches = available.filter((name) => name.startsWith(`${primary}.`) || name.startsWith(primary));
20
- if (matches.length === 1)
21
- return matches[0];
22
- if (matches.length > 1) {
23
- const numeric = matches.filter((name) => name.startsWith(`${primary}.`));
24
- if (numeric.length === 1)
25
- return numeric[0];
26
- return matches[0];
27
- }
28
- throw new Error(`Could not resolve ONNX tensor name for '${primary}'. Available: ${available.join(", ")}`);
6
+ let enginePromise = null;
7
+ const getEngine = () => {
8
+ if (enginePromise == null)
9
+ enginePromise = loadWasm().then((w) => HamaEngine.fromBytes(w));
10
+ return enginePromise;
29
11
  };
30
12
  export class G2PNodeModel {
31
- constructor(sessions, opts) {
32
- this.session = sessions.session;
33
- this.encoderSession = sessions.encoderSession;
34
- this.decoderStepSession = sessions.decoderStepSession;
13
+ constructor(engine, encHandle, decHandle, opts) {
14
+ this.engine = engine;
15
+ this.encHandle = encHandle;
16
+ this.decHandle = decHandle;
35
17
  this.maxInputLen = opts.maxInputLen;
36
18
  this.maxOutputLen = opts.maxOutputLen;
37
19
  }
@@ -39,36 +21,19 @@ export class G2PNodeModel {
39
21
  if ((options.encoderModelPath === undefined) !== (options.decoderStepModelPath === undefined)) {
40
22
  throw new Error("encoderModelPath and decoderStepModelPath must be provided together");
41
23
  }
42
- let resolvedModelPath = options.modelPath ?? defaultModelPath;
43
- let resolvedEncoderPath = options.encoderModelPath ?? defaultEncoderModelPath;
44
- let resolvedDecoderStepPath = options.decoderStepModelPath ?? defaultDecoderStepModelPath;
45
- if (options.modelPath &&
46
- fs.existsSync(options.modelPath) &&
47
- fs.statSync(options.modelPath).isDirectory()) {
48
- resolvedEncoderPath = path.join(options.modelPath, "encoder.onnx");
49
- resolvedDecoderStepPath = path.join(options.modelPath, "decoder_step.onnx");
50
- resolvedModelPath = path.join(options.modelPath, "g2p_fp16.onnx");
51
- }
52
24
  const opts = {
53
- modelPath: resolvedModelPath,
54
- encoderModelPath: resolvedEncoderPath,
55
- decoderStepModelPath: resolvedDecoderStepPath,
25
+ modelPath: options.modelPath ?? "",
26
+ encoderModelPath: options.encoderModelPath ?? "",
27
+ decoderStepModelPath: options.decoderStepModelPath ?? "",
56
28
  maxInputLen: options.maxInputLen ?? 128,
57
- // Retained for API compatibility; autoregressive ONNX sets output length in-graph.
58
29
  maxOutputLen: options.maxOutputLen ?? 32,
59
30
  };
60
- const sessionOptions = { graphOptimizationLevel: "disabled" };
61
- const shouldUseSplit = (options.encoderModelPath !== undefined && options.decoderStepModelPath !== undefined) ||
62
- (fs.existsSync(opts.encoderModelPath) && fs.existsSync(opts.decoderStepModelPath));
63
- if (shouldUseSplit) {
64
- const [encoderSession, decoderStepSession] = await Promise.all([
65
- InferenceSession.create(opts.encoderModelPath, sessionOptions),
66
- InferenceSession.create(opts.decoderStepModelPath, sessionOptions),
67
- ]);
68
- return new G2PNodeModel({ encoderSession, decoderStepSession }, opts);
69
- }
70
- const session = await InferenceSession.create(opts.modelPath, sessionOptions);
71
- return new G2PNodeModel({ session }, opts);
31
+ const engine = await getEngine();
32
+ const encBytes = resolveModelBytes(options.encoderModelPath ?? options.modelPath, "encoder.hama");
33
+ const decBytes = resolveModelBytes(options.decoderStepModelPath ?? options.modelPath, "decoder_step.hama");
34
+ const encHandle = engine.loadEncoder(encBytes);
35
+ const decHandle = engine.loadDecoder(decBytes);
36
+ return new G2PNodeModel(engine, encHandle, decHandle, opts);
72
37
  }
73
38
  async predict(text, options = {}) {
74
39
  const splitDelimiter = options.splitDelimiter ?? /\s+/u;
@@ -117,116 +82,29 @@ export class G2PNodeModel {
117
82
  alignments: [],
118
83
  };
119
84
  }
120
- if (this.encoderSession && this.decoderStepSession) {
121
- return this.predictSingleSplit(prepared.modelText, text, prepared.charIndexMap, baseCharIndex, preserveLiterals);
122
- }
123
- if (!this.session) {
124
- throw new Error("No ONNX session initialized");
125
- }
126
- const encoded = encodeText(prepared.modelText, this.maxInputLen);
127
- const inputIds = new BigInt64Array(encoded.ids);
128
- const inputLengths = new BigInt64Array([BigInt(encoded.length || 1)]);
129
- const feeds = {
130
- input_ids: new Tensor("int64", inputIds, [1, this.maxInputLen]),
131
- input_lengths: new Tensor("int64", inputLengths, [1]),
132
- };
133
- const outputs = await this.session.run(feeds);
134
- const decoded = outputs.decoded_ids.data;
135
- const attn = outputs.attn_indices.data;
136
- const rawResult = decodeIdsToResult(decoded, attn, encoded.positionMap);
137
- const relativeAlignments = rawResult.alignments.map((alignment, idx) => ({
138
- phoneme: alignment.phoneme,
139
- phonemeIndex: idx,
140
- charIndex: alignment.charIndex >= 0 && alignment.charIndex < prepared.charIndexMap.length
141
- ? prepared.charIndexMap[alignment.charIndex]
142
- : -1,
143
- }));
144
- return {
145
- ipa: rawResult.ipa,
146
- displayIpa: preserveLiterals === "punct"
147
- ? buildDisplayIpa(rawResult.ipa, relativeAlignments, text)
148
- : rawResult.ipa,
149
- alignments: relativeAlignments.map((alignment, idx) => ({
150
- phoneme: alignment.phoneme,
151
- phonemeIndex: idx,
152
- charIndex: alignment.charIndex < 0 ? alignment.charIndex : alignment.charIndex + baseCharIndex,
153
- })),
154
- };
85
+ return this.predictSingleSplit(prepared.modelText, text, prepared.charIndexMap, baseCharIndex, preserveLiterals);
155
86
  }
156
- async predictSingleSplit(text, originalText, charIndexMap, baseCharIndex, preserveLiterals) {
157
- if (!this.encoderSession || !this.decoderStepSession) {
158
- throw new Error("Split ONNX sessions are not initialized");
159
- }
87
+ predictSingleSplit(text, originalText, charIndexMap, baseCharIndex, preserveLiterals) {
160
88
  const encoded = encodeText(text, this.maxInputLen);
161
89
  const inputIds = new BigInt64Array(encoded.ids);
162
- const inputLengths = new BigInt64Array([BigInt(encoded.length || 1)]);
163
- const encoderFeeds = {
164
- input_ids: new Tensor("int64", inputIds, [1, this.maxInputLen]),
165
- input_lengths: new Tensor("int64", inputLengths, [1]),
166
- };
167
- const encoderOutputs = await this.encoderSession.run(encoderFeeds);
168
- const encoderOutputNames = this.encoderSession.outputNames;
169
- const decoderInputNames = this.decoderStepSession.inputNames;
170
- const decoderOutputNames = this.decoderStepSession.outputNames;
171
- const encNames = {
172
- encoder_outputs: resolveName(encoderOutputNames, "encoder_outputs"),
173
- projected_keys: resolveName(encoderOutputNames, "projected_keys"),
174
- encoder_mask: resolveName(encoderOutputNames, "encoder_mask"),
175
- hidden: resolveName(encoderOutputNames, "hidden"),
176
- prev_attn: resolveName(encoderOutputNames, "prev_attn"),
177
- };
178
- const decIn = {
179
- decoder_input_ids: resolveName(decoderInputNames, "decoder_input_ids"),
180
- encoder_outputs: resolveName(decoderInputNames, "encoder_outputs"),
181
- projected_keys: resolveName(decoderInputNames, "projected_keys"),
182
- encoder_mask: resolveName(decoderInputNames, "encoder_mask"),
183
- prev_attn: resolveName(decoderInputNames, "prev_attn", "prev_attn_in"),
184
- hidden: resolveName(decoderInputNames, "hidden", "hidden_in"),
185
- positions: resolveName(decoderInputNames, "positions"),
186
- };
187
- const decOut = {
188
- next_token_ids: resolveName(decoderOutputNames, "next_token_ids"),
189
- hidden: resolveName(decoderOutputNames, "hidden_out", "hidden"),
190
- prev_attn: resolveName(decoderOutputNames, "prev_attn_out", "prev_attn"),
191
- attn_argmax: resolveName(decoderOutputNames, "attn_argmax"),
192
- };
193
- const encoderStates = {
194
- encoder_outputs: encoderOutputs[encNames.encoder_outputs],
195
- projected_keys: encoderOutputs[encNames.projected_keys],
196
- encoder_mask: encoderOutputs[encNames.encoder_mask],
197
- hidden: encoderOutputs[encNames.hidden],
198
- prev_attn: encoderOutputs[encNames.prev_attn],
199
- };
200
- const srcLen = Number(encoderStates.encoder_outputs.dims[1] ?? 0);
201
- const positions = new Float32Array(srcLen);
202
- for (let i = 0; i < srcLen; i++)
90
+ const enc = this.engine.encoderRun(this.encHandle, inputIds, encoded.length || 1);
91
+ const positions = new Float32Array(enc.T);
92
+ for (let i = 0; i < enc.T; i++)
203
93
  positions[i] = i;
204
- const positionsTensor = new Tensor("float32", positions, [1, srcLen]);
205
- let decoderInput = new Tensor("int64", new BigInt64Array([BigInt(decoderIds.sos)]), [1, 1]);
206
- let hidden = encoderStates.hidden;
207
- let prevAttn = encoderStates.prev_attn;
94
+ let hidden = enc.hidden;
95
+ let prevAttn = enc.prevAttn;
96
+ let token = decoderIds.sos;
208
97
  const decoded = [];
209
98
  const attnIndices = [];
210
99
  for (let step = 0; step < this.maxOutputLen; step++) {
211
- const stepOutputs = await this.decoderStepSession.run({
212
- [decIn.decoder_input_ids]: decoderInput,
213
- [decIn.encoder_outputs]: encoderStates.encoder_outputs,
214
- [decIn.projected_keys]: encoderStates.projected_keys,
215
- [decIn.encoder_mask]: encoderStates.encoder_mask,
216
- [decIn.prev_attn]: prevAttn,
217
- [decIn.hidden]: hidden,
218
- [decIn.positions]: positionsTensor,
219
- });
220
- const nextToken = firstInt64(stepOutputs[decOut.next_token_ids]);
221
- const attnIdx = firstInt64(stepOutputs[decOut.attn_argmax]);
222
- decoded.push(nextToken);
223
- attnIndices.push(attnIdx);
224
- hidden = stepOutputs[decOut.hidden];
225
- prevAttn = stepOutputs[decOut.prev_attn];
226
- decoderInput = new Tensor("int64", new BigInt64Array([nextToken]), [1, 1]);
227
- if (nextToken === BigInt(decoderIds.eos)) {
100
+ const out = this.engine.decoderStep(this.decHandle, token, enc.encoderOutputs, enc.projectedKeys, enc.mask, prevAttn, hidden, positions);
101
+ decoded.push(out.nextToken);
102
+ attnIndices.push(out.attnArgmax);
103
+ hidden = out.hiddenOut;
104
+ prevAttn = out.prevOut;
105
+ token = out.nextToken;
106
+ if (token === decoderIds.eos)
228
107
  break;
229
- }
230
108
  }
231
109
  const rawResult = decodeIdsToResult(decoded, attnIndices, encoded.positionMap);
232
110
  const relativeAlignments = rawResult.alignments.map((alignment, idx) => ({
@@ -249,11 +127,6 @@ export class G2PNodeModel {
249
127
  };
250
128
  }
251
129
  }
252
- const firstInt64 = (tensor) => {
253
- const data = tensor.data;
254
- const value = data[0];
255
- return typeof value === "bigint" ? value : BigInt(Math.trunc(Number(value)));
256
- };
257
130
  const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
258
131
  const toGlobalRegex = (delimiter) => {
259
132
  if (typeof delimiter === "string") {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,UAAU,EAEV,wBAAwB,GAEzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAKL,6BAA6B,EAI7B,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAgB5B,IAAI,gCAAgC,GAAiC,IAAI,CAAC;AAC1E,IAAI,aAAa,GAA+B,IAAI,CAAC;AAErD,MAAM,SAAS,GAAG,GAAwB,EAAE;IAC1C,IAAI,aAAa,IAAI,IAAI;QAAE,aAAa,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3F,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,OAAO,YAAY;IAOvB,YAAoB,MAAkB,EAAE,SAAiB,EAAE,SAAiB,EAAE,IAA0B;QACtG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAsB,EAAE;QAC1C,IAAI,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,KAAK,SAAS,CAAC,EAAE,CAAC;YAC9F,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;QACzF,CAAC;QACD,MAAM,IAAI,GAAyB;YACjC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;YAClC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,EAAE;YAChD,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,IAAI,EAAE;YACxD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG;YACvC,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;SACzC,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAClG,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,oBAAoB,IAAI,OAAO,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QAC3G,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC/C,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,UAA0B,EAAE;QACtD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,MAAM,CAAC;QACxD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,GAAG,CAAC;QACvD,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,MAAM,CAAC;QAC5D,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACrD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAC7B,IAAI,CAAC,aAAa,CAChB,OAAO,CAAC,IAAI,EACZ,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,EAC5C,gBAAgB,CACjB,CACF,CACF,CAAC;QAEF,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,MAAM,UAAU,GAA4B,EAAE,CAAC;QAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,GAAG,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC1C,IAAI,CAAC,GAAG,CAAC;gBAAE,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC9C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC9B,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YACzC,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;gBAC9C,UAAU,CAAC,IAAI,CAAC;oBACd,OAAO,EAAE,SAAS,CAAC,OAAO;oBAC1B,YAAY,EAAE,UAAU,CAAC,MAAM;oBAC/B,SAAS,EAAE,SAAS,CAAC,SAAS;iBAC/B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;IACnF,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,IAAY,EACZ,KAAwC,EACxC,UAAoC,EAAE;QAEtC,OAAO,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,oBAAoB,CACxB,IAAY,EACZ,KAAwC,EACxC,UAAuC,EAAE;QAEzC,OAAO,6BAA6B,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,IAAY,EACZ,aAAqB,EACrB,gBAAsC;QAEtC,MAAM,QAAQ,GAAG,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAClE,IAAI,gBAAgB,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACpE,OAAO;gBACL,GAAG,EAAE,EAAE;gBACP,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvE,UAAU,EAAE,EAAE;aACf,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,YAAY,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;IACnH,CAAC;IAEO,kBAAkB,CACxB,IAAY,EACZ,YAAoB,EACpB,YAAsB,EACtB,aAAqB,EACrB,gBAAsC;QAEtC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAElF,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE;YAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAEjD,IAAI,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACxB,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC5B,IAAI,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC;QAC3B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAa,EAAE,CAAC;QAEjC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC;YACpD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CACjC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CACpG,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC5B,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACjC,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC;YACvB,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC;YACvB,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC;YACtB,IAAI,KAAK,KAAK,UAAU,CAAC,GAAG;gBAAE,MAAM;QACtC,CAAC;QAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAC/E,MAAM,kBAAkB,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACvE,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,YAAY,EAAE,GAAG;YACjB,SAAS,EACP,SAAS,CAAC,SAAS,IAAI,CAAC,IAAI,SAAS,CAAC,SAAS,GAAG,YAAY,CAAC,MAAM;gBACnE,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC;gBACnC,CAAC,CAAC,CAAC,CAAC;SACT,CAAC,CAAC,CAAC;QACJ,OAAO;YACL,GAAG,EAAE,SAAS,CAAC,GAAG;YAClB,UAAU,EACR,gBAAgB,KAAK,OAAO;gBAC1B,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,GAAG,EAAE,kBAAkB,EAAE,YAAY,CAAC;gBAClE,CAAC,CAAC,SAAS,CAAC,GAAG;YACnB,UAAU,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;gBACtD,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,YAAY,EAAE,GAAG;gBACjB,SAAS,EACP,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,GAAG,aAAa;aACtF,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF;AAED,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAE5F,MAAM,aAAa,GAAG,CAAC,SAA0B,EAAU,EAAE;IAC3D,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,IAAI,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,GAAG,CAAC;IACtF,OAAO,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AACjF,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CACpB,IAAY,EACZ,SAAiC,EACe,EAAE;IAClD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;IAEpB,MAAM,QAAQ,GAAmD,EAAE,CAAC;IACpE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QAC7B,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,KAAK,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,IAAY,EAAE,cAAsB,EAAU,EAAE;IACvE,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,cAAc,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,cAAc,IAAI,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,4BAA4B,GAAG,GAA0B,EAAE;IAC/D,IAAI,gCAAgC,IAAI,IAAI,EAAE,CAAC;QAC7C,gCAAgC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC;IAC3D,CAAC;IACD,OAAO,gCAAgC,CAAC;AAC1C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EACpC,IAAY,EACZ,KAAwC,EACxC,UAAoC,EAAE,EACJ,EAAE,CACpC,0BAA0B,CAAC,MAAM,4BAA4B,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAEzF,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EACvC,IAAY,EACZ,KAAwC,EACxC,UAAuC,EAAE,EACJ,EAAE,CACvC,6BAA6B,CAAC,MAAM,4BAA4B,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAE5F,OAAO,EACL,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAC"}
@@ -222,10 +222,11 @@ const prepareTokens = async (text, model, options, phoneEncoder) => {
222
222
  const cacheKey = normText || token.rawText;
223
223
  let cached = tokenCache.get(cacheKey);
224
224
  if (!cached) {
225
- const phoneTokens = await phonemizeText(normText || token.rawText, model);
225
+ const aligned = await phonemizeTextAligned(normText || token.rawText, model);
226
226
  cached = {
227
- phoneTokens,
228
- phones: phoneTokens.map((phone) => phoneEncoder.encode(phone)),
227
+ phoneTokens: aligned.phoneTokens,
228
+ phones: aligned.phoneTokens.map((phone) => phoneEncoder.encode(phone)),
229
+ charIndexes: aligned.charIndexes,
229
230
  };
230
231
  tokenCache.set(cacheKey, cached);
231
232
  }
@@ -238,6 +239,7 @@ const prepareTokens = async (text, model, options, phoneEncoder) => {
238
239
  endCodeUnit: token.endCodeUnit,
239
240
  phones: [...cached.phones],
240
241
  phoneTokens: [...cached.phoneTokens],
242
+ charPhones: buildTokenCharPhones(token.rawText, normText, cached.phones, cached.phoneTokens, cached.charIndexes),
241
243
  });
242
244
  }
243
245
  return prepared;
@@ -445,20 +447,98 @@ const scanCompiledByCharacters = async (text, tokens, compiled, options, qgramEn
445
447
  const lengths = windowLengths(tokenCounts, options);
446
448
  const rawMatches = [];
447
449
  const windowCache = new Map();
450
+ // Approximate phones per character unit, sliced out of each token's
451
+ // alignment buckets. They let us reject the vast majority of candidate
452
+ // windows with pure-JS filters before paying for a real G2P inference.
453
+ const unitPhones = charUnits.map((unit) => {
454
+ const token = tokens[unit.tokenIndex];
455
+ if (!token.charPhones)
456
+ return null;
457
+ return token.charPhones[unit.startChar - token.startChar] ?? null;
458
+ });
459
+ const prefixPhoneCounts = [0];
460
+ const prefixUnmappable = [0];
461
+ for (let idx = 0; idx < charUnits.length; idx += 1) {
462
+ const phones = unitPhones[idx];
463
+ prefixPhoneCounts.push(prefixPhoneCounts[idx] + (phones ? phones.length : 0));
464
+ prefixUnmappable.push(prefixUnmappable[idx] + (phones ? 0 : 1));
465
+ }
466
+ // Concatenated per-character phones approximate the true G2P output of the
467
+ // window text, so the prefilter widens every variant threshold by this slack
468
+ // before discarding a window without verification.
469
+ const approxSlackFor = (variant) => Math.max(2, Math.ceil(variant.phoneLen * 0.25));
448
470
  for (let startUnit = 0; startUnit < charUnits.length; startUnit += 1) {
449
471
  for (const windowLength of lengths) {
450
472
  const endUnit = startUnit + windowLength;
451
473
  if (endUnit > charUnits.length)
452
474
  continue;
453
475
  stats.windowCount = (stats.windowCount ?? 0) + 1;
454
- const window = await buildCharacterWindow(text, charUnits, startUnit, endUnit, model, phoneEncoder, windowCache, maxInputLen);
455
- if (!window) {
476
+ const firstUnit = charUnits[startUnit];
477
+ const lastUnit = charUnits[endUnit - 1];
478
+ const windowText = text.slice(firstUnit.startCodeUnit, lastUnit.endCodeUnit);
479
+ const windowNorm = normalizeForMatch(windowText);
480
+ if (maxInputLen != null &&
481
+ estimatePredictorInputLength(windowNorm || windowText) > maxInputLen) {
456
482
  stats.rejectedByInputLimit = (stats.rejectedByInputLimit ?? 0) + 1;
457
483
  continue;
458
484
  }
459
485
  const relevantCounts = candidateTokenBuckets(windowLength, tokenCounts, options);
460
486
  if (relevantCounts.length === 0)
461
487
  continue;
488
+ // Alignment-based prefilter: only windows that plausibly match some
489
+ // variant (under slackened thresholds) are sent to the predictor.
490
+ const windowMappable = prefixUnmappable[endUnit] - prefixUnmappable[startUnit] === 0;
491
+ if (windowMappable) {
492
+ const approxLen = prefixPhoneCounts[endUnit] - prefixPhoneCounts[startUnit];
493
+ let approxLengthRejected = 0;
494
+ let approxQgramRejected = 0;
495
+ let approxDistanceRejected = 0;
496
+ const lengthOkVariants = [];
497
+ for (const count of relevantCounts) {
498
+ for (const variant of compiled.byTokenCount.get(count) ?? []) {
499
+ if (Math.abs(approxLen - variant.phoneLen) > variant.thresholdK + approxSlackFor(variant)) {
500
+ approxLengthRejected += 1;
501
+ continue;
502
+ }
503
+ lengthOkVariants.push(variant);
504
+ }
505
+ }
506
+ let plausible = false;
507
+ if (lengthOkVariants.length > 0) {
508
+ const approxPhones = [];
509
+ for (let unit = startUnit; unit < endUnit; unit += 1) {
510
+ approxPhones.push(...unitPhones[unit]);
511
+ }
512
+ const approxQfreq = qgramFrequency(approxPhones, options.qgramSize, qgramEncoder);
513
+ for (const variant of lengthOkVariants) {
514
+ const slackK = variant.thresholdK + approxSlackFor(variant);
515
+ const required = requiredOverlap(variant.phoneLen, approxPhones.length, options.qgramSize, slackK);
516
+ if (qgramOverlap(approxQfreq, variant.qgramFreq) < required) {
517
+ approxQgramRejected += 1;
518
+ continue;
519
+ }
520
+ if (verifyDistance(variant.phones, approxPhones, slackK, options.verifier) == null) {
521
+ approxDistanceRejected += 1;
522
+ continue;
523
+ }
524
+ plausible = true;
525
+ break;
526
+ }
527
+ }
528
+ if (!plausible) {
529
+ stats.candidateVariantsConsidered =
530
+ (stats.candidateVariantsConsidered ?? 0) + lengthOkVariants.length;
531
+ stats.rejectedByLength = (stats.rejectedByLength ?? 0) + approxLengthRejected;
532
+ stats.rejectedByQgram = (stats.rejectedByQgram ?? 0) + approxQgramRejected;
533
+ stats.rejectedByDistance = (stats.rejectedByDistance ?? 0) + approxDistanceRejected;
534
+ continue;
535
+ }
536
+ }
537
+ const window = await buildCharacterWindow(text, charUnits, startUnit, endUnit, model, phoneEncoder, windowCache, maxInputLen);
538
+ if (!window) {
539
+ stats.rejectedByInputLimit = (stats.rejectedByInputLimit ?? 0) + 1;
540
+ continue;
541
+ }
462
542
  const lengthOkIds = new Set();
463
543
  for (const count of relevantCounts) {
464
544
  for (const variant of compiled.byTokenCount.get(count) ?? []) {
@@ -1074,8 +1154,12 @@ const coerceTerm = (term) => {
1074
1154
  };
1075
1155
  };
1076
1156
  const phonemizeText = async (text, model) => {
1157
+ const { phoneTokens } = await phonemizeTextAligned(text, model);
1158
+ return phoneTokens;
1159
+ };
1160
+ const phonemizeTextAligned = async (text, model) => {
1077
1161
  const normalized = normalizeForMatch(text);
1078
- const fallback = pseudoPhones(normalized);
1162
+ const fallback = pseudoPhonesAligned(normalized);
1079
1163
  if (!normalized)
1080
1164
  return fallback;
1081
1165
  try {
@@ -1084,13 +1168,106 @@ const phonemizeText = async (text, model) => {
1084
1168
  outputDelimiter: "",
1085
1169
  preserveLiterals: "none",
1086
1170
  });
1087
- const phones = result.alignments.map((alignment) => alignment.phoneme);
1088
- return phones.length > 0 ? phones : fallback;
1171
+ // Some languages decode with literal separator tokens between phonemes.
1172
+ // They carry no pronunciation signal, so drop them before matching.
1173
+ const aligned = result.alignments.filter((alignment) => alignment.phoneme.trim() !== "");
1174
+ if (aligned.length === 0)
1175
+ return fallback;
1176
+ return {
1177
+ phoneTokens: aligned.map((alignment) => alignment.phoneme),
1178
+ charIndexes: aligned.map((alignment) => alignment.charIndex),
1179
+ };
1089
1180
  }
1090
1181
  catch {
1091
1182
  return fallback;
1092
1183
  }
1093
1184
  };
1185
+ /** Mirrors pseudoPhones but keeps the source character index per pseudo-phone. */
1186
+ const pseudoPhonesAligned = (text) => {
1187
+ const phoneTokens = [];
1188
+ const charIndexes = [];
1189
+ Array.from(text).forEach((ch, idx) => {
1190
+ if (/\s/u.test(ch) || ch === "-" || ch === "'")
1191
+ return;
1192
+ phoneTokens.push(ch);
1193
+ charIndexes.push(idx);
1194
+ });
1195
+ if (phoneTokens.length === 0) {
1196
+ return { phoneTokens: ["<unk>"], charIndexes: [-1] };
1197
+ }
1198
+ return { phoneTokens, charIndexes };
1199
+ };
1200
+ /**
1201
+ * Buckets a token's encoded phones by raw character offset using the
1202
+ * predictor's normalized-input character alignments. Returns null when the
1203
+ * raw→normalized offset mapping is not compositional (per-character
1204
+ * normalization lengths fail to add up to the normalized string).
1205
+ */
1206
+ const buildTokenCharPhones = (rawText, normText, phones, phoneTokens, charIndexes) => {
1207
+ const rawChars = Array.from(rawText);
1208
+ if (rawChars.length === 0)
1209
+ return null;
1210
+ const normLen = Array.from(normText).length;
1211
+ // Spell-out mode: when every phone is literally its source character the
1212
+ // predictor is naming letters, not pronouncing the word, so per-character
1213
+ // slices would not approximate how a sub-span is actually pronounced.
1214
+ const normChars = Array.from(normText);
1215
+ let letterIdentity = phoneTokens.length > 0;
1216
+ for (let idx = 0; idx < phoneTokens.length && letterIdentity; idx += 1) {
1217
+ const charIndex = charIndexes[idx];
1218
+ if (charIndex < 0 || charIndex >= normChars.length || phoneTokens[idx] !== normChars[charIndex]) {
1219
+ letterIdentity = false;
1220
+ }
1221
+ }
1222
+ if (letterIdentity)
1223
+ return null;
1224
+ // Trailing characters with no aligned phones usually mean the prediction was
1225
+ // truncated; windows over the tail would look spuriously short.
1226
+ let maxAligned = -1;
1227
+ for (const charIndex of charIndexes) {
1228
+ if (charIndex > maxAligned)
1229
+ maxAligned = charIndex;
1230
+ }
1231
+ if (normLen - 1 - maxAligned >= 3)
1232
+ return null;
1233
+ const cum = [0];
1234
+ for (const ch of rawChars) {
1235
+ cum.push(cum[cum.length - 1] + Array.from(normalizeForMatch(ch)).length);
1236
+ }
1237
+ if (cum[cum.length - 1] !== normLen)
1238
+ return null;
1239
+ const buckets = rawChars.map(() => []);
1240
+ for (let idx = 0; idx < phones.length; idx += 1) {
1241
+ const charIndex = charIndexes[idx] ?? -1;
1242
+ let target;
1243
+ if (charIndex < 0) {
1244
+ target = 0;
1245
+ }
1246
+ else if (charIndex >= normLen) {
1247
+ target = rawChars.length - 1;
1248
+ }
1249
+ else {
1250
+ let lo = 0;
1251
+ let hi = rawChars.length - 1;
1252
+ target = rawChars.length - 1;
1253
+ while (lo <= hi) {
1254
+ const mid = (lo + hi) >> 1;
1255
+ if (cum[mid] <= charIndex && charIndex < cum[mid + 1]) {
1256
+ target = mid;
1257
+ break;
1258
+ }
1259
+ if (charIndex < cum[mid]) {
1260
+ hi = mid - 1;
1261
+ }
1262
+ else {
1263
+ lo = mid + 1;
1264
+ }
1265
+ }
1266
+ }
1267
+ buckets[target].push(phones[idx]);
1268
+ }
1269
+ return buckets;
1270
+ };
1094
1271
  const pseudoPhones = (text) => {
1095
1272
  const compact = compactSurface(text);
1096
1273
  return Array.from(compact).filter((ch) => !/\s/u.test(ch)).length > 0
@@ -1120,6 +1297,16 @@ const effectiveThreshold = (length, maxDistanceRatio, minDistance, maxDistance,
1120
1297
  }
1121
1298
  return threshold;
1122
1299
  };
1300
+ const qgramOverlap = (left, right) => {
1301
+ const [small, large] = left.size <= right.size ? [left, right] : [right, left];
1302
+ let overlap = 0;
1303
+ for (const [qgramId, count] of small.entries()) {
1304
+ const other = large.get(qgramId);
1305
+ if (other != null)
1306
+ overlap += Math.min(count, other);
1307
+ }
1308
+ return overlap;
1309
+ };
1123
1310
  const qgramFrequency = (sequence, q, encoder) => {
1124
1311
  const freq = new Map();
1125
1312
  if (q <= 0 || sequence.length < q)