gpt-tokenizer 1.0.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/LICENSE +23 -0
- package/README.md +194 -0
- package/cjs/encoder.d.ts +16 -0
- package/cjs/encoder.js +201 -0
- package/cjs/encoder.js.map +1 -0
- package/cjs/encoder.test.d.ts +1 -0
- package/cjs/encoder.test.js +86 -0
- package/cjs/encoder.test.js.map +1 -0
- package/cjs/getBpe.d.ts +1 -0
- package/cjs/getBpe.js +17 -0
- package/cjs/getBpe.js.map +1 -0
- package/cjs/main.d.ts +1 -0
- package/cjs/main.js +18 -0
- package/cjs/main.js.map +1 -0
- package/cjs/utils.d.ts +6 -0
- package/cjs/utils.js +37 -0
- package/cjs/utils.js.map +1 -0
- package/esm/encoder.d.ts +16 -0
- package/esm/encoder.js +188 -0
- package/esm/encoder.js.map +1 -0
- package/esm/encoder.test.d.ts +1 -0
- package/esm/encoder.test.js +84 -0
- package/esm/encoder.test.js.map +1 -0
- package/esm/getBpe.d.ts +1 -0
- package/esm/getBpe.js +12 -0
- package/esm/getBpe.js.map +1 -0
- package/esm/main.d.ts +1 -0
- package/esm/main.js +2 -0
- package/esm/main.js.map +1 -0
- package/esm/utils.d.ts +6 -0
- package/esm/utils.js +28 -0
- package/esm/utils.js.map +1 -0
- package/package.json +116 -0
- package/src/encoder.test.ts +102 -0
- package/src/encoder.ts +252 -0
- package/src/getBpe.ts +23 -0
- package/src/main.ts +1 -0
- package/src/utils.ts +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 AIDungeon
|
|
4
|
+
Copyright (c) 2023 syonfox
|
|
5
|
+
Copyright (c) 2023 Bazyli Brzoska
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# `gpt-tokenizer`
|
|
2
|
+
|
|
3
|
+
`gpt-tokenizer` is a highly optimized Token Byte Pair Encoder/Decoder for GPT-2, GPT-3, GPT-3.5 and GPT-4 designed for JavaScript applications. OpenAI's GPT models utilize byte pair encoding to transform text into a sequence of integers before feeding them into the model. This package is a JavaScript implementation of OpenAI's original Python encoder/decoder, which can be found [here](https://github.com/openai/gpt-2).
|
|
4
|
+
|
|
5
|
+
This package is a fork of [latitudegames/GPT-3-Encoder](https://github.com/latitudegames/GPT-3-Encoder), improving on various aspects, such as:
|
|
6
|
+
|
|
7
|
+
- Adding generator versions of both decoder and encoder
|
|
8
|
+
- Providing the ability to decode an asynchronous stream of data (using `decodeAsyncGenerator` and `decodeGenerator` with any iterable input)
|
|
9
|
+
- Removing the global cache to prevent memory leaks
|
|
10
|
+
- Adding a highly performant `isWithinTokenLimit` function to assess token limit without encoding the entire text
|
|
11
|
+
- Improving overall performance by eliminating transitive arrays
|
|
12
|
+
- Including precomputed `bpeRanks`
|
|
13
|
+
- Adding type-checking
|
|
14
|
+
- Fixing minor bugs (thanks to TypeScript)
|
|
15
|
+
- Works in the browser out-of-the-box
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
As NPM package:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install gpt-tokenizer
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
As an UMD module:
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<script src="https://unpkg.com/gpt-tokenizer" />
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import {
|
|
35
|
+
encode,
|
|
36
|
+
decode,
|
|
37
|
+
isWithinTokenLimit,
|
|
38
|
+
encodeGenerator,
|
|
39
|
+
decodeGenerator,
|
|
40
|
+
decodeAsyncGenerator,
|
|
41
|
+
} from 'gpt-tokenizer'
|
|
42
|
+
|
|
43
|
+
const text = 'Hello, world!'
|
|
44
|
+
const tokenLimit = 10
|
|
45
|
+
|
|
46
|
+
// Encode text into tokens
|
|
47
|
+
const tokens = encode(text)
|
|
48
|
+
|
|
49
|
+
// Decode tokens back into text
|
|
50
|
+
const decodedText = decode(tokens)
|
|
51
|
+
|
|
52
|
+
// Check if text is within the token limit
|
|
53
|
+
// returns false if the limit is exceeded, otherwise returns the actual number of tokens (truthy value)
|
|
54
|
+
const withinTokenLimit = isWithinTokenLimit(text, tokenLimit)
|
|
55
|
+
|
|
56
|
+
// Encode text using generator
|
|
57
|
+
for (const tokenChunk of encodeGenerator(text)) {
|
|
58
|
+
console.log(tokenChunk)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Decode tokens using generator
|
|
62
|
+
for (const textChunk of decodeGenerator(tokens)) {
|
|
63
|
+
console.log(textChunk)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Decode tokens using async generator
|
|
67
|
+
// (assuming `asyncTokens` is an AsyncIterableIterator<number>)
|
|
68
|
+
for await (const textChunk of decodeAsyncGenerator(asyncTokens)) {
|
|
69
|
+
console.log(textChunk)
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Caching Between Runs of Encode-related Functions
|
|
74
|
+
|
|
75
|
+
You may want to encode multiple pieces of text with similar content or structure. In such cases, using a single cache between runs of encode-related functions can help improve performance. By sharing the cache, you can reuse the results of previously calculated byte pair encodings, thereby reducing redundant computations.
|
|
76
|
+
|
|
77
|
+
However, it's important to be aware of potential memory consumption issues when using a shared cache when encoding lots of higher range unicode characters (non-latin/complex alphabets, emojis), potentially leading to performance degradation or even crashes due to excessive memory usage.
|
|
78
|
+
|
|
79
|
+
In such a case, it is recommended to use a custom `Map` implementation that uses a LRU cache to limit the size of the cache.
|
|
80
|
+
|
|
81
|
+
Here's an example of how to use a shared cache between runs of the `encode` function:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { encode } from 'gpt-tokenizer'
|
|
85
|
+
|
|
86
|
+
const cache = new Map()
|
|
87
|
+
|
|
88
|
+
const text1 = 'Hello, world!'
|
|
89
|
+
const text2 = 'Hello, everyone!'
|
|
90
|
+
|
|
91
|
+
const tokens1 = encode(text1, cache)
|
|
92
|
+
const tokens2 = encode(text2, cache)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## API
|
|
96
|
+
|
|
97
|
+
### `encode(text: string, cache?: Map<string, string>): number[]`
|
|
98
|
+
|
|
99
|
+
Encodes the given text into a sequence of tokens. Use this method when you need to transform a piece of text into the token format that GPT-2 or GPT-3 models can process. You can provide an optional cache to store and reuse byte pair encoding results between multiple calls.
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { encode } from 'gpt-tokenizer'
|
|
105
|
+
|
|
106
|
+
const text = 'Hello, world!'
|
|
107
|
+
const tokens = encode(text)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `decode(tokens: number[]): string`
|
|
111
|
+
|
|
112
|
+
Decodes a sequence of tokens back into text. Use this method when you want to convert the output tokens from GPT-2 or GPT-3 models back into human-readable text.
|
|
113
|
+
|
|
114
|
+
Example:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { decode } from 'gpt-tokenizer'
|
|
118
|
+
|
|
119
|
+
const tokens = [18435, 198, 23132, 328]
|
|
120
|
+
const text = decode(tokens)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `isWithinTokenLimit(text: string, tokenLimit: number, cache?: Map<string, string>): false | number`
|
|
124
|
+
|
|
125
|
+
Checks if the text is within the token limit. Returns `false` if the limit is exceeded, otherwise returns the number of tokens. Use this method to quickly check if a given text is within the token limit imposed by GPT-2 or GPT-3 models, without encoding the entire text.
|
|
126
|
+
|
|
127
|
+
Example:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { isWithinTokenLimit } from 'gpt-tokenizer'
|
|
131
|
+
|
|
132
|
+
const text = 'Hello, world!'
|
|
133
|
+
const tokenLimit = 10
|
|
134
|
+
const withinTokenLimit = isWithinTokenLimit(text, tokenLimit)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `encodeGenerator(text: string, cache?: Map<string, string>): Generator<number[], void, undefined>`
|
|
138
|
+
|
|
139
|
+
Encodes the given text using a generator, yielding chunks of tokens.
|
|
140
|
+
Use this method when you want to encode text in chunks, which can be useful for processing large texts or streaming data.
|
|
141
|
+
|
|
142
|
+
Example:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { encodeGenerator } from 'gpt-tokenizer'
|
|
146
|
+
|
|
147
|
+
const text = 'Hello, world!'
|
|
148
|
+
const tokens = []
|
|
149
|
+
for (const tokenChunk of encodeGenerator(text)) {
|
|
150
|
+
tokens.push(...tokenChunk)
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `decodeGenerator(tokens: Iterable<number>): Generator<string, void, undefined>`
|
|
155
|
+
|
|
156
|
+
Decodes a sequence of tokens using a generator, yielding chunks of decoded text.
|
|
157
|
+
Use this method when you want to decode tokens in chunks, which can be useful for processing large outputs or streaming data.
|
|
158
|
+
|
|
159
|
+
Example:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { decodeGenerator } from 'gpt-tokenizer'
|
|
163
|
+
|
|
164
|
+
const tokens = [18435, 198, 23132, 328]
|
|
165
|
+
let decodedText = ''
|
|
166
|
+
for (const textChunk of decodeGenerator(tokens)) {
|
|
167
|
+
decodedText += textChunk
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### `decodeAsyncGenerator(tokens: AsyncIterable<number>): AsyncGenerator<string, void, undefined>`
|
|
172
|
+
|
|
173
|
+
Decodes a sequence of tokens asynchronously using a generator, yielding chunks of decoded text. Use this method when you want to decode tokens in chunks asynchronously, which can be useful for processing large outputs or streaming data in an asynchronous context.
|
|
174
|
+
|
|
175
|
+
Example:
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
import { decodeAsyncGenerator } from 'gpt-tokenizer'
|
|
179
|
+
|
|
180
|
+
async function processTokens(asyncTokensIterator) {
|
|
181
|
+
let decodedText = ''
|
|
182
|
+
for await (const textChunk of decodeAsyncGenerator(asyncTokensIterator)) {
|
|
183
|
+
decodedText += textChunk
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
MIT
|
|
191
|
+
|
|
192
|
+
## Contributing
|
|
193
|
+
|
|
194
|
+
Contributions are welcome! Please open a pull request or an issue to discuss your ideas, bug reports, or any other inquiries.
|
package/cjs/encoder.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @returns {false | number} false if token limit is exceeded, otherwise the number of tokens
|
|
3
|
+
*/
|
|
4
|
+
export declare function isWithinTokenLimit(text: string, tokenLimit: number, cache?: Map<string, string>): false | number;
|
|
5
|
+
export declare function encode(text: string, cache?: Map<string, string>): number[];
|
|
6
|
+
export declare function decodeToken(token: number): string;
|
|
7
|
+
export declare function endsWithIncompleteUtfPairSurrogate(string: string): boolean;
|
|
8
|
+
export declare function decodeGenerator(tokens: Iterable<number>): Generator<string, void, undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* Decode tokens asynchronously and yield the decoded strings, one by one.
|
|
11
|
+
* Will not yield for tokens that include a high surrogate, but wait for the next token.
|
|
12
|
+
* @param {AsyncIterable<number>} tokens
|
|
13
|
+
* @returns {AsyncGenerator<string, void, undefined>}
|
|
14
|
+
*/
|
|
15
|
+
export declare function decodeAsyncGenerator(tokens: AsyncIterable<number>): AsyncGenerator<string, void, undefined>;
|
|
16
|
+
export declare function decode(tokens: number[]): string;
|
package/cjs/encoder.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable unicorn/prefer-spread */
|
|
3
|
+
/* eslint-disable unicorn/prefer-code-point */
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.decode = exports.decodeAsyncGenerator = exports.decodeGenerator = exports.endsWithIncompleteUtfPairSurrogate = exports.decodeToken = exports.encode = exports.isWithinTokenLimit = void 0;
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const bpeRanks_json_1 = __importDefault(require("../data/bpeRanks.json"));
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
const encoder_json_1 = __importDefault(require("../data/encoder.json"));
|
|
15
|
+
const utils_1 = require("./utils");
|
|
16
|
+
const encoder = encoder_json_1.default;
|
|
17
|
+
const bpeRanks = bpeRanks_json_1.default;
|
|
18
|
+
const decoder = (0, utils_1.dictZip)(Object.values(encoder), Object.keys(encoder));
|
|
19
|
+
const textEncoder = new TextEncoder();
|
|
20
|
+
const textDecoder = new TextDecoder();
|
|
21
|
+
// eslint-disable-next-line no-magic-numbers
|
|
22
|
+
const UPPER_BYTE_VALUE = 2 ** 8;
|
|
23
|
+
function createByteToUnicodeMap() {
|
|
24
|
+
const asciiRange = (0, utils_1.range)((0, utils_1.getCharCode)('!'), (0, utils_1.getCharCode)('~') + 1);
|
|
25
|
+
const latin1Range1 = (0, utils_1.range)((0, utils_1.getCharCode)('¡'), (0, utils_1.getCharCode)('¬') + 1);
|
|
26
|
+
const latin1Range2 = (0, utils_1.range)((0, utils_1.getCharCode)('®'), (0, utils_1.getCharCode)('ÿ') + 1);
|
|
27
|
+
const initialCodePoints = [...asciiRange, ...latin1Range1, ...latin1Range2];
|
|
28
|
+
const mappedCodePoints = [...initialCodePoints];
|
|
29
|
+
let newCodePointOffset = 0;
|
|
30
|
+
for (let byteValue = 0; byteValue < UPPER_BYTE_VALUE; byteValue++) {
|
|
31
|
+
if (!initialCodePoints.includes(byteValue)) {
|
|
32
|
+
initialCodePoints.push(byteValue);
|
|
33
|
+
mappedCodePoints.push(UPPER_BYTE_VALUE + newCodePointOffset);
|
|
34
|
+
newCodePointOffset += 1;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const unicodeChars = mappedCodePoints.map(utils_1.getCharFromCode);
|
|
38
|
+
return new Map(initialCodePoints.map((x, i) => [x, unicodeChars[i]]));
|
|
39
|
+
}
|
|
40
|
+
const pat = /'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+/gu;
|
|
41
|
+
const byteEncoder = createByteToUnicodeMap();
|
|
42
|
+
const byteDecoder = new Map([...byteEncoder].map(([k, v]) => [v, k]));
|
|
43
|
+
function bpe(token, cache = new Map()) {
|
|
44
|
+
if (cache.has(token)) {
|
|
45
|
+
return cache.get(token);
|
|
46
|
+
}
|
|
47
|
+
let word = (0, utils_1.splitToken)(token);
|
|
48
|
+
let pairs = (0, utils_1.getPairs)(word);
|
|
49
|
+
if (pairs.length === 0) {
|
|
50
|
+
return token;
|
|
51
|
+
}
|
|
52
|
+
// eslint-disable-next-line no-constant-condition
|
|
53
|
+
while (true) {
|
|
54
|
+
const minPairs = new Map();
|
|
55
|
+
pairs.forEach((pair) => {
|
|
56
|
+
const rank = bpeRanks[pair.join(',')];
|
|
57
|
+
minPairs.set(
|
|
58
|
+
// eslint-disable-next-line no-magic-numbers
|
|
59
|
+
typeof rank === 'undefined' || Number.isNaN(rank) ? 10e10 : rank, pair);
|
|
60
|
+
});
|
|
61
|
+
const keys = [...minPairs.keys()];
|
|
62
|
+
const bigram = minPairs.get(Math.min(...keys));
|
|
63
|
+
if (!bigram || !(bigram.join(',') in bpeRanks)) {
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
const [first, second] = bigram;
|
|
67
|
+
let newWord = [];
|
|
68
|
+
let i = 0;
|
|
69
|
+
while (i < word.length) {
|
|
70
|
+
const j = word.indexOf(first, i);
|
|
71
|
+
if (j === -1) {
|
|
72
|
+
newWord = newWord.concat(word.slice(i));
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
newWord = newWord.concat(word.slice(i, j));
|
|
76
|
+
i = j;
|
|
77
|
+
if (word[i] === first && i < word.length - 1 && word[i + 1] === second) {
|
|
78
|
+
newWord.push(first + second);
|
|
79
|
+
i += 2;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
newWord.push(word[i]);
|
|
83
|
+
i += 1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
word = newWord;
|
|
87
|
+
if (word.length === 1) {
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
pairs = (0, utils_1.getPairs)(word);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const result = word.join(' ');
|
|
95
|
+
cache.set(token, result);
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
function* encodeGenerator(text, cache = new Map()) {
|
|
99
|
+
for (let [token] of text.matchAll(pat)) {
|
|
100
|
+
token = [...textEncoder.encode(token)]
|
|
101
|
+
.map((x) => byteEncoder.get(x) ?? '')
|
|
102
|
+
.join('');
|
|
103
|
+
const newTokens = bpe(token, cache)
|
|
104
|
+
.split(' ')
|
|
105
|
+
.map((x) => encoder[x]);
|
|
106
|
+
yield newTokens;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* @returns {false | number} false if token limit is exceeded, otherwise the number of tokens
|
|
111
|
+
*/
|
|
112
|
+
function isWithinTokenLimit(text, tokenLimit, cache = new Map()) {
|
|
113
|
+
const tokenGenerator = encodeGenerator(text, cache);
|
|
114
|
+
let count = 0;
|
|
115
|
+
for (const tokens of tokenGenerator) {
|
|
116
|
+
count += tokens.length;
|
|
117
|
+
if (count > tokenLimit) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return count;
|
|
122
|
+
}
|
|
123
|
+
exports.isWithinTokenLimit = isWithinTokenLimit;
|
|
124
|
+
function encode(text, cache = new Map()) {
|
|
125
|
+
return [...encodeGenerator(text, cache)].flat(1);
|
|
126
|
+
}
|
|
127
|
+
exports.encode = encode;
|
|
128
|
+
function decodeToken(token) {
|
|
129
|
+
const decodedToken = decoder[token];
|
|
130
|
+
if (typeof decodedToken === 'undefined') {
|
|
131
|
+
return '';
|
|
132
|
+
}
|
|
133
|
+
const decodedBytes = (0, utils_1.splitToken)(decodedToken).map((x) => byteDecoder.get(x));
|
|
134
|
+
return textDecoder.decode(new Uint8Array(decodedBytes), {
|
|
135
|
+
stream: true,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
exports.decodeToken = decodeToken;
|
|
139
|
+
const HIGH_SURROGATE_START = 55296;
|
|
140
|
+
const HIGH_SURROGATE_END = 56319;
|
|
141
|
+
function endsWithIncompleteUtfPairSurrogate(string) {
|
|
142
|
+
if (string.length === 0)
|
|
143
|
+
return false;
|
|
144
|
+
// Check if the last character is a high surrogate
|
|
145
|
+
const lastCharCode = string.charCodeAt(string.length - 1);
|
|
146
|
+
return (lastCharCode >= HIGH_SURROGATE_START && lastCharCode <= HIGH_SURROGATE_END);
|
|
147
|
+
}
|
|
148
|
+
exports.endsWithIncompleteUtfPairSurrogate = endsWithIncompleteUtfPairSurrogate;
|
|
149
|
+
function* decodeGenerator(tokens) {
|
|
150
|
+
let buffer = '';
|
|
151
|
+
for (const token of tokens) {
|
|
152
|
+
buffer += decodeToken(token);
|
|
153
|
+
if (buffer.length === 0 || endsWithIncompleteUtfPairSurrogate(buffer)) {
|
|
154
|
+
// Keep the high surrogate in the buffer and continue with the next token
|
|
155
|
+
// eslint-disable-next-line no-continue
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
yield buffer;
|
|
160
|
+
// reset buffer
|
|
161
|
+
buffer = '';
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Yield any remaining characters in the buffer
|
|
165
|
+
if (buffer.length > 0) {
|
|
166
|
+
yield buffer;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.decodeGenerator = decodeGenerator;
|
|
170
|
+
/**
|
|
171
|
+
* Decode tokens asynchronously and yield the decoded strings, one by one.
|
|
172
|
+
* Will not yield for tokens that include a high surrogate, but wait for the next token.
|
|
173
|
+
* @param {AsyncIterable<number>} tokens
|
|
174
|
+
* @returns {AsyncGenerator<string, void, undefined>}
|
|
175
|
+
*/
|
|
176
|
+
async function* decodeAsyncGenerator(tokens) {
|
|
177
|
+
let buffer = '';
|
|
178
|
+
for await (const token of tokens) {
|
|
179
|
+
buffer += decodeToken(token);
|
|
180
|
+
if (buffer.length === 0 || endsWithIncompleteUtfPairSurrogate(buffer)) {
|
|
181
|
+
// Keep the high surrogate in the buffer and continue with the next token
|
|
182
|
+
// eslint-disable-next-line no-continue
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
yield buffer;
|
|
187
|
+
// reset buffer
|
|
188
|
+
buffer = '';
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Yield any remaining characters in the buffer
|
|
192
|
+
if (buffer.length > 0) {
|
|
193
|
+
yield buffer;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.decodeAsyncGenerator = decodeAsyncGenerator;
|
|
197
|
+
function decode(tokens) {
|
|
198
|
+
return [...decodeGenerator(tokens)].join('');
|
|
199
|
+
}
|
|
200
|
+
exports.decode = decode;
|
|
201
|
+
//# sourceMappingURL=encoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoder.js","sourceRoot":"","sources":["../src/encoder.ts"],"names":[],"mappings":";AAAA,0CAA0C;AAC1C,8CAA8C;;;;;;AAE9C,wGAAwG;AACxG,aAAa;AACb,0EAAgD;AAChD,wGAAwG;AACxG,aAAa;AACb,wEAA8C;AAC9C,mCAOgB;AAEhB,MAAM,OAAO,GAA2B,sBAAW,CAAA;AACnD,MAAM,QAAQ,GAA2B,uBAAY,CAAA;AAErD,MAAM,OAAO,GAA2B,IAAA,eAAO,EAC7C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EACtB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CACrB,CAAA;AAED,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAA;AACrC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAA;AAErC,4CAA4C;AAC5C,MAAM,gBAAgB,GAAG,CAAC,IAAI,CAAC,CAAA;AAE/B,SAAS,sBAAsB;IAC7B,MAAM,UAAU,GAAG,IAAA,aAAK,EAAC,IAAA,mBAAW,EAAC,GAAG,CAAC,EAAE,IAAA,mBAAW,EAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAChE,MAAM,YAAY,GAAG,IAAA,aAAK,EAAC,IAAA,mBAAW,EAAC,GAAG,CAAC,EAAE,IAAA,mBAAW,EAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAClE,MAAM,YAAY,GAAG,IAAA,aAAK,EAAC,IAAA,mBAAW,EAAC,GAAG,CAAC,EAAE,IAAA,mBAAW,EAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAElE,MAAM,iBAAiB,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,YAAY,EAAE,GAAG,YAAY,CAAC,CAAA;IAC3E,MAAM,gBAAgB,GAAG,CAAC,GAAG,iBAAiB,CAAC,CAAA;IAE/C,IAAI,kBAAkB,GAAG,CAAC,CAAA;IAC1B,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,gBAAgB,EAAE,SAAS,EAAE,EAAE;QACjE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;YAC1C,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACjC,gBAAgB,CAAC,IAAI,CAAC,gBAAgB,GAAG,kBAAkB,CAAC,CAAA;YAC5D,kBAAkB,IAAI,CAAC,CAAA;SACxB;KACF;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CAAC,uBAAe,CAAC,CAAA;IAC1D,OAAO,IAAI,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAA;AACxE,CAAC;AAED,MAAM,GAAG,GACP,8EAA8E,CAAA;AAEhF,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAA;AAC5C,MAAM,WAAW,GAAwB,IAAI,GAAG,CAC9C,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CACzC,CAAA;AAED,SAAS,GAAG,CAAC,KAAa,EAAE,QAA6B,IAAI,GAAG,EAAE;IAChE,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QACpB,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,CAAE,CAAA;KACzB;IAED,IAAI,IAAI,GAAG,IAAA,kBAAU,EAAC,KAAK,CAAC,CAAA;IAC5B,IAAI,KAAK,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAA;IAE1B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QACtB,OAAO,KAAK,CAAA;KACb;IAED,iDAAiD;IACjD,OAAO,IAAI,EAAE;QACX,MAAM,QAAQ,GAAkC,IAAI,GAAG,EAAE,CAAA;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;YACrC,QAAQ,CAAC,GAAG;YACV,4CAA4C;YAC5C,OAAO,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAChE,IAAI,CACL,CAAA;QACH,CAAC,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;QAEjC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QAE9C,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,EAAE;YAC9C,MAAK;SACN;QAED,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,MAAM,CAAA;QAC9B,IAAI,OAAO,GAAa,EAAE,CAAA;QAC1B,IAAI,CAAC,GAAG,CAAC,CAAA;QAET,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE;YACtB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YAChC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE;gBACZ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;gBACvC,MAAK;aACN;YACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YAC1C,CAAC,GAAG,CAAC,CAAA;YAEL,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE;gBACtE,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,CAAA;gBAC5B,CAAC,IAAI,CAAC,CAAA;aACP;iBAAM;gBACL,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAA;gBACtB,CAAC,IAAI,CAAC,CAAA;aACP;SACF;QAED,IAAI,GAAG,OAAO,CAAA;QACd,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;YACrB,MAAK;SACN;aAAM;YACL,KAAK,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAA;SACvB;KACF;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC7B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAExB,OAAO,MAAM,CAAA;AACf,CAAC;AAED,QAAQ,CAAC,CAAC,eAAe,CACvB,IAAY,EACZ,QAA6B,IAAI,GAAG,EAAE;IAEtC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;QACtC,KAAK,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;aACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpC,IAAI,CAAC,EAAE,CAAC,CAAA;QAEX,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;aAChC,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAA;QAE1B,MAAM,SAAS,CAAA;KAChB;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAChC,IAAY,EACZ,UAAkB,EAClB,QAA6B,IAAI,GAAG,EAAE;IAEtC,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACnD,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE;QACnC,KAAK,IAAI,MAAM,CAAC,MAAM,CAAA;QACtB,IAAI,KAAK,GAAG,UAAU,EAAE;YACtB,OAAO,KAAK,CAAA;SACb;KACF;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAdD,gDAcC;AAED,SAAgB,MAAM,CACpB,IAAY,EACZ,QAA6B,IAAI,GAAG,EAAE;IAEtC,OAAO,CAAC,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAClD,CAAC;AALD,wBAKC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IACnC,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE;QACvC,OAAO,EAAE,CAAA;KACV;IACD,MAAM,YAAY,GAAG,IAAA,kBAAU,EAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAA;IAC7E,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE;QACtD,MAAM,EAAE,IAAI;KACb,CAAC,CAAA;AACJ,CAAC;AATD,kCASC;AAED,MAAM,oBAAoB,GAAG,KAAM,CAAA;AACnC,MAAM,kBAAkB,GAAG,KAAM,CAAA;AACjC,SAAgB,kCAAkC,CAAC,MAAc;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrC,kDAAkD;IAClD,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACzD,OAAO,CACL,YAAY,IAAI,oBAAoB,IAAI,YAAY,IAAI,kBAAkB,CAC3E,CAAA;AACH,CAAC;AAPD,gFAOC;AAED,QAAe,CAAC,CAAC,eAAe,CAC9B,MAAwB;IAExB,IAAI,MAAM,GAAG,EAAE,CAAA;IAEf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;QAC1B,MAAM,IAAI,WAAW,CAAC,KAAK,CAAC,CAAA;QAE5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,kCAAkC,CAAC,MAAM,CAAC,EAAE;YACrE,yEAAyE;YACzE,uCAAuC;YACvC,SAAQ;SACT;aAAM;YACL,MAAM,MAAM,CAAA;YACZ,eAAe;YACf,MAAM,GAAG,EAAE,CAAA;SACZ;KACF;IAED,+CAA+C;IAC/C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;QACrB,MAAM,MAAM,CAAA;KACb;AACH,CAAC;AAvBD,0CAuBC;AAED;;;;;GAKG;AACI,KAAK,SAAS,CAAC,CAAC,oBAAoB,CACzC,MAA6B;IAE7B,IAAI,MAAM,GAAG,EAAE,CAAA;IAEf,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE;QAChC,MAAM,IAAI,WAAW,CAAC,KAAK,CAAC,CAAA;QAE5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,kCAAkC,CAAC,MAAM,CAAC,EAAE;YACrE,yEAAyE;YACzE,uCAAuC;YACvC,SAAQ;SACT;aAAM;YACL,MAAM,MAAM,CAAA;YACZ,eAAe;YACf,MAAM,GAAG,EAAE,CAAA;SACZ;KACF;IAED,+CAA+C;IAC/C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;QACrB,MAAM,MAAM,CAAA;KACb;AACH,CAAC;AAvBD,oDAuBC;AAED,SAAgB,MAAM,CAAC,MAAgB;IACrC,OAAO,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC9C,CAAC;AAFD,wBAEC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/* eslint-disable compat/compat */
|
|
4
|
+
const encoder_1 = require("./encoder");
|
|
5
|
+
describe('basic functionality', () => {
|
|
6
|
+
it('empty string', () => {
|
|
7
|
+
const str = '';
|
|
8
|
+
expect((0, encoder_1.encode)(str)).toEqual([]);
|
|
9
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
10
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 0)).toBe(0);
|
|
11
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 3)).toBe(0);
|
|
12
|
+
});
|
|
13
|
+
it('space', () => {
|
|
14
|
+
const str = ' ';
|
|
15
|
+
expect((0, encoder_1.encode)(str)).toEqual([220]);
|
|
16
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
17
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 3)).toBe(1);
|
|
18
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 0)).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it('tab', () => {
|
|
21
|
+
const str = '\t';
|
|
22
|
+
expect((0, encoder_1.encode)(str)).toEqual([197]);
|
|
23
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
24
|
+
});
|
|
25
|
+
it('simple text', () => {
|
|
26
|
+
const str = 'This is some text';
|
|
27
|
+
expect((0, encoder_1.encode)(str)).toEqual([1212, 318, 617, 2420]);
|
|
28
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
29
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 3)).toBe(false);
|
|
30
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 5)).toBe(4);
|
|
31
|
+
});
|
|
32
|
+
it('multi-token word', () => {
|
|
33
|
+
const str = 'indivisible';
|
|
34
|
+
expect((0, encoder_1.encode)(str)).toEqual([521, 452, 12843]);
|
|
35
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
36
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 3)).toBe(3);
|
|
37
|
+
});
|
|
38
|
+
const helloWorldTokens = [31373, 50169, 233, 995, 12520, 234, 235];
|
|
39
|
+
it('emojis', () => {
|
|
40
|
+
const str = 'hello 👋 world 🌍';
|
|
41
|
+
expect((0, encoder_1.encode)(str)).toEqual(helloWorldTokens);
|
|
42
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
43
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 4)).toBe(false);
|
|
44
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 400)).toBe(7);
|
|
45
|
+
});
|
|
46
|
+
it('decode token-by-token via generator', () => {
|
|
47
|
+
const generator = (0, encoder_1.decodeGenerator)(helloWorldTokens);
|
|
48
|
+
expect(generator.next().value).toBe('hello');
|
|
49
|
+
expect(generator.next().value).toBe(' ');
|
|
50
|
+
expect(generator.next().value).toBe('👋');
|
|
51
|
+
expect(generator.next().value).toBe(' world');
|
|
52
|
+
expect(generator.next().value).toBe(' ');
|
|
53
|
+
expect(generator.next().value).toBe('🌍');
|
|
54
|
+
});
|
|
55
|
+
async function* getHelloWorldTokensAsync() {
|
|
56
|
+
for (const token of helloWorldTokens) {
|
|
57
|
+
// eslint-disable-next-line no-await-in-loop
|
|
58
|
+
yield await Promise.resolve(token);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
it('decode token-by-token via async generator', async () => {
|
|
62
|
+
const generator = (0, encoder_1.decodeAsyncGenerator)(getHelloWorldTokensAsync());
|
|
63
|
+
const decoded = ['hello', ' ', '👋', ' world', ' ', '🌍'];
|
|
64
|
+
for await (const value of generator) {
|
|
65
|
+
expect(value).toEqual(decoded.shift());
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
it('properties of Object', () => {
|
|
69
|
+
const str = 'toString constructor hasOwnProperty valueOf';
|
|
70
|
+
expect((0, encoder_1.encode)(str)).toEqual([
|
|
71
|
+
1462, 10100, 23772, 468, 23858, 21746, 1988, 5189,
|
|
72
|
+
]);
|
|
73
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
74
|
+
});
|
|
75
|
+
it('text with commas', () => {
|
|
76
|
+
const str = 'hello, I am a text, and I have commas. a,b,c';
|
|
77
|
+
expect((0, encoder_1.decode)((0, encoder_1.encode)(str))).toEqual(str);
|
|
78
|
+
expect((0, encoder_1.encode)(str)).toStrictEqual([
|
|
79
|
+
31373, 11, 314, 716, 257, 2420, 11, 290, 314, 423, 725, 292, 13, 257,
|
|
80
|
+
11, 65, 11, 66,
|
|
81
|
+
]);
|
|
82
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 15)).toBe(false);
|
|
83
|
+
expect((0, encoder_1.isWithinTokenLimit)(str, 300)).toBe(18);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=encoder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoder.test.js","sourceRoot":"","sources":["../src/encoder.test.ts"],"names":[],"mappings":"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"}
|
package/cjs/getBpe.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/cjs/getBpe.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
const bpeFile = fs_1.default.readFileSync(path_1.default.join(__dirname, '../data/vocab.bpe'), 'utf8');
|
|
10
|
+
const lines = bpeFile.split('\n');
|
|
11
|
+
const bpeMerges = lines.slice(1, -1).map((x) => x
|
|
12
|
+
.split(/(\s+)/)
|
|
13
|
+
.filter((e) => e.trim().length > 0)
|
|
14
|
+
.join(','));
|
|
15
|
+
const bpeRanks = (0, utils_1.dictZip)(bpeMerges, (0, utils_1.range)(0, bpeMerges.length));
|
|
16
|
+
fs_1.default.writeFileSync(path_1.default.join(__dirname, '../data/bpeRanks.json'), JSON.stringify(bpeRanks));
|
|
17
|
+
//# sourceMappingURL=getBpe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getBpe.js","sourceRoot":"","sources":["../src/getBpe.ts"],"names":[],"mappings":";;;;;AAAA,4CAAmB;AACnB,gDAAuB;AACvB,mCAAwC;AAExC,MAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAC7B,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,EACzC,MAAM,CACP,CAAA;AACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AAEjC,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7C,CAAC;KACE,KAAK,CAAC,OAAO,CAAC;KACd,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;KAClC,IAAI,CAAC,GAAG,CAAC,CACb,CAAA;AAED,MAAM,QAAQ,GAAG,IAAA,eAAO,EAAC,SAAS,EAAE,IAAA,aAAK,EAAC,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;AAE/D,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC,EAC7C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CACzB,CAAA"}
|
package/cjs/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './encoder';
|
package/cjs/main.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./encoder"), exports);
|
|
18
|
+
//# sourceMappingURL=main.js.map
|
package/cjs/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB"}
|
package/cjs/utils.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function dictZip<T extends PropertyKey, U>(x: T[], y: U[]): Record<T, U>;
|
|
2
|
+
export declare function range(x: number, y: number): number[];
|
|
3
|
+
export declare const getCharCode: (x: string) => number;
|
|
4
|
+
export declare const getCharFromCode: (x: number) => string;
|
|
5
|
+
export declare function getPairs(word: string[]): [string, string][];
|
|
6
|
+
export declare const splitToken: (token: string) => string[];
|
package/cjs/utils.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable unicorn/prefer-spread */
|
|
3
|
+
/* eslint-disable unicorn/prefer-code-point */
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.splitToken = exports.getPairs = exports.getCharFromCode = exports.getCharCode = exports.range = exports.dictZip = void 0;
|
|
6
|
+
function dictZip(x, y) {
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
8
|
+
const result = {};
|
|
9
|
+
x.forEach((k, i) => {
|
|
10
|
+
result[k] = y[i];
|
|
11
|
+
});
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
exports.dictZip = dictZip;
|
|
15
|
+
function range(x, y) {
|
|
16
|
+
return Array.from({ length: y - x }, (_, i) => x + i);
|
|
17
|
+
}
|
|
18
|
+
exports.range = range;
|
|
19
|
+
const getCharCode = (x) => x.charCodeAt(0);
|
|
20
|
+
exports.getCharCode = getCharCode;
|
|
21
|
+
const getCharFromCode = (x) => String.fromCharCode(x);
|
|
22
|
+
exports.getCharFromCode = getCharFromCode;
|
|
23
|
+
function getPairs(word) {
|
|
24
|
+
/** @type {[string, string][]} */
|
|
25
|
+
const pairs = [];
|
|
26
|
+
let prevChar = word[0];
|
|
27
|
+
for (let i = 1; i < word.length; i++) {
|
|
28
|
+
const char = word[i];
|
|
29
|
+
pairs.push([prevChar, char]);
|
|
30
|
+
prevChar = char;
|
|
31
|
+
}
|
|
32
|
+
return pairs;
|
|
33
|
+
}
|
|
34
|
+
exports.getPairs = getPairs;
|
|
35
|
+
const splitToken = (token) => token.split('');
|
|
36
|
+
exports.splitToken = splitToken;
|
|
37
|
+
//# sourceMappingURL=utils.js.map
|
package/cjs/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAAA,0CAA0C;AAC1C,8CAA8C;;;AAE9C,SAAgB,OAAO,CACrB,CAAM,EACN,CAAM;IAEN,yEAAyE;IACzE,MAAM,MAAM,GAAG,EAAkB,CAAA;IACjC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACjB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAA;IACnB,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACf,CAAC;AAVD,0BAUC;AAED,SAAgB,KAAK,CAAC,CAAS,EAAE,CAAS;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;AACvD,CAAC;AAFD,sBAEC;AAEM,MAAM,WAAW,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;AAApD,QAAA,WAAW,eAAyC;AAE1D,MAAM,eAAe,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;AAA/D,QAAA,eAAe,mBAAgD;AAE5E,SAAgB,QAAQ,CAAC,IAAc;IACrC,iCAAiC;IACjC,MAAM,KAAK,GAAuB,EAAE,CAAA;IACpC,IAAI,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACpB,KAAK,CAAC,IAAI,CAAC,CAAC,QAAS,EAAE,IAAK,CAAC,CAAC,CAAA;QAC9B,QAAQ,GAAG,IAAI,CAAA;KAChB;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAVD,4BAUC;AAEM,MAAM,UAAU,GAAG,CAAC,KAAa,EAAY,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;AAAzD,QAAA,UAAU,cAA+C"}
|