@sohqureshi/tokenwise 1.0.3 → 1.0.7
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 +13 -8
- package/dist/{chunk-3ECVBELU.js → chunk-6VRLDRJK.js} +5 -3
- package/dist/{chunk-GQ62V6ZK.js → chunk-IOMOVRC7.js} +33 -12
- package/dist/{chunk-YMOSWQGE.js → chunk-L7BC62MT.js} +11 -3
- package/dist/{chunk-2IQAGI7Q.js → chunk-P6KXISNT.js} +7 -7
- package/dist/chunk-U433WUUT.js +55 -0
- package/dist/{chunk-EUFLW42L.js → chunk-XE36GLJP.js} +1 -1
- package/dist/{chunk-IAV75SZA.js → chunk-ZD536GZF.js} +1 -1
- package/dist/cli.cjs +91 -19
- package/dist/cli.js +8 -8
- package/dist/core/analyze.cjs +88 -16
- package/dist/core/analyze.d.cts +16 -3
- package/dist/core/analyze.d.ts +16 -3
- package/dist/core/analyze.js +6 -6
- package/dist/core/compact.cjs +1 -1
- package/dist/core/compact.js +2 -2
- package/dist/core/flatten.cjs +11 -3
- package/dist/core/flatten.d.cts +1 -1
- package/dist/core/flatten.d.ts +1 -1
- package/dist/core/flatten.js +1 -1
- package/dist/core/prune.cjs +1 -1
- package/dist/core/prune.js +1 -1
- package/dist/core/token.cjs +54 -5
- package/dist/core/token.d.cts +21 -9
- package/dist/core/token.d.ts +21 -9
- package/dist/core/token.js +7 -3
- package/dist/core/toon.cjs +5 -3
- package/dist/core/toon.js +1 -1
- package/dist/index.cjs +96 -18
- package/dist/index.d.cts +13 -9
- package/dist/index.d.ts +13 -9
- package/dist/index.js +11 -8
- package/package.json +6 -1
- package/dist/chunk-TM6L7YF2.js +0 -9
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
estimateTokens: () => estimateTokens,
|
|
28
28
|
flatten: () => flatten,
|
|
29
29
|
prune: () => prune,
|
|
30
|
+
serializeForTokenEstimate: () => serializeForTokenEstimate,
|
|
30
31
|
toNatural: () => toNatural,
|
|
31
32
|
toTOON: () => toTOON
|
|
32
33
|
});
|
|
@@ -53,7 +54,7 @@ function prune(obj, options = {}) {
|
|
|
53
54
|
return arr;
|
|
54
55
|
}
|
|
55
56
|
const result = {};
|
|
56
|
-
for (const key
|
|
57
|
+
for (const key of Object.keys(obj)) {
|
|
57
58
|
if (removeKeys.includes(key)) continue;
|
|
58
59
|
const value = prune(obj[key], normalizedOptions);
|
|
59
60
|
if (value === void 0) continue;
|
|
@@ -69,20 +70,28 @@ function prune(obj, options = {}) {
|
|
|
69
70
|
function flatten(obj, prefix = "", res = {}) {
|
|
70
71
|
if (obj === null || obj === void 0) return res;
|
|
71
72
|
if (typeof obj !== "object") {
|
|
72
|
-
res
|
|
73
|
+
setValue(res, prefix, obj);
|
|
73
74
|
return res;
|
|
74
75
|
}
|
|
75
|
-
for (const key
|
|
76
|
+
for (const key of Object.keys(obj)) {
|
|
76
77
|
const value = obj[key];
|
|
77
78
|
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
78
79
|
if (typeof value === "object" && value !== null) {
|
|
79
80
|
flatten(value, newKey, res);
|
|
80
81
|
} else {
|
|
81
|
-
res
|
|
82
|
+
setValue(res, newKey, value);
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
return res;
|
|
85
86
|
}
|
|
87
|
+
function setValue(res, key, value) {
|
|
88
|
+
if (Object.prototype.hasOwnProperty.call(res, key)) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Cannot flatten input: the path "${key}" collides with an existing key. Use keys without dots or rename one of the conflicting properties.`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
res[key] = value;
|
|
94
|
+
}
|
|
86
95
|
|
|
87
96
|
// src/core/compact.ts
|
|
88
97
|
function compact(obj) {
|
|
@@ -106,11 +115,11 @@ function toTOON(data, indent = 0) {
|
|
|
106
115
|
}
|
|
107
116
|
return result;
|
|
108
117
|
}
|
|
109
|
-
return `${space}[${data.length}]: ${data.join(",")}`;
|
|
118
|
+
return `${space}[${data.length}]: ${data.map(formatValue).join(",")}`;
|
|
110
119
|
}
|
|
111
120
|
if (typeof data === "object" && data !== null) {
|
|
112
121
|
let result = "";
|
|
113
|
-
for (const key
|
|
122
|
+
for (const key of Object.keys(data)) {
|
|
114
123
|
const value = data[key];
|
|
115
124
|
if (typeof value === "object" && value !== null) {
|
|
116
125
|
result += `${space}${key}:
|
|
@@ -129,7 +138,9 @@ ${toTOON(value, indent + 1)}
|
|
|
129
138
|
}
|
|
130
139
|
function formatValue(val) {
|
|
131
140
|
if (val === null || val === void 0) return "";
|
|
132
|
-
if (typeof val === "string")
|
|
141
|
+
if (typeof val === "string") {
|
|
142
|
+
return val === "" || /[,\n\r]/.test(val) ? JSON.stringify(val) : val;
|
|
143
|
+
}
|
|
133
144
|
return String(val);
|
|
134
145
|
}
|
|
135
146
|
function isPlainObject(value) {
|
|
@@ -137,13 +148,63 @@ function isPlainObject(value) {
|
|
|
137
148
|
}
|
|
138
149
|
|
|
139
150
|
// src/core/token.ts
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
151
|
+
var import_node_module = require("module");
|
|
152
|
+
var import_meta = {};
|
|
153
|
+
var require2 = (0, import_node_module.createRequire)(import_meta.url);
|
|
154
|
+
function serializeForTokenEstimate(value) {
|
|
155
|
+
if (typeof value === "string") return value;
|
|
156
|
+
const serialized = JSON.stringify(value);
|
|
157
|
+
return serialized ?? "";
|
|
158
|
+
}
|
|
159
|
+
function estimateTokensHeuristic(value) {
|
|
160
|
+
return Math.ceil(serializeForTokenEstimate(value).length / 4);
|
|
161
|
+
}
|
|
162
|
+
function estimateTokens(value, options = {}) {
|
|
163
|
+
return estimateTokensWithMeta(value, options).count;
|
|
164
|
+
}
|
|
165
|
+
function estimateTokensWithMeta(value, options = {}) {
|
|
166
|
+
const { exact = false, model = "gpt-4o-mini", fallbackToHeuristic = true } = options;
|
|
167
|
+
const heuristic = estimateTokensHeuristic(value);
|
|
168
|
+
const heuristicEstimator = "heuristic: 1 token \u2248 4 characters";
|
|
169
|
+
if (!exact) {
|
|
170
|
+
return { count: heuristic, estimator: heuristicEstimator };
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const tiktoken = require2("tiktoken");
|
|
174
|
+
const encoder = tiktoken.encoding_for_model(model);
|
|
175
|
+
const text = serializeForTokenEstimate(value);
|
|
176
|
+
const count = encoder.encode(text).length;
|
|
177
|
+
let encodingName = null;
|
|
178
|
+
if (encoder.name) encodingName = encoder.name;
|
|
179
|
+
if (!encodingName && typeof tiktoken.model_to_encoding === "function") {
|
|
180
|
+
try {
|
|
181
|
+
encodingName = tiktoken.model_to_encoding(model);
|
|
182
|
+
} catch (e) {
|
|
183
|
+
encodingName = null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (!encodingName) {
|
|
187
|
+
const m = String(model || "").toLowerCase();
|
|
188
|
+
if (m.includes("davinci") || m.startsWith("text-")) encodingName = "r50k_base";
|
|
189
|
+
else encodingName = "cl100k_base";
|
|
190
|
+
}
|
|
191
|
+
const estimator = `exact tokenizer: model=${model} encoding=${encodingName}`;
|
|
192
|
+
return { count, estimator };
|
|
193
|
+
} catch (e) {
|
|
194
|
+
if (!fallbackToHeuristic) {
|
|
195
|
+
return { count: heuristic, estimator: "exact requested but tokenizer unavailable" };
|
|
196
|
+
}
|
|
197
|
+
return { count: heuristic, estimator: heuristicEstimator };
|
|
198
|
+
}
|
|
143
199
|
}
|
|
144
200
|
|
|
145
201
|
// src/core/analyze.ts
|
|
146
202
|
function analyze(input, options = {}) {
|
|
203
|
+
const {
|
|
204
|
+
exact = false,
|
|
205
|
+
model = "gpt-4o-mini",
|
|
206
|
+
fallbackToHeuristic = true
|
|
207
|
+
} = options;
|
|
147
208
|
if (!input || typeof input === "object" && input !== null && Object.keys(input).length === 0) {
|
|
148
209
|
return {
|
|
149
210
|
originalTokens: 0,
|
|
@@ -151,11 +212,18 @@ function analyze(input, options = {}) {
|
|
|
151
212
|
savings: 0,
|
|
152
213
|
savingsPercent: 0,
|
|
153
214
|
optimizedData: null,
|
|
154
|
-
reductionRatio: 1
|
|
215
|
+
reductionRatio: 1,
|
|
216
|
+
originalCharacters: 0,
|
|
217
|
+
optimizedCharacters: 0,
|
|
218
|
+
estimator: exact ? `exact tokenizer: model=${model}` : "heuristic: 1 token \u2248 4 characters"
|
|
155
219
|
};
|
|
156
220
|
}
|
|
157
|
-
|
|
158
|
-
|
|
221
|
+
const originalMeta = estimateTokensWithMeta(input, {
|
|
222
|
+
exact,
|
|
223
|
+
model,
|
|
224
|
+
fallbackToHeuristic
|
|
225
|
+
});
|
|
226
|
+
const originalTokens = originalMeta.count;
|
|
159
227
|
let optimizedData = input;
|
|
160
228
|
if (options.prune && Array.isArray(options.prune)) {
|
|
161
229
|
optimizedData = prune(optimizedData, options.prune);
|
|
@@ -169,18 +237,26 @@ function analyze(input, options = {}) {
|
|
|
169
237
|
if (options.toTOON === true || options.toon === true) {
|
|
170
238
|
optimizedData = toTOON(optimizedData);
|
|
171
239
|
}
|
|
172
|
-
|
|
173
|
-
|
|
240
|
+
const optimizedMeta = estimateTokensWithMeta(optimizedData, {
|
|
241
|
+
exact,
|
|
242
|
+
model,
|
|
243
|
+
fallbackToHeuristic
|
|
244
|
+
});
|
|
245
|
+
const optimizedTokens = optimizedMeta.count;
|
|
174
246
|
const savings = Math.max(0, originalTokens - optimizedTokens);
|
|
175
247
|
const savingsPercent = originalTokens > 0 ? Math.round(savings / originalTokens * 100) : 0;
|
|
176
248
|
const reductionRatio = originalTokens > 0 ? optimizedTokens / originalTokens : 1;
|
|
249
|
+
const estimatorLabel = originalMeta && originalMeta.estimator ? originalMeta.estimator : optimizedMeta.estimator;
|
|
177
250
|
return {
|
|
178
251
|
originalTokens,
|
|
179
252
|
optimizedTokens,
|
|
180
253
|
savings,
|
|
181
254
|
savingsPercent,
|
|
182
255
|
optimizedData,
|
|
183
|
-
reductionRatio
|
|
256
|
+
reductionRatio,
|
|
257
|
+
originalCharacters: serializeForTokenEstimate(input).length,
|
|
258
|
+
optimizedCharacters: serializeForTokenEstimate(optimizedData).length,
|
|
259
|
+
estimator: estimatorLabel
|
|
184
260
|
};
|
|
185
261
|
}
|
|
186
262
|
|
|
@@ -310,8 +386,8 @@ var AIChain = class {
|
|
|
310
386
|
toNatural() {
|
|
311
387
|
return toNatural(this.data);
|
|
312
388
|
}
|
|
313
|
-
analyze() {
|
|
314
|
-
return analyze(this.data);
|
|
389
|
+
analyze(options) {
|
|
390
|
+
return analyze(this.data, options);
|
|
315
391
|
}
|
|
316
392
|
value() {
|
|
317
393
|
return this.data;
|
|
@@ -329,6 +405,7 @@ ai.toTOON = toTOON;
|
|
|
329
405
|
ai.analyze = analyze;
|
|
330
406
|
ai.toNatural = toNatural;
|
|
331
407
|
ai.estimateTokens = estimateTokens;
|
|
408
|
+
ai.serializeForTokenEstimate = serializeForTokenEstimate;
|
|
332
409
|
ai.AIChain = AIChain;
|
|
333
410
|
var index_default = ai;
|
|
334
411
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -339,6 +416,7 @@ var index_default = ai;
|
|
|
339
416
|
estimateTokens,
|
|
340
417
|
flatten,
|
|
341
418
|
prune,
|
|
419
|
+
serializeForTokenEstimate,
|
|
342
420
|
toNatural,
|
|
343
421
|
toTOON
|
|
344
422
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { estimateTokens } from './core/token.cjs';
|
|
2
|
-
import { toNatural } from './core/natural.cjs';
|
|
3
|
-
import { analyze } from './core/analyze.cjs';
|
|
4
|
-
import { toTOON } from './core/toon.cjs';
|
|
5
|
-
import { flatten } from './core/flatten.cjs';
|
|
6
|
-
import { compact } from './core/compact.cjs';
|
|
7
1
|
import { prune } from './core/prune.cjs';
|
|
2
|
+
import { compact } from './core/compact.cjs';
|
|
3
|
+
import { flatten } from './core/flatten.cjs';
|
|
4
|
+
import { toTOON } from './core/toon.cjs';
|
|
5
|
+
import { analyze } from './core/analyze.cjs';
|
|
6
|
+
import { toNatural } from './core/natural.cjs';
|
|
7
|
+
import { estimateTokens, serializeForTokenEstimate } from './core/token.cjs';
|
|
8
8
|
|
|
9
9
|
declare class AIChain {
|
|
10
10
|
private data;
|
|
@@ -14,13 +14,16 @@ declare class AIChain {
|
|
|
14
14
|
flatten(): this;
|
|
15
15
|
toTOON(): this;
|
|
16
16
|
toNatural(): string;
|
|
17
|
-
analyze(): {
|
|
17
|
+
analyze(options?: any): {
|
|
18
18
|
originalTokens: number;
|
|
19
19
|
optimizedTokens: number;
|
|
20
20
|
savings: number;
|
|
21
21
|
savingsPercent: number;
|
|
22
|
-
optimizedData:
|
|
22
|
+
optimizedData: unknown;
|
|
23
23
|
reductionRatio: number;
|
|
24
|
+
originalCharacters: number;
|
|
25
|
+
optimizedCharacters: number;
|
|
26
|
+
estimator: string;
|
|
24
27
|
};
|
|
25
28
|
value(): any;
|
|
26
29
|
}
|
|
@@ -34,7 +37,8 @@ declare namespace ai {
|
|
|
34
37
|
var analyze: typeof analyze;
|
|
35
38
|
var toNatural: typeof toNatural;
|
|
36
39
|
var estimateTokens: typeof estimateTokens;
|
|
40
|
+
var serializeForTokenEstimate: typeof serializeForTokenEstimate;
|
|
37
41
|
var AIChain: typeof AIChain;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
export { AIChain, analyze, compact, ai as default, estimateTokens, flatten, prune, toNatural, toTOON };
|
|
44
|
+
export { AIChain, analyze, compact, ai as default, estimateTokens, flatten, prune, serializeForTokenEstimate, toNatural, toTOON };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { estimateTokens } from './core/token.js';
|
|
2
|
-
import { toNatural } from './core/natural.js';
|
|
3
|
-
import { analyze } from './core/analyze.js';
|
|
4
|
-
import { toTOON } from './core/toon.js';
|
|
5
|
-
import { flatten } from './core/flatten.js';
|
|
6
|
-
import { compact } from './core/compact.js';
|
|
7
1
|
import { prune } from './core/prune.js';
|
|
2
|
+
import { compact } from './core/compact.js';
|
|
3
|
+
import { flatten } from './core/flatten.js';
|
|
4
|
+
import { toTOON } from './core/toon.js';
|
|
5
|
+
import { analyze } from './core/analyze.js';
|
|
6
|
+
import { toNatural } from './core/natural.js';
|
|
7
|
+
import { estimateTokens, serializeForTokenEstimate } from './core/token.js';
|
|
8
8
|
|
|
9
9
|
declare class AIChain {
|
|
10
10
|
private data;
|
|
@@ -14,13 +14,16 @@ declare class AIChain {
|
|
|
14
14
|
flatten(): this;
|
|
15
15
|
toTOON(): this;
|
|
16
16
|
toNatural(): string;
|
|
17
|
-
analyze(): {
|
|
17
|
+
analyze(options?: any): {
|
|
18
18
|
originalTokens: number;
|
|
19
19
|
optimizedTokens: number;
|
|
20
20
|
savings: number;
|
|
21
21
|
savingsPercent: number;
|
|
22
|
-
optimizedData:
|
|
22
|
+
optimizedData: unknown;
|
|
23
23
|
reductionRatio: number;
|
|
24
|
+
originalCharacters: number;
|
|
25
|
+
optimizedCharacters: number;
|
|
26
|
+
estimator: string;
|
|
24
27
|
};
|
|
25
28
|
value(): any;
|
|
26
29
|
}
|
|
@@ -34,7 +37,8 @@ declare namespace ai {
|
|
|
34
37
|
var analyze: typeof analyze;
|
|
35
38
|
var toNatural: typeof toNatural;
|
|
36
39
|
var estimateTokens: typeof estimateTokens;
|
|
40
|
+
var serializeForTokenEstimate: typeof serializeForTokenEstimate;
|
|
37
41
|
var AIChain: typeof AIChain;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
export { AIChain, analyze, compact, ai as default, estimateTokens, flatten, prune, toNatural, toTOON };
|
|
44
|
+
export { AIChain, analyze, compact, ai as default, estimateTokens, flatten, prune, serializeForTokenEstimate, toNatural, toTOON };
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AIChain
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-P6KXISNT.js";
|
|
4
4
|
import {
|
|
5
5
|
analyze
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IOMOVRC7.js";
|
|
7
7
|
import {
|
|
8
8
|
toTOON
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-6VRLDRJK.js";
|
|
10
10
|
import {
|
|
11
11
|
compact
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XE36GLJP.js";
|
|
13
13
|
import {
|
|
14
14
|
flatten
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-L7BC62MT.js";
|
|
16
16
|
import {
|
|
17
17
|
toNatural
|
|
18
18
|
} from "./chunk-D4CFTFM3.js";
|
|
19
19
|
import {
|
|
20
20
|
prune
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ZD536GZF.js";
|
|
22
22
|
import {
|
|
23
|
-
estimateTokens
|
|
24
|
-
|
|
23
|
+
estimateTokens,
|
|
24
|
+
serializeForTokenEstimate
|
|
25
|
+
} from "./chunk-U433WUUT.js";
|
|
25
26
|
|
|
26
27
|
// src/index.ts
|
|
27
28
|
function ai(data) {
|
|
@@ -34,6 +35,7 @@ ai.toTOON = toTOON;
|
|
|
34
35
|
ai.analyze = analyze;
|
|
35
36
|
ai.toNatural = toNatural;
|
|
36
37
|
ai.estimateTokens = estimateTokens;
|
|
38
|
+
ai.serializeForTokenEstimate = serializeForTokenEstimate;
|
|
37
39
|
ai.AIChain = AIChain;
|
|
38
40
|
var index_default = ai;
|
|
39
41
|
export {
|
|
@@ -44,6 +46,7 @@ export {
|
|
|
44
46
|
estimateTokens,
|
|
45
47
|
flatten,
|
|
46
48
|
prune,
|
|
49
|
+
serializeForTokenEstimate,
|
|
47
50
|
toNatural,
|
|
48
51
|
toTOON
|
|
49
52
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sohqureshi/tokenwise",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Optimize JSON data for AI by reducing token usage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -60,6 +60,8 @@
|
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "tsup src/index.ts src/cli.ts src/core/analyze.ts src/core/compact.ts src/core/flatten.ts src/core/natural.ts src/core/prune.ts src/core/token.ts src/core/toon.ts --format esm,cjs --dts",
|
|
62
62
|
"test": "vitest",
|
|
63
|
+
"test:run": "vitest run",
|
|
64
|
+
"typecheck": "tsc --noEmit",
|
|
63
65
|
"prepare": "npm run build"
|
|
64
66
|
},
|
|
65
67
|
"keywords": [
|
|
@@ -73,6 +75,9 @@
|
|
|
73
75
|
],
|
|
74
76
|
"author": "Mohammad Sohail",
|
|
75
77
|
"license": "MIT",
|
|
78
|
+
"dependencies": {
|
|
79
|
+
"tiktoken": "^1.0.22"
|
|
80
|
+
},
|
|
76
81
|
"devDependencies": {
|
|
77
82
|
"@types/node": "^25.6.0",
|
|
78
83
|
"tsup": "^8.0.0",
|