Spaces:
Running
Running
| // src/utils/data-structures/DictionarySplitter.ts | |
| var DictionarySplitter = class { | |
| /** | |
| * @param dictionary The dictionary of words to use for splitting. | |
| */ | |
| constructor(dictionary) { | |
| this.trie = this._build_trie(dictionary); | |
| } | |
| /** | |
| * Builds a trie from the given dictionary. | |
| * @param dictionary The dictionary of words to build the trie from. | |
| * @returns The root node of the trie. | |
| * @private | |
| */ | |
| _build_trie(dictionary) { | |
| const trie = /* @__PURE__ */ Object.create(null); | |
| for (const word of dictionary) { | |
| let node = trie; | |
| for (let i = 0; i < word.length; ++i) { | |
| const char = word[i]; | |
| node = node[char] ??= /* @__PURE__ */ Object.create(null); | |
| } | |
| node.end = word; | |
| } | |
| return trie; | |
| } | |
| /** | |
| * Splits the input text into tokens based on the dictionary. | |
| * @param text The input text to split. | |
| * @returns An array of tokens. | |
| */ | |
| split(text) { | |
| const result = []; | |
| const n = text.length; | |
| let start = 0; | |
| let i = 0; | |
| while (i < n) { | |
| let node = this.trie; | |
| let match = null; | |
| let j = i; | |
| while (j < n && (node = node[text[j]])) { | |
| if (node.end) { | |
| match = node.end; | |
| } | |
| ++j; | |
| } | |
| if (match) { | |
| if (i > start) { | |
| result.push(text.slice(start, i)); | |
| } | |
| result.push(match); | |
| i += match.length; | |
| start = i; | |
| } else { | |
| ++i; | |
| } | |
| } | |
| if (start < n) { | |
| result.push(text.slice(start)); | |
| } | |
| return result; | |
| } | |
| }; | |
| var DictionarySplitter_default = DictionarySplitter; | |
| // src/core/AddedToken.ts | |
| var AddedToken = class { | |
| /** | |
| * Creates a new instance of AddedToken. | |
| * @param config Added token configuration object. | |
| */ | |
| constructor(config) { | |
| this.content = config.content; | |
| this.id = config.id; | |
| this.single_word = config.single_word ?? false; | |
| this.lstrip = config.lstrip ?? false; | |
| this.rstrip = config.rstrip ?? false; | |
| this.special = config.special ?? false; | |
| this.normalized = config.normalized ?? !this.special; | |
| } | |
| }; | |
| var AddedToken_default = AddedToken; | |
| // src/static/constants.ts | |
| var BYTES_TO_UNICODE = (() => { | |
| const bs = [ | |
| ...Array.from( | |
| { length: "~".charCodeAt(0) - "!".charCodeAt(0) + 1 }, | |
| (_, i) => i + "!".charCodeAt(0) | |
| ), | |
| ...Array.from( | |
| { length: "\xAC".charCodeAt(0) - "\xA1".charCodeAt(0) + 1 }, | |
| (_, i) => i + "\xA1".charCodeAt(0) | |
| ), | |
| ...Array.from( | |
| { length: "\xFF".charCodeAt(0) - "\xAE".charCodeAt(0) + 1 }, | |
| (_, i) => i + "\xAE".charCodeAt(0) | |
| ) | |
| ]; | |
| const cs = bs.slice(); | |
| let n = 0; | |
| for (let b = 0; b < 256; ++b) { | |
| if (!bs.includes(b)) { | |
| bs.push(b); | |
| cs.push(256 + n); | |
| n += 1; | |
| } | |
| } | |
| const ccs = cs.map((n2) => String.fromCharCode(n2)); | |
| return Object.fromEntries(bs.map((b, i) => [b, ccs[i]])); | |
| })(); | |
| var reverse_dictionary = (data) => Object.fromEntries(Object.entries(data).map(([key, value]) => [value, key])); | |
| var UNICODE_TO_BYTES = reverse_dictionary(BYTES_TO_UNICODE); | |
| var BLOOM_SPLIT_CHARS = ".,!?\u2026\u3002\uFF0C\u3001\u0964\u06D4\u060C"; | |
| var PROBLEMATIC_REGEX_MAP = /* @__PURE__ */ new Map([ | |
| // These uses the case insensitive group modifier, which is not supported in JavaScript. | |
| // When parsing the regex, an "Invalid group" error is thrown. | |
| [ | |
| "(?i:'s|'t|'re|'ve|'m|'ll|'d)", | |
| "(?:'([sS]|[tT]|[rR][eE]|[vV][eE]|[mM]|[lL][lL]|[dD]))" | |
| ], | |
| [ | |
| "(?i:[sdmt]|ll|ve|re)", | |
| "(?:[sS]|[dD]|[mM]|[tT]|[lL][lL]|[vV][eE]|[rR][eE])" | |
| ], | |
| // JS doesn't support possessive quantifiers (these are used in recent OpenAI tokenizers). | |
| ["[^\\r\\n\\p{L}\\p{N}]?+", "[^\\r\\n\\p{L}\\p{N}]?"], | |
| ["[^\\s\\p{L}\\p{N}]++", "[^\\s\\p{L}\\p{N}]+"], | |
| // JS doesn't support atomic groups (these are used in AFMoE tokenizers). | |
| ["(?>\\p{Nd}{510})", "(?:\\p{Nd}{510})"], | |
| // JS doesn't support stacking quantifiers. | |
| // Uncaught SyntaxError: Invalid regular expression: /\p{Nd}{3}+/u: Nothing to repeat | |
| ["\\p{Nd}{3}+", "(?:\\p{Nd}{3})+"], | |
| // \G is an invalid escape in JS, and in most cases is just used as an optimization. | |
| // So, we can safely remove it. | |
| ["\\G", ""], | |
| // Used to override the default (invalid) regex of the bloom pretokenizer. | |
| // For more information, see https://github.com/huggingface/transformers.js/issues/94 | |
| [` ?[^(\\s|[${BLOOM_SPLIT_CHARS}])]+`, ` ?[^\\s${BLOOM_SPLIT_CHARS}]+`] | |
| ]); | |
| var PUNCTUATION_REGEX = "\\p{P}\\u0021-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u007E"; | |
| // src/utils/core.ts | |
| var clean_up_tokenization = (text) => text.replace(/ \./g, ".").replace(/ \?/g, "?").replace(/ \!/g, "!").replace(/ ,/g, ",").replace(/ \' /g, "'").replace(/ n't/g, "n't").replace(/ 'm/g, "'m").replace(/ 's/g, "'s").replace(/ 've/g, "'ve").replace(/ 're/g, "'re"); | |
| var create_pattern = (pattern, invert = true) => { | |
| if (pattern.Regex !== void 0) { | |
| let regex = pattern.Regex.replace(/\\([#&~])/g, "$1"); | |
| regex = regex.replace(/\\A/g, "^").replace(/\\z/g, "$").replace(/\\Z/g, "(?=\\r?\\n?$)"); | |
| for (const [key, value] of PROBLEMATIC_REGEX_MAP) { | |
| regex = regex.replaceAll(key, value); | |
| } | |
| try { | |
| return new RegExp(regex, "gu"); | |
| } catch (error) { | |
| if (!(error instanceof SyntaxError) || !error.message.toLowerCase().includes("invalid property name")) | |
| throw error; | |
| let changed = false; | |
| const fixed = regex.replace(/(\\[pP])\{([^}=]+)\}/g, (_, p, n) => { | |
| try { | |
| new RegExp(`\\p{${n}}`, "u"); | |
| return `${p}{${n}}`; | |
| } catch { | |
| changed = true; | |
| return `${p}{Script=${n}}`; | |
| } | |
| }); | |
| if (!changed) throw error; | |
| try { | |
| return new RegExp(fixed, "gu"); | |
| } catch (e) { | |
| throw error; | |
| } | |
| } | |
| } else if (pattern.String !== void 0) { | |
| const escaped = escape_reg_exp(pattern.String); | |
| return new RegExp(invert ? escaped : `(${escaped})`, "gu"); | |
| } else { | |
| console.warn("Unknown pattern type:", pattern); | |
| return null; | |
| } | |
| }; | |
| var escape_reg_exp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); | |
| var fuse_unk = (arr, tokens_to_ids, unk_token_id) => { | |
| const fused = []; | |
| let i = 0; | |
| while (i < arr.length) { | |
| fused.push(arr[i]); | |
| const token_id = tokens_to_ids.get(arr[i]) ?? unk_token_id; | |
| if (token_id !== unk_token_id) { | |
| ++i; | |
| continue; | |
| } | |
| while (++i < arr.length && (tokens_to_ids.get(arr[i]) ?? unk_token_id) === unk_token_id) { | |
| if (tokens_to_ids.get(fused.at(-1)) !== unk_token_id) { | |
| fused[fused.length - 1] += arr[i]; | |
| } | |
| } | |
| } | |
| return fused; | |
| }; | |
| var is_chinese_char = (cp) => cp >= 19968 && cp <= 40959 || cp >= 13312 && cp <= 19903 || cp >= 131072 && cp <= 173791 || cp >= 173824 && cp <= 177983 || cp >= 177984 && cp <= 178207 || cp >= 178208 && cp <= 183983 || cp >= 63744 && cp <= 64255 || cp >= 194560 && cp <= 195103; | |
| var is_integral_number = (x) => Number.isInteger(x) || typeof x === "bigint"; | |
| var len = (s) => { | |
| let length = 0; | |
| for (const c of s) ++length; | |
| return length; | |
| }; | |
| var lowercase_and_remove_accents = (text) => remove_accents(text.toLowerCase()); | |
| var merge_arrays = (...arrs) => Array.prototype.concat.apply([], arrs); | |
| var object_to_map = (obj) => new Map(Object.entries(obj)); | |
| var regex_split = (text, regex) => { | |
| const result = []; | |
| let prev = 0; | |
| for (const match of text.matchAll(regex)) { | |
| const full_match = match[0]; | |
| if (prev < match.index) { | |
| result.push(text.slice(prev, match.index)); | |
| } | |
| if (full_match.length > 0) { | |
| result.push(full_match); | |
| } | |
| prev = match.index + full_match.length; | |
| } | |
| if (prev < text.length) { | |
| result.push(text.slice(prev)); | |
| } | |
| return result; | |
| }; | |
| var remove_accents = (text) => text.replace(/\p{M}/gu, ""); | |
| var validate_object = (obj, name, required_keys = []) => { | |
| if (!obj || Array.isArray(obj) || typeof obj !== "object") { | |
| return `${name} must be a valid object`; | |
| } | |
| for (const key of required_keys) { | |
| if (!(key in obj)) { | |
| return `${name} must contain a "${key}" property`; | |
| } | |
| } | |
| return null; | |
| }; | |
| var whitespace_split = (text) => text.match(/\S+/g) || []; | |
| // src/utils/Callable.ts | |
| var Callable = class { | |
| /** | |
| * Creates a new instance of the Callable class. | |
| */ | |
| constructor() { | |
| const closure = function(...args) { | |
| return closure._call(...args); | |
| }; | |
| return Object.setPrototypeOf(closure, new.target.prototype); | |
| } | |
| }; | |
| var Callable_default = Callable; | |
| // src/core/Normalizer.ts | |
| var Normalizer = class extends Callable_default { | |
| /** | |
| * @param config The configuration object for the normalizer. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| } | |
| /** | |
| * Alias for {@link Normalizer#normalize}. | |
| * @param text The text to normalize. | |
| * @returns The normalized text. | |
| */ | |
| _call(text) { | |
| return this.normalize(text); | |
| } | |
| }; | |
| var Normalizer_default = Normalizer; | |
| // src/core/normalizer/BertNormalizer.ts | |
| var BertNormalizer = class extends Normalizer_default { | |
| /** | |
| * Adds whitespace around any CJK (Chinese, Japanese, or Korean) character in the input text. | |
| * | |
| * @param text The input text to tokenize. | |
| * @returns The tokenized text with whitespace added around CJK characters. | |
| */ | |
| tokenize_chinese_chars(text) { | |
| const output = []; | |
| for (let i = 0; i < text.length; ++i) { | |
| const char = text[i]; | |
| const cp = char.charCodeAt(0); | |
| if (is_chinese_char(cp)) { | |
| output.push(" "); | |
| output.push(char); | |
| output.push(" "); | |
| } else { | |
| output.push(char); | |
| } | |
| } | |
| return output.join(""); | |
| } | |
| /** | |
| * Strips accents from the given text. | |
| * @param text The text to strip accents from. | |
| * @returns The text with accents removed. | |
| */ | |
| strip_accents(text) { | |
| return text.normalize("NFD").replace(/\p{Mn}/gu, ""); | |
| } | |
| /** | |
| * Checks whether `char` is a control character. | |
| * @param char The character to check. | |
| * @returns Whether `char` is a control character. | |
| */ | |
| is_control(char) { | |
| switch (char) { | |
| case " ": | |
| case "\n": | |
| case "\r": | |
| return false; | |
| default: | |
| return /^\p{Cc}|\p{Cf}|\p{Co}|\p{Cs}$/u.test(char); | |
| } | |
| } | |
| /** | |
| * Performs invalid character removal and whitespace cleanup on text. | |
| * @param text The text to clean. | |
| * @returns The cleaned text. | |
| */ | |
| clean_text(text) { | |
| const output = []; | |
| for (const char of text) { | |
| const cp = char.charCodeAt(0); | |
| if (cp === 0 || cp === 65533 || this.is_control(char)) { | |
| continue; | |
| } | |
| if (/^\s$/.test(char)) { | |
| output.push(" "); | |
| } else { | |
| output.push(char); | |
| } | |
| } | |
| return output.join(""); | |
| } | |
| /** | |
| * Normalizes the given text based on the configuration. | |
| * @param text The text to normalize. | |
| * @returns The normalized text. | |
| */ | |
| normalize(text) { | |
| if (this.config.clean_text) { | |
| text = this.clean_text(text); | |
| } | |
| if (this.config.handle_chinese_chars) { | |
| text = this.tokenize_chinese_chars(text); | |
| } | |
| if (this.config.lowercase) { | |
| text = text.toLowerCase(); | |
| if (this.config.strip_accents !== false) { | |
| text = this.strip_accents(text); | |
| } | |
| } else if (this.config.strip_accents) { | |
| text = this.strip_accents(text); | |
| } | |
| return text; | |
| } | |
| }; | |
| var BertNormalizer_default = BertNormalizer; | |
| // src/core/normalizer/Precompiled.ts | |
| var Precompiled = class extends Normalizer_default { | |
| /** | |
| * Create a new instance of Precompiled normalizer. | |
| * @param config The configuration object. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.charsmap = config.precompiled_charsmap ?? null; | |
| } | |
| /** | |
| * Normalizes the given text by applying the precompiled charsmap. | |
| * @param text The text to normalize. | |
| * @returns The normalized text. | |
| */ | |
| normalize(text) { | |
| text = text.replace( | |
| /[\u0001-\u0008\u000B\u000E-\u001F\u007F\u008F\u009F]/gm, | |
| "" | |
| ); | |
| text = text.replace( | |
| /[\u0009\u000A\u000C\u000D\u00A0\u1680\u2000-\u200F\u2028\u2029\u202F\u205F\u2581\u3000\uFEFF\uFFFD]/gm, | |
| " " | |
| ); | |
| if (text.includes("\uFF5E")) { | |
| const parts = text.split("\uFF5E"); | |
| text = parts.map((part) => part.normalize("NFKC")).join("\uFF5E"); | |
| } else { | |
| text = text.normalize("NFKC"); | |
| } | |
| return text; | |
| } | |
| }; | |
| var Precompiled_default = Precompiled; | |
| // src/core/normalizer/Sequence.ts | |
| var Sequence = class extends Normalizer_default { | |
| /** | |
| * Create a new instance of NormalizerSequence. | |
| * @param config The configuration object. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.normalizers = (config.normalizers ?? []).map( | |
| (x) => create_normalizer_default(x) | |
| ); | |
| } | |
| /** | |
| * Apply a sequence of Normalizers to the input text. | |
| * @param text The text to normalize. | |
| * @returns The normalized text. | |
| */ | |
| normalize(text) { | |
| return this.normalizers.reduce((t, normalizer) => { | |
| return normalizer ? normalizer.normalize(t) : t; | |
| }, text); | |
| } | |
| }; | |
| var Sequence_default = Sequence; | |
| // src/core/normalizer/Replace.ts | |
| var Replace = class extends Normalizer_default { | |
| /** | |
| * Normalize the input text by replacing the pattern with the content. | |
| * @param text The input text to be normalized. | |
| * @returns The normalized text after replacing the pattern with the content. | |
| */ | |
| normalize(text) { | |
| const pattern = create_pattern(this.config.pattern ?? {}); | |
| return pattern === null ? text : text.replaceAll(pattern, this.config.content ?? ""); | |
| } | |
| }; | |
| var Replace_default = Replace; | |
| // src/core/normalizer/UnicodeNormalizer.ts | |
| var UnicodeNormalizer = class extends Normalizer_default { | |
| constructor() { | |
| super(...arguments); | |
| /** | |
| * The Unicode normalization form to apply. | |
| * Should be one of: 'NFC', 'NFD', 'NFKC', or 'NFKD'. | |
| */ | |
| this.form = "NFC"; | |
| } | |
| /** | |
| * Normalize the input text by applying Unicode normalization. | |
| * @param text The input text to be normalized. | |
| * @returns The normalized text. | |
| */ | |
| normalize(text) { | |
| text = text.normalize(this.form); | |
| return text; | |
| } | |
| }; | |
| var UnicodeNormalizer_default = UnicodeNormalizer; | |
| // src/core/normalizer/NFC.ts | |
| var NFC = class extends UnicodeNormalizer_default { | |
| constructor() { | |
| super(...arguments); | |
| this.form = "NFC"; | |
| } | |
| }; | |
| var NFC_default = NFC; | |
| // src/core/normalizer/NFD.ts | |
| var NFD = class extends UnicodeNormalizer_default { | |
| constructor() { | |
| super(...arguments); | |
| this.form = "NFD"; | |
| } | |
| }; | |
| var NFD_default = NFD; | |
| // src/core/normalizer/NFKC.ts | |
| var NFKC = class extends UnicodeNormalizer_default { | |
| constructor() { | |
| super(...arguments); | |
| this.form = "NFKC"; | |
| } | |
| }; | |
| var NFKC_default = NFKC; | |
| // src/core/normalizer/NFKD.ts | |
| var NFKD = class extends UnicodeNormalizer_default { | |
| constructor() { | |
| super(...arguments); | |
| this.form = "NFKD"; | |
| } | |
| }; | |
| var NFKD_default = NFKD; | |
| // src/core/normalizer/Strip.ts | |
| var Strip = class extends Normalizer_default { | |
| /** | |
| * Strip leading and/or trailing whitespace from the input text. | |
| * @param text The input text. | |
| * @returns The normalized text. | |
| */ | |
| normalize(text) { | |
| if (this.config.strip_left && this.config.strip_right) { | |
| text = text.trim(); | |
| } else { | |
| if (this.config.strip_left) { | |
| text = text.trimStart(); | |
| } | |
| if (this.config.strip_right) { | |
| text = text.trimEnd(); | |
| } | |
| } | |
| return text; | |
| } | |
| }; | |
| var Strip_default = Strip; | |
| // src/core/normalizer/StripAccents.ts | |
| var StripAccents = class extends Normalizer_default { | |
| /** | |
| * Remove all accents from the text. | |
| * @param text The input text. | |
| * @returns The normalized text without accents. | |
| */ | |
| normalize(text) { | |
| return remove_accents(text); | |
| } | |
| }; | |
| var StripAccents_default = StripAccents; | |
| // src/core/normalizer/Lowercase.ts | |
| var Lowercase = class extends Normalizer_default { | |
| /** | |
| * Lowercases the input string. | |
| * @param {string} text The text to normalize. | |
| * @returns {string} The normalized text. | |
| */ | |
| normalize(text) { | |
| return text.toLowerCase(); | |
| } | |
| }; | |
| var Lowercase_default = Lowercase; | |
| // src/core/normalizer/Prepend.ts | |
| var Prepend = class extends Normalizer_default { | |
| /** | |
| * Prepends the input string. | |
| * @param text The text to normalize. | |
| * @returns The normalized text. | |
| */ | |
| normalize(text) { | |
| text = this.config.prepend + text; | |
| return text; | |
| } | |
| }; | |
| var Prepend_default = Prepend; | |
| // src/core/normalizer/create_normalizer.ts | |
| function create_normalizer(config) { | |
| if (config === null) return null; | |
| switch (config.type) { | |
| case "BertNormalizer": | |
| return new BertNormalizer_default(config); | |
| case "Precompiled": | |
| return new Precompiled_default(config); | |
| case "Sequence": | |
| return new Sequence_default(config); | |
| case "Replace": | |
| return new Replace_default(config); | |
| case "NFC": | |
| return new NFC_default(config); | |
| case "NFD": | |
| return new NFD_default(config); | |
| case "NFKC": | |
| return new NFKC_default(config); | |
| case "NFKD": | |
| return new NFKD_default(config); | |
| case "Strip": | |
| return new Strip_default(config); | |
| case "StripAccents": | |
| return new StripAccents_default(config); | |
| case "Lowercase": | |
| return new Lowercase_default(config); | |
| case "Prepend": | |
| return new Prepend_default(config); | |
| default: | |
| throw new Error(`Unknown Normalizer type: ${config.type}`); | |
| } | |
| } | |
| var create_normalizer_default = create_normalizer; | |
| // src/core/PreTokenizer.ts | |
| var PreTokenizer = class extends Callable_default { | |
| /** | |
| * Tokenizes the given text into pre-tokens. | |
| * @param text The text or array of texts to pre-tokenize. | |
| * @param options Additional options for the pre-tokenization logic. | |
| * @returns An array of pre-tokens. | |
| */ | |
| pre_tokenize(text, options) { | |
| return (Array.isArray(text) ? text.map((x) => this.pre_tokenize_text(x, options)) : this.pre_tokenize_text(text, options)).flat(); | |
| } | |
| /** | |
| * Alias for {@link PreTokenizer#pre_tokenize}. | |
| * @param text The text or array of texts to pre-tokenize. | |
| * @param options Additional options for the pre-tokenization logic. | |
| * @returns An array of pre-tokens. | |
| */ | |
| _call(text, options) { | |
| return this.pre_tokenize(text, options); | |
| } | |
| }; | |
| var PreTokenizer_default = PreTokenizer; | |
| // src/core/preTokenizer/ByteLevel.ts | |
| var ByteLevel = class extends PreTokenizer_default { | |
| /** | |
| * Creates a new instance of the `ByteLevelPreTokenizer` class. | |
| * @param config The configuration object. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| this.add_prefix_space = this.config.add_prefix_space ?? false; | |
| this.trim_offsets = this.config.trim_offsets ?? false; | |
| this.use_regex = this.config.use_regex ?? true; | |
| this.pattern = /'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+/gu; | |
| this.byte_encoder = BYTES_TO_UNICODE; | |
| this.text_encoder = new TextEncoder(); | |
| } | |
| /** | |
| * Tokenizes a single piece of text using byte-level tokenization. | |
| * @param text The text to tokenize. | |
| * @param options Additional options for the pre-tokenization logic. | |
| * @returns An array of tokens. | |
| */ | |
| pre_tokenize_text(text, options) { | |
| if (this.add_prefix_space && !text.startsWith(" ")) { | |
| text = " " + text; | |
| } | |
| const tokens = this.use_regex ? text.match(this.pattern) || [] : [text]; | |
| return tokens.map( | |
| (token) => Array.from( | |
| this.text_encoder.encode(token), | |
| (byte) => this.byte_encoder[byte] | |
| ).join("") | |
| ); | |
| } | |
| }; | |
| var ByteLevel_default = ByteLevel; | |
| // src/core/preTokenizer/Whitespace.ts | |
| var Whitespace = class extends PreTokenizer_default { | |
| /** | |
| * Pre-tokenizes the input text by splitting it on word boundaries. | |
| * @param text The text to be pre-tokenized. | |
| * @param options Additional options for the pre-tokenization logic. | |
| * @returns An array of tokens produced by splitting the input text on whitespace. | |
| */ | |
| pre_tokenize_text(text, options) { | |
| return text.match(/\w+|[^\w\s]+/g) || []; | |
| } | |
| }; | |
| var Whitespace_default = Whitespace; | |
| // src/core/preTokenizer/Metaspace.ts | |
| var Metaspace = class extends PreTokenizer_default { | |
| /** | |
| * @param config The configuration object for the MetaspacePreTokenizer. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.replacement = config.replacement ?? "\u2581"; | |
| this.str_rep = config.str_rep || this.replacement; | |
| this.prepend_scheme = config.prepend_scheme ?? "always"; | |
| } | |
| /** | |
| * This method takes a string, replaces spaces with the replacement character, | |
| * adds a prefix space if requested, and returns a new list of tokens. | |
| * @param text The text to pre-tokenize. | |
| * @param options The options for the pre-tokenization. | |
| * @returns A new list of pre-tokenized tokens. | |
| */ | |
| pre_tokenize_text(text, options) { | |
| const { section_index = void 0 } = options ?? {}; | |
| let normalized = text.replaceAll(" ", this.str_rep); | |
| if ( | |
| // We add a prefix space if: | |
| // (1) The normalized token does not already start with the replacement character. | |
| !normalized.startsWith(this.replacement) && // and (2) either: | |
| // (a) prepend_scheme is 'always' | |
| // (b) prepend_scheme is 'first' and this is the first section | |
| (this.prepend_scheme === "always" || this.prepend_scheme === "first" && section_index === 0) | |
| ) { | |
| normalized = this.str_rep + normalized; | |
| } | |
| return [normalized]; | |
| } | |
| }; | |
| var Metaspace_default = Metaspace; | |
| // src/core/preTokenizer/Split.ts | |
| var Split = class extends PreTokenizer_default { | |
| /** | |
| * @param config The configuration options for the pre-tokenizer. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| this.pattern = create_pattern( | |
| this.config.pattern ?? {}, | |
| this.config.invert ?? true | |
| ); | |
| } | |
| /** | |
| * Tokenizes text by splitting it using the given pattern. | |
| * @param text The text to tokenize. | |
| * @returns An array of tokens. | |
| */ | |
| pre_tokenize_text(text) { | |
| if (this.pattern === null) { | |
| return []; | |
| } | |
| if (this.config.invert) { | |
| return text.match(this.pattern) || []; | |
| } else if (this.config.behavior?.toLowerCase() === "removed") { | |
| return text.split(this.pattern).filter((x) => x); | |
| } else { | |
| return regex_split(text, this.pattern); | |
| } | |
| } | |
| }; | |
| var Split_default = Split; | |
| // src/core/preTokenizer/Punctuation.ts | |
| var Punctuation = class extends PreTokenizer_default { | |
| /** | |
| * @param config The configuration options for the pre-tokenizer. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| this.pattern = new RegExp( | |
| `[^${PUNCTUATION_REGEX}]+|[${PUNCTUATION_REGEX}]+`, | |
| "gu" | |
| ); | |
| } | |
| /** | |
| * Tokenizes text by splitting it using the given pattern. | |
| * @param text The text to tokenize. | |
| * @returns An array of tokens. | |
| */ | |
| pre_tokenize_text(text) { | |
| return text.match(this.pattern) || []; | |
| } | |
| }; | |
| var Punctuation_default = Punctuation; | |
| // src/core/preTokenizer/Digits.ts | |
| var Digits = class extends PreTokenizer_default { | |
| /** | |
| * @param config The configuration options for the pre-tokenizer. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| const digit_pattern = `[^\\d]+|\\d${this.config.individual_digits ? "" : "+"}`; | |
| this.pattern = new RegExp(digit_pattern, "gu"); | |
| } | |
| /** | |
| * Tokenizes text by splitting it using the given pattern. | |
| * @param text The text to tokenize. | |
| * @returns An array of tokens. | |
| */ | |
| pre_tokenize_text(text) { | |
| return text.match(this.pattern) || []; | |
| } | |
| }; | |
| var Digits_default = Digits; | |
| // src/core/preTokenizer/BertPreTokenizer.ts | |
| var BertPreTokenizer = class extends PreTokenizer_default { | |
| /** | |
| * A PreTokenizer that splits text into wordpieces using a basic tokenization scheme | |
| * similar to that used in the original implementation of BERT. | |
| */ | |
| constructor() { | |
| super(); | |
| this.pattern = new RegExp( | |
| `[^\\s${PUNCTUATION_REGEX}]+|[${PUNCTUATION_REGEX}]`, | |
| "gu" | |
| ); | |
| } | |
| /** | |
| * Tokenizes a single text using the BERT pre-tokenization scheme. | |
| * | |
| * @param text The text to tokenize. | |
| * @param options Additional options for the pre-tokenization logic. | |
| * @returns An array of tokens. | |
| */ | |
| pre_tokenize_text(text, options) { | |
| return text.trim().match(this.pattern) || []; | |
| } | |
| }; | |
| var BertPreTokenizer_default = BertPreTokenizer; | |
| // src/core/preTokenizer/Replace.ts | |
| var Replace2 = class extends PreTokenizer_default { | |
| /** | |
| * @param config The configuration options for the pre-tokenizer. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| this.pattern = create_pattern(this.config.pattern ?? {}); | |
| this.content = this.config.content ?? ""; | |
| } | |
| /** | |
| * Pre-tokenizes the input text by replacing certain characters. | |
| * @param text The text to be pre-tokenized. | |
| * @returns An array of tokens produced by replacing certain characters. | |
| */ | |
| pre_tokenize_text(text) { | |
| if (this.pattern === null) { | |
| return [text]; | |
| } | |
| return [text.replaceAll(this.pattern, this.config.content ?? "")]; | |
| } | |
| }; | |
| var Replace_default2 = Replace2; | |
| // src/core/preTokenizer/Sequence.ts | |
| var Sequence2 = class extends PreTokenizer_default { | |
| /** | |
| * Creates an instance of PreTokenizerSequence. | |
| * @param config The configuration object for the pre-tokenizer sequence. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.tokenizers = (config.pretokenizers ?? []).map( | |
| (x) => create_pre_tokenizer_default(x) | |
| ); | |
| } | |
| /** | |
| * Applies each pre-tokenizer in the sequence to the input text in turn. | |
| * @param text The text to pre-tokenize. | |
| * @param options Additional options for the pre-tokenization logic. | |
| * @returns The pre-tokenized text. | |
| */ | |
| pre_tokenize_text(text, options) { | |
| return this.tokenizers.reduce( | |
| (pre_tokenized_text, tokenizer) => { | |
| return tokenizer ? tokenizer.pre_tokenize(pre_tokenized_text, options) : pre_tokenized_text; | |
| }, | |
| [text] | |
| ); | |
| } | |
| }; | |
| var Sequence_default2 = Sequence2; | |
| // src/core/preTokenizer/WhitespaceSplit.ts | |
| var WhitespaceSplit = class extends PreTokenizer_default { | |
| /** | |
| * Pre-tokenizes the input text by splitting it on whitespace characters. | |
| * @param text The text to be pre-tokenized. | |
| * @returns An array of tokens produced by splitting the input text on whitespace. | |
| */ | |
| pre_tokenize_text(text) { | |
| return whitespace_split(text); | |
| } | |
| }; | |
| var WhitespaceSplit_default = WhitespaceSplit; | |
| // src/core/preTokenizer/FixedLength.ts | |
| var FixedLength = class extends PreTokenizer_default { | |
| /** | |
| * @param config The configuration options for the pre-tokenizer. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| this._length = config.length; | |
| } | |
| /** | |
| * Pre-tokenizes the input text by splitting it into fixed-length tokens. | |
| * @param text The text to be pre-tokenized. | |
| * @returns An array of tokens produced by splitting the input text into fixed-length tokens. | |
| */ | |
| pre_tokenize_text(text) { | |
| const tokens = []; | |
| for (let i = 0; i < text.length; i += this._length) { | |
| tokens.push(text.slice(i, i + this._length)); | |
| } | |
| return tokens; | |
| } | |
| }; | |
| var FixedLength_default = FixedLength; | |
| // src/core/preTokenizer/create_pre_tokenizer.ts | |
| function create_pre_tokenizer(config) { | |
| if (config === null) return null; | |
| switch (config.type) { | |
| case "BertPreTokenizer": | |
| return new BertPreTokenizer_default(); | |
| case "Sequence": | |
| return new Sequence_default2(config); | |
| case "Whitespace": | |
| return new Whitespace_default(); | |
| case "WhitespaceSplit": | |
| return new WhitespaceSplit_default(); | |
| case "Metaspace": | |
| return new Metaspace_default(config); | |
| case "ByteLevel": | |
| return new ByteLevel_default(config); | |
| case "Split": | |
| return new Split_default(config); | |
| case "Punctuation": | |
| return new Punctuation_default(config); | |
| case "Digits": | |
| return new Digits_default(config); | |
| case "Replace": | |
| return new Replace_default2(config); | |
| case "FixedLength": | |
| return new FixedLength_default(config); | |
| default: | |
| throw new Error(`Unknown PreTokenizer type: ${config.type}`); | |
| } | |
| } | |
| var create_pre_tokenizer_default = create_pre_tokenizer; | |
| // src/core/TokenizerModel.ts | |
| var TokenizerModel = class extends Callable_default { | |
| /** | |
| * Creates a new instance of TokenizerModel. | |
| * @param config The configuration object for the TokenizerModel. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| this.vocab = []; | |
| this.tokens_to_ids = /* @__PURE__ */ new Map(); | |
| this.unk_token_id = void 0; | |
| this.unk_token = void 0; | |
| this.end_of_word_suffix = void 0; | |
| this.fuse_unk = this.config.fuse_unk ?? false; | |
| } | |
| /** | |
| * Internal function to call the TokenizerModel instance. | |
| * @param tokens The tokens to encode. | |
| * @returns The encoded tokens. | |
| */ | |
| _call(tokens) { | |
| let result = this.encode(tokens); | |
| if (this.fuse_unk) { | |
| result = fuse_unk(result, this.tokens_to_ids, this.unk_token_id); | |
| } | |
| return result; | |
| } | |
| }; | |
| var TokenizerModel_default = TokenizerModel; | |
| // src/core/tokenizerModelImplementations/WordPiece.ts | |
| var WordPieceTokenizer = class extends TokenizerModel_default { | |
| /** | |
| * @param config The configuration object. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| /** The maximum number of characters per word. */ | |
| this.max_input_chars_per_word = 100; | |
| this.tokens_to_ids = object_to_map(config.vocab); | |
| this.unk_token_id = this.tokens_to_ids.get(config.unk_token); | |
| this.unk_token = config.unk_token; | |
| this.max_input_chars_per_word = config.max_input_chars_per_word ?? 100; | |
| this.vocab = new Array(this.tokens_to_ids.size); | |
| for (const [key, value] of this.tokens_to_ids) { | |
| this.vocab[value] = key; | |
| } | |
| } | |
| /** | |
| * Encodes an array of tokens using WordPiece encoding. | |
| * @param tokens The tokens to encode. | |
| * @returns An array of encoded tokens. | |
| */ | |
| encode(tokens) { | |
| const output_tokens = []; | |
| for (const token of tokens) { | |
| const chars = [...token]; | |
| if (chars.length > this.max_input_chars_per_word) { | |
| output_tokens.push(this.unk_token); | |
| continue; | |
| } | |
| let is_unknown = false; | |
| let start = 0; | |
| const sub_tokens = []; | |
| while (start < chars.length) { | |
| let end = chars.length; | |
| let current_substring = null; | |
| while (start < end) { | |
| let substr = chars.slice(start, end).join(""); | |
| if (start > 0) { | |
| substr = this.config.continuing_subword_prefix + substr; | |
| } | |
| if (this.tokens_to_ids.has(substr)) { | |
| current_substring = substr; | |
| break; | |
| } | |
| --end; | |
| } | |
| if (current_substring === null) { | |
| is_unknown = true; | |
| break; | |
| } | |
| sub_tokens.push(current_substring); | |
| start = end; | |
| } | |
| if (is_unknown) { | |
| output_tokens.push(this.unk_token); | |
| } else { | |
| output_tokens.push(...sub_tokens); | |
| } | |
| } | |
| return output_tokens; | |
| } | |
| }; | |
| var WordPiece_default = WordPieceTokenizer; | |
| // src/utils/data-structures/CharTrie.ts | |
| var CharTrieNode = class _CharTrieNode { | |
| /** | |
| * Create a new CharTrieNode. | |
| * @param is_leaf Whether the node is a leaf node or not. | |
| * @param children A map containing the node's children, where the key is a character and the value is a `CharTrieNode`. | |
| */ | |
| constructor(is_leaf, children) { | |
| this.is_leaf = is_leaf; | |
| this.children = children; | |
| } | |
| /** | |
| * Returns a new `CharTrieNode` instance with default values. | |
| * @returns A new `CharTrieNode` instance with `is_leaf` set to `false` and an empty `children` map. | |
| */ | |
| static default() { | |
| return new _CharTrieNode(false, /* @__PURE__ */ new Map()); | |
| } | |
| }; | |
| var CharTrie = class { | |
| constructor() { | |
| this.root = CharTrieNode.default(); | |
| } | |
| /** | |
| * Adds one or more `texts` to the trie. | |
| * @param texts The strings to add to the trie. | |
| */ | |
| extend(texts) { | |
| for (const text of texts) { | |
| this.push(text); | |
| } | |
| } | |
| /** | |
| * Adds text to the trie. | |
| * @param text The string to add to the trie. | |
| */ | |
| push(text) { | |
| let node = this.root; | |
| for (const ch of text) { | |
| let child = node.children.get(ch); | |
| if (child === void 0) { | |
| child = CharTrieNode.default(); | |
| node.children.set(ch, child); | |
| } | |
| node = child; | |
| } | |
| node.is_leaf = true; | |
| } | |
| /** | |
| * Searches the trie for all strings with a common prefix of `text`. | |
| * @param text The common prefix to search for. | |
| * @yields Each string in the trie that has `text` as a prefix. | |
| */ | |
| *common_prefix_search(text) { | |
| let node = this.root; | |
| if (node === void 0) return; | |
| let prefix = ""; | |
| for (const ch of text) { | |
| prefix += ch; | |
| node = node.children.get(ch); | |
| if (node === void 0) return; | |
| if (node.is_leaf) { | |
| yield prefix; | |
| } | |
| } | |
| } | |
| }; | |
| var CharTrie_default = CharTrie; | |
| // src/utils/data-structures/TokenLattice.ts | |
| var TokenLatticeNode = class _TokenLatticeNode { | |
| /** | |
| * Represents a node in a token lattice for a given sentence. | |
| * @param token_id The ID of the token associated with this node. | |
| * @param node_id The ID of this node. | |
| * @param pos The starting position of the token in the sentence. | |
| * @param length The length of the token. | |
| * @param score The score associated with the token. | |
| */ | |
| constructor(token_id, node_id, pos, length, score) { | |
| this.token_id = token_id; | |
| this.node_id = node_id; | |
| this.pos = pos; | |
| this.length = length; | |
| this.score = score; | |
| this.prev = null; | |
| this.backtrace_score = 0; | |
| } | |
| /** | |
| * Returns a clone of this node. | |
| * @returns A clone of this node. | |
| */ | |
| clone() { | |
| const n = new _TokenLatticeNode( | |
| this.token_id, | |
| this.node_id, | |
| this.pos, | |
| this.length, | |
| this.score | |
| ); | |
| n.prev = this.prev; | |
| n.backtrace_score = this.backtrace_score; | |
| return n; | |
| } | |
| }; | |
| var TokenLattice = class { | |
| /** | |
| * Creates a new TokenLattice instance. | |
| * | |
| * @param sentence The input sentence to be tokenized. | |
| * @param bos_token_id The beginning-of-sequence token ID. | |
| * @param eos_token_id The end-of-sequence token ID. | |
| */ | |
| constructor(sentence, bos_token_id, eos_token_id) { | |
| this.chars = Array.from(sentence); | |
| this.len = this.chars.length; | |
| this.bos_token_id = bos_token_id; | |
| this.eos_token_id = eos_token_id; | |
| this.nodes = []; | |
| this.begin_nodes = Array.from( | |
| { length: this.len + 1 }, | |
| () => [] | |
| ); | |
| this.end_nodes = Array.from({ length: this.len + 1 }, () => []); | |
| const bos = new TokenLatticeNode(this.bos_token_id ?? 0, 0, 0, 0, 0); | |
| const eos = new TokenLatticeNode( | |
| this.eos_token_id ?? 0, | |
| 1, | |
| this.len, | |
| 0, | |
| 0 | |
| ); | |
| this.nodes.push(bos.clone()); | |
| this.nodes.push(eos.clone()); | |
| this.begin_nodes[this.len].push(eos); | |
| this.end_nodes[0].push(bos); | |
| } | |
| /** | |
| * Inserts a new token node into the token lattice. | |
| * | |
| * @param pos The starting position of the token. | |
| * @param length The length of the token. | |
| * @param score The score of the token. | |
| * @param token_id The token ID of the token. | |
| */ | |
| insert(pos, length, score, token_id) { | |
| const node_id = this.nodes.length; | |
| const node = new TokenLatticeNode(token_id, node_id, pos, length, score); | |
| this.begin_nodes[pos].push(node); | |
| this.end_nodes[pos + length].push(node); | |
| this.nodes.push(node); | |
| } | |
| /** | |
| * Implements the Viterbi algorithm to compute the most likely sequence of tokens. | |
| * | |
| * @returns The most likely sequence of tokens. | |
| */ | |
| viterbi() { | |
| const len2 = this.len; | |
| let pos = 0; | |
| while (pos <= len2) { | |
| if (this.begin_nodes[pos].length == 0) { | |
| return []; | |
| } | |
| for (let rnode of this.begin_nodes[pos]) { | |
| rnode.prev = null; | |
| let best_score = 0; | |
| let best_node = null; | |
| for (let lnode of this.end_nodes[pos]) { | |
| const score = lnode.backtrace_score + rnode.score; | |
| if (best_node === null || score > best_score) { | |
| best_node = lnode.clone(); | |
| best_score = score; | |
| } | |
| } | |
| if (best_node !== null) { | |
| rnode.prev = best_node; | |
| rnode.backtrace_score = best_score; | |
| } else { | |
| return []; | |
| } | |
| } | |
| ++pos; | |
| } | |
| const results = []; | |
| const root = this.begin_nodes[len2][0]; | |
| const prev = root.prev; | |
| if (prev === null) { | |
| return []; | |
| } | |
| let node = prev.clone(); | |
| while (node.prev !== null) { | |
| results.push(node.clone()); | |
| const n = node.clone(); | |
| node = n.prev.clone(); | |
| } | |
| results.reverse(); | |
| return results; | |
| } | |
| /** | |
| * Get the text piece for a given node. | |
| * @param node The node to get the piece for. | |
| * @returns The array of nodes representing the most likely sequence of tokens. | |
| */ | |
| piece(node) { | |
| return this.chars.slice(node.pos, node.pos + node.length).join(""); | |
| } | |
| /** | |
| * @returns The most likely sequence of tokens. | |
| */ | |
| tokens() { | |
| const nodes = this.viterbi(); | |
| return nodes.map((x) => this.piece(x)); | |
| } | |
| /** | |
| * @returns The most likely sequence of token ids. | |
| */ | |
| token_ids() { | |
| const nodes = this.viterbi(); | |
| return nodes.map((x) => x.token_id); | |
| } | |
| }; | |
| var TokenLattice_default = TokenLattice; | |
| // src/utils/maths.ts | |
| function min(arr) { | |
| if (arr.length === 0) throw new Error("Array must not be empty"); | |
| let min_value = arr[0]; | |
| let index_of_min = 0; | |
| for (let i = 1; i < arr.length; ++i) { | |
| if (arr[i] < min_value) { | |
| min_value = arr[i]; | |
| index_of_min = i; | |
| } | |
| } | |
| return [min_value, index_of_min]; | |
| } | |
| // src/core/tokenizerModelImplementations/Unigram.ts | |
| var Unigram = class extends TokenizerModel_default { | |
| /** | |
| * Create a new Unigram tokenizer model. | |
| * @param config The configuration object for the Unigram model. | |
| * @param eos_token | |
| */ | |
| constructor(config, eos_token) { | |
| super(config); | |
| const vocab_size = config.vocab.length; | |
| this.vocab = new Array(vocab_size); | |
| this.scores = new Array(vocab_size); | |
| for (let i = 0; i < vocab_size; ++i) { | |
| [this.vocab[i], this.scores[i]] = config.vocab[i]; | |
| } | |
| this.unk_token_id = config.unk_id; | |
| this.unk_token = this.vocab[config.unk_id]; | |
| this.tokens_to_ids = new Map(this.vocab.map((x, i) => [x, i])); | |
| this.bos_token = " "; | |
| this.bos_token_id = this.tokens_to_ids.get(this.bos_token); | |
| this.eos_token = eos_token; | |
| this.eos_token_id = this.tokens_to_ids.get(this.eos_token); | |
| this.unk_token = this.vocab[this.unk_token_id]; | |
| this.min_score = min(this.scores)[0]; | |
| this.unk_score = this.min_score - 10; | |
| this.scores[this.unk_token_id] = this.unk_score; | |
| this.trie = new CharTrie_default(); | |
| this.trie.extend(this.vocab); | |
| this.fuse_unk = true; | |
| } | |
| /** | |
| * Populates lattice nodes. | |
| * @param lattice The token lattice to populate with nodes. | |
| */ | |
| populate_nodes(lattice) { | |
| const chars = lattice.chars; | |
| const mblen = 1; | |
| let begin_pos = 0; | |
| while (begin_pos < chars.length) { | |
| let has_single_node = false; | |
| const tokens = []; | |
| const sliced = chars.slice(begin_pos).join(""); | |
| const prefixed_tokens = this.trie.common_prefix_search(sliced); | |
| for (const token of prefixed_tokens) { | |
| tokens.push(token); | |
| const token_id = this.tokens_to_ids.get(token); | |
| const token_score = this.scores[token_id]; | |
| const n = len(token); | |
| lattice.insert(begin_pos, n, token_score, token_id); | |
| if (!has_single_node && n === mblen) { | |
| has_single_node = true; | |
| } | |
| } | |
| if (!has_single_node) { | |
| lattice.insert(begin_pos, mblen, this.unk_score, this.unk_token_id); | |
| } | |
| begin_pos += mblen; | |
| } | |
| } | |
| /** | |
| * Encodes an array of tokens into an array of subtokens using the unigram model. | |
| * | |
| * @param normalized The normalized string. | |
| * @returns An array of subtokens obtained by encoding the input tokens using the unigram model. | |
| */ | |
| tokenize(normalized) { | |
| const lattice = new TokenLattice_default( | |
| normalized, | |
| this.bos_token_id, | |
| this.eos_token_id | |
| ); | |
| this.populate_nodes(lattice); | |
| return lattice.tokens(); | |
| } | |
| /** | |
| * Encodes an array of tokens using Unigram encoding. | |
| * @param tokens The tokens to encode. | |
| * @returns An array of encoded tokens. | |
| */ | |
| encode(tokens) { | |
| const to_return = []; | |
| for (const token of tokens) { | |
| const tokenized = this.tokenize(token); | |
| to_return.push(...tokenized); | |
| } | |
| return to_return; | |
| } | |
| }; | |
| var Unigram_default = Unigram; | |
| // src/utils/data-structures/PriorityQueue.ts | |
| var PriorityQueue = class { | |
| /** | |
| * Create a new PriorityQueue. | |
| * @param comparator Comparator function to determine priority. Defaults to a MaxHeap. | |
| * @param max_size Maximum size of the queue. Defaults to Infinity. | |
| */ | |
| constructor(comparator = (a, b) => a > b, max_size = Infinity) { | |
| this._heap = []; | |
| this._comparator = comparator; | |
| this._max_size = max_size; | |
| } | |
| /** | |
| * The size of the queue | |
| */ | |
| get size() { | |
| return this._heap.length; | |
| } | |
| /** | |
| * Check if the queue is empty. | |
| * @returns `true` if the queue is empty, `false` otherwise. | |
| */ | |
| is_empty() { | |
| return this.size === 0; | |
| } | |
| /** | |
| * Return the element with the highest priority in the queue. | |
| * @returns The highest priority element in the queue. | |
| */ | |
| peek() { | |
| return this._heap[0]; | |
| } | |
| /** | |
| * Add one or more elements to the queue. | |
| * @param values The values to push into the queue. | |
| * @returns The new size of the queue. | |
| */ | |
| push(...values) { | |
| return this.extend(values); | |
| } | |
| /** | |
| * Add multiple elements to the queue. | |
| * @param values The values to push into the queue. | |
| * @returns The new size of the queue. | |
| */ | |
| extend(values) { | |
| for (const value of values) { | |
| if (this.size < this._max_size) { | |
| this._heap.push(value); | |
| this._sift_up(); | |
| } else { | |
| const smallest = this._smallest(); | |
| if (this._comparator(value, this._heap[smallest])) { | |
| this._heap[smallest] = value; | |
| this._sift_up_from(smallest); | |
| } | |
| } | |
| } | |
| return this.size; | |
| } | |
| /** | |
| * Remove and return the element with the highest priority in the queue. | |
| * @returns The element with the highest priority in the queue. | |
| */ | |
| pop() { | |
| const popped_value = this.peek(); | |
| const bottom = this.size - 1; | |
| if (bottom > 0) { | |
| this._swap(0, bottom); | |
| } | |
| this._heap.pop(); | |
| this._sift_down(); | |
| return popped_value; | |
| } | |
| /** | |
| * Replace the element with the highest priority in the queue with a new value. | |
| * @param value The new value. | |
| * @returns The replaced value. | |
| */ | |
| replace(value) { | |
| const replaced_value = this.peek(); | |
| this._heap[0] = value; | |
| this._sift_down(); | |
| return replaced_value; | |
| } | |
| /** | |
| * Compute the index for the parent of the node at index `i`. | |
| * @param i The index of the node to get the parent of. | |
| * @returns The index of the parent node. | |
| * @private | |
| */ | |
| _parent(i) { | |
| return (i + 1 >>> 1) - 1; | |
| } | |
| /** | |
| * Compute the index for the left child of the node at index `i`. | |
| * @param i The index of the node to get the left child of. | |
| * @returns The index of the left child. | |
| * @private | |
| */ | |
| _left(i) { | |
| return (i << 1) + 1; | |
| } | |
| /** | |
| * Compute the index for the right child of the node at index `i`. | |
| * @param i The index of the node to get the right child of. | |
| * @returns The index of the right child. | |
| * @private | |
| */ | |
| _right(i) { | |
| return i + 1 << 1; | |
| } | |
| /** | |
| * Check if the element at index `i` is greater than the element at index `j`. | |
| * @param i The index of the first element to compare. | |
| * @param j The index of the second element to compare. | |
| * @returns `true` if the element at index `i` is greater than the element at index `j`, `false` otherwise. | |
| * @private | |
| */ | |
| _greater(i, j) { | |
| return this._comparator(this._heap[i], this._heap[j]); | |
| } | |
| /** | |
| * Swap the elements at indices `i` and `j`. | |
| * @param i The index of the first element to swap. | |
| * @param j The index of the second element to swap. | |
| * @private | |
| */ | |
| _swap(i, j) { | |
| const temp = this._heap[i]; | |
| this._heap[i] = this._heap[j]; | |
| this._heap[j] = temp; | |
| } | |
| /** | |
| * Maintain the heap property by updating positions in the heap, | |
| * starting at the last element and moving up the heap. | |
| * @private | |
| */ | |
| _sift_up() { | |
| this._sift_up_from(this.size - 1); | |
| } | |
| /** | |
| * Helper function to sift up from a given node. | |
| * @param node The index of the node to start sifting up from. | |
| */ | |
| _sift_up_from(node) { | |
| while (node > 0 && this._greater(node, this._parent(node))) { | |
| this._swap(node, this._parent(node)); | |
| node = this._parent(node); | |
| } | |
| } | |
| /** | |
| * Maintain the heap property by updating positions in the heap, | |
| * starting at the first element and moving down the heap. | |
| * @private | |
| */ | |
| _sift_down() { | |
| let node = 0; | |
| while (this._left(node) < this.size && this._greater(this._left(node), node) || this._right(node) < this.size && this._greater(this._right(node), node)) { | |
| const max_child = this._right(node) < this.size && this._greater(this._right(node), this._left(node)) ? this._right(node) : this._left(node); | |
| this._swap(node, max_child); | |
| node = max_child; | |
| } | |
| } | |
| /** | |
| * Get the index of the smallest element in the heap. Since we use an array-based heap, | |
| * the index can be computed without needing to traverse the heap. | |
| * @private | |
| */ | |
| _smallest() { | |
| return 2 ** Math.floor(Math.log2(this.size)) - 1; | |
| } | |
| }; | |
| var PriorityQueue_default = PriorityQueue; | |
| // src/utils/data-structures/LRUCache.ts | |
| var LRUCache = class { | |
| /** | |
| * Creates an LRUCache instance. | |
| * @param capacity The maximum number of items the cache can hold. | |
| */ | |
| constructor(capacity) { | |
| this.capacity = capacity; | |
| this.cache = /* @__PURE__ */ new Map(); | |
| } | |
| /** | |
| * Retrieves the value associated with the given key and marks the key as recently used. | |
| * @param key The key to retrieve. | |
| * @returns The value associated with the key, or undefined if the key does not exist. | |
| */ | |
| get(key) { | |
| if (!this.cache.has(key)) return void 0; | |
| const value = this.cache.get(key); | |
| this.cache.delete(key); | |
| this.cache.set(key, value); | |
| return value; | |
| } | |
| /** | |
| * Inserts or updates the key-value pair in the cache. | |
| * If the key already exists, it is updated and marked as recently used. | |
| * If the cache exceeds its capacity, the least recently used item is evicted. | |
| * @param key The key to add or update. | |
| * @param value The value to associate with the key. | |
| */ | |
| put(key, value) { | |
| if (this.cache.has(key)) { | |
| this.cache.delete(key); | |
| } | |
| this.cache.set(key, value); | |
| if (this.cache.size > this.capacity) { | |
| this.cache.delete(this.cache.keys().next().value); | |
| } | |
| } | |
| /** | |
| * Clears the cache. | |
| */ | |
| clear() { | |
| this.cache.clear(); | |
| } | |
| }; | |
| var LRUCache_default = LRUCache; | |
| // src/core/tokenizerModelImplementations/BPE.ts | |
| var BPE = class extends TokenizerModel_default { | |
| /** | |
| * Create a BPE instance. | |
| * @param config The configuration object for BPE. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.tokens_to_ids = object_to_map(config.vocab); | |
| this.unk_token_id = this.tokens_to_ids.get(config.unk_token); | |
| this.unk_token = config.unk_token; | |
| this.vocab = new Array(this.tokens_to_ids.size); | |
| for (const [key, value] of this.tokens_to_ids) { | |
| this.vocab[value] = key; | |
| } | |
| const use_new_merge_format = Array.isArray(config.merges[0]); | |
| this.merges = use_new_merge_format ? config.merges : config.merges.map( | |
| (x) => x.split(" ", 2) | |
| ); | |
| this.bpe_ranks = new Map(this.merges.map((x, i) => [JSON.stringify(x), i])); | |
| this.end_of_word_suffix = config.end_of_word_suffix; | |
| this.continuing_subword_suffix = config.continuing_subword_suffix ?? null; | |
| this.byte_fallback = this.config.byte_fallback ?? false; | |
| if (this.byte_fallback) { | |
| this.text_encoder = new TextEncoder(); | |
| } | |
| this.ignore_merges = this.config.ignore_merges ?? false; | |
| this.max_length_to_cache = 256; | |
| this.cache_capacity = 1e4; | |
| this.cache = new LRUCache_default(this.cache_capacity); | |
| } | |
| /** | |
| * Clears the cache. | |
| */ | |
| clear_cache() { | |
| this.cache.clear(); | |
| } | |
| /** | |
| * Apply Byte-Pair-Encoding (BPE) to a given token. Efficient heap-based priority | |
| * queue implementation adapted from https://github.com/belladoreai/llama-tokenizer-js. | |
| * @param token The token to encode. | |
| * @returns The BPE encoded tokens. | |
| */ | |
| bpe(token) { | |
| if (token.length === 0) { | |
| return []; | |
| } | |
| const cached = this.cache.get(token); | |
| if (cached !== void 0) { | |
| return cached; | |
| } | |
| const word = Array.from(token); | |
| if (this.end_of_word_suffix) { | |
| word[word.length - 1] += this.end_of_word_suffix; | |
| } | |
| let result = []; | |
| if (word.length > 1) { | |
| const queue = new PriorityQueue_default((a, b) => a.score < b.score); | |
| let starting_node = { | |
| token: word[0], | |
| bias: 0, | |
| prev: null, | |
| next: null | |
| }; | |
| let previous_node = starting_node; | |
| for (let i = 1; i < word.length; ++i) { | |
| const current_node = { | |
| bias: i / word.length, | |
| // Add fractional component to break ties | |
| token: word[i], | |
| prev: previous_node, | |
| next: null | |
| }; | |
| previous_node.next = current_node; | |
| this.add_node(queue, previous_node); | |
| previous_node = current_node; | |
| } | |
| while (!queue.is_empty()) { | |
| const node = queue.pop(); | |
| if (node.deleted || !node.next || node.next.deleted) continue; | |
| node.deleted = true; | |
| node.next.deleted = true; | |
| if (node.prev) { | |
| const new_previous_node = { ...node.prev }; | |
| node.prev.deleted = true; | |
| node.prev = new_previous_node; | |
| if (new_previous_node.prev) { | |
| new_previous_node.prev.next = new_previous_node; | |
| } else { | |
| starting_node = new_previous_node; | |
| } | |
| } | |
| const merged = { | |
| token: node.token + node.next.token, | |
| bias: node.bias, | |
| prev: node.prev, | |
| next: node.next.next | |
| }; | |
| if (merged.prev) { | |
| merged.prev.next = merged; | |
| this.add_node(queue, merged.prev); | |
| } else { | |
| starting_node = merged; | |
| } | |
| if (merged.next) { | |
| merged.next.prev = merged; | |
| this.add_node(queue, merged); | |
| } | |
| } | |
| for (let current_node = starting_node; current_node !== null; current_node = current_node.next) { | |
| result.push(current_node.token); | |
| } | |
| } else { | |
| result = word; | |
| } | |
| if (this.continuing_subword_suffix) { | |
| for (let i = 0; i < result.length - 1; ++i) { | |
| result[i] += this.continuing_subword_suffix; | |
| } | |
| } | |
| if (token.length < this.max_length_to_cache) { | |
| this.cache.put(token, result); | |
| } | |
| return result; | |
| } | |
| /** | |
| * Helper function to add a node to the priority queue. | |
| * @param queue | |
| * @param node | |
| */ | |
| add_node(queue, node) { | |
| const rank = this.bpe_ranks.get( | |
| JSON.stringify([node.token, node.next.token]) | |
| ); | |
| if (rank !== void 0) { | |
| node.score = rank + node.bias; | |
| queue.push(node); | |
| } | |
| } | |
| /** | |
| * Encodes the input sequence of tokens using the BPE algorithm and returns the resulting subword tokens. | |
| * @param tokens The input sequence of tokens to encode. | |
| * @returns The resulting subword tokens after applying the BPE algorithm to the input sequence of tokens. | |
| */ | |
| encode(tokens) { | |
| const output_tokens = []; | |
| for (const token of tokens) { | |
| if (this.ignore_merges && this.tokens_to_ids.has(token)) { | |
| output_tokens.push(token); | |
| continue; | |
| } | |
| const bpe_token_list = this.bpe(token); | |
| for (const t of bpe_token_list) { | |
| if (this.tokens_to_ids.has(t)) { | |
| output_tokens.push(t); | |
| } else if (this.byte_fallback) { | |
| const byte_tokens = Array.from(this.text_encoder.encode(t)).map( | |
| (x) => `<0x${x.toString(16).toUpperCase().padStart(2, "0")}>` | |
| ); | |
| if (byte_tokens.every((x) => this.tokens_to_ids.has(x))) { | |
| output_tokens.push(...byte_tokens); | |
| } else if (this.unk_token != null) { | |
| output_tokens.push(this.unk_token); | |
| } | |
| } else if (this.unk_token != null) { | |
| output_tokens.push(this.unk_token); | |
| } | |
| } | |
| } | |
| return output_tokens; | |
| } | |
| }; | |
| var BPE_default = BPE; | |
| // src/core/tokenizerModelImplementations/Legacy.ts | |
| var Legacy = class extends TokenizerModel_default { | |
| /** | |
| * Create a Legacy tokenizer model instance. | |
| * @param config The configuration object for Legacy tokenizer model. | |
| * @param more_config Additional configuration object for the Legacy tokenizer model. | |
| */ | |
| constructor(config, more_config) { | |
| super(config); | |
| const vocab = config.vocab; | |
| this.tokens_to_ids = object_to_map( | |
| more_config.target_lang ? vocab[more_config.target_lang] : vocab | |
| ); | |
| this.bos_token = more_config.bos_token; | |
| this.bos_token_id = this.tokens_to_ids.get(this.bos_token); | |
| this.eos_token = more_config.eos_token; | |
| this.eos_token_id = this.tokens_to_ids.get(this.eos_token); | |
| this.pad_token = more_config.pad_token; | |
| this.pad_token_id = this.tokens_to_ids.get(this.pad_token); | |
| this.unk_token = more_config.unk_token; | |
| this.unk_token_id = this.tokens_to_ids.get(this.unk_token); | |
| this.vocab = new Array(this.tokens_to_ids.size); | |
| for (const [key, value] of this.tokens_to_ids) { | |
| this.vocab[value] = key; | |
| } | |
| } | |
| encode(tokens) { | |
| return tokens; | |
| } | |
| }; | |
| var Legacy_default = Legacy; | |
| // src/core/tokenizerModelImplementations/create_tokenizer_model.ts | |
| function create_tokenizer_model(model_config, config) { | |
| switch (model_config.type) { | |
| case "WordPiece": | |
| return new WordPiece_default(model_config); | |
| case "Unigram": | |
| return new Unigram_default(model_config, config.eos_token); | |
| case "BPE": | |
| return new BPE_default(model_config); | |
| default: | |
| if (model_config.vocab) { | |
| if (Array.isArray(model_config.vocab)) { | |
| return new Unigram_default(model_config, config.eos_token); | |
| } else if (Object.hasOwn(model_config, "continuing_subword_prefix") && Object.hasOwn(model_config, "unk_token")) { | |
| if (Object.hasOwn(model_config, "merges")) { | |
| return new BPE_default(model_config); | |
| } else { | |
| return new WordPiece_default(model_config); | |
| } | |
| } else { | |
| return new Legacy_default(model_config, { | |
| target_lang: config.target_lang, | |
| bos_token: config.bos_token, | |
| eos_token: config.eos_token, | |
| pad_token: config.pad_token, | |
| unk_token: config.unk_token | |
| }); | |
| } | |
| } | |
| throw new Error( | |
| `Unknown TokenizerModel type: ${model_config?.type}` | |
| ); | |
| } | |
| } | |
| var create_tokenizer_model_default = create_tokenizer_model; | |
| // src/core/PostProcessor.ts | |
| var PostProcessor = class extends Callable_default { | |
| /** | |
| * @param config The configuration for the post-processor. | |
| */ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| } | |
| /** | |
| * Alias for {@link PostProcessor#post_process}. | |
| * @param tokens The text or array of texts to post-process. | |
| * @param args Additional arguments required by the post-processing logic. | |
| * @returns The post-processed tokens. | |
| */ | |
| _call(tokens, ...args) { | |
| return this.post_process(tokens, ...args); | |
| } | |
| }; | |
| var PostProcessor_default = PostProcessor; | |
| // src/core/postProcessor/TemplateProcessing.ts | |
| var TemplateProcessing = class extends PostProcessor_default { | |
| /** | |
| * Replaces special tokens in the template with actual tokens. | |
| * @param tokens The list of tokens for the first sequence. | |
| * @param tokens_pair The list of tokens for the second sequence (optional). | |
| * @param add_special_tokens Whether to add the special tokens to the beginning and end of the input. | |
| * @returns An object containing the list of tokens with the special tokens replaced with actual tokens. | |
| */ | |
| post_process(tokens, tokens_pair = null, add_special_tokens = true) { | |
| const type = tokens_pair === null ? this.config.single : this.config.pair; | |
| let processed_tokens = []; | |
| let types = []; | |
| for (const item of type) { | |
| if ("SpecialToken" in item) { | |
| if (add_special_tokens) { | |
| processed_tokens.push(item.SpecialToken.id); | |
| types.push(item.SpecialToken.type_id); | |
| } | |
| } else if ("Sequence" in item) { | |
| if (item.Sequence.id === "A") { | |
| processed_tokens = merge_arrays(processed_tokens, tokens); | |
| types = merge_arrays( | |
| types, | |
| new Array(tokens.length).fill(item.Sequence.type_id) | |
| ); | |
| } else if (item.Sequence.id === "B") { | |
| processed_tokens = merge_arrays(processed_tokens, tokens_pair); | |
| types = merge_arrays( | |
| types, | |
| new Array(tokens_pair.length).fill(item.Sequence.type_id) | |
| ); | |
| } | |
| } | |
| } | |
| return { tokens: processed_tokens, token_type_ids: types }; | |
| } | |
| }; | |
| var TemplateProcessing_default = TemplateProcessing; | |
| // src/core/postProcessor/ByteLevel.ts | |
| var ByteLevel2 = class extends PostProcessor_default { | |
| /** | |
| * Post process the given tokens. | |
| * @param tokens The list of tokens for the first sequence. | |
| * @param tokens_pair The list of tokens for the second sequence (optional). | |
| * @returns An object containing the post-processed tokens. | |
| */ | |
| post_process(tokens, tokens_pair = null) { | |
| return { tokens, tokens_pair }; | |
| } | |
| }; | |
| var ByteLevel_default2 = ByteLevel2; | |
| // src/core/postProcessor/BertProcessing.ts | |
| var BertProcessing = class extends PostProcessor_default { | |
| /** | |
| * @param config The configuration for the post-processor. | |
| * @param config.cls The special tokens to add to the beginning of the input. | |
| * @param config.sep The special tokens to add to the end of the input. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.sep = config.sep; | |
| this.cls = config.cls; | |
| } | |
| /** | |
| * Adds the special tokens to the beginning and end of the input. | |
| * @param tokens The input tokens. | |
| * @param tokens_pair An optional second set of input tokens. | |
| * @param add_special_tokens Whether to add the special tokens to the beginning and end of the input. | |
| * @returns The post-processed tokens with the special tokens added to the beginning and end. | |
| */ | |
| post_process(tokens, tokens_pair = null, add_special_tokens = true) { | |
| if (add_special_tokens) { | |
| tokens = merge_arrays([this.cls[0]], tokens, [this.sep[0]]); | |
| } | |
| let token_type_ids = new Array(tokens.length).fill(0); | |
| if (tokens_pair) { | |
| const middle = []; | |
| const after = add_special_tokens ? [this.sep[0]] : []; | |
| tokens = merge_arrays(tokens, middle, tokens_pair, after); | |
| token_type_ids = merge_arrays( | |
| token_type_ids, | |
| new Array(tokens_pair.length + middle.length + after.length).fill(1) | |
| ); | |
| } | |
| return { tokens, token_type_ids }; | |
| } | |
| }; | |
| var BertProcessing_default = BertProcessing; | |
| // src/core/postProcessor/RobertaProcessing.ts | |
| var RobertaProcessing = class extends PostProcessor_default { | |
| /** | |
| * @param config The configuration for the post-processor. | |
| * @param config.cls The special tokens to add to the beginning of the input. | |
| * @param config.sep The special tokens to add to the end of the input. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.sep = config.sep; | |
| this.cls = config.cls; | |
| } | |
| /** | |
| * Adds the special tokens to the beginning and end of the input. | |
| * @param tokens The input tokens. | |
| * @param tokens_pair An optional second set of input tokens. | |
| * @param add_special_tokens Whether to add the special tokens to the beginning and end of the input. | |
| * @returns The post-processed tokens with the special tokens added to the beginning and end. | |
| */ | |
| post_process(tokens, tokens_pair, add_special_tokens = true) { | |
| if (add_special_tokens) { | |
| tokens = merge_arrays([this.cls[0]], tokens, [this.sep[0]]); | |
| } | |
| let token_type_ids = new Array(tokens.length).fill(0); | |
| if (tokens_pair) { | |
| const middle = add_special_tokens ? [this.sep[0]] : []; | |
| const after = add_special_tokens ? [this.sep[0]] : []; | |
| tokens = merge_arrays(tokens, middle, tokens_pair, after); | |
| token_type_ids = merge_arrays( | |
| token_type_ids, | |
| new Array(tokens_pair.length + middle.length + after.length).fill(1) | |
| ); | |
| } | |
| return { tokens, token_type_ids }; | |
| } | |
| }; | |
| var RobertaProcessing_default = RobertaProcessing; | |
| // src/core/postProcessor/Sequence.ts | |
| var Sequence3 = class extends PostProcessor_default { | |
| /** | |
| * Creates a new instance of Sequence post-processor. | |
| * @param config The configuration object. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.processors = (config.processors ?? []).map((x) => create_post_processor_default(x)); | |
| } | |
| /** | |
| * Post process the given tokens. | |
| * @param tokens The list of tokens for the first sequence. | |
| * @param tokens_pair The list of tokens for the second sequence (optional). | |
| * @param add_special_tokens Whether to add the special tokens to the beginning and end of the input. | |
| * @returns An object containing the post-processed tokens. | |
| */ | |
| post_process(tokens, tokens_pair = null, add_special_tokens = true) { | |
| let processed_tokens = { tokens, tokens_pair }; | |
| for (const processor of this.processors) { | |
| processed_tokens = processor.post_process( | |
| processed_tokens.tokens, | |
| processed_tokens.tokens_pair, | |
| add_special_tokens | |
| ); | |
| } | |
| return processed_tokens; | |
| } | |
| }; | |
| var Sequence_default3 = Sequence3; | |
| // src/core/postProcessor/create_post_processor.ts | |
| function create_post_processor(config) { | |
| if (config === null) return null; | |
| switch (config.type) { | |
| case "TemplateProcessing": | |
| return new TemplateProcessing_default(config); | |
| case "ByteLevel": | |
| return new ByteLevel_default2(config); | |
| case "BertProcessing": | |
| return new BertProcessing_default(config); | |
| case "RobertaProcessing": | |
| return new RobertaProcessing_default(config); | |
| case "Sequence": | |
| return new Sequence_default3(config); | |
| default: | |
| throw new Error(`Unknown PostProcessor type: ${config.type}`); | |
| } | |
| } | |
| var create_post_processor_default = create_post_processor; | |
| // src/core/Decoder.ts | |
| var Decoder = class extends Callable_default { | |
| /** | |
| * Creates an instance of `Decoder`. | |
| * @param config The configuration object. | |
| **/ | |
| constructor(config) { | |
| super(); | |
| this.config = config; | |
| this.added_tokens = []; | |
| this.end_of_word_suffix = null; | |
| this.trim_offsets = "trim_offsets" in config ? config.trim_offsets : false; | |
| } | |
| /** | |
| * Calls the `decode` method. | |
| * | |
| * @param tokens The list of tokens. | |
| * @returns The decoded string. | |
| */ | |
| _call(tokens) { | |
| return this.decode(tokens); | |
| } | |
| /** | |
| * Decodes a list of tokens. | |
| * @param tokens The list of tokens. | |
| * @returns The decoded string. | |
| */ | |
| decode(tokens) { | |
| return this.decode_chain(tokens).join(""); | |
| } | |
| }; | |
| var Decoder_default = Decoder; | |
| // src/core/decoder/ByteLevel.ts | |
| var ByteLevel3 = class extends Decoder_default { | |
| /** | |
| * Create a `ByteLevelDecoder` object. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.byte_decoder = UNICODE_TO_BYTES; | |
| this.text_decoder = new TextDecoder("utf-8", { | |
| fatal: false, | |
| // eslint-disable-next-line @typescript-eslint/naming-convention | |
| ignoreBOM: true | |
| }); | |
| this.end_of_word_suffix = null; | |
| } | |
| /** | |
| * Convert an array of tokens to string by decoding each byte. | |
| * @param tokens Array of tokens to be decoded. | |
| * @returns The decoded string. | |
| */ | |
| convert_tokens_to_string(tokens) { | |
| const text = tokens.join(""); | |
| const byte_array = new Uint8Array( | |
| [...text].map((c) => this.byte_decoder[c]) | |
| ); | |
| return this.text_decoder.decode(byte_array); | |
| } | |
| decode_chain(tokens) { | |
| const sub_texts = []; | |
| let current_sub_text = []; | |
| for (const token of tokens) { | |
| if (this.added_tokens.find((x) => x.content === token) !== void 0) { | |
| if (current_sub_text.length > 0) { | |
| sub_texts.push(this.convert_tokens_to_string(current_sub_text)); | |
| current_sub_text = []; | |
| } | |
| sub_texts.push(token); | |
| } else { | |
| current_sub_text.push(token); | |
| } | |
| } | |
| if (current_sub_text.length > 0) { | |
| sub_texts.push(this.convert_tokens_to_string(current_sub_text)); | |
| } | |
| return sub_texts; | |
| } | |
| }; | |
| var ByteLevel_default3 = ByteLevel3; | |
| // src/core/decoder/WordPiece.ts | |
| var WordPiece = class extends Decoder_default { | |
| /** | |
| * Creates a new instance of WordPieceDecoder. | |
| * @param config The configuration object. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.cleanup = config.cleanup; | |
| } | |
| decode_chain(tokens) { | |
| return tokens.map((token, i) => { | |
| if (i !== 0) { | |
| const prefix = this.config.prefix; | |
| if (prefix && token.startsWith(prefix)) { | |
| token = token.replace(prefix, ""); | |
| } else { | |
| token = " " + token; | |
| } | |
| } | |
| if (this.cleanup) { | |
| token = clean_up_tokenization(token); | |
| } | |
| return token; | |
| }); | |
| } | |
| }; | |
| var WordPiece_default2 = WordPiece; | |
| // src/core/decoder/Metaspace.ts | |
| var Metaspace2 = class extends Decoder_default { | |
| /** | |
| * Constructs a new MetaspaceDecoder object. | |
| * @param config The configuration object for the MetaspaceDecoder. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.replacement = config.replacement ?? "\u2581"; | |
| } | |
| decode_chain(tokens) { | |
| const result = []; | |
| for (let i = 0; i < tokens.length; ++i) { | |
| let normalized = tokens[i].replaceAll(this.replacement, " "); | |
| if (i == 0 && normalized.startsWith(" ")) { | |
| normalized = normalized.substring(1); | |
| } | |
| result.push(normalized); | |
| } | |
| return result; | |
| } | |
| }; | |
| var Metaspace_default2 = Metaspace2; | |
| // src/core/decoder/BPE.ts | |
| var BPE2 = class extends Decoder_default { | |
| constructor(config) { | |
| super(config); | |
| this.suffix = config.suffix ?? ""; | |
| } | |
| decode_chain(tokens) { | |
| return tokens.map((token, i) => { | |
| return token.replaceAll(this.suffix, i === tokens.length - 1 ? "" : " "); | |
| }); | |
| } | |
| }; | |
| var BPE_default2 = BPE2; | |
| // src/core/decoder/CTC.ts | |
| var CTC = class extends Decoder_default { | |
| constructor(config) { | |
| super(config); | |
| this.pad_token = config.pad_token ?? ""; | |
| this.word_delimiter_token = config.word_delimiter_token ?? ""; | |
| this.cleanup = config.cleanup; | |
| } | |
| /** | |
| * Converts a connectionist-temporal-classification (CTC) output tokens into a single string. | |
| * @param tokens Array of tokens to be decoded. | |
| * @returns The decoded string. | |
| */ | |
| convert_tokens_to_string(tokens) { | |
| if (tokens.length === 0) return ""; | |
| const grouped_tokens = [tokens[0]]; | |
| for (let i = 1; i < tokens.length; ++i) { | |
| if (tokens[i] !== grouped_tokens.at(-1)) { | |
| grouped_tokens.push(tokens[i]); | |
| } | |
| } | |
| const filtered_tokens = grouped_tokens.filter( | |
| (token) => token !== this.pad_token | |
| ); | |
| let text = filtered_tokens.join(""); | |
| if (this.cleanup) { | |
| text = clean_up_tokenization(text).replaceAll(this.word_delimiter_token, " ").trim(); | |
| } | |
| return text; | |
| } | |
| decode_chain(tokens) { | |
| return [this.convert_tokens_to_string(tokens)]; | |
| } | |
| }; | |
| var CTC_default = CTC; | |
| // src/core/decoder/Sequence.ts | |
| var Sequence4 = class extends Decoder_default { | |
| /** | |
| * Creates a new instance of DecoderSequence. | |
| * @param config The configuration object. | |
| */ | |
| constructor(config) { | |
| super(config); | |
| this.decoders = (config.decoders ?? []).map((x) => create_decoder_default(x)); | |
| } | |
| decode_chain(tokens) { | |
| return this.decoders.reduce((toks, decoder) => { | |
| return decoder.decode_chain(toks); | |
| }, tokens); | |
| } | |
| }; | |
| var Sequence_default4 = Sequence4; | |
| // src/core/decoder/Replace.ts | |
| var Replace3 = class extends Decoder_default { | |
| decode_chain(tokens) { | |
| const pattern = create_pattern(this.config.pattern); | |
| const content = this.config.content ?? ""; | |
| return pattern === null ? tokens : tokens.map((token) => token.replaceAll(pattern, content)); | |
| } | |
| }; | |
| var Replace_default3 = Replace3; | |
| // src/core/decoder/Fuse.ts | |
| var Fuse = class extends Decoder_default { | |
| decode_chain(tokens) { | |
| return [tokens.join("")]; | |
| } | |
| }; | |
| var Fuse_default = Fuse; | |
| // src/core/decoder/Strip.ts | |
| var Strip2 = class extends Decoder_default { | |
| constructor(config) { | |
| super(config); | |
| this.content = config.content ?? ""; | |
| this.start = config.start ?? 0; | |
| this.stop = config.stop ?? 0; | |
| } | |
| decode_chain(tokens) { | |
| return tokens.map((token) => { | |
| let start_cut = 0; | |
| for (let i = 0; i < this.start; ++i) { | |
| if (token[i] === this.content) { | |
| start_cut = i + 1; | |
| continue; | |
| } else { | |
| break; | |
| } | |
| } | |
| let stop_cut = token.length; | |
| for (let i = 0; i < this.stop; ++i) { | |
| const index = token.length - i - 1; | |
| if (token[index] === this.content) { | |
| stop_cut = index; | |
| continue; | |
| } else { | |
| break; | |
| } | |
| } | |
| return token.slice(start_cut, stop_cut); | |
| }); | |
| } | |
| }; | |
| var Strip_default2 = Strip2; | |
| // src/core/decoder/ByteFallback.ts | |
| var ByteFallback = class extends Decoder_default { | |
| constructor(config) { | |
| super(config); | |
| this.text_decoder = new TextDecoder(); | |
| } | |
| decode_chain(tokens) { | |
| const new_tokens = []; | |
| let previous_byte_tokens = []; | |
| for (const token of tokens) { | |
| let bytes = null; | |
| if (token.length === 6 && token.startsWith("<0x") && token.endsWith(">")) { | |
| const byte = parseInt(token.slice(3, 5), 16); | |
| if (!isNaN(byte)) { | |
| bytes = byte; | |
| } | |
| } | |
| if (bytes !== null) { | |
| previous_byte_tokens.push(bytes); | |
| } else { | |
| if (previous_byte_tokens.length > 0) { | |
| const string = this.text_decoder.decode( | |
| Uint8Array.from(previous_byte_tokens) | |
| ); | |
| new_tokens.push(string); | |
| previous_byte_tokens = []; | |
| } | |
| new_tokens.push(token); | |
| } | |
| } | |
| if (previous_byte_tokens.length > 0) { | |
| const string = this.text_decoder.decode( | |
| Uint8Array.from(previous_byte_tokens) | |
| ); | |
| new_tokens.push(string); | |
| previous_byte_tokens = []; | |
| } | |
| return new_tokens; | |
| } | |
| }; | |
| var ByteFallback_default = ByteFallback; | |
| // src/core/decoder/create_decoder.ts | |
| function create_decoder(config) { | |
| if (config === null) return null; | |
| switch (config.type) { | |
| case "ByteLevel": | |
| return new ByteLevel_default3(config); | |
| case "WordPiece": | |
| return new WordPiece_default2(config); | |
| case "Metaspace": | |
| return new Metaspace_default2(config); | |
| case "BPEDecoder": | |
| return new BPE_default2(config); | |
| case "CTC": | |
| return new CTC_default(config); | |
| case "Sequence": | |
| return new Sequence_default4(config); | |
| case "Replace": | |
| return new Replace_default3(config); | |
| case "Fuse": | |
| return new Fuse_default(config); | |
| case "Strip": | |
| return new Strip_default2(config); | |
| case "ByteFallback": | |
| return new ByteFallback_default(config); | |
| default: | |
| throw new Error(`Unknown Decoder type: ${config.type}`); | |
| } | |
| } | |
| var create_decoder_default = create_decoder; | |
| // src/core/Tokenizer.ts | |
| var Tokenizer = class { | |
| constructor(tokenizer, config) { | |
| const tokenizer_error = validate_object(tokenizer, "Tokenizer", [ | |
| "model", | |
| "decoder", | |
| "post_processor", | |
| "pre_tokenizer", | |
| "normalizer" | |
| ]); | |
| if (tokenizer_error) { | |
| throw new Error(tokenizer_error); | |
| } | |
| const config_error = validate_object(config, "Config"); | |
| if (config_error) { | |
| throw new Error(config_error); | |
| } | |
| this.tokenizer = tokenizer; | |
| this.config = config; | |
| this.normalizer = create_normalizer_default(this.tokenizer.normalizer); | |
| this.pre_tokenizer = create_pre_tokenizer_default(this.tokenizer.pre_tokenizer); | |
| this.model = create_tokenizer_model_default(this.tokenizer.model, this.config); | |
| this.post_processor = create_post_processor_default(this.tokenizer.post_processor); | |
| this.decoder = create_decoder_default(this.tokenizer.decoder); | |
| this.special_tokens = []; | |
| this.all_special_ids = []; | |
| this.added_tokens = []; | |
| const unnormalized_contents = []; | |
| const normalized_contents = []; | |
| this.added_tokens_map = /* @__PURE__ */ new Map(); | |
| for (const added_token of this.tokenizer.added_tokens) { | |
| const token = new AddedToken_default(added_token); | |
| this.added_tokens.push(token); | |
| this.model.tokens_to_ids.set(token.content, token.id); | |
| this.model.vocab[token.id] = token.content; | |
| if (token.special) { | |
| this.special_tokens.push(token.content); | |
| this.all_special_ids.push(token.id); | |
| } | |
| this.added_tokens_map.set(token.content, token); | |
| if (token.normalized && this.normalizer !== null) { | |
| const normalized_content = this.normalizer(token.content); | |
| normalized_contents.push(normalized_content); | |
| this.added_tokens_map.set(normalized_content, token); | |
| } else { | |
| unnormalized_contents.push(token.content); | |
| } | |
| } | |
| (this.config.additional_special_tokens ?? []).forEach((token) => { | |
| if (!this.special_tokens.includes(token)) this.special_tokens.push(token); | |
| }); | |
| if (this.decoder) { | |
| this.decoder.added_tokens = this.added_tokens; | |
| this.decoder.end_of_word_suffix = this.model.end_of_word_suffix; | |
| } | |
| this.splitter_unnormalized = new DictionarySplitter_default(unnormalized_contents); | |
| this.splitter_normalized = new DictionarySplitter_default(normalized_contents); | |
| this.remove_space = this.config.remove_space; | |
| this.clean_up_tokenization_spaces = this.config.clean_up_tokenization_spaces ?? true; | |
| this.do_lowercase_and_remove_accent = this.config.do_lowercase_and_remove_accent ?? false; | |
| } | |
| // Implementation | |
| encode(text, { | |
| text_pair = null, | |
| add_special_tokens = true, | |
| return_token_type_ids = null | |
| } = {}) { | |
| const { tokens, token_type_ids } = this.tokenize_helper(text, { | |
| text_pair, | |
| add_special_tokens | |
| }); | |
| const input_ids = tokens.map( | |
| (t) => this.added_tokens_map.get(t)?.id ?? this.model.tokens_to_ids.get(t) ?? this.model.unk_token_id | |
| ); | |
| const result = { | |
| ids: input_ids, | |
| tokens, | |
| attention_mask: new Array(input_ids.length).fill(1) | |
| }; | |
| if (return_token_type_ids && token_type_ids) { | |
| result.token_type_ids = token_type_ids; | |
| } | |
| return result; | |
| } | |
| decode(token_ids, options = {}) { | |
| if (!Array.isArray(token_ids) || token_ids.length === 0 || !is_integral_number(token_ids[0])) { | |
| throw Error("token_ids must be a non-empty array of integers."); | |
| } | |
| let tokens = token_ids.map( | |
| (i) => this.model.vocab[Number(i)] ?? this.model.unk_token | |
| ); | |
| if (options.skip_special_tokens) { | |
| tokens = tokens.filter((x) => !this.special_tokens.includes(x)); | |
| } | |
| let decoded = this.decoder ? this.decoder(tokens) : tokens.join(" "); | |
| if (this.decoder && this.decoder.end_of_word_suffix) { | |
| decoded = decoded.replaceAll(this.decoder.end_of_word_suffix, " "); | |
| if (options.skip_special_tokens) { | |
| decoded = decoded.trim(); | |
| } | |
| } | |
| if (options.clean_up_tokenization_spaces ?? this.clean_up_tokenization_spaces) { | |
| decoded = clean_up_tokenization(decoded); | |
| } | |
| return decoded; | |
| } | |
| /** | |
| * Converts a string into a sequence of tokens. | |
| * @param text The sequence to be encoded. | |
| * @param options An optional object containing the following properties: | |
| * @returns The list of tokens. | |
| */ | |
| tokenize(text, { text_pair = null, add_special_tokens = false } = {}) { | |
| return this.tokenize_helper(text, { text_pair, add_special_tokens }).tokens; | |
| } | |
| encode_text(text) { | |
| if (text === null) { | |
| return null; | |
| } | |
| const sections = this.splitter_unnormalized.split(text); | |
| sections.forEach((section, i) => { | |
| const added_token = this.added_tokens_map.get(section); | |
| if (added_token) { | |
| if (added_token.lstrip && i > 0) { | |
| sections[i - 1] = sections[i - 1].trimEnd(); | |
| } | |
| if (added_token.rstrip && i < sections.length - 1) { | |
| sections[i + 1] = sections[i + 1].trimStart(); | |
| } | |
| } | |
| }); | |
| return sections.flatMap((processed_text, section_index) => { | |
| if (processed_text.length === 0) { | |
| return []; | |
| } | |
| if (this.added_tokens_map.has(processed_text)) { | |
| return [processed_text]; | |
| } | |
| if (this.remove_space === true) { | |
| processed_text = processed_text.trim().split(/\s+/).join(" "); | |
| } | |
| if (this.do_lowercase_and_remove_accent) { | |
| processed_text = lowercase_and_remove_accents(processed_text); | |
| } | |
| if (this.normalizer !== null) { | |
| processed_text = this.normalizer(processed_text); | |
| } | |
| if (processed_text.length === 0) { | |
| return []; | |
| } | |
| const subsections = this.splitter_normalized.split(processed_text); | |
| subsections.forEach((subsection, j) => { | |
| const added_token = this.added_tokens_map.get(subsection); | |
| if (added_token) { | |
| if (added_token.lstrip && j > 0) { | |
| subsections[j - 1] = subsections[j - 1].trimEnd(); | |
| } | |
| if (added_token.rstrip && j < subsections.length - 1) { | |
| subsections[j + 1] = subsections[j + 1].trimStart(); | |
| } | |
| } | |
| }); | |
| return subsections.flatMap((subsection) => { | |
| if (subsection.length === 0) { | |
| return []; | |
| } | |
| if (this.added_tokens_map.has(subsection)) { | |
| return [subsection]; | |
| } | |
| const section_tokens = this.pre_tokenizer !== null ? this.pre_tokenizer(subsection, { | |
| section_index | |
| }) : [subsection]; | |
| return this.model(section_tokens); | |
| }); | |
| }); | |
| } | |
| tokenize_helper(text, { text_pair = null, add_special_tokens = true }) { | |
| const tokens1 = this.encode_text(text); | |
| const tokens2 = this.encode_text(text_pair || null); | |
| return this.post_processor ? this.post_processor(tokens1, tokens2, add_special_tokens) : { tokens: merge_arrays(tokens1 ?? [], tokens2 ?? []) }; | |
| } | |
| /** | |
| * Converts a token string to its corresponding token ID. | |
| * @param token The token string to convert. | |
| * @returns The token ID, or undefined if the token is not in the vocabulary. | |
| */ | |
| token_to_id(token) { | |
| return this.model.tokens_to_ids.get(token); | |
| } | |
| /** | |
| * Converts a token ID to its corresponding token string. | |
| * @param id The token ID to convert. | |
| * @returns The token string, or undefined if the ID is not in the vocabulary. | |
| */ | |
| id_to_token(id) { | |
| return this.model.vocab[id]; | |
| } | |
| /** | |
| * Returns a mapping of token IDs to AddedToken objects for all added tokens. | |
| * @returns A Map where keys are token IDs and values are AddedToken objects. | |
| */ | |
| get_added_tokens_decoder() { | |
| const decoder = /* @__PURE__ */ new Map(); | |
| for (const token of this.added_tokens) { | |
| decoder.set(token.id, token); | |
| } | |
| return decoder; | |
| } | |
| /** | |
| * Get the underlying vocabulary | |
| * @param with_added_tokens Whether to include the added tokens | |
| * @returns The vocabulary | |
| */ | |
| get_vocab(with_added_tokens = true) { | |
| const vocab = /* @__PURE__ */ new Map(); | |
| for (let i = 0; i < this.model.vocab.length; ++i) { | |
| const token = this.model.vocab[i]; | |
| if (with_added_tokens || !this.added_tokens_map.has(token)) { | |
| vocab.set(token, i); | |
| } | |
| } | |
| return vocab; | |
| } | |
| }; | |
| var Tokenizer_default = Tokenizer; | |
| export { | |
| AddedToken_default as AddedToken, | |
| BPE_default as BPE, | |
| BPE_default2 as BPEDecoder, | |
| BertNormalizer_default as BertNormalizer, | |
| BertPreTokenizer_default as BertPreTokenizer, | |
| BertProcessing_default as BertProcessingPostProcessor, | |
| ByteFallback_default as ByteFallbackDecoder, | |
| ByteLevel_default3 as ByteLevelDecoder, | |
| ByteLevel_default2 as ByteLevelPostProcessor, | |
| ByteLevel_default as ByteLevelPreTokenizer, | |
| CTC_default as CTCDecoder, | |
| Decoder_default as Decoder, | |
| Digits_default as DigitsPreTokenizer, | |
| FixedLength_default as FixedLengthPreTokenizer, | |
| Fuse_default as FuseDecoder, | |
| Lowercase_default as LowercaseNormalizer, | |
| Metaspace_default2 as MetaspaceDecoder, | |
| Metaspace_default as MetaspacePreTokenizer, | |
| TokenizerModel_default as Model, | |
| NFC_default as NFCNormalizer, | |
| NFD_default as NFDNormalizer, | |
| NFKC_default as NFKCNormalizer, | |
| NFKD_default as NFKDNormalizer, | |
| Normalizer_default as Normalizer, | |
| PostProcessor_default as PostProcessor, | |
| PreTokenizer_default as PreTokenizer, | |
| Precompiled_default as PrecompiledNormalizer, | |
| Prepend_default as PrependNormalizer, | |
| Punctuation_default as PunctuationPreTokenizer, | |
| Replace_default3 as ReplaceDecoder, | |
| Replace_default as ReplaceNormalizer, | |
| Replace_default2 as ReplacePreTokenizer, | |
| RobertaProcessing_default as RobertaProcessingPostProcessor, | |
| Sequence_default4 as SequenceDecoder, | |
| Sequence_default as SequenceNormalizer, | |
| Sequence_default3 as SequencePostProcessor, | |
| Sequence_default2 as SequencePreTokenizer, | |
| Split_default as SplitPreTokenizer, | |
| StripAccents_default as StripAccentsNormalizer, | |
| Strip_default2 as StripDecoder, | |
| Strip_default as StripNormalizer, | |
| TemplateProcessing_default as TemplateProcessingPostProcessor, | |
| Tokenizer_default as Tokenizer, | |
| Unigram_default as Unigram, | |
| Whitespace_default as WhitespacePreTokenizer, | |
| WhitespaceSplit_default as WhitespaceSplitPreTokenizer, | |
| WordPiece_default as WordPiece, | |
| WordPiece_default2 as WordPieceDecoder | |
| }; | |