@sohqureshi/tokenwise 1.0.7 → 1.0.9
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/README.md +18 -4
- package/dist/{chunk-IOMOVRC7.js → chunk-2TDVL6BJ.js} +2 -2
- package/dist/chunk-L3HY6AWL.js +69 -0
- package/dist/{chunk-P6KXISNT.js → chunk-QHCUNOUH.js} +1 -1
- package/dist/cli.cjs +33 -19
- package/dist/cli.js +4 -4
- package/dist/core/analyze.cjs +32 -18
- package/dist/core/analyze.js +2 -2
- package/dist/core/token.cjs +31 -17
- package/dist/core/token.d.cts +2 -8
- package/dist/core/token.d.ts +2 -8
- package/dist/core/token.js +1 -1
- package/dist/index.cjs +32 -18
- package/dist/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-U433WUUT.js +0 -55
package/README.md
CHANGED
|
@@ -210,10 +210,24 @@ LLMs charge and reason over tokens. Sending raw JSON often includes repeated key
|
|
|
210
210
|
node demo.js
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
-
Use `--analyze` to compare serialized input and output with
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
Use `--analyze` to compare serialized input and output with the model's
|
|
214
|
+
`tiktoken` encoding. `estimateTokens()` and `analyze()` use exact
|
|
215
|
+
model-aware counts by default; pass `exact: false` to opt into the
|
|
216
|
+
four-characters-per-token heuristic. Use `model` to select the tokenizer
|
|
217
|
+
used by `tiktoken`.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Release Notes
|
|
222
|
+
|
|
223
|
+
### v1.0.8 — 2026-09-06
|
|
224
|
+
|
|
225
|
+
- Expose exact tokenizer metadata when available (model + encoding), and fall back to a clear, model-aware estimator in browser demos.
|
|
226
|
+
- Demo updated to show selected model and expected encoding when the exact tokenizer (tiktoken) is not available in-browser.
|
|
227
|
+
- Updated analyze() to surface tokenizer encoding in analysis output so the demo shows "Estimator: model=gpt-4 expected_encoding=cl100k_base" even when using the heuristic fallback.
|
|
228
|
+
- Misc: build artifacts updated and docs demo import bumped to v1.0.7 CDN bundle.
|
|
229
|
+
|
|
230
|
+
If you want the browser demo to display truly exact token counts, run the demo against a small Node endpoint (or local server) that has tiktoken installed and uses analyze(..., { exact: true }). The estimator will display the real tokenizer encoding when tiktoken is present.
|
|
217
231
|
|
|
218
232
|
---
|
|
219
233
|
|
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
estimateTokensWithMeta,
|
|
15
15
|
serializeForTokenEstimate
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-L3HY6AWL.js";
|
|
17
17
|
|
|
18
18
|
// src/core/analyze.ts
|
|
19
19
|
function analyze(input, options = {}) {
|
|
20
20
|
const {
|
|
21
|
-
exact =
|
|
21
|
+
exact = true,
|
|
22
22
|
model = "gpt-4o-mini",
|
|
23
23
|
fallbackToHeuristic = true
|
|
24
24
|
} = options;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// src/core/token.ts
|
|
2
|
+
import { createRequire } from "module";
|
|
3
|
+
var require2 = createRequire(import.meta.url);
|
|
4
|
+
function serializeForTokenEstimate(value) {
|
|
5
|
+
if (typeof value === "string") return value;
|
|
6
|
+
const serialized = JSON.stringify(value);
|
|
7
|
+
return serialized ?? "";
|
|
8
|
+
}
|
|
9
|
+
function estimateTokensHeuristic(value) {
|
|
10
|
+
return Math.ceil(serializeForTokenEstimate(value).length / 4);
|
|
11
|
+
}
|
|
12
|
+
function expectedEncodingForModel(model) {
|
|
13
|
+
const normalizedModel = model.toLowerCase();
|
|
14
|
+
if (normalizedModel.includes("gpt-4o") || normalizedModel.includes("gpt-4.1") || normalizedModel.includes("o1") || normalizedModel.includes("o3") || normalizedModel.includes("o4")) {
|
|
15
|
+
return "o200k_base";
|
|
16
|
+
}
|
|
17
|
+
if (normalizedModel.includes("davinci") || normalizedModel.startsWith("text-") || normalizedModel.includes("babbage") || normalizedModel.includes("curie")) {
|
|
18
|
+
return "r50k_base";
|
|
19
|
+
}
|
|
20
|
+
return "cl100k_base";
|
|
21
|
+
}
|
|
22
|
+
function estimateTokens(value, options = {}) {
|
|
23
|
+
return estimateTokensWithMeta(value, options).count;
|
|
24
|
+
}
|
|
25
|
+
function estimateTokensWithMeta(value, options = {}) {
|
|
26
|
+
const { exact = true, model = "gpt-4o-mini", fallbackToHeuristic = true } = options;
|
|
27
|
+
const heuristic = estimateTokensHeuristic(value);
|
|
28
|
+
const heuristicEstimator = "heuristic: 1 token \u2248 4 characters";
|
|
29
|
+
if (!exact) {
|
|
30
|
+
return { count: heuristic, estimator: heuristicEstimator };
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const tiktoken = require2("tiktoken");
|
|
34
|
+
const encoder = tiktoken.encoding_for_model(model);
|
|
35
|
+
const count = encoder.encode(serializeForTokenEstimate(value)).length;
|
|
36
|
+
let encodingName = encoder.name;
|
|
37
|
+
if (!encodingName && typeof tiktoken.model_to_encoding === "function") {
|
|
38
|
+
try {
|
|
39
|
+
encodingName = tiktoken.model_to_encoding(model);
|
|
40
|
+
} catch {
|
|
41
|
+
encodingName = void 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
encodingName ?? (encodingName = expectedEncodingForModel(model));
|
|
45
|
+
encoder.free?.();
|
|
46
|
+
return {
|
|
47
|
+
count,
|
|
48
|
+
estimator: `exact tokenizer: model=${model} encoding=${encodingName}`
|
|
49
|
+
};
|
|
50
|
+
} catch {
|
|
51
|
+
const expectedEncoding = expectedEncodingForModel(model);
|
|
52
|
+
if (!fallbackToHeuristic) {
|
|
53
|
+
return {
|
|
54
|
+
count: heuristic,
|
|
55
|
+
estimator: `exact requested but tokenizer unavailable (expected encoding=${expectedEncoding} for model=${model})`
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
count: heuristic,
|
|
60
|
+
estimator: `${heuristicEstimator} (model=${model} expected_encoding=${expectedEncoding})`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
serializeForTokenEstimate,
|
|
67
|
+
estimateTokens,
|
|
68
|
+
estimateTokensWithMeta
|
|
69
|
+
};
|
package/dist/cli.cjs
CHANGED
|
@@ -153,8 +153,18 @@ function serializeForTokenEstimate(value) {
|
|
|
153
153
|
function estimateTokensHeuristic(value) {
|
|
154
154
|
return Math.ceil(serializeForTokenEstimate(value).length / 4);
|
|
155
155
|
}
|
|
156
|
+
function expectedEncodingForModel(model) {
|
|
157
|
+
const normalizedModel = model.toLowerCase();
|
|
158
|
+
if (normalizedModel.includes("gpt-4o") || normalizedModel.includes("gpt-4.1") || normalizedModel.includes("o1") || normalizedModel.includes("o3") || normalizedModel.includes("o4")) {
|
|
159
|
+
return "o200k_base";
|
|
160
|
+
}
|
|
161
|
+
if (normalizedModel.includes("davinci") || normalizedModel.startsWith("text-") || normalizedModel.includes("babbage") || normalizedModel.includes("curie")) {
|
|
162
|
+
return "r50k_base";
|
|
163
|
+
}
|
|
164
|
+
return "cl100k_base";
|
|
165
|
+
}
|
|
156
166
|
function estimateTokensWithMeta(value, options = {}) {
|
|
157
|
-
const { exact =
|
|
167
|
+
const { exact = true, model = "gpt-4o-mini", fallbackToHeuristic = true } = options;
|
|
158
168
|
const heuristic = estimateTokensHeuristic(value);
|
|
159
169
|
const heuristicEstimator = "heuristic: 1 token \u2248 4 characters";
|
|
160
170
|
if (!exact) {
|
|
@@ -163,36 +173,40 @@ function estimateTokensWithMeta(value, options = {}) {
|
|
|
163
173
|
try {
|
|
164
174
|
const tiktoken = require2("tiktoken");
|
|
165
175
|
const encoder = tiktoken.encoding_for_model(model);
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
let encodingName = null;
|
|
169
|
-
if (encoder.name) encodingName = encoder.name;
|
|
176
|
+
const count = encoder.encode(serializeForTokenEstimate(value)).length;
|
|
177
|
+
let encodingName = encoder.name;
|
|
170
178
|
if (!encodingName && typeof tiktoken.model_to_encoding === "function") {
|
|
171
179
|
try {
|
|
172
180
|
encodingName = tiktoken.model_to_encoding(model);
|
|
173
|
-
} catch
|
|
174
|
-
encodingName =
|
|
181
|
+
} catch {
|
|
182
|
+
encodingName = void 0;
|
|
175
183
|
}
|
|
176
184
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
+
encodingName ?? (encodingName = expectedEncodingForModel(model));
|
|
186
|
+
encoder.free?.();
|
|
187
|
+
return {
|
|
188
|
+
count,
|
|
189
|
+
estimator: `exact tokenizer: model=${model} encoding=${encodingName}`
|
|
190
|
+
};
|
|
191
|
+
} catch {
|
|
192
|
+
const expectedEncoding = expectedEncodingForModel(model);
|
|
185
193
|
if (!fallbackToHeuristic) {
|
|
186
|
-
return {
|
|
194
|
+
return {
|
|
195
|
+
count: heuristic,
|
|
196
|
+
estimator: `exact requested but tokenizer unavailable (expected encoding=${expectedEncoding} for model=${model})`
|
|
197
|
+
};
|
|
187
198
|
}
|
|
188
|
-
return {
|
|
199
|
+
return {
|
|
200
|
+
count: heuristic,
|
|
201
|
+
estimator: `${heuristicEstimator} (model=${model} expected_encoding=${expectedEncoding})`
|
|
202
|
+
};
|
|
189
203
|
}
|
|
190
204
|
}
|
|
191
205
|
|
|
192
206
|
// src/core/analyze.ts
|
|
193
207
|
function analyze(input, options = {}) {
|
|
194
208
|
const {
|
|
195
|
-
exact =
|
|
209
|
+
exact = true,
|
|
196
210
|
model = "gpt-4o-mini",
|
|
197
211
|
fallbackToHeuristic = true
|
|
198
212
|
} = options;
|
|
@@ -395,7 +409,7 @@ Usage:
|
|
|
395
409
|
Options:
|
|
396
410
|
--toon Convert JSON to TOON format
|
|
397
411
|
--compact Convert JSON to compact format
|
|
398
|
-
--analyze Show token analysis (
|
|
412
|
+
--analyze Show token analysis (tiktoken estimate)
|
|
399
413
|
`);
|
|
400
414
|
process.exit(0);
|
|
401
415
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
AIChain
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-QHCUNOUH.js";
|
|
5
|
+
import "./chunk-2TDVL6BJ.js";
|
|
6
6
|
import "./chunk-6VRLDRJK.js";
|
|
7
7
|
import "./chunk-XE36GLJP.js";
|
|
8
8
|
import "./chunk-L7BC62MT.js";
|
|
9
9
|
import "./chunk-D4CFTFM3.js";
|
|
10
10
|
import "./chunk-ZD536GZF.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-L3HY6AWL.js";
|
|
12
12
|
|
|
13
13
|
// src/cli.ts
|
|
14
14
|
import fs from "fs";
|
|
@@ -22,7 +22,7 @@ Usage:
|
|
|
22
22
|
Options:
|
|
23
23
|
--toon Convert JSON to TOON format
|
|
24
24
|
--compact Convert JSON to compact format
|
|
25
|
-
--analyze Show token analysis (
|
|
25
|
+
--analyze Show token analysis (tiktoken estimate)
|
|
26
26
|
`);
|
|
27
27
|
process.exit(0);
|
|
28
28
|
}
|
package/dist/core/analyze.cjs
CHANGED
|
@@ -150,8 +150,18 @@ function serializeForTokenEstimate(value) {
|
|
|
150
150
|
function estimateTokensHeuristic(value) {
|
|
151
151
|
return Math.ceil(serializeForTokenEstimate(value).length / 4);
|
|
152
152
|
}
|
|
153
|
+
function expectedEncodingForModel(model) {
|
|
154
|
+
const normalizedModel = model.toLowerCase();
|
|
155
|
+
if (normalizedModel.includes("gpt-4o") || normalizedModel.includes("gpt-4.1") || normalizedModel.includes("o1") || normalizedModel.includes("o3") || normalizedModel.includes("o4")) {
|
|
156
|
+
return "o200k_base";
|
|
157
|
+
}
|
|
158
|
+
if (normalizedModel.includes("davinci") || normalizedModel.startsWith("text-") || normalizedModel.includes("babbage") || normalizedModel.includes("curie")) {
|
|
159
|
+
return "r50k_base";
|
|
160
|
+
}
|
|
161
|
+
return "cl100k_base";
|
|
162
|
+
}
|
|
153
163
|
function estimateTokensWithMeta(value, options = {}) {
|
|
154
|
-
const { exact =
|
|
164
|
+
const { exact = true, model = "gpt-4o-mini", fallbackToHeuristic = true } = options;
|
|
155
165
|
const heuristic = estimateTokensHeuristic(value);
|
|
156
166
|
const heuristicEstimator = "heuristic: 1 token \u2248 4 characters";
|
|
157
167
|
if (!exact) {
|
|
@@ -160,36 +170,40 @@ function estimateTokensWithMeta(value, options = {}) {
|
|
|
160
170
|
try {
|
|
161
171
|
const tiktoken = require2("tiktoken");
|
|
162
172
|
const encoder = tiktoken.encoding_for_model(model);
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
let encodingName = null;
|
|
166
|
-
if (encoder.name) encodingName = encoder.name;
|
|
173
|
+
const count = encoder.encode(serializeForTokenEstimate(value)).length;
|
|
174
|
+
let encodingName = encoder.name;
|
|
167
175
|
if (!encodingName && typeof tiktoken.model_to_encoding === "function") {
|
|
168
176
|
try {
|
|
169
177
|
encodingName = tiktoken.model_to_encoding(model);
|
|
170
|
-
} catch
|
|
171
|
-
encodingName =
|
|
178
|
+
} catch {
|
|
179
|
+
encodingName = void 0;
|
|
172
180
|
}
|
|
173
181
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
+
encodingName ?? (encodingName = expectedEncodingForModel(model));
|
|
183
|
+
encoder.free?.();
|
|
184
|
+
return {
|
|
185
|
+
count,
|
|
186
|
+
estimator: `exact tokenizer: model=${model} encoding=${encodingName}`
|
|
187
|
+
};
|
|
188
|
+
} catch {
|
|
189
|
+
const expectedEncoding = expectedEncodingForModel(model);
|
|
182
190
|
if (!fallbackToHeuristic) {
|
|
183
|
-
return {
|
|
191
|
+
return {
|
|
192
|
+
count: heuristic,
|
|
193
|
+
estimator: `exact requested but tokenizer unavailable (expected encoding=${expectedEncoding} for model=${model})`
|
|
194
|
+
};
|
|
184
195
|
}
|
|
185
|
-
return {
|
|
196
|
+
return {
|
|
197
|
+
count: heuristic,
|
|
198
|
+
estimator: `${heuristicEstimator} (model=${model} expected_encoding=${expectedEncoding})`
|
|
199
|
+
};
|
|
186
200
|
}
|
|
187
201
|
}
|
|
188
202
|
|
|
189
203
|
// src/core/analyze.ts
|
|
190
204
|
function analyze(input, options = {}) {
|
|
191
205
|
const {
|
|
192
|
-
exact =
|
|
206
|
+
exact = true,
|
|
193
207
|
model = "gpt-4o-mini",
|
|
194
208
|
fallbackToHeuristic = true
|
|
195
209
|
} = options;
|
package/dist/core/analyze.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
analyze
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-2TDVL6BJ.js";
|
|
4
4
|
import "../chunk-6VRLDRJK.js";
|
|
5
5
|
import "../chunk-XE36GLJP.js";
|
|
6
6
|
import "../chunk-L7BC62MT.js";
|
|
7
7
|
import "../chunk-ZD536GZF.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-L3HY6AWL.js";
|
|
9
9
|
export {
|
|
10
10
|
analyze
|
|
11
11
|
};
|
package/dist/core/token.cjs
CHANGED
|
@@ -36,11 +36,21 @@ function serializeForTokenEstimate(value) {
|
|
|
36
36
|
function estimateTokensHeuristic(value) {
|
|
37
37
|
return Math.ceil(serializeForTokenEstimate(value).length / 4);
|
|
38
38
|
}
|
|
39
|
+
function expectedEncodingForModel(model) {
|
|
40
|
+
const normalizedModel = model.toLowerCase();
|
|
41
|
+
if (normalizedModel.includes("gpt-4o") || normalizedModel.includes("gpt-4.1") || normalizedModel.includes("o1") || normalizedModel.includes("o3") || normalizedModel.includes("o4")) {
|
|
42
|
+
return "o200k_base";
|
|
43
|
+
}
|
|
44
|
+
if (normalizedModel.includes("davinci") || normalizedModel.startsWith("text-") || normalizedModel.includes("babbage") || normalizedModel.includes("curie")) {
|
|
45
|
+
return "r50k_base";
|
|
46
|
+
}
|
|
47
|
+
return "cl100k_base";
|
|
48
|
+
}
|
|
39
49
|
function estimateTokens(value, options = {}) {
|
|
40
50
|
return estimateTokensWithMeta(value, options).count;
|
|
41
51
|
}
|
|
42
52
|
function estimateTokensWithMeta(value, options = {}) {
|
|
43
|
-
const { exact =
|
|
53
|
+
const { exact = true, model = "gpt-4o-mini", fallbackToHeuristic = true } = options;
|
|
44
54
|
const heuristic = estimateTokensHeuristic(value);
|
|
45
55
|
const heuristicEstimator = "heuristic: 1 token \u2248 4 characters";
|
|
46
56
|
if (!exact) {
|
|
@@ -49,29 +59,33 @@ function estimateTokensWithMeta(value, options = {}) {
|
|
|
49
59
|
try {
|
|
50
60
|
const tiktoken = require2("tiktoken");
|
|
51
61
|
const encoder = tiktoken.encoding_for_model(model);
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
let encodingName = null;
|
|
55
|
-
if (encoder.name) encodingName = encoder.name;
|
|
62
|
+
const count = encoder.encode(serializeForTokenEstimate(value)).length;
|
|
63
|
+
let encodingName = encoder.name;
|
|
56
64
|
if (!encodingName && typeof tiktoken.model_to_encoding === "function") {
|
|
57
65
|
try {
|
|
58
66
|
encodingName = tiktoken.model_to_encoding(model);
|
|
59
|
-
} catch
|
|
60
|
-
encodingName =
|
|
67
|
+
} catch {
|
|
68
|
+
encodingName = void 0;
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
encodingName ?? (encodingName = expectedEncodingForModel(model));
|
|
72
|
+
encoder.free?.();
|
|
73
|
+
return {
|
|
74
|
+
count,
|
|
75
|
+
estimator: `exact tokenizer: model=${model} encoding=${encodingName}`
|
|
76
|
+
};
|
|
77
|
+
} catch {
|
|
78
|
+
const expectedEncoding = expectedEncodingForModel(model);
|
|
71
79
|
if (!fallbackToHeuristic) {
|
|
72
|
-
return {
|
|
80
|
+
return {
|
|
81
|
+
count: heuristic,
|
|
82
|
+
estimator: `exact requested but tokenizer unavailable (expected encoding=${expectedEncoding} for model=${model})`
|
|
83
|
+
};
|
|
73
84
|
}
|
|
74
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
count: heuristic,
|
|
87
|
+
estimator: `${heuristicEstimator} (model=${model} expected_encoding=${expectedEncoding})`
|
|
88
|
+
};
|
|
75
89
|
}
|
|
76
90
|
}
|
|
77
91
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/core/token.d.cts
CHANGED
|
@@ -4,20 +4,14 @@ interface TokenEstimateOptions {
|
|
|
4
4
|
fallbackToHeuristic?: boolean;
|
|
5
5
|
}
|
|
6
6
|
declare function serializeForTokenEstimate(value: unknown): string;
|
|
7
|
-
/**
|
|
8
|
-
* Estimates tokens using a transparent four-characters-per-token heuristic.
|
|
9
|
-
* JSON values are serialized first, matching the compact form normally sent
|
|
10
|
-
* to an API. Set exact=true to attempt a model-specific tokenizer count when
|
|
11
|
-
* the runtime has the tokenizer installed.
|
|
12
|
-
*/
|
|
13
7
|
type TokenEstimateResult = {
|
|
14
8
|
count: number;
|
|
15
9
|
estimator: string;
|
|
16
10
|
};
|
|
17
11
|
declare function estimateTokens(value: unknown, options?: TokenEstimateOptions): number;
|
|
18
12
|
/**
|
|
19
|
-
* Returns
|
|
20
|
-
*
|
|
13
|
+
* Returns an exact model tokenizer count by default. Set exact=false to use the
|
|
14
|
+
* lightweight four-characters-per-token fallback explicitly.
|
|
21
15
|
*/
|
|
22
16
|
declare function estimateTokensWithMeta(value: unknown, options?: TokenEstimateOptions): TokenEstimateResult;
|
|
23
17
|
|
package/dist/core/token.d.ts
CHANGED
|
@@ -4,20 +4,14 @@ interface TokenEstimateOptions {
|
|
|
4
4
|
fallbackToHeuristic?: boolean;
|
|
5
5
|
}
|
|
6
6
|
declare function serializeForTokenEstimate(value: unknown): string;
|
|
7
|
-
/**
|
|
8
|
-
* Estimates tokens using a transparent four-characters-per-token heuristic.
|
|
9
|
-
* JSON values are serialized first, matching the compact form normally sent
|
|
10
|
-
* to an API. Set exact=true to attempt a model-specific tokenizer count when
|
|
11
|
-
* the runtime has the tokenizer installed.
|
|
12
|
-
*/
|
|
13
7
|
type TokenEstimateResult = {
|
|
14
8
|
count: number;
|
|
15
9
|
estimator: string;
|
|
16
10
|
};
|
|
17
11
|
declare function estimateTokens(value: unknown, options?: TokenEstimateOptions): number;
|
|
18
12
|
/**
|
|
19
|
-
* Returns
|
|
20
|
-
*
|
|
13
|
+
* Returns an exact model tokenizer count by default. Set exact=false to use the
|
|
14
|
+
* lightweight four-characters-per-token fallback explicitly.
|
|
21
15
|
*/
|
|
22
16
|
declare function estimateTokensWithMeta(value: unknown, options?: TokenEstimateOptions): TokenEstimateResult;
|
|
23
17
|
|
package/dist/core/token.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -159,11 +159,21 @@ function serializeForTokenEstimate(value) {
|
|
|
159
159
|
function estimateTokensHeuristic(value) {
|
|
160
160
|
return Math.ceil(serializeForTokenEstimate(value).length / 4);
|
|
161
161
|
}
|
|
162
|
+
function expectedEncodingForModel(model) {
|
|
163
|
+
const normalizedModel = model.toLowerCase();
|
|
164
|
+
if (normalizedModel.includes("gpt-4o") || normalizedModel.includes("gpt-4.1") || normalizedModel.includes("o1") || normalizedModel.includes("o3") || normalizedModel.includes("o4")) {
|
|
165
|
+
return "o200k_base";
|
|
166
|
+
}
|
|
167
|
+
if (normalizedModel.includes("davinci") || normalizedModel.startsWith("text-") || normalizedModel.includes("babbage") || normalizedModel.includes("curie")) {
|
|
168
|
+
return "r50k_base";
|
|
169
|
+
}
|
|
170
|
+
return "cl100k_base";
|
|
171
|
+
}
|
|
162
172
|
function estimateTokens(value, options = {}) {
|
|
163
173
|
return estimateTokensWithMeta(value, options).count;
|
|
164
174
|
}
|
|
165
175
|
function estimateTokensWithMeta(value, options = {}) {
|
|
166
|
-
const { exact =
|
|
176
|
+
const { exact = true, model = "gpt-4o-mini", fallbackToHeuristic = true } = options;
|
|
167
177
|
const heuristic = estimateTokensHeuristic(value);
|
|
168
178
|
const heuristicEstimator = "heuristic: 1 token \u2248 4 characters";
|
|
169
179
|
if (!exact) {
|
|
@@ -172,36 +182,40 @@ function estimateTokensWithMeta(value, options = {}) {
|
|
|
172
182
|
try {
|
|
173
183
|
const tiktoken = require2("tiktoken");
|
|
174
184
|
const encoder = tiktoken.encoding_for_model(model);
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
let encodingName = null;
|
|
178
|
-
if (encoder.name) encodingName = encoder.name;
|
|
185
|
+
const count = encoder.encode(serializeForTokenEstimate(value)).length;
|
|
186
|
+
let encodingName = encoder.name;
|
|
179
187
|
if (!encodingName && typeof tiktoken.model_to_encoding === "function") {
|
|
180
188
|
try {
|
|
181
189
|
encodingName = tiktoken.model_to_encoding(model);
|
|
182
|
-
} catch
|
|
183
|
-
encodingName =
|
|
190
|
+
} catch {
|
|
191
|
+
encodingName = void 0;
|
|
184
192
|
}
|
|
185
193
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
+
encodingName ?? (encodingName = expectedEncodingForModel(model));
|
|
195
|
+
encoder.free?.();
|
|
196
|
+
return {
|
|
197
|
+
count,
|
|
198
|
+
estimator: `exact tokenizer: model=${model} encoding=${encodingName}`
|
|
199
|
+
};
|
|
200
|
+
} catch {
|
|
201
|
+
const expectedEncoding = expectedEncodingForModel(model);
|
|
194
202
|
if (!fallbackToHeuristic) {
|
|
195
|
-
return {
|
|
203
|
+
return {
|
|
204
|
+
count: heuristic,
|
|
205
|
+
estimator: `exact requested but tokenizer unavailable (expected encoding=${expectedEncoding} for model=${model})`
|
|
206
|
+
};
|
|
196
207
|
}
|
|
197
|
-
return {
|
|
208
|
+
return {
|
|
209
|
+
count: heuristic,
|
|
210
|
+
estimator: `${heuristicEstimator} (model=${model} expected_encoding=${expectedEncoding})`
|
|
211
|
+
};
|
|
198
212
|
}
|
|
199
213
|
}
|
|
200
214
|
|
|
201
215
|
// src/core/analyze.ts
|
|
202
216
|
function analyze(input, options = {}) {
|
|
203
217
|
const {
|
|
204
|
-
exact =
|
|
218
|
+
exact = true,
|
|
205
219
|
model = "gpt-4o-mini",
|
|
206
220
|
fallbackToHeuristic = true
|
|
207
221
|
} = options;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AIChain
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QHCUNOUH.js";
|
|
4
4
|
import {
|
|
5
5
|
analyze
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2TDVL6BJ.js";
|
|
7
7
|
import {
|
|
8
8
|
toTOON
|
|
9
9
|
} from "./chunk-6VRLDRJK.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
estimateTokens,
|
|
24
24
|
serializeForTokenEstimate
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-L3HY6AWL.js";
|
|
26
26
|
|
|
27
27
|
// src/index.ts
|
|
28
28
|
function ai(data) {
|
package/package.json
CHANGED
package/dist/chunk-U433WUUT.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// src/core/token.ts
|
|
2
|
-
import { createRequire } from "module";
|
|
3
|
-
var require2 = createRequire(import.meta.url);
|
|
4
|
-
function serializeForTokenEstimate(value) {
|
|
5
|
-
if (typeof value === "string") return value;
|
|
6
|
-
const serialized = JSON.stringify(value);
|
|
7
|
-
return serialized ?? "";
|
|
8
|
-
}
|
|
9
|
-
function estimateTokensHeuristic(value) {
|
|
10
|
-
return Math.ceil(serializeForTokenEstimate(value).length / 4);
|
|
11
|
-
}
|
|
12
|
-
function estimateTokens(value, options = {}) {
|
|
13
|
-
return estimateTokensWithMeta(value, options).count;
|
|
14
|
-
}
|
|
15
|
-
function estimateTokensWithMeta(value, options = {}) {
|
|
16
|
-
const { exact = false, model = "gpt-4o-mini", fallbackToHeuristic = true } = options;
|
|
17
|
-
const heuristic = estimateTokensHeuristic(value);
|
|
18
|
-
const heuristicEstimator = "heuristic: 1 token \u2248 4 characters";
|
|
19
|
-
if (!exact) {
|
|
20
|
-
return { count: heuristic, estimator: heuristicEstimator };
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
const tiktoken = require2("tiktoken");
|
|
24
|
-
const encoder = tiktoken.encoding_for_model(model);
|
|
25
|
-
const text = serializeForTokenEstimate(value);
|
|
26
|
-
const count = encoder.encode(text).length;
|
|
27
|
-
let encodingName = null;
|
|
28
|
-
if (encoder.name) encodingName = encoder.name;
|
|
29
|
-
if (!encodingName && typeof tiktoken.model_to_encoding === "function") {
|
|
30
|
-
try {
|
|
31
|
-
encodingName = tiktoken.model_to_encoding(model);
|
|
32
|
-
} catch (e) {
|
|
33
|
-
encodingName = null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (!encodingName) {
|
|
37
|
-
const m = String(model || "").toLowerCase();
|
|
38
|
-
if (m.includes("davinci") || m.startsWith("text-")) encodingName = "r50k_base";
|
|
39
|
-
else encodingName = "cl100k_base";
|
|
40
|
-
}
|
|
41
|
-
const estimator = `exact tokenizer: model=${model} encoding=${encodingName}`;
|
|
42
|
-
return { count, estimator };
|
|
43
|
-
} catch (e) {
|
|
44
|
-
if (!fallbackToHeuristic) {
|
|
45
|
-
return { count: heuristic, estimator: "exact requested but tokenizer unavailable" };
|
|
46
|
-
}
|
|
47
|
-
return { count: heuristic, estimator: heuristicEstimator };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export {
|
|
52
|
-
serializeForTokenEstimate,
|
|
53
|
-
estimateTokens,
|
|
54
|
-
estimateTokensWithMeta
|
|
55
|
-
};
|