@tryhamster/gerbil 1.3.1 → 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.
- package/dist/architectures-Ol7yUmKf.mjs.map +1 -1
- package/dist/browser/index.d.ts +7 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/cli.mjs +7 -7
- package/dist/cli.mjs.map +1 -1
- package/dist/{defaults-CudhglS1.mjs → defaults-KnrRSIeJ.mjs} +20 -7
- package/dist/defaults-KnrRSIeJ.mjs.map +1 -0
- package/dist/frameworks/express.d.mts +2 -2
- package/dist/frameworks/express.mjs +1 -1
- package/dist/frameworks/fastify.d.mts +2 -2
- package/dist/frameworks/fastify.mjs +1 -1
- package/dist/frameworks/hono.d.mts +2 -2
- package/dist/frameworks/hono.mjs +1 -1
- package/dist/frameworks/next.d.mts +4 -4
- package/dist/frameworks/next.mjs +1 -1
- package/dist/frameworks/react.d.mts +2 -2
- package/dist/frameworks/trpc.d.mts +2 -2
- package/dist/frameworks/trpc.mjs +1 -1
- package/dist/gerbil-CUzVDAU7.mjs +4 -0
- package/dist/{gerbil-Du-1M2Wq.mjs → gerbil-DGrCwGtJ.mjs} +26 -3
- package/dist/{gerbil-Du-1M2Wq.mjs.map → gerbil-DGrCwGtJ.mjs.map} +1 -1
- package/dist/{gerbil-4Xid85_Z.d.mts → gerbil-_68_JSGV.d.mts} +15 -4
- package/dist/gerbil-_68_JSGV.d.mts.map +1 -0
- package/dist/gpu/hooks.d.mts +21 -16
- package/dist/gpu/hooks.d.mts.map +1 -1
- package/dist/gpu/hooks.mjs +20 -15
- package/dist/gpu/hooks.mjs.map +1 -1
- package/dist/gpu/index.d.mts +3 -3
- package/dist/gpu/index.mjs +4 -4
- package/dist/{gpu-BECDib8p.mjs → gpu-DbB321DN.mjs} +1530 -235
- package/dist/gpu-DbB321DN.mjs.map +1 -0
- package/dist/{index-C4kJrqs1.d.mts → index-BdbeBDTz.d.mts} +210 -9
- package/dist/index-BdbeBDTz.d.mts.map +1 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +5 -5
- package/dist/integrations/ai-sdk.d.mts +2 -2
- package/dist/integrations/ai-sdk.mjs +1 -1
- package/dist/integrations/langchain.d.mts +2 -2
- package/dist/integrations/langchain.mjs +1 -1
- package/dist/integrations/llamaindex.d.mts +2 -2
- package/dist/integrations/llamaindex.mjs +1 -1
- package/dist/integrations/mcp.d.mts +4 -4
- package/dist/integrations/mcp.mjs +4 -4
- package/dist/{mcp-4imtBQLX.mjs → mcp-DcE3wn-L.mjs} +3 -3
- package/dist/{mcp-4imtBQLX.mjs.map → mcp-DcE3wn-L.mjs.map} +1 -1
- package/dist/{moonshine-stt-BO5gZ_D6.mjs → moonshine-stt-BGmctcdO.mjs} +555 -7
- package/dist/moonshine-stt-BGmctcdO.mjs.map +1 -0
- package/dist/moonshine-stt-QoNJeCzR.mjs +4 -0
- package/dist/{one-liner-X5vMbWzs.mjs → one-liner-DTGg6zdm.mjs} +2 -2
- package/dist/{one-liner-X5vMbWzs.mjs.map → one-liner-DTGg6zdm.mjs.map} +1 -1
- package/dist/{outetts-DmR0NfSG.d.mts → outetts-Cr5oGk4z.d.mts} +9 -6
- package/dist/{outetts-DmR0NfSG.d.mts.map → outetts-Cr5oGk4z.d.mts.map} +1 -1
- package/dist/{repl-CGadrKcY.mjs → repl-Ci0zXCT_.mjs} +3 -3
- package/dist/skills/index.d.mts +6 -6
- package/dist/skills/index.mjs +3 -3
- package/dist/{skills-BFGAXYkm.mjs → skills-Dsf0op66.mjs} +2 -2
- package/dist/{skills-BFGAXYkm.mjs.map → skills-Dsf0op66.mjs.map} +1 -1
- package/dist/{types-Cpf-aOxX.d.mts → types-CjG36Vzj.d.mts} +9 -3
- package/dist/{types-Cpf-aOxX.d.mts.map → types-CjG36Vzj.d.mts.map} +1 -1
- package/package.json +1 -1
- package/dist/defaults-CudhglS1.mjs.map +0 -1
- package/dist/gerbil-4Xid85_Z.d.mts.map +0 -1
- package/dist/gerbil-BikD0xFU.mjs +0 -4
- package/dist/gpu-BECDib8p.mjs.map +0 -1
- package/dist/index-C4kJrqs1.d.mts.map +0 -1
- package/dist/moonshine-stt-BO5gZ_D6.mjs.map +0 -1
- package/dist/moonshine-stt-fVw-UB4s.mjs +0 -4
|
@@ -6608,6 +6608,142 @@ const crossAttentionSpec = {
|
|
|
6608
6608
|
]);
|
|
6609
6609
|
}
|
|
6610
6610
|
};
|
|
6611
|
+
const t5AttentionSpec = {
|
|
6612
|
+
shaderCode: `\
|
|
6613
|
+
const WG: u32 = 256u;
|
|
6614
|
+
const MAX_S: u32 = 2048u;
|
|
6615
|
+
|
|
6616
|
+
struct Params {
|
|
6617
|
+
S: u32, // sequence length (query == key length)
|
|
6618
|
+
num_heads: u32,
|
|
6619
|
+
head_dim: u32,
|
|
6620
|
+
_pad: u32,
|
|
6621
|
+
}
|
|
6622
|
+
|
|
6623
|
+
@group(0) @binding(0) var<storage, read> Q: array<f32>; // [S, num_heads*head_dim]
|
|
6624
|
+
@group(0) @binding(1) var<storage, read> K: array<f32>; // [S, num_heads*head_dim]
|
|
6625
|
+
@group(0) @binding(2) var<storage, read> V: array<f32>; // [S, num_heads*head_dim]
|
|
6626
|
+
@group(0) @binding(3) var<storage, read> bias: array<f32>; // [num_heads, S, S]
|
|
6627
|
+
@group(0) @binding(4) var<storage, read_write> output: array<f32>; // [S, num_heads*head_dim]
|
|
6628
|
+
@group(0) @binding(5) var<storage, read> params: Params;
|
|
6629
|
+
|
|
6630
|
+
var<workgroup> scores: array<f32, MAX_S>;
|
|
6631
|
+
var<workgroup> red: array<f32, WG>;
|
|
6632
|
+
|
|
6633
|
+
@compute @workgroup_size(256)
|
|
6634
|
+
fn main(
|
|
6635
|
+
@builtin(local_invocation_id) lid: vec3u,
|
|
6636
|
+
@builtin(workgroup_id) wid: vec3u,
|
|
6637
|
+
) {
|
|
6638
|
+
let q_pos = wid.x;
|
|
6639
|
+
let head = wid.y;
|
|
6640
|
+
if (q_pos >= params.S || head >= params.num_heads) { return; }
|
|
6641
|
+
|
|
6642
|
+
let tid = lid.x;
|
|
6643
|
+
let hd = params.head_dim;
|
|
6644
|
+
let S = params.S;
|
|
6645
|
+
let stride = params.num_heads * hd;
|
|
6646
|
+
let q_base = q_pos * stride + head * hd;
|
|
6647
|
+
let bias_base = (head * S + q_pos) * S;
|
|
6648
|
+
|
|
6649
|
+
// ── Step 1: scores[k] = sum_d Q[q,d]*K[k,d] + bias[head,q,k] (each thread strides over k). ──
|
|
6650
|
+
var k = tid;
|
|
6651
|
+
while (k < S) {
|
|
6652
|
+
let k_base = k * stride + head * hd;
|
|
6653
|
+
var dot: f32 = 0.0;
|
|
6654
|
+
for (var d: u32 = 0u; d < hd; d = d + 1u) {
|
|
6655
|
+
dot = dot + Q[q_base + d] * K[k_base + d];
|
|
6656
|
+
}
|
|
6657
|
+
scores[k] = dot + bias[bias_base + k];
|
|
6658
|
+
k = k + WG;
|
|
6659
|
+
}
|
|
6660
|
+
workgroupBarrier();
|
|
6661
|
+
|
|
6662
|
+
// ── Step 2: row max (parallel reduction over the WG threads' local maxima). ──
|
|
6663
|
+
var local_max: f32 = -1e30;
|
|
6664
|
+
k = tid;
|
|
6665
|
+
while (k < S) {
|
|
6666
|
+
local_max = max(local_max, scores[k]);
|
|
6667
|
+
k = k + WG;
|
|
6668
|
+
}
|
|
6669
|
+
red[tid] = local_max;
|
|
6670
|
+
workgroupBarrier();
|
|
6671
|
+
var stride_r: u32 = WG / 2u;
|
|
6672
|
+
while (stride_r > 0u) {
|
|
6673
|
+
if (tid < stride_r) { red[tid] = max(red[tid], red[tid + stride_r]); }
|
|
6674
|
+
workgroupBarrier();
|
|
6675
|
+
stride_r = stride_r / 2u;
|
|
6676
|
+
}
|
|
6677
|
+
let row_max = red[0];
|
|
6678
|
+
workgroupBarrier();
|
|
6679
|
+
|
|
6680
|
+
// ── Step 3: exponentiate in place, then sum. ──
|
|
6681
|
+
k = tid;
|
|
6682
|
+
while (k < S) {
|
|
6683
|
+
scores[k] = exp(max(scores[k] - row_max, -80.0));
|
|
6684
|
+
k = k + WG;
|
|
6685
|
+
}
|
|
6686
|
+
workgroupBarrier();
|
|
6687
|
+
var local_sum: f32 = 0.0;
|
|
6688
|
+
k = tid;
|
|
6689
|
+
while (k < S) {
|
|
6690
|
+
local_sum = local_sum + scores[k];
|
|
6691
|
+
k = k + WG;
|
|
6692
|
+
}
|
|
6693
|
+
red[tid] = local_sum;
|
|
6694
|
+
workgroupBarrier();
|
|
6695
|
+
stride_r = WG / 2u;
|
|
6696
|
+
while (stride_r > 0u) {
|
|
6697
|
+
if (tid < stride_r) { red[tid] = red[tid] + red[tid + stride_r]; }
|
|
6698
|
+
workgroupBarrier();
|
|
6699
|
+
stride_r = stride_r / 2u;
|
|
6700
|
+
}
|
|
6701
|
+
let inv_sum = 1.0 / max(red[0], 1e-20);
|
|
6702
|
+
workgroupBarrier();
|
|
6703
|
+
|
|
6704
|
+
// ── Step 4: output[q,d] = sum_k softmax(scores)[k] * V[k,d]. Thread tid owns dim
|
|
6705
|
+
// tid (+ WG strides for head_dim > 256). ──
|
|
6706
|
+
var d = tid;
|
|
6707
|
+
while (d < hd) {
|
|
6708
|
+
var acc: f32 = 0.0;
|
|
6709
|
+
for (var kk: u32 = 0u; kk < S; kk = kk + 1u) {
|
|
6710
|
+
acc = acc + scores[kk] * V[kk * stride + head * hd + d];
|
|
6711
|
+
}
|
|
6712
|
+
output[q_base + d] = acc * inv_sum;
|
|
6713
|
+
d = d + WG;
|
|
6714
|
+
}
|
|
6715
|
+
}
|
|
6716
|
+
`,
|
|
6717
|
+
entryPoint: "main",
|
|
6718
|
+
bindings: [
|
|
6719
|
+
{ type: "storage-read" },
|
|
6720
|
+
{ type: "storage-read" },
|
|
6721
|
+
{ type: "storage-read" },
|
|
6722
|
+
{ type: "storage-read" },
|
|
6723
|
+
{ type: "storage-read-write" },
|
|
6724
|
+
{ type: "uniform" }
|
|
6725
|
+
],
|
|
6726
|
+
getDispatchSize(op, resolvedShapes) {
|
|
6727
|
+
const num_heads = op.attributes.num_heads;
|
|
6728
|
+
const outShape = resolvedShapes[op.outputs[0]];
|
|
6729
|
+
return [
|
|
6730
|
+
outShape ? outShape[0] : op.attributes.S,
|
|
6731
|
+
num_heads,
|
|
6732
|
+
1
|
|
6733
|
+
];
|
|
6734
|
+
},
|
|
6735
|
+
buildParams(op, resolvedShapes) {
|
|
6736
|
+
const num_heads = op.attributes.num_heads;
|
|
6737
|
+
const head_dim = op.attributes.head_dim;
|
|
6738
|
+
const outShape = resolvedShapes[op.outputs[0]];
|
|
6739
|
+
return buildUniformBuffer([
|
|
6740
|
+
outShape ? outShape[0] : op.attributes.S,
|
|
6741
|
+
num_heads,
|
|
6742
|
+
head_dim,
|
|
6743
|
+
0
|
|
6744
|
+
]);
|
|
6745
|
+
}
|
|
6746
|
+
};
|
|
6611
6747
|
const KV_CACHE_APPEND_PACKED_F16_SPEC = {
|
|
6612
6748
|
shaderCode: WGSL_KV_CACHE_APPEND_PACKED_F16,
|
|
6613
6749
|
entryPoint: "main",
|
|
@@ -7918,6 +8054,7 @@ const KERNEL_REGISTRY = {
|
|
|
7918
8054
|
RoPE: ropeSpec,
|
|
7919
8055
|
Attention: attentionSpec,
|
|
7920
8056
|
CrossAttention: crossAttentionSpec,
|
|
8057
|
+
T5Attention: t5AttentionSpec,
|
|
7921
8058
|
Softmax: softmaxSpec,
|
|
7922
8059
|
CausalConv1d: causalConv1dSpec,
|
|
7923
8060
|
CausalConv1dSiLU: causalConv1dSiluSpec,
|
|
@@ -8557,6 +8694,72 @@ var Executor = class Executor {
|
|
|
8557
8694
|
return out;
|
|
8558
8695
|
}
|
|
8559
8696
|
/**
|
|
8697
|
+
* Autoregressive step for a multi-output decoder graph (e.g. Parler-TTS's 9 codebook
|
|
8698
|
+
* lm_heads). Dispatches the whole graph ONCE at the current seqPos (so the per-layer
|
|
8699
|
+
* KVCacheAppend writes at the right cache row), reads back each named output, then
|
|
8700
|
+
* advances seqPos by `tokens` (default 1, for a prefilled prompt span pass tokens=T).
|
|
8701
|
+
* The caller writes inputs (dec_input_embed + frozen cross-attn K/V) and reset()s
|
|
8702
|
+
* before the first step. Unlike forward(), there is no single "logits" output —
|
|
8703
|
+
* the caller decodes each codebook row itself.
|
|
8704
|
+
*/
|
|
8705
|
+
async runGraphStep(outputs, tokens = 1) {
|
|
8706
|
+
const resolvedShapes = this.resolveShapes(tokens);
|
|
8707
|
+
const runtimeContext = { seqPos: this.seqPos };
|
|
8708
|
+
const entries = this.dispatchEntries;
|
|
8709
|
+
const dispatchSizes = new Array(entries.length);
|
|
8710
|
+
for (let i = 0; i < entries.length; i++) {
|
|
8711
|
+
const entry = entries[i];
|
|
8712
|
+
const paramsData = entry.spec.buildParams(entry.node, resolvedShapes, runtimeContext);
|
|
8713
|
+
this.ctx.device.queue.writeBuffer(entry.uniformBuffer, 0, paramsData);
|
|
8714
|
+
dispatchSizes[i] = entry.spec.getDispatchSize(entry.node, resolvedShapes, runtimeContext);
|
|
8715
|
+
}
|
|
8716
|
+
if (this.needsMultiEncoder) {
|
|
8717
|
+
const group = this.webkitGroupSize;
|
|
8718
|
+
for (let start = 0; start < entries.length; start += group) {
|
|
8719
|
+
const enc = this.ctx.device.createCommandEncoder();
|
|
8720
|
+
const end = Math.min(start + group, entries.length);
|
|
8721
|
+
for (let i = start; i < end; i++) {
|
|
8722
|
+
const pass = enc.beginComputePass();
|
|
8723
|
+
pass.setPipeline(entries[i].pipeline);
|
|
8724
|
+
pass.setBindGroup(0, entries[i].bindGroup);
|
|
8725
|
+
pass.dispatchWorkgroups(...dispatchSizes[i]);
|
|
8726
|
+
pass.end();
|
|
8727
|
+
}
|
|
8728
|
+
this.ctx.device.queue.submit([enc.finish()]);
|
|
8729
|
+
await this.ctx.device.queue.onSubmittedWorkDone();
|
|
8730
|
+
}
|
|
8731
|
+
} else {
|
|
8732
|
+
const encoder = this.ctx.device.createCommandEncoder({ label: "runGraphStep" });
|
|
8733
|
+
const pass = encoder.beginComputePass({ label: "step_pass" });
|
|
8734
|
+
for (let i = 0; i < entries.length; i++) {
|
|
8735
|
+
pass.setPipeline(entries[i].pipeline);
|
|
8736
|
+
pass.setBindGroup(0, entries[i].bindGroup);
|
|
8737
|
+
pass.dispatchWorkgroups(...dispatchSizes[i]);
|
|
8738
|
+
}
|
|
8739
|
+
pass.end();
|
|
8740
|
+
this.ctx.device.queue.submit([encoder.finish()]);
|
|
8741
|
+
}
|
|
8742
|
+
const results = [];
|
|
8743
|
+
for (const { name, elemCount } of outputs) {
|
|
8744
|
+
const outBuffer = this.getBuffer(name);
|
|
8745
|
+
if (!outBuffer) throw new Error(`runGraphStep: no GPU buffer for output "${name}".`);
|
|
8746
|
+
const byteLen = Math.min(elemCount * 4, outBuffer.size);
|
|
8747
|
+
const readback = this.ctx.device.createBuffer({
|
|
8748
|
+
size: byteLen,
|
|
8749
|
+
usage: 9
|
|
8750
|
+
});
|
|
8751
|
+
const enc = this.ctx.device.createCommandEncoder();
|
|
8752
|
+
enc.copyBufferToBuffer(outBuffer, 0, readback, 0, byteLen);
|
|
8753
|
+
this.ctx.device.queue.submit([enc.finish()]);
|
|
8754
|
+
await readback.mapAsync(MAP_MODE_READ$1, 0, byteLen);
|
|
8755
|
+
results.push(new Float32Array(readback.getMappedRange(0, byteLen).slice(0)));
|
|
8756
|
+
readback.unmap();
|
|
8757
|
+
readback.destroy();
|
|
8758
|
+
}
|
|
8759
|
+
this.seqPos += tokens;
|
|
8760
|
+
return results;
|
|
8761
|
+
}
|
|
8762
|
+
/**
|
|
8560
8763
|
* Greedy decode step: forward + GPU argmax. Returns token ID directly.
|
|
8561
8764
|
* Always uses matvec kernels (M=1). Reads back 4 bytes instead of vocab_size*4.
|
|
8562
8765
|
*/
|
|
@@ -10274,6 +10477,8 @@ const UNICODE_TO_BYTE = /* @__PURE__ */ new Map();
|
|
|
10274
10477
|
UNICODE_TO_BYTE.set(cs[i], bs[i]);
|
|
10275
10478
|
}
|
|
10276
10479
|
}
|
|
10480
|
+
/** SentencePiece metaspace marker (U+2581, "▁") used by T5/Unigram tokenizers. */
|
|
10481
|
+
const METASPACE = "▁";
|
|
10277
10482
|
var Tokenizer = class Tokenizer {
|
|
10278
10483
|
vocab;
|
|
10279
10484
|
vocabReverse;
|
|
@@ -10287,9 +10492,11 @@ var Tokenizer = class Tokenizer {
|
|
|
10287
10492
|
* raw bytes fall back to <0xHH> tokens. When false, GPT-2 byte-level BPE.
|
|
10288
10493
|
*/
|
|
10289
10494
|
spmMode;
|
|
10495
|
+
/** Unigram (SentencePiece) model, set only when the tokenizer.json is Unigram. */
|
|
10496
|
+
unigram;
|
|
10290
10497
|
config;
|
|
10291
10498
|
vocabSize;
|
|
10292
|
-
constructor(vocab, vocabReverse, merges, specialTokens, addedTokens, config, vocabSize, spmMode) {
|
|
10499
|
+
constructor(vocab, vocabReverse, merges, specialTokens, addedTokens, config, vocabSize, spmMode, unigram = null) {
|
|
10293
10500
|
this.vocab = vocab;
|
|
10294
10501
|
this.vocabReverse = vocabReverse;
|
|
10295
10502
|
this.merges = merges;
|
|
@@ -10297,6 +10504,7 @@ var Tokenizer = class Tokenizer {
|
|
|
10297
10504
|
this.addedTokens = addedTokens;
|
|
10298
10505
|
this.byteFallback = /* @__PURE__ */ new Map();
|
|
10299
10506
|
this.spmMode = spmMode;
|
|
10507
|
+
this.unigram = unigram;
|
|
10300
10508
|
this.config = config;
|
|
10301
10509
|
this.vocabSize = vocabSize;
|
|
10302
10510
|
for (let b = 0; b < 256; b++) {
|
|
@@ -10309,7 +10517,8 @@ var Tokenizer = class Tokenizer {
|
|
|
10309
10517
|
*/
|
|
10310
10518
|
static fromJSON(tokenizerJSON, tokenizerConfigJSON) {
|
|
10311
10519
|
const model = tokenizerJSON.model;
|
|
10312
|
-
if (
|
|
10520
|
+
if (model?.type === "Unigram") return Tokenizer.fromUnigramJSON(tokenizerJSON, tokenizerConfigJSON);
|
|
10521
|
+
if (!model || model.type !== "BPE") throw new Error(`Unsupported tokenizer type: ${model?.type ?? "unknown"}. Only BPE and Unigram are supported.`);
|
|
10313
10522
|
const vocab = /* @__PURE__ */ new Map();
|
|
10314
10523
|
const vocabReverse = /* @__PURE__ */ new Map();
|
|
10315
10524
|
for (const [token, id] of Object.entries(model.vocab)) {
|
|
@@ -10358,6 +10567,60 @@ var Tokenizer = class Tokenizer {
|
|
|
10358
10567
|
}, vocab.size, spmMode);
|
|
10359
10568
|
}
|
|
10360
10569
|
/**
|
|
10570
|
+
* Build a Unigram (SentencePiece) tokenizer from a `model.type === "Unigram"`
|
|
10571
|
+
* tokenizer.json (e.g. Flan-T5, which fronts Parler-TTS). The Unigram model is a
|
|
10572
|
+
* list of `[piece, log_score]` rows plus an `unk_id`; encoding runs Viterbi
|
|
10573
|
+
* best-segmentation over the lattice (maximize summed log-scores), normalizing
|
|
10574
|
+
* input NFKC-style + collapsing whitespace, replacing spaces with the metaspace
|
|
10575
|
+
* marker (▁), and appending the post-processor's eos (</s>) like HF's T5Tokenizer.
|
|
10576
|
+
*/
|
|
10577
|
+
static fromUnigramJSON(tokenizerJSON, tokenizerConfigJSON) {
|
|
10578
|
+
const model = tokenizerJSON.model;
|
|
10579
|
+
const vocab = /* @__PURE__ */ new Map();
|
|
10580
|
+
const vocabReverse = /* @__PURE__ */ new Map();
|
|
10581
|
+
const pieces = /* @__PURE__ */ new Map();
|
|
10582
|
+
const rawVocab = model.vocab;
|
|
10583
|
+
for (let id = 0; id < rawVocab.length; id++) {
|
|
10584
|
+
const [piece, score] = rawVocab[id];
|
|
10585
|
+
vocab.set(piece, id);
|
|
10586
|
+
vocabReverse.set(id, piece);
|
|
10587
|
+
pieces.set(piece, {
|
|
10588
|
+
id,
|
|
10589
|
+
score
|
|
10590
|
+
});
|
|
10591
|
+
}
|
|
10592
|
+
const specialTokens = /* @__PURE__ */ new Map();
|
|
10593
|
+
const addedTokensMap = /* @__PURE__ */ new Map();
|
|
10594
|
+
const addedTokensList = tokenizerJSON.added_tokens;
|
|
10595
|
+
if (addedTokensList) for (const t of addedTokensList) {
|
|
10596
|
+
vocab.set(t.content, t.id);
|
|
10597
|
+
vocabReverse.set(t.id, t.content);
|
|
10598
|
+
addedTokensMap.set(t.content, t.id);
|
|
10599
|
+
if (t.special) specialTokens.set(t.content, t.id);
|
|
10600
|
+
}
|
|
10601
|
+
const preTok = tokenizerJSON.pre_tokenizer;
|
|
10602
|
+
const prependMetaspace = preTok?.type === "Metaspace" ? (preTok.prepend_scheme ?? "always") !== "never" : true;
|
|
10603
|
+
const eosToken = tokenizerConfigJSON?.eos_token ?? "</s>";
|
|
10604
|
+
const eosId = vocab.get(eosToken) ?? null;
|
|
10605
|
+
const unkId = model.unk_id ?? vocab.get("<unk>") ?? 0;
|
|
10606
|
+
const config = {
|
|
10607
|
+
bosToken: null,
|
|
10608
|
+
eosToken,
|
|
10609
|
+
bosTokenId: null,
|
|
10610
|
+
eosTokenId: eosId,
|
|
10611
|
+
chatTemplate: tokenizerConfigJSON?.chat_template ?? null,
|
|
10612
|
+
addBosToken: false,
|
|
10613
|
+
addEosToken: false
|
|
10614
|
+
};
|
|
10615
|
+
const unigram = {
|
|
10616
|
+
pieces,
|
|
10617
|
+
unkId,
|
|
10618
|
+
prependMetaspace,
|
|
10619
|
+
eosId
|
|
10620
|
+
};
|
|
10621
|
+
return new Tokenizer(vocab, vocabReverse, /* @__PURE__ */ new Map(), specialTokens, addedTokensMap, config, vocab.size, false, unigram);
|
|
10622
|
+
}
|
|
10623
|
+
/**
|
|
10361
10624
|
* Resolve a literal token string (e.g. "<|endoftext|>") to its vocab id,
|
|
10362
10625
|
* or null if it isn't in the vocabulary.
|
|
10363
10626
|
*/
|
|
@@ -10369,6 +10632,7 @@ var Tokenizer = class Tokenizer {
|
|
|
10369
10632
|
*/
|
|
10370
10633
|
encode(text) {
|
|
10371
10634
|
if (!text) return [];
|
|
10635
|
+
if (this.unigram) return this.encodeUnigram(text);
|
|
10372
10636
|
const ids = [];
|
|
10373
10637
|
if (this.config.addBosToken && this.config.bosTokenId !== null) ids.push(this.config.bosTokenId);
|
|
10374
10638
|
const parts = this.splitOnSpecialTokens(text);
|
|
@@ -10396,6 +10660,10 @@ var Tokenizer = class Tokenizer {
|
|
|
10396
10660
|
if (skipSpecialTokens && this.specialTokens.has(token)) continue;
|
|
10397
10661
|
pieces.push(token);
|
|
10398
10662
|
}
|
|
10663
|
+
if (this.unigram) {
|
|
10664
|
+
const joined = pieces.join("").replace(/▁/g, " ");
|
|
10665
|
+
return joined.startsWith(" ") ? joined.slice(1) : joined;
|
|
10666
|
+
}
|
|
10399
10667
|
if (this.spmMode) {
|
|
10400
10668
|
let out = "";
|
|
10401
10669
|
let byteRun = [];
|
|
@@ -10588,7 +10856,127 @@ var Tokenizer = class Tokenizer {
|
|
|
10588
10856
|
}
|
|
10589
10857
|
return ids;
|
|
10590
10858
|
}
|
|
10859
|
+
/**
|
|
10860
|
+
* Encode text with the Unigram model: split on registered added/special tokens,
|
|
10861
|
+
* normalize each plain span (NFKC + whitespace collapse), apply the metaspace
|
|
10862
|
+
* pre-tokenizer (spaces → ▁, leading ▁ prepended), Viterbi-segment each ▁-word,
|
|
10863
|
+
* then append the post-processor eos. Mirrors HF's T5Tokenizer id stream.
|
|
10864
|
+
*/
|
|
10865
|
+
encodeUnigram(text) {
|
|
10866
|
+
const uni = this.unigram;
|
|
10867
|
+
const ids = [];
|
|
10868
|
+
for (const part of this.splitOnSpecialTokens(text)) {
|
|
10869
|
+
if (part.special) {
|
|
10870
|
+
const id = this.addedTokens.get(part.text);
|
|
10871
|
+
if (id !== void 0) ids.push(id);
|
|
10872
|
+
continue;
|
|
10873
|
+
}
|
|
10874
|
+
const normalized = normalizeUnigram(part.text);
|
|
10875
|
+
if (!normalized) continue;
|
|
10876
|
+
const encoded = ((uni.prependMetaspace ? " " : "") + normalized).replace(/ /g, METASPACE).replace(/^▁+/, METASPACE);
|
|
10877
|
+
const words = this.splitMetaspaceWords(encoded);
|
|
10878
|
+
for (const word of words) for (const id of this.viterbiEncode(word)) ids.push(id);
|
|
10879
|
+
}
|
|
10880
|
+
if (uni.eosId !== null) ids.push(uni.eosId);
|
|
10881
|
+
return ids;
|
|
10882
|
+
}
|
|
10883
|
+
/** Split a ▁-encoded string into ▁-prefixed words (keep ▁ with the following run). */
|
|
10884
|
+
splitMetaspaceWords(encoded) {
|
|
10885
|
+
const chars = [...encoded];
|
|
10886
|
+
const words = [];
|
|
10887
|
+
let i = 0;
|
|
10888
|
+
while (i < chars.length) {
|
|
10889
|
+
let j = i + 1;
|
|
10890
|
+
while (j < chars.length && chars[j] !== METASPACE) j++;
|
|
10891
|
+
words.push(chars.slice(i, j).join(""));
|
|
10892
|
+
i = j;
|
|
10893
|
+
}
|
|
10894
|
+
return words;
|
|
10895
|
+
}
|
|
10896
|
+
/**
|
|
10897
|
+
* Viterbi best-segmentation of a single piece over the Unigram vocab: find the
|
|
10898
|
+
* segmentation maximizing the sum of piece log-scores. Characters with no covering
|
|
10899
|
+
* vocab piece fall back to the unk id (SentencePiece treats an unknown character
|
|
10900
|
+
* as a single unk token).
|
|
10901
|
+
*/
|
|
10902
|
+
viterbiEncode(word) {
|
|
10903
|
+
const uni = this.unigram;
|
|
10904
|
+
const chars = [...word];
|
|
10905
|
+
const n = chars.length;
|
|
10906
|
+
if (n === 0) return [];
|
|
10907
|
+
const NEG = Number.NEGATIVE_INFINITY;
|
|
10908
|
+
const best = new Float64Array(n + 1).fill(NEG);
|
|
10909
|
+
best[0] = 0;
|
|
10910
|
+
const backLen = new Int32Array(n + 1).fill(0);
|
|
10911
|
+
const backId = new Int32Array(n + 1).fill(uni.unkId);
|
|
10912
|
+
const unkScore = this.unigramUnkScore;
|
|
10913
|
+
for (let end = 1; end <= n; end++) {
|
|
10914
|
+
const maxLen = Math.min(end, this.unigramMaxPieceLen);
|
|
10915
|
+
for (let len = 1; len <= maxLen; len++) {
|
|
10916
|
+
const start = end - len;
|
|
10917
|
+
if (best[start] === NEG) continue;
|
|
10918
|
+
const piece = chars.slice(start, end).join("");
|
|
10919
|
+
const entry = uni.pieces.get(piece);
|
|
10920
|
+
if (entry === void 0) continue;
|
|
10921
|
+
const score = best[start] + entry.score;
|
|
10922
|
+
if (score > best[end]) {
|
|
10923
|
+
best[end] = score;
|
|
10924
|
+
backLen[end] = len;
|
|
10925
|
+
backId[end] = entry.id;
|
|
10926
|
+
}
|
|
10927
|
+
}
|
|
10928
|
+
if (best[end - 1] !== NEG) {
|
|
10929
|
+
const score = best[end - 1] + unkScore;
|
|
10930
|
+
if (score > best[end]) {
|
|
10931
|
+
best[end] = score;
|
|
10932
|
+
backLen[end] = 1;
|
|
10933
|
+
backId[end] = uni.unkId;
|
|
10934
|
+
}
|
|
10935
|
+
}
|
|
10936
|
+
}
|
|
10937
|
+
const out = [];
|
|
10938
|
+
let pos = n;
|
|
10939
|
+
while (pos > 0) {
|
|
10940
|
+
const len = backLen[pos] || 1;
|
|
10941
|
+
out.push(backId[pos]);
|
|
10942
|
+
pos -= len;
|
|
10943
|
+
}
|
|
10944
|
+
out.reverse();
|
|
10945
|
+
return out;
|
|
10946
|
+
}
|
|
10947
|
+
/** Lazily-computed longest vocab piece length (in codepoints). */
|
|
10948
|
+
get unigramMaxPieceLen() {
|
|
10949
|
+
if (this._unigramMaxPieceLen === void 0) {
|
|
10950
|
+
let max = 1;
|
|
10951
|
+
for (const piece of this.unigram.pieces.keys()) {
|
|
10952
|
+
const len = [...piece].length;
|
|
10953
|
+
if (len > max) max = len;
|
|
10954
|
+
}
|
|
10955
|
+
this._unigramMaxPieceLen = max;
|
|
10956
|
+
}
|
|
10957
|
+
return this._unigramMaxPieceLen;
|
|
10958
|
+
}
|
|
10959
|
+
_unigramMaxPieceLen;
|
|
10960
|
+
/** Lazily-computed unk emission score (min vocab score − 10, SentencePiece-style). */
|
|
10961
|
+
get unigramUnkScore() {
|
|
10962
|
+
if (this._unigramUnkScore === void 0) {
|
|
10963
|
+
let min = Number.POSITIVE_INFINITY;
|
|
10964
|
+
for (const { score } of this.unigram.pieces.values()) if (score < min) min = score;
|
|
10965
|
+
this._unigramUnkScore = (Number.isFinite(min) ? min : 0) - 10;
|
|
10966
|
+
}
|
|
10967
|
+
return this._unigramUnkScore;
|
|
10968
|
+
}
|
|
10969
|
+
_unigramUnkScore;
|
|
10591
10970
|
};
|
|
10971
|
+
/**
|
|
10972
|
+
* Normalize text for the SentencePiece Unigram path: NFKC (matches T5's Precompiled
|
|
10973
|
+
* charsmap on the BMP) followed by whitespace normalization — every run of Unicode
|
|
10974
|
+
* whitespace collapses to a single ASCII space, and leading/trailing single spaces
|
|
10975
|
+
* are preserved (SentencePiece's remove_extra_whitespaces behaviour).
|
|
10976
|
+
*/
|
|
10977
|
+
function normalizeUnigram(text) {
|
|
10978
|
+
return text.normalize("NFKC").replace(/\s+/g, " ");
|
|
10979
|
+
}
|
|
10592
10980
|
|
|
10593
10981
|
//#endregion
|
|
10594
10982
|
//#region src/gpu/vocab-prune.ts
|
|
@@ -10970,11 +11358,28 @@ async function initFs() {
|
|
|
10970
11358
|
function getCachePath(cacheDir, filename) {
|
|
10971
11359
|
return _path.join(cacheDir, filename.replace(/\//g, "_"));
|
|
10972
11360
|
}
|
|
11361
|
+
/** Node's writeSync/readSync cap a single call at 2 GiB − 1; chunk above this. */
|
|
11362
|
+
const FS_CHUNK = 1073741824;
|
|
10973
11363
|
function readCachedFile(cacheDir, filename) {
|
|
10974
11364
|
if (!_fs || !_path) return null;
|
|
10975
11365
|
const p = getCachePath(cacheDir, filename);
|
|
10976
11366
|
try {
|
|
10977
|
-
|
|
11367
|
+
const size = _fs.statSync(p).size;
|
|
11368
|
+
if (size <= FS_CHUNK) return _fs.readFileSync(p);
|
|
11369
|
+
const buf = Buffer.allocUnsafe(size);
|
|
11370
|
+
const fd = _fs.openSync(p, "r");
|
|
11371
|
+
try {
|
|
11372
|
+
let offset = 0;
|
|
11373
|
+
while (offset < size) {
|
|
11374
|
+
const len = Math.min(FS_CHUNK, size - offset);
|
|
11375
|
+
const read = _fs.readSync(fd, buf, offset, len, offset);
|
|
11376
|
+
if (read <= 0) break;
|
|
11377
|
+
offset += read;
|
|
11378
|
+
}
|
|
11379
|
+
return offset === size ? buf : null;
|
|
11380
|
+
} finally {
|
|
11381
|
+
_fs.closeSync(fd);
|
|
11382
|
+
}
|
|
10978
11383
|
} catch {
|
|
10979
11384
|
return null;
|
|
10980
11385
|
}
|
|
@@ -10985,9 +11390,22 @@ function writeCacheFile(cacheDir, filename, data) {
|
|
|
10985
11390
|
const p = getCachePath(cacheDir, filename);
|
|
10986
11391
|
let buf;
|
|
10987
11392
|
if (Buffer.isBuffer(data)) buf = data;
|
|
10988
|
-
else if (data instanceof Uint8Array) buf = Buffer.from(data);
|
|
11393
|
+
else if (data instanceof Uint8Array) buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
10989
11394
|
else buf = Buffer.from(data);
|
|
10990
|
-
|
|
11395
|
+
if (buf.byteLength <= FS_CHUNK) {
|
|
11396
|
+
_fs.writeFileSync(p, buf);
|
|
11397
|
+
return;
|
|
11398
|
+
}
|
|
11399
|
+
const fd = _fs.openSync(p, "w");
|
|
11400
|
+
try {
|
|
11401
|
+
let offset = 0;
|
|
11402
|
+
while (offset < buf.byteLength) {
|
|
11403
|
+
const len = Math.min(FS_CHUNK, buf.byteLength - offset);
|
|
11404
|
+
offset += _fs.writeSync(fd, buf, offset, len, offset);
|
|
11405
|
+
}
|
|
11406
|
+
} finally {
|
|
11407
|
+
_fs.closeSync(fd);
|
|
11408
|
+
}
|
|
10991
11409
|
}
|
|
10992
11410
|
const BROWSER_CACHE_NAME = "gerbil-models-v4";
|
|
10993
11411
|
const TENSOR_CACHE_ENABLED = (typeof process === "undefined" || process.env?.GERBIL_TENSOR_CACHE !== "0") && globalThis.GERBIL_TENSOR_CACHE !== false;
|
|
@@ -12306,6 +12724,136 @@ async function loadOuteTTS(options) {
|
|
|
12306
12724
|
rawConfig
|
|
12307
12725
|
};
|
|
12308
12726
|
}
|
|
12727
|
+
const PARLER_DEFAULT_REPO = "parler-tts/parler-tts-mini-v1";
|
|
12728
|
+
/** Fold a weight-norm conv (g [Cout,1,1] or [Cout,1], v [Cout,...]) → plain weight. */
|
|
12729
|
+
function foldDacWeightNorm(g, v, vShape) {
|
|
12730
|
+
const cout = vShape[0];
|
|
12731
|
+
const inner = v.length / cout;
|
|
12732
|
+
const out = new Float32Array(v.length);
|
|
12733
|
+
for (let o = 0; o < cout; o++) {
|
|
12734
|
+
let norm = 0;
|
|
12735
|
+
const base = o * inner;
|
|
12736
|
+
for (let j = 0; j < inner; j++) {
|
|
12737
|
+
const val = v[base + j];
|
|
12738
|
+
norm += val * val;
|
|
12739
|
+
}
|
|
12740
|
+
norm = Math.sqrt(norm);
|
|
12741
|
+
const scale = norm > 0 ? g[o] / norm : 0;
|
|
12742
|
+
for (let j = 0; j < inner; j++) out[base + j] = v[base + j] * scale;
|
|
12743
|
+
}
|
|
12744
|
+
return out;
|
|
12745
|
+
}
|
|
12746
|
+
/**
|
|
12747
|
+
* Fold the parler `audio_encoder.model.*` DAC tensors into the canonical `dac.*`
|
|
12748
|
+
* decoder weight map (the same shape generateDacSpeechDecoderGraph consumes, with
|
|
12749
|
+
* numCodebooks 9 / rates [8,8,4,2]). Decoder-only (synthesis never runs the encoder).
|
|
12750
|
+
*/
|
|
12751
|
+
function buildParlerDacWeights(raw, numCodebooks) {
|
|
12752
|
+
const out = /* @__PURE__ */ new Map();
|
|
12753
|
+
const prefix = "audio_encoder.model.";
|
|
12754
|
+
for (const [key, t] of raw) {
|
|
12755
|
+
if (!key.startsWith(`${prefix}decoder.`)) continue;
|
|
12756
|
+
const sub = key.slice(20);
|
|
12757
|
+
if (sub.endsWith(".weight_v")) {
|
|
12758
|
+
const base = sub.slice(0, -9);
|
|
12759
|
+
const g = raw.get(`${prefix}${base}.weight_g`);
|
|
12760
|
+
if (!g) throw new Error(`Parler DAC: missing weight_g for ${base}`);
|
|
12761
|
+
out.set(`dac.${base}.weight`, {
|
|
12762
|
+
data: foldDacWeightNorm(g.data, t.data, t.shape),
|
|
12763
|
+
shape: t.shape
|
|
12764
|
+
});
|
|
12765
|
+
} else if (sub.endsWith(".weight_g")) {} else if (sub.endsWith(".bias")) out.set(`dac.${sub}`, {
|
|
12766
|
+
data: t.data,
|
|
12767
|
+
shape: t.shape
|
|
12768
|
+
});
|
|
12769
|
+
else if (sub.endsWith(".alpha")) out.set(`dac.${sub}`, {
|
|
12770
|
+
data: t.data,
|
|
12771
|
+
shape: [t.shape[1]]
|
|
12772
|
+
});
|
|
12773
|
+
}
|
|
12774
|
+
const D = 8;
|
|
12775
|
+
let latentDim = 1024;
|
|
12776
|
+
const codebooks = [];
|
|
12777
|
+
const outW = [];
|
|
12778
|
+
const outB = [];
|
|
12779
|
+
for (let c = 0; c < numCodebooks; c++) {
|
|
12780
|
+
const qp = `${prefix}quantizer.quantizers.${c}`;
|
|
12781
|
+
const cb = raw.get(`${qp}.codebook.weight`);
|
|
12782
|
+
const owg = raw.get(`${qp}.out_proj.weight_g`);
|
|
12783
|
+
const owv = raw.get(`${qp}.out_proj.weight_v`);
|
|
12784
|
+
const ob = raw.get(`${qp}.out_proj.bias`);
|
|
12785
|
+
if (!(cb && owg && owv && ob)) throw new Error(`Parler DAC: missing quantizer ${c} tensors`);
|
|
12786
|
+
latentDim = owv.shape[0];
|
|
12787
|
+
codebooks.push(cb.data);
|
|
12788
|
+
outW.push(foldDacWeightNorm(owg.data, owv.data, owv.shape));
|
|
12789
|
+
outB.push(ob.data);
|
|
12790
|
+
}
|
|
12791
|
+
const stack = (arrs) => {
|
|
12792
|
+
const total = arrs.reduce((a, x) => a + x.length, 0);
|
|
12793
|
+
const merged = new Float32Array(total);
|
|
12794
|
+
let off = 0;
|
|
12795
|
+
for (const a of arrs) {
|
|
12796
|
+
merged.set(a, off);
|
|
12797
|
+
off += a.length;
|
|
12798
|
+
}
|
|
12799
|
+
return merged;
|
|
12800
|
+
};
|
|
12801
|
+
out.set("dac.quantizer.codebook", {
|
|
12802
|
+
data: stack(codebooks),
|
|
12803
|
+
shape: [
|
|
12804
|
+
numCodebooks,
|
|
12805
|
+
PARLER_CODEBOOK_SIZE_F,
|
|
12806
|
+
D
|
|
12807
|
+
]
|
|
12808
|
+
});
|
|
12809
|
+
out.set("dac.quantizer.out_proj.weight", {
|
|
12810
|
+
data: stack(outW),
|
|
12811
|
+
shape: [
|
|
12812
|
+
numCodebooks,
|
|
12813
|
+
latentDim,
|
|
12814
|
+
D
|
|
12815
|
+
]
|
|
12816
|
+
});
|
|
12817
|
+
out.set("dac.quantizer.out_proj.bias", {
|
|
12818
|
+
data: stack(outB),
|
|
12819
|
+
shape: [numCodebooks, latentDim]
|
|
12820
|
+
});
|
|
12821
|
+
return out;
|
|
12822
|
+
}
|
|
12823
|
+
const PARLER_CODEBOOK_SIZE_F = 1024;
|
|
12824
|
+
async function loadParlerTTS(options) {
|
|
12825
|
+
const revision = options.revision ?? "main";
|
|
12826
|
+
const baseURL = await resolveModelBaseURL(options.repo ?? PARLER_DEFAULT_REPO, revision);
|
|
12827
|
+
await initFs();
|
|
12828
|
+
options.onProgress?.(0, 100, "Fetching config + tokenizer…");
|
|
12829
|
+
const [rawConfig, tokenizerJSON] = await Promise.all([fetchJSON(baseURL, "config.json", options.hfToken, options.cacheDir), fetchJSON(baseURL, "tokenizer.json", options.hfToken, options.cacheDir)]);
|
|
12830
|
+
const tokenizerConfig = await fetchJSON(baseURL, "tokenizer_config.json", options.hfToken, options.cacheDir).catch(() => null);
|
|
12831
|
+
const tokenizer = Tokenizer.fromJSON(tokenizerJSON, tokenizerConfig);
|
|
12832
|
+
options.onProgress?.(8, 100, "Downloading Parler weights…");
|
|
12833
|
+
const buf = await fetchBinary(baseURL, "model.safetensors", options.hfToken, (loaded, total) => options.onProgress?.(8 + loaded / (total || 1) * 85, 100, "weights"), options.cacheDir);
|
|
12834
|
+
const file = parseSafetensorsHeader(buf);
|
|
12835
|
+
const modelWeights = /* @__PURE__ */ new Map();
|
|
12836
|
+
const dacRaw = /* @__PURE__ */ new Map();
|
|
12837
|
+
for (const entry of file.entries) {
|
|
12838
|
+
const f32 = toF32(entry, buf, file);
|
|
12839
|
+
if (entry.name.startsWith("audio_encoder.")) dacRaw.set(entry.name, {
|
|
12840
|
+
data: f32,
|
|
12841
|
+
shape: entry.shape
|
|
12842
|
+
});
|
|
12843
|
+
else modelWeights.set(entry.name, {
|
|
12844
|
+
data: f32,
|
|
12845
|
+
shape: entry.shape
|
|
12846
|
+
});
|
|
12847
|
+
}
|
|
12848
|
+
const codecWeights = buildParlerDacWeights(dacRaw, (rawConfig.decoder ?? {}).num_codebooks ?? 9);
|
|
12849
|
+
options.onProgress?.(100, 100, "Parler-TTS loaded.");
|
|
12850
|
+
return {
|
|
12851
|
+
modelWeights,
|
|
12852
|
+
codecWeights,
|
|
12853
|
+
tokenizer,
|
|
12854
|
+
rawConfig
|
|
12855
|
+
};
|
|
12856
|
+
}
|
|
12309
12857
|
|
|
12310
12858
|
//#endregion
|
|
12311
12859
|
//#region src/gpu/moonshine-executor.ts
|
|
@@ -12671,5 +13219,5 @@ function selectGraphWeights(graph, weights) {
|
|
|
12671
13219
|
}
|
|
12672
13220
|
|
|
12673
13221
|
//#endregion
|
|
12674
|
-
export {
|
|
12675
|
-
//# sourceMappingURL=moonshine-stt-
|
|
13222
|
+
export { verifyGPU as S, createStorageBuffer as _, loadMoonshine as a, getOrCreatePipeline as b, quantizeBackboneInt4 as c, Tokenizer as d, Executor as f, createBindGroup as g, clearPipelineCache as h, loadModel as i, quantizeKaniBackbone as l, MATMUL_BIAS_F16C_SPEC as m, MoonshineEncoderExecutor as n, loadOuteTTS as o, KERNEL_REGISTRY as p, loadKaniTTS as r, loadParlerTTS as s, MoonshineSTT as t, remapPrunedToken as u, createUniformBuffer as v, initGPU as x, destroyBuffers as y };
|
|
13223
|
+
//# sourceMappingURL=moonshine-stt-BGmctcdO.mjs.map
|