hama-js
Version:
G2P, phoneme-ASR, and P2G inference for Node, Bun, and browsers, powered by a self-contained WASM engine (no onnxruntime).
49 lines • 2.33 kB
JavaScript
// Phoneme-to-grapheme (P2G) inference for Node/Bun, run by the WASM engine.
import vocabData from "./assets/p2g_vocab.json";
import { HamaEngine } from "./engine.js";
import { loadWasm, resolveModelBytes } from "./engine.node.js";
import { decodeP2GOutput, normalizePhonemeTokens } from "./p2g-text.js";
export const P2G_MAX_INPUT_LEN = 192;
export const P2G_MAX_OUTPUT_LEN = 192;
export const P2G_MAX_SEQUENCE_LEN = 416;
let p2gEnginePromise = null;
const getP2gEngine = () => {
if (p2gEnginePromise == null)
p2gEnginePromise = loadWasm().then((w) => HamaEngine.fromBytes(w));
return p2gEnginePromise;
};
export class P2GNodeModel {
constructor(engine, handle, tokens) {
this.engine = engine;
this.handle = handle;
this.tokens = tokens;
this.token2id = new Map(tokens.map((t, i) => [t, i]));
this.bos = this.token2id.get("<bos>");
this.src = this.token2id.get("<src>");
this.tgt = this.token2id.get("<tgt>");
this.eos = this.token2id.get("<eos>");
this.pad = this.token2id.get("<pad>");
this.unk = this.token2id.get("<unk>");
}
static async create(options = {}) {
const engine = await getP2gEngine();
const handle = engine.loadP2g(resolveModelBytes(options.modelPath, "p2g.hama"));
const tokens = options.vocabPath
? JSON.parse(await (await import("node:fs/promises")).readFile(options.vocabPath, "utf-8")).tokens
: vocabData.tokens;
return new P2GNodeModel(engine, handle, tokens.map(String));
}
predict(phonemes) {
const source = normalizePhonemeTokens(phonemes).slice(0, P2G_MAX_INPUT_LEN);
if (source.length === 0)
source.push("<unk>");
let prefix = [this.bos, this.src, ...source.map((t) => this.token2id.get(t) ?? this.unk), this.tgt];
if (prefix.length >= P2G_MAX_SEQUENCE_LEN) {
prefix = [...prefix.slice(0, P2G_MAX_SEQUENCE_LEN - 1), this.tgt];
}
const maxNew = Math.min(P2G_MAX_OUTPUT_LEN + 1, P2G_MAX_SEQUENCE_LEN - prefix.length);
const { ids, align } = this.engine.p2gGreedyAlign(this.handle, BigInt64Array.from(prefix, BigInt), maxNew, this.eos, this.pad);
return decodeP2GOutput(ids, align, this.tokens, source);
}
}
//# sourceMappingURL=p2g.js.map