gpt-tokenizer 4.0.0 → 4.0.2
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/cjs/BytePairEncodingCore.js +75 -31
- package/cjs/BytePairEncodingCore.js.map +1 -1
- package/cjs/GptEncoding.d.ts +2 -2
- package/cjs/encoding/cl100k_base.d.ts +1 -1
- package/cjs/encoding/o200k_base.d.ts +1 -1
- package/cjs/encoding/o200k_harmony.d.ts +1 -1
- package/cjs/encoding/p50k_edit.d.ts +1 -1
- package/cjs/encodingParams/constants.js +3 -3
- package/cjs/encodingParams/constants.js.map +1 -1
- package/cjs/model/chat-latest.d.ts +1 -1
- package/cjs/model/chatgpt-4o-latest.d.ts +1 -1
- package/cjs/model/codex-mini-latest.d.ts +1 -1
- package/cjs/model/computer-use-preview-2025-03-11.d.ts +1 -1
- package/cjs/model/computer-use-preview.d.ts +1 -1
- package/cjs/model/daybreak-blue-latest.d.ts +1 -1
- package/cjs/model/daybreak-red-latest.d.ts +1 -1
- package/cjs/model/gpt-3.5-0301.d.ts +1 -1
- package/cjs/model/gpt-3.5-turbo-0125.d.ts +1 -1
- package/cjs/model/gpt-3.5-turbo-0613.d.ts +1 -1
- package/cjs/model/gpt-3.5-turbo-1106.d.ts +1 -1
- package/cjs/model/gpt-3.5-turbo-16k-0613.d.ts +1 -1
- package/cjs/model/gpt-3.5-turbo-instruct.d.ts +1 -1
- package/cjs/model/gpt-3.5-turbo.d.ts +1 -1
- package/cjs/model/gpt-3.5.d.ts +1 -1
- package/cjs/model/gpt-4-0125-preview.d.ts +1 -1
- package/cjs/model/gpt-4-0314.d.ts +1 -1
- package/cjs/model/gpt-4-0613.d.ts +1 -1
- package/cjs/model/gpt-4-1106-preview.d.ts +1 -1
- package/cjs/model/gpt-4-1106-vision-preview.d.ts +1 -1
- package/cjs/model/gpt-4-32k.d.ts +1 -1
- package/cjs/model/gpt-4-turbo-2024-04-09.d.ts +1 -1
- package/cjs/model/gpt-4-turbo-preview.d.ts +1 -1
- package/cjs/model/gpt-4-turbo.d.ts +1 -1
- package/cjs/model/gpt-4.1-2025-04-14.d.ts +1 -1
- package/cjs/model/gpt-4.1-mini-2025-04-14.d.ts +1 -1
- package/cjs/model/gpt-4.1-mini.d.ts +1 -1
- package/cjs/model/gpt-4.1-nano-2025-04-14.d.ts +1 -1
- package/cjs/model/gpt-4.1-nano.d.ts +1 -1
- package/cjs/model/gpt-4.1.d.ts +1 -1
- package/cjs/model/gpt-4.5-preview-2025-02-27.d.ts +1 -1
- package/cjs/model/gpt-4.5-preview.d.ts +1 -1
- package/cjs/model/gpt-4.d.ts +1 -1
- package/cjs/model/gpt-4o-2024-05-13.d.ts +1 -1
- package/cjs/model/gpt-4o-2024-08-06.d.ts +1 -1
- package/cjs/model/gpt-4o-2024-11-20.d.ts +1 -1
- package/cjs/model/gpt-4o-audio-preview-2024-10-01.d.ts +1 -1
- package/cjs/model/gpt-4o-audio-preview-2024-12-17.d.ts +1 -1
- package/cjs/model/gpt-4o-audio-preview-2025-06-03.d.ts +1 -1
- package/cjs/model/gpt-4o-audio-preview.d.ts +1 -1
- package/cjs/model/gpt-4o-mini-2024-07-18.d.ts +1 -1
- package/cjs/model/gpt-4o-mini-audio-preview-2024-12-17.d.ts +1 -1
- package/cjs/model/gpt-4o-mini-audio-preview.d.ts +1 -1
- package/cjs/model/gpt-4o-mini-search-preview-2025-03-11.d.ts +1 -1
- package/cjs/model/gpt-4o-mini-search-preview.d.ts +1 -1
- package/cjs/model/gpt-4o-mini.d.ts +1 -1
- package/cjs/model/gpt-4o-search-preview-2025-03-11.d.ts +1 -1
- package/cjs/model/gpt-4o-search-preview.d.ts +1 -1
- package/cjs/model/gpt-4o.d.ts +1 -1
- package/cjs/model/gpt-5-2025-08-07.d.ts +1 -1
- package/cjs/model/gpt-5-chat-latest.d.ts +1 -1
- package/cjs/model/gpt-5-codex.d.ts +1 -1
- package/cjs/model/gpt-5-mini-2025-08-07.d.ts +1 -1
- package/cjs/model/gpt-5-mini.d.ts +1 -1
- package/cjs/model/gpt-5-nano-2025-08-07.d.ts +1 -1
- package/cjs/model/gpt-5-nano.d.ts +1 -1
- package/cjs/model/gpt-5-pro-2025-10-06.d.ts +1 -1
- package/cjs/model/gpt-5-pro.d.ts +1 -1
- package/cjs/model/gpt-5.1-2025-11-13.d.ts +1 -1
- package/cjs/model/gpt-5.1-chat-latest.d.ts +1 -1
- package/cjs/model/gpt-5.1-codex-max.d.ts +1 -1
- package/cjs/model/gpt-5.1-codex-mini.d.ts +1 -1
- package/cjs/model/gpt-5.1-codex.d.ts +1 -1
- package/cjs/model/gpt-5.1.d.ts +1 -1
- package/cjs/model/gpt-5.2-2025-12-11.d.ts +1 -1
- package/cjs/model/gpt-5.2-chat-latest.d.ts +1 -1
- package/cjs/model/gpt-5.2-codex.d.ts +1 -1
- package/cjs/model/gpt-5.2-pro-2025-12-11.d.ts +1 -1
- package/cjs/model/gpt-5.2-pro.d.ts +1 -1
- package/cjs/model/gpt-5.2.d.ts +1 -1
- package/cjs/model/gpt-5.3-chat-latest.d.ts +1 -1
- package/cjs/model/gpt-5.3-codex.d.ts +1 -1
- package/cjs/model/gpt-5.4-2026-03-05.d.ts +1 -1
- package/cjs/model/gpt-5.4-mini-2026-03-17.d.ts +1 -1
- package/cjs/model/gpt-5.4-mini.d.ts +1 -1
- package/cjs/model/gpt-5.4-nano-2026-03-17.d.ts +1 -1
- package/cjs/model/gpt-5.4-nano.d.ts +1 -1
- package/cjs/model/gpt-5.4-pro-2026-03-05.d.ts +1 -1
- package/cjs/model/gpt-5.4-pro.d.ts +1 -1
- package/cjs/model/gpt-5.4.d.ts +1 -1
- package/cjs/model/gpt-5.5-2026-04-23.d.ts +1 -1
- package/cjs/model/gpt-5.5-pro-2026-04-23.d.ts +1 -1
- package/cjs/model/gpt-5.5-pro.d.ts +1 -1
- package/cjs/model/gpt-5.5.d.ts +1 -1
- package/cjs/model/gpt-5.6-cyber.d.ts +1 -1
- package/cjs/model/gpt-5.6-luna.d.ts +1 -1
- package/cjs/model/gpt-5.6-sol.d.ts +1 -1
- package/cjs/model/gpt-5.6-terra.d.ts +1 -1
- package/cjs/model/gpt-5.d.ts +1 -1
- package/cjs/model/gpt-audio-1.5.d.ts +1 -1
- package/cjs/model/gpt-audio-2025-08-28.d.ts +1 -1
- package/cjs/model/gpt-audio-mini-2025-10-06.d.ts +1 -1
- package/cjs/model/gpt-audio-mini-2025-12-15.d.ts +1 -1
- package/cjs/model/gpt-audio-mini.d.ts +1 -1
- package/cjs/model/gpt-audio.d.ts +1 -1
- package/cjs/model/gpt-image-1.d.ts +1 -1
- package/cjs/model/gpt-oss-120b.d.ts +1 -1
- package/cjs/model/gpt-oss-20b.d.ts +1 -1
- package/cjs/model/o1-2024-12-17.d.ts +1 -1
- package/cjs/model/o1-mini-2024-09-12.d.ts +1 -1
- package/cjs/model/o1-mini.d.ts +1 -1
- package/cjs/model/o1-preview-2024-09-12.d.ts +1 -1
- package/cjs/model/o1-preview.d.ts +1 -1
- package/cjs/model/o1-pro-2025-03-19.d.ts +1 -1
- package/cjs/model/o1-pro.d.ts +1 -1
- package/cjs/model/o1.d.ts +1 -1
- package/cjs/model/o3-2025-04-16.d.ts +1 -1
- package/cjs/model/o3-deep-research-2025-06-26.d.ts +1 -1
- package/cjs/model/o3-deep-research.d.ts +1 -1
- package/cjs/model/o3-mini-2025-01-31.d.ts +1 -1
- package/cjs/model/o3-mini.d.ts +1 -1
- package/cjs/model/o3-pro-2025-06-10.d.ts +1 -1
- package/cjs/model/o3-pro.d.ts +1 -1
- package/cjs/model/o3.d.ts +1 -1
- package/cjs/model/o4-mini-2025-04-16.d.ts +1 -1
- package/cjs/model/o4-mini-deep-research-2025-06-26.d.ts +1 -1
- package/cjs/model/o4-mini-deep-research.d.ts +1 -1
- package/cjs/model/o4-mini.d.ts +1 -1
- package/cjs/utfUtil.d.ts +2 -1
- package/cjs/utfUtil.js +8 -1
- package/cjs/utfUtil.js.map +1 -1
- package/esm/BytePairEncodingCore.js +76 -32
- package/esm/BytePairEncodingCore.js.map +1 -1
- package/esm/encodingParams/constants.js +3 -3
- package/esm/encodingParams/constants.js.map +1 -1
- package/esm/utfUtil.d.ts +2 -1
- package/esm/utfUtil.js +8 -2
- package/esm/utfUtil.js.map +1 -1
- package/package.json +1 -1
- package/src/BytePairEncodingCore.test.ts +13 -0
- package/src/BytePairEncodingCore.ts +107 -69
- package/src/encodingParams/constants.ts +7 -3
- package/src/unicodeWhiteSpace.test.ts +247 -0
- package/src/utfUtil.ts +12 -1
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
// The split patterns below use `\p{White_Space}` / `\P{White_Space}` where
|
|
2
|
+
// tiktoken's patterns use `\s` / `\S`: the regex engine behind tiktoken treats
|
|
3
|
+
// `\s` as the Unicode White_Space property, whereas JavaScript's `\s` differs
|
|
4
|
+
// from it on exactly two code points (U+0085 and U+FEFF).
|
|
1
5
|
export const R50K_TOKEN_SPLIT_REGEX =
|
|
2
|
-
/'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\
|
|
6
|
+
/'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\p{White_Space}\p{L}\p{N}]+|\p{White_Space}+(?!\P{White_Space})|\p{White_Space}+/gu
|
|
3
7
|
|
|
4
8
|
const CONTRACTION_SUFFIX_PATTERN = String.raw`'(?:[sS]|[dD]|[mM]|[tT]|[lL][lL]|[vV][eE]|[rR][eE])`
|
|
5
9
|
|
|
6
10
|
const OPTIONAL_CONTRACTION_SUFFIX = String.raw`(?:${CONTRACTION_SUFFIX_PATTERN})?`
|
|
7
11
|
|
|
8
|
-
const CL100K_TOKEN_SPLIT_PATTERN = String.raw`${CONTRACTION_SUFFIX_PATTERN}|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\
|
|
12
|
+
const CL100K_TOKEN_SPLIT_PATTERN = String.raw`${CONTRACTION_SUFFIX_PATTERN}|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\p{White_Space}\p{L}\p{N}]+[\r\n]*|\p{White_Space}+$|\p{White_Space}*[\r\n]|\p{White_Space}+(?!\P{White_Space})|\p{White_Space}`
|
|
9
13
|
|
|
10
14
|
export const CL100K_TOKEN_SPLIT_REGEX = new RegExp(
|
|
11
15
|
CL100K_TOKEN_SPLIT_PATTERN,
|
|
12
16
|
'gu',
|
|
13
17
|
)
|
|
14
18
|
|
|
15
|
-
const O200K_TOKEN_SPLIT_PATTERN = String.raw`[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]*[\p{Ll}\p{Lm}\p{Lo}\p{M}]+${OPTIONAL_CONTRACTION_SUFFIX}|[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]+[\p{Ll}\p{Lm}\p{Lo}\p{M}]*${OPTIONAL_CONTRACTION_SUFFIX}|\p{N}{1,3}| ?[^\
|
|
19
|
+
const O200K_TOKEN_SPLIT_PATTERN = String.raw`[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]*[\p{Ll}\p{Lm}\p{Lo}\p{M}]+${OPTIONAL_CONTRACTION_SUFFIX}|[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]+[\p{Ll}\p{Lm}\p{Lo}\p{M}]*${OPTIONAL_CONTRACTION_SUFFIX}|\p{N}{1,3}| ?[^\p{White_Space}\p{L}\p{N}]+[\r\n/]*|\p{White_Space}*[\r\n]+|\p{White_Space}+(?!\P{White_Space})|\p{White_Space}+`
|
|
16
20
|
|
|
17
21
|
export const O200K_TOKEN_SPLIT_REGEX = new RegExp(
|
|
18
22
|
O200K_TOKEN_SPLIT_PATTERN,
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vite-plus/test'
|
|
2
|
+
import { GptEncoding } from './GptEncoding.js'
|
|
3
|
+
import { type EncodingName } from './mapping.js'
|
|
4
|
+
import { resolveEncoding } from './resolveEncoding.js'
|
|
5
|
+
|
|
6
|
+
const getEncoding = (encodingName: string) =>
|
|
7
|
+
GptEncoding.getEncodingApi(encodingName as EncodingName, resolveEncoding)
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Two things have to line up with tiktoken for these strings:
|
|
11
|
+
*
|
|
12
|
+
* - the split patterns must treat `\s` as the Unicode White_Space property.
|
|
13
|
+
* JavaScript's own `\s` differs from it on exactly two code points: U+0085
|
|
14
|
+
* (White_Space only) and U+FEFF (JavaScript `\s` only);
|
|
15
|
+
* - tokens that start with the UTF-8 byte order mark (EF BB BF, i.e. U+FEFF)
|
|
16
|
+
* must stay reachable, even though a plain `TextDecoder` strips that mark.
|
|
17
|
+
*
|
|
18
|
+
* Reference vectors generated with the Python `tiktoken` package
|
|
19
|
+
* (`encoding.encode(text)`).
|
|
20
|
+
*/
|
|
21
|
+
const unicodeWhiteSpaceCases: [
|
|
22
|
+
encodingName: string,
|
|
23
|
+
text: string,
|
|
24
|
+
expected: number[],
|
|
25
|
+
][] = [
|
|
26
|
+
['cl100k_base', 'a\ufeffb', [64, 3305, 65]],
|
|
27
|
+
['cl100k_base', 'Hello\ufeff\n', [9906, 62619]],
|
|
28
|
+
['o200k_base', 'x\ufeff\ufeffy', [87, 135153, 88]],
|
|
29
|
+
['o200k_base', 'a \u0085b', [64, 220, 126, 227, 65]],
|
|
30
|
+
['cl100k_base', 'a \u0085b', [64, 220, 126, 227, 65]],
|
|
31
|
+
['p50k_base', 'a \ufeffb', [64, 27332, 119, 123, 65]],
|
|
32
|
+
['r50k_base', 'a \ufeffb', [64, 27332, 119, 123, 65]],
|
|
33
|
+
['r50k_base', 'a \u0085b', [64, 220, 126, 227, 65]],
|
|
34
|
+
['p50k_base', 'a \u0085b', [64, 220, 126, 227, 65]],
|
|
35
|
+
['o200k_base', 'a\ufeffb', [64, 5574, 65]],
|
|
36
|
+
['cl100k_base', 'x\ufeff\ufeffy', [87, 3305, 3305, 88]],
|
|
37
|
+
['o200k_base', 'Hello\ufeff\n', [13225, 61992]],
|
|
38
|
+
['o200k_base', '\ufeffHello world', [5574, 13225, 2375]],
|
|
39
|
+
['cl100k_base', '\ufeffHello world', [3305, 9906, 1917]],
|
|
40
|
+
['o200k_base', 'a\u0085b', [64, 126, 227, 65]],
|
|
41
|
+
['cl100k_base', 'a\u0085\n\u0085b', [64, 126, 227, 198, 126, 227, 65]],
|
|
42
|
+
['o200k_base', 'line one\u0085line two', [1137, 1001, 126, 227, 1137, 1920]],
|
|
43
|
+
['cl100k_base', 'line one\u0085line two', [1074, 832, 126, 227, 1074, 1403]],
|
|
44
|
+
['p50k_base', 'a\ufeffb', [64, 171, 119, 123, 65]],
|
|
45
|
+
['r50k_base', 'a\ufeffb', [64, 171, 119, 123, 65]],
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Ordinary whitespace must keep tokenizing exactly as before (and exactly like
|
|
50
|
+
* tiktoken): the change above only affects U+0085 and U+FEFF.
|
|
51
|
+
*/
|
|
52
|
+
const ordinaryWhiteSpaceCases: [
|
|
53
|
+
encodingName: string,
|
|
54
|
+
label: string,
|
|
55
|
+
text: string,
|
|
56
|
+
expected: number[],
|
|
57
|
+
][] = [
|
|
58
|
+
['cl100k_base', 'space', 'a b', [64, 220, 293]],
|
|
59
|
+
['cl100k_base', 'tabs', 'a\t\tb\tc', [64, 197, 2282, 1470]],
|
|
60
|
+
['cl100k_base', 'newlines', 'a\n\nb\r\nc\n', [64, 271, 65, 319, 66, 198]],
|
|
61
|
+
['cl100k_base', 'nbsp', 'a\u00a0b \u00a0c', [64, 4194, 65, 220, 4194, 66]],
|
|
62
|
+
[
|
|
63
|
+
'cl100k_base',
|
|
64
|
+
'ideographic space',
|
|
65
|
+
'a\u3000b\u3000\u3000c',
|
|
66
|
+
[64, 23249, 65, 23249, 23249, 66],
|
|
67
|
+
],
|
|
68
|
+
[
|
|
69
|
+
'cl100k_base',
|
|
70
|
+
'line and paragraph separators',
|
|
71
|
+
'a\u2028b\u2029c \u2028',
|
|
72
|
+
[64, 378, 101, 65, 378, 102, 66, 639, 101],
|
|
73
|
+
],
|
|
74
|
+
[
|
|
75
|
+
'cl100k_base',
|
|
76
|
+
'mixed unicode spaces',
|
|
77
|
+
'x\u2003y\u2009\u200az\u202f\u205f',
|
|
78
|
+
[87, 378, 225, 88, 378, 231, 378, 232, 89, 378, 107, 53233, 253],
|
|
79
|
+
],
|
|
80
|
+
[
|
|
81
|
+
'cl100k_base',
|
|
82
|
+
'vertical tab and form feed',
|
|
83
|
+
'a\u000bb\fc',
|
|
84
|
+
[64, 199, 65, 200, 66],
|
|
85
|
+
],
|
|
86
|
+
['cl100k_base', 'trailing whitespace', 'hello \n ', [15339, 5996, 256]],
|
|
87
|
+
['cl100k_base', 'leading whitespace', ' hello', [256, 24748]],
|
|
88
|
+
['o200k_base', 'space', 'a b', [64, 220, 287]],
|
|
89
|
+
['o200k_base', 'tabs', 'a\t\tb\tc', [64, 197, 3722, 2736]],
|
|
90
|
+
['o200k_base', 'newlines', 'a\n\nb\r\nc\n', [64, 279, 65, 370, 66, 198]],
|
|
91
|
+
['o200k_base', 'nbsp', 'a\u00a0b \u00a0c', [64, 5310, 65, 220, 5310, 66]],
|
|
92
|
+
[
|
|
93
|
+
'o200k_base',
|
|
94
|
+
'ideographic space',
|
|
95
|
+
'a\u3000b\u3000\u3000c',
|
|
96
|
+
[64, 1397, 65, 1397, 1397, 66],
|
|
97
|
+
],
|
|
98
|
+
[
|
|
99
|
+
'o200k_base',
|
|
100
|
+
'line and paragraph separators',
|
|
101
|
+
'a\u2028b\u2029c \u2028',
|
|
102
|
+
[64, 51008, 65, 318, 102, 66, 121514],
|
|
103
|
+
],
|
|
104
|
+
[
|
|
105
|
+
'o200k_base',
|
|
106
|
+
'mixed unicode spaces',
|
|
107
|
+
'x\u2003y\u2009\u200az\u202f\u205f',
|
|
108
|
+
[87, 33203, 88, 29106, 86741, 89, 35971, 37127, 253],
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
'o200k_base',
|
|
112
|
+
'vertical tab and form feed',
|
|
113
|
+
'a\u000bb\fc',
|
|
114
|
+
[64, 199, 65, 200, 66],
|
|
115
|
+
],
|
|
116
|
+
['o200k_base', 'trailing whitespace', 'hello \n ', [24912, 10190, 256]],
|
|
117
|
+
['o200k_base', 'leading whitespace', ' hello', [256, 40617]],
|
|
118
|
+
['p50k_base', 'space', 'a b', [64, 220, 275]],
|
|
119
|
+
['p50k_base', 'tabs', 'a\t\tb\tc', [64, 197, 197, 65, 197, 66]],
|
|
120
|
+
[
|
|
121
|
+
'p50k_base',
|
|
122
|
+
'newlines',
|
|
123
|
+
'a\n\nb\r\nc\n',
|
|
124
|
+
[64, 198, 198, 65, 201, 198, 66, 198],
|
|
125
|
+
],
|
|
126
|
+
['p50k_base', 'nbsp', 'a\u00a0b \u00a0c', [64, 1849, 65, 220, 1849, 66]],
|
|
127
|
+
[
|
|
128
|
+
'p50k_base',
|
|
129
|
+
'ideographic space',
|
|
130
|
+
'a\u3000b\u3000\u3000c',
|
|
131
|
+
[64, 5099, 222, 65, 5099, 222, 5099, 222, 66],
|
|
132
|
+
],
|
|
133
|
+
[
|
|
134
|
+
'p50k_base',
|
|
135
|
+
'line and paragraph separators',
|
|
136
|
+
'a\u2028b\u2029c \u2028',
|
|
137
|
+
[64, 447, 101, 65, 447, 102, 66, 564, 101],
|
|
138
|
+
],
|
|
139
|
+
[
|
|
140
|
+
'p50k_base',
|
|
141
|
+
'mixed unicode spaces',
|
|
142
|
+
'x\u2003y\u2009\u200az\u202f\u205f',
|
|
143
|
+
[87, 447, 225, 88, 447, 231, 447, 232, 89, 447, 107, 46256, 253],
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
'p50k_base',
|
|
147
|
+
'vertical tab and form feed',
|
|
148
|
+
'a\u000bb\fc',
|
|
149
|
+
[64, 199, 65, 200, 66],
|
|
150
|
+
],
|
|
151
|
+
[
|
|
152
|
+
'p50k_base',
|
|
153
|
+
'trailing whitespace',
|
|
154
|
+
'hello \n ',
|
|
155
|
+
[31373, 50258, 198, 50257],
|
|
156
|
+
],
|
|
157
|
+
['p50k_base', 'leading whitespace', ' hello', [50257, 23748]],
|
|
158
|
+
['r50k_base', 'space', 'a b', [64, 220, 275]],
|
|
159
|
+
['r50k_base', 'tabs', 'a\t\tb\tc', [64, 197, 197, 65, 197, 66]],
|
|
160
|
+
[
|
|
161
|
+
'r50k_base',
|
|
162
|
+
'newlines',
|
|
163
|
+
'a\n\nb\r\nc\n',
|
|
164
|
+
[64, 198, 198, 65, 201, 198, 66, 198],
|
|
165
|
+
],
|
|
166
|
+
['r50k_base', 'nbsp', 'a\u00a0b \u00a0c', [64, 1849, 65, 220, 1849, 66]],
|
|
167
|
+
[
|
|
168
|
+
'r50k_base',
|
|
169
|
+
'ideographic space',
|
|
170
|
+
'a\u3000b\u3000\u3000c',
|
|
171
|
+
[64, 5099, 222, 65, 5099, 222, 5099, 222, 66],
|
|
172
|
+
],
|
|
173
|
+
[
|
|
174
|
+
'r50k_base',
|
|
175
|
+
'line and paragraph separators',
|
|
176
|
+
'a\u2028b\u2029c \u2028',
|
|
177
|
+
[64, 447, 101, 65, 447, 102, 66, 564, 101],
|
|
178
|
+
],
|
|
179
|
+
[
|
|
180
|
+
'r50k_base',
|
|
181
|
+
'mixed unicode spaces',
|
|
182
|
+
'x\u2003y\u2009\u200az\u202f\u205f',
|
|
183
|
+
[87, 447, 225, 88, 447, 231, 447, 232, 89, 447, 107, 46256, 253],
|
|
184
|
+
],
|
|
185
|
+
[
|
|
186
|
+
'r50k_base',
|
|
187
|
+
'vertical tab and form feed',
|
|
188
|
+
'a\u000bb\fc',
|
|
189
|
+
[64, 199, 65, 200, 66],
|
|
190
|
+
],
|
|
191
|
+
[
|
|
192
|
+
'r50k_base',
|
|
193
|
+
'trailing whitespace',
|
|
194
|
+
'hello \n ',
|
|
195
|
+
[31373, 220, 220, 220, 198, 220, 220],
|
|
196
|
+
],
|
|
197
|
+
['r50k_base', 'leading whitespace', ' hello', [220, 220, 23748]],
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
describe('Unicode White_Space handling in the split patterns', () => {
|
|
201
|
+
// Keep this test first: the shared TextDecoder only strips a BOM on its very
|
|
202
|
+
// first decode, so later decodes in this file would hide a regression.
|
|
203
|
+
test('decode keeps U+FEFF tokens', () => {
|
|
204
|
+
const encoding = getEncoding('cl100k_base')
|
|
205
|
+
const feff = String.fromCodePoint(0xfeff)
|
|
206
|
+
|
|
207
|
+
// 3305 is the single token for the bytes EF BB BF
|
|
208
|
+
expect(encoding.decode([3305])).toBe(feff)
|
|
209
|
+
expect(encoding.decode([64, 3305, 65])).toBe(`a${feff}b`)
|
|
210
|
+
// 62619 is the single token for the bytes EF BB BF 0A
|
|
211
|
+
expect(encoding.decode([9906, 62_619])).toBe(`Hello${feff}\n`)
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
describe.each(unicodeWhiteSpaceCases)(
|
|
215
|
+
'%s: %j',
|
|
216
|
+
(encodingName, text, expected) => {
|
|
217
|
+
const encoding = getEncoding(encodingName)
|
|
218
|
+
|
|
219
|
+
test('encode matches tiktoken', () => {
|
|
220
|
+
expect(encoding.encode(text)).toEqual(expected)
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
test('countTokens agrees with encode', () => {
|
|
224
|
+
expect(encoding.countTokens(text)).toBe(expected.length)
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
test('decode round-trips', () => {
|
|
228
|
+
expect(encoding.decode(encoding.encode(text))).toBe(text)
|
|
229
|
+
})
|
|
230
|
+
},
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
describe.each(ordinaryWhiteSpaceCases)(
|
|
234
|
+
'%s: %s',
|
|
235
|
+
(encodingName, _label, text, expected) => {
|
|
236
|
+
const encoding = getEncoding(encodingName)
|
|
237
|
+
|
|
238
|
+
test('encode matches tiktoken', () => {
|
|
239
|
+
expect(encoding.encode(text)).toEqual(expected)
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
test('decode round-trips', () => {
|
|
243
|
+
expect(encoding.decode(encoding.encode(text))).toBe(text)
|
|
244
|
+
})
|
|
245
|
+
},
|
|
246
|
+
)
|
|
247
|
+
})
|
package/src/utfUtil.ts
CHANGED
|
@@ -71,7 +71,18 @@ function isValidUTF8(bytes: Uint8Array): boolean {
|
|
|
71
71
|
return true
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
export function startsWithByteOrderMark(bytes: Uint8Array): boolean {
|
|
75
|
+
return (
|
|
76
|
+
bytes.length >= 3 &&
|
|
77
|
+
bytes[0] === 0xef &&
|
|
78
|
+
bytes[1] === 0xbb &&
|
|
79
|
+
bytes[2] === 0xbf
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// `ignoreBOM: true` keeps a leading U+FEFF in the output instead of silently
|
|
84
|
+
// stripping it, so the bytes EF BB BF map to U+FEFF rather than to an empty string.
|
|
85
|
+
const textDecoder = new TextDecoder('utf8', { fatal: false, ignoreBOM: true })
|
|
75
86
|
|
|
76
87
|
export function tryConvertToString(arr: Uint8Array): string | undefined {
|
|
77
88
|
if (!isValidUTF8(arr)) {
|