smoltalk 0.0.19 → 0.0.20
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/dist/client.js +9 -5
- package/dist/functions.js +3 -1
- package/dist/models.d.ts +38 -2
- package/dist/models.js +90 -0
- package/dist/types.d.ts +7 -4
- package/package.json +3 -3
package/dist/client.js
CHANGED
|
@@ -4,25 +4,29 @@ export * from "./clients/openaiResponses.js";
|
|
|
4
4
|
import { SmolGoogle } from "./clients/google.js";
|
|
5
5
|
import { SmolOpenAi } from "./clients/openai.js";
|
|
6
6
|
import { SmolOpenAiResponses } from "./clients/openaiResponses.js";
|
|
7
|
-
import { getModel, isTextModel } from "./models.js";
|
|
7
|
+
import { getModel, isModelConfig, isTextModel, pickModel } from "./models.js";
|
|
8
8
|
import { SmolError } from "./smolError.js";
|
|
9
9
|
import { getLogger } from "./logger.js";
|
|
10
10
|
import { SmolOllama } from "./clients/ollama.js";
|
|
11
11
|
export function getClient(config) {
|
|
12
12
|
// Initialize logger singleton with desired log level
|
|
13
13
|
const logger = getLogger(config.logLevel);
|
|
14
|
+
// Resolve ModelConfig to a concrete model name
|
|
15
|
+
const modelName = isModelConfig(config.model)
|
|
16
|
+
? pickModel(config.model)
|
|
17
|
+
: config.model;
|
|
14
18
|
let provider = config.provider;
|
|
15
19
|
if (!provider) {
|
|
16
|
-
const model = getModel(
|
|
20
|
+
const model = getModel(modelName);
|
|
17
21
|
if (model === undefined) {
|
|
18
|
-
throw new SmolError(`Model ${
|
|
22
|
+
throw new SmolError(`Model ${modelName} is not recognized. Please specify a known model, or explicitly set the provider option in the config.`);
|
|
19
23
|
}
|
|
20
24
|
if (!isTextModel(model)) {
|
|
21
|
-
throw new SmolError(`Only text models are supported currently. ${
|
|
25
|
+
throw new SmolError(`Only text models are supported currently. ${modelName} is a ${model?.type} model.`);
|
|
22
26
|
}
|
|
23
27
|
provider = model.provider;
|
|
24
28
|
}
|
|
25
|
-
const clientConfig = { ...config };
|
|
29
|
+
const clientConfig = { ...config, model: modelName };
|
|
26
30
|
switch (provider) {
|
|
27
31
|
case "openai":
|
|
28
32
|
if (!config.openAiApiKey) {
|
package/dist/functions.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getClient } from "./client.js";
|
|
2
|
+
import { isModelConfig, pickModel } from "./models.js";
|
|
2
3
|
function splitConfig(config) {
|
|
3
|
-
const { openAiApiKey, googleApiKey, ollamaApiKey, ollamaHost, model, provider, logLevel, toolLoopDetection, ...promptConfig } = config;
|
|
4
|
+
const { openAiApiKey, googleApiKey, ollamaApiKey, ollamaHost, model: rawModel, provider, logLevel, toolLoopDetection, ...promptConfig } = config;
|
|
5
|
+
const model = isModelConfig(rawModel) ? pickModel(rawModel) : rawModel;
|
|
4
6
|
return {
|
|
5
7
|
smolConfig: {
|
|
6
8
|
openAiApiKey,
|
package/dist/models.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type Provider = "local" | "ollama" | "openai" | "openai-responses" | "anthropic" | "google" | "replicate" | "modal";
|
|
2
2
|
export type BaseModel = {
|
|
3
3
|
modelName: string;
|
|
4
|
-
provider:
|
|
4
|
+
provider: Provider;
|
|
5
5
|
description?: string;
|
|
6
6
|
inputTokenCost?: number;
|
|
7
7
|
cachedInputTokenCost?: number;
|
|
@@ -23,6 +23,7 @@ export type TextModel = BaseModel & {
|
|
|
23
23
|
modelName: string;
|
|
24
24
|
maxInputTokens: number;
|
|
25
25
|
maxOutputTokens: number;
|
|
26
|
+
outputTokensPerSecond?: number;
|
|
26
27
|
};
|
|
27
28
|
export type EmbeddingsModel = {
|
|
28
29
|
type: "embeddings";
|
|
@@ -49,6 +50,7 @@ export declare const textModels: readonly [{
|
|
|
49
50
|
readonly inputTokenCost: 0.15;
|
|
50
51
|
readonly cachedInputTokenCost: 0.075;
|
|
51
52
|
readonly outputTokenCost: 0.6;
|
|
53
|
+
readonly outputTokensPerSecond: 65;
|
|
52
54
|
readonly provider: "openai";
|
|
53
55
|
}, {
|
|
54
56
|
readonly type: "text";
|
|
@@ -59,6 +61,7 @@ export declare const textModels: readonly [{
|
|
|
59
61
|
readonly inputTokenCost: 2.5;
|
|
60
62
|
readonly cachedInputTokenCost: 1.25;
|
|
61
63
|
readonly outputTokenCost: 10;
|
|
64
|
+
readonly outputTokensPerSecond: 143;
|
|
62
65
|
readonly provider: "openai";
|
|
63
66
|
}, {
|
|
64
67
|
readonly type: "text";
|
|
@@ -69,6 +72,7 @@ export declare const textModels: readonly [{
|
|
|
69
72
|
readonly inputTokenCost: 2;
|
|
70
73
|
readonly cachedInputTokenCost: 0.5;
|
|
71
74
|
readonly outputTokenCost: 8;
|
|
75
|
+
readonly outputTokensPerSecond: 94;
|
|
72
76
|
readonly provider: "openai";
|
|
73
77
|
}, {
|
|
74
78
|
readonly type: "text";
|
|
@@ -79,6 +83,7 @@ export declare const textModels: readonly [{
|
|
|
79
83
|
readonly inputTokenCost: 1.1;
|
|
80
84
|
readonly cachedInputTokenCost: 0.55;
|
|
81
85
|
readonly outputTokenCost: 4.4;
|
|
86
|
+
readonly outputTokensPerSecond: 214;
|
|
82
87
|
readonly provider: "openai";
|
|
83
88
|
}, {
|
|
84
89
|
readonly type: "text";
|
|
@@ -89,6 +94,7 @@ export declare const textModels: readonly [{
|
|
|
89
94
|
readonly inputTokenCost: 1.1;
|
|
90
95
|
readonly cachedInputTokenCost: 0.55;
|
|
91
96
|
readonly outputTokenCost: 4.4;
|
|
97
|
+
readonly outputTokensPerSecond: 135;
|
|
92
98
|
readonly provider: "openai";
|
|
93
99
|
}, {
|
|
94
100
|
readonly type: "text";
|
|
@@ -99,6 +105,7 @@ export declare const textModels: readonly [{
|
|
|
99
105
|
readonly inputTokenCost: 15;
|
|
100
106
|
readonly cachedInputTokenCost: 7.5;
|
|
101
107
|
readonly outputTokenCost: 60;
|
|
108
|
+
readonly outputTokensPerSecond: 100;
|
|
102
109
|
readonly provider: "openai";
|
|
103
110
|
}, {
|
|
104
111
|
readonly type: "text";
|
|
@@ -166,6 +173,7 @@ export declare const textModels: readonly [{
|
|
|
166
173
|
readonly maxOutputTokens: 8192;
|
|
167
174
|
readonly inputTokenCost: 1.25;
|
|
168
175
|
readonly outputTokenCost: 10;
|
|
176
|
+
readonly outputTokensPerSecond: 175;
|
|
169
177
|
readonly provider: "google";
|
|
170
178
|
}, {
|
|
171
179
|
readonly type: "text";
|
|
@@ -175,6 +183,7 @@ export declare const textModels: readonly [{
|
|
|
175
183
|
readonly maxOutputTokens: 8192;
|
|
176
184
|
readonly inputTokenCost: 0.3;
|
|
177
185
|
readonly outputTokenCost: 2.5;
|
|
186
|
+
readonly outputTokensPerSecond: 225;
|
|
178
187
|
readonly provider: "google";
|
|
179
188
|
}, {
|
|
180
189
|
readonly type: "text";
|
|
@@ -184,6 +193,7 @@ export declare const textModels: readonly [{
|
|
|
184
193
|
readonly maxOutputTokens: 8192;
|
|
185
194
|
readonly inputTokenCost: 0.1;
|
|
186
195
|
readonly outputTokenCost: 0.4;
|
|
196
|
+
readonly outputTokensPerSecond: 400;
|
|
187
197
|
readonly provider: "google";
|
|
188
198
|
}, {
|
|
189
199
|
readonly type: "text";
|
|
@@ -193,6 +203,7 @@ export declare const textModels: readonly [{
|
|
|
193
203
|
readonly maxOutputTokens: 8192;
|
|
194
204
|
readonly inputTokenCost: 0.1;
|
|
195
205
|
readonly outputTokenCost: 0.4;
|
|
206
|
+
readonly outputTokensPerSecond: 213;
|
|
196
207
|
readonly disabled: true;
|
|
197
208
|
readonly provider: "google";
|
|
198
209
|
}, {
|
|
@@ -222,6 +233,7 @@ export declare const textModels: readonly [{
|
|
|
222
233
|
readonly maxOutputTokens: 8192;
|
|
223
234
|
readonly inputTokenCost: 0.01875;
|
|
224
235
|
readonly outputTokenCost: 0.075;
|
|
236
|
+
readonly outputTokensPerSecond: 178;
|
|
225
237
|
readonly costUnit: "characters";
|
|
226
238
|
readonly provider: "google";
|
|
227
239
|
}, {
|
|
@@ -232,6 +244,7 @@ export declare const textModels: readonly [{
|
|
|
232
244
|
readonly maxOutputTokens: 8192;
|
|
233
245
|
readonly inputTokenCost: 0.3125;
|
|
234
246
|
readonly outputTokenCost: 1.25;
|
|
247
|
+
readonly outputTokensPerSecond: 59;
|
|
235
248
|
readonly costUnit: "characters";
|
|
236
249
|
readonly provider: "google";
|
|
237
250
|
}, {
|
|
@@ -252,6 +265,7 @@ export declare const textModels: readonly [{
|
|
|
252
265
|
readonly maxOutputTokens: 8192;
|
|
253
266
|
readonly inputTokenCost: 3;
|
|
254
267
|
readonly outputTokenCost: 15;
|
|
268
|
+
readonly outputTokensPerSecond: 78;
|
|
255
269
|
readonly provider: "anthropic";
|
|
256
270
|
}, {
|
|
257
271
|
readonly type: "text";
|
|
@@ -261,6 +275,7 @@ export declare const textModels: readonly [{
|
|
|
261
275
|
readonly maxOutputTokens: 8192;
|
|
262
276
|
readonly inputTokenCost: 0.8;
|
|
263
277
|
readonly outputTokenCost: 4;
|
|
278
|
+
readonly outputTokensPerSecond: 66;
|
|
264
279
|
readonly provider: "anthropic";
|
|
265
280
|
}, {
|
|
266
281
|
readonly type: "text";
|
|
@@ -352,6 +367,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
352
367
|
readonly inputTokenCost: 0.15;
|
|
353
368
|
readonly cachedInputTokenCost: 0.075;
|
|
354
369
|
readonly outputTokenCost: 0.6;
|
|
370
|
+
readonly outputTokensPerSecond: 65;
|
|
355
371
|
readonly provider: "openai";
|
|
356
372
|
} | {
|
|
357
373
|
readonly type: "text";
|
|
@@ -362,6 +378,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
362
378
|
readonly inputTokenCost: 2.5;
|
|
363
379
|
readonly cachedInputTokenCost: 1.25;
|
|
364
380
|
readonly outputTokenCost: 10;
|
|
381
|
+
readonly outputTokensPerSecond: 143;
|
|
365
382
|
readonly provider: "openai";
|
|
366
383
|
} | {
|
|
367
384
|
readonly type: "text";
|
|
@@ -372,6 +389,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
372
389
|
readonly inputTokenCost: 2;
|
|
373
390
|
readonly cachedInputTokenCost: 0.5;
|
|
374
391
|
readonly outputTokenCost: 8;
|
|
392
|
+
readonly outputTokensPerSecond: 94;
|
|
375
393
|
readonly provider: "openai";
|
|
376
394
|
} | {
|
|
377
395
|
readonly type: "text";
|
|
@@ -382,6 +400,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
382
400
|
readonly inputTokenCost: 1.1;
|
|
383
401
|
readonly cachedInputTokenCost: 0.55;
|
|
384
402
|
readonly outputTokenCost: 4.4;
|
|
403
|
+
readonly outputTokensPerSecond: 214;
|
|
385
404
|
readonly provider: "openai";
|
|
386
405
|
} | {
|
|
387
406
|
readonly type: "text";
|
|
@@ -392,6 +411,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
392
411
|
readonly inputTokenCost: 1.1;
|
|
393
412
|
readonly cachedInputTokenCost: 0.55;
|
|
394
413
|
readonly outputTokenCost: 4.4;
|
|
414
|
+
readonly outputTokensPerSecond: 135;
|
|
395
415
|
readonly provider: "openai";
|
|
396
416
|
} | {
|
|
397
417
|
readonly type: "text";
|
|
@@ -402,6 +422,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
402
422
|
readonly inputTokenCost: 15;
|
|
403
423
|
readonly cachedInputTokenCost: 7.5;
|
|
404
424
|
readonly outputTokenCost: 60;
|
|
425
|
+
readonly outputTokensPerSecond: 100;
|
|
405
426
|
readonly provider: "openai";
|
|
406
427
|
} | {
|
|
407
428
|
readonly type: "text";
|
|
@@ -469,6 +490,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
469
490
|
readonly maxOutputTokens: 8192;
|
|
470
491
|
readonly inputTokenCost: 1.25;
|
|
471
492
|
readonly outputTokenCost: 10;
|
|
493
|
+
readonly outputTokensPerSecond: 175;
|
|
472
494
|
readonly provider: "google";
|
|
473
495
|
} | {
|
|
474
496
|
readonly type: "text";
|
|
@@ -478,6 +500,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
478
500
|
readonly maxOutputTokens: 8192;
|
|
479
501
|
readonly inputTokenCost: 0.3;
|
|
480
502
|
readonly outputTokenCost: 2.5;
|
|
503
|
+
readonly outputTokensPerSecond: 225;
|
|
481
504
|
readonly provider: "google";
|
|
482
505
|
} | {
|
|
483
506
|
readonly type: "text";
|
|
@@ -487,6 +510,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
487
510
|
readonly maxOutputTokens: 8192;
|
|
488
511
|
readonly inputTokenCost: 0.1;
|
|
489
512
|
readonly outputTokenCost: 0.4;
|
|
513
|
+
readonly outputTokensPerSecond: 400;
|
|
490
514
|
readonly provider: "google";
|
|
491
515
|
} | {
|
|
492
516
|
readonly type: "text";
|
|
@@ -496,6 +520,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
496
520
|
readonly maxOutputTokens: 8192;
|
|
497
521
|
readonly inputTokenCost: 0.1;
|
|
498
522
|
readonly outputTokenCost: 0.4;
|
|
523
|
+
readonly outputTokensPerSecond: 213;
|
|
499
524
|
readonly disabled: true;
|
|
500
525
|
readonly provider: "google";
|
|
501
526
|
} | {
|
|
@@ -525,6 +550,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
525
550
|
readonly maxOutputTokens: 8192;
|
|
526
551
|
readonly inputTokenCost: 0.01875;
|
|
527
552
|
readonly outputTokenCost: 0.075;
|
|
553
|
+
readonly outputTokensPerSecond: 178;
|
|
528
554
|
readonly costUnit: "characters";
|
|
529
555
|
readonly provider: "google";
|
|
530
556
|
} | {
|
|
@@ -535,6 +561,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
535
561
|
readonly maxOutputTokens: 8192;
|
|
536
562
|
readonly inputTokenCost: 0.3125;
|
|
537
563
|
readonly outputTokenCost: 1.25;
|
|
564
|
+
readonly outputTokensPerSecond: 59;
|
|
538
565
|
readonly costUnit: "characters";
|
|
539
566
|
readonly provider: "google";
|
|
540
567
|
} | {
|
|
@@ -555,6 +582,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
555
582
|
readonly maxOutputTokens: 8192;
|
|
556
583
|
readonly inputTokenCost: 3;
|
|
557
584
|
readonly outputTokenCost: 15;
|
|
585
|
+
readonly outputTokensPerSecond: 78;
|
|
558
586
|
readonly provider: "anthropic";
|
|
559
587
|
} | {
|
|
560
588
|
readonly type: "text";
|
|
@@ -564,6 +592,7 @@ export declare function getModel(modelName: ModelName): {
|
|
|
564
592
|
readonly maxOutputTokens: 8192;
|
|
565
593
|
readonly inputTokenCost: 0.8;
|
|
566
594
|
readonly outputTokenCost: 4;
|
|
595
|
+
readonly outputTokensPerSecond: 66;
|
|
567
596
|
readonly provider: "anthropic";
|
|
568
597
|
} | {
|
|
569
598
|
readonly type: "text";
|
|
@@ -630,6 +659,13 @@ export declare function isImageModel(model: Model): model is ImageModel;
|
|
|
630
659
|
export declare function isTextModel(model: Model): model is TextModel;
|
|
631
660
|
export declare function isSpeechToTextModel(model: Model): model is SpeechToTextModel;
|
|
632
661
|
export declare function isEmbeddingsModel(model: Model): model is EmbeddingsModel;
|
|
662
|
+
export type Optimization = "speed" | "accuracy" | "cost" | "large-context";
|
|
663
|
+
export type ModelConfig = {
|
|
664
|
+
optimizeFor: Optimization[];
|
|
665
|
+
providers: Provider[];
|
|
666
|
+
};
|
|
667
|
+
export declare function isModelConfig(model: ModelName | ModelConfig): model is ModelConfig;
|
|
668
|
+
export declare function pickModel(config: ModelConfig, models?: readonly (typeof textModels)[number][]): TextModelName;
|
|
633
669
|
export declare function calculateCost(modelName: ModelName, usage: {
|
|
634
670
|
inputTokens: number;
|
|
635
671
|
outputTokens: number;
|
package/dist/models.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SmolError } from "./smolError.js";
|
|
1
2
|
import { round } from "./util.js";
|
|
2
3
|
export const speechToTextModels = [
|
|
3
4
|
{ type: "speech-to-text", modelName: "whisper-local", provider: "local" },
|
|
@@ -28,6 +29,7 @@ export const textModels = [
|
|
|
28
29
|
inputTokenCost: 0.15,
|
|
29
30
|
cachedInputTokenCost: 0.075,
|
|
30
31
|
outputTokenCost: 0.6,
|
|
32
|
+
outputTokensPerSecond: 65,
|
|
31
33
|
provider: "openai",
|
|
32
34
|
},
|
|
33
35
|
{
|
|
@@ -39,6 +41,7 @@ export const textModels = [
|
|
|
39
41
|
inputTokenCost: 2.5,
|
|
40
42
|
cachedInputTokenCost: 1.25,
|
|
41
43
|
outputTokenCost: 10,
|
|
44
|
+
outputTokensPerSecond: 143,
|
|
42
45
|
provider: "openai",
|
|
43
46
|
},
|
|
44
47
|
{
|
|
@@ -50,6 +53,7 @@ export const textModels = [
|
|
|
50
53
|
inputTokenCost: 2,
|
|
51
54
|
cachedInputTokenCost: 0.5,
|
|
52
55
|
outputTokenCost: 8,
|
|
56
|
+
outputTokensPerSecond: 94,
|
|
53
57
|
provider: "openai",
|
|
54
58
|
},
|
|
55
59
|
{
|
|
@@ -61,6 +65,7 @@ export const textModels = [
|
|
|
61
65
|
inputTokenCost: 1.1,
|
|
62
66
|
cachedInputTokenCost: 0.55,
|
|
63
67
|
outputTokenCost: 4.4,
|
|
68
|
+
outputTokensPerSecond: 214,
|
|
64
69
|
provider: "openai",
|
|
65
70
|
},
|
|
66
71
|
{
|
|
@@ -72,6 +77,7 @@ export const textModels = [
|
|
|
72
77
|
inputTokenCost: 1.1,
|
|
73
78
|
cachedInputTokenCost: 0.55,
|
|
74
79
|
outputTokenCost: 4.4,
|
|
80
|
+
outputTokensPerSecond: 135,
|
|
75
81
|
provider: "openai",
|
|
76
82
|
},
|
|
77
83
|
{
|
|
@@ -83,6 +89,7 @@ export const textModels = [
|
|
|
83
89
|
inputTokenCost: 15,
|
|
84
90
|
cachedInputTokenCost: 7.5,
|
|
85
91
|
outputTokenCost: 60,
|
|
92
|
+
outputTokensPerSecond: 100,
|
|
86
93
|
provider: "openai",
|
|
87
94
|
},
|
|
88
95
|
{
|
|
@@ -157,6 +164,7 @@ export const textModels = [
|
|
|
157
164
|
maxOutputTokens: 8192,
|
|
158
165
|
inputTokenCost: 1.25,
|
|
159
166
|
outputTokenCost: 10.0,
|
|
167
|
+
outputTokensPerSecond: 175,
|
|
160
168
|
provider: "google",
|
|
161
169
|
},
|
|
162
170
|
{
|
|
@@ -167,6 +175,7 @@ export const textModels = [
|
|
|
167
175
|
maxOutputTokens: 8192,
|
|
168
176
|
inputTokenCost: 0.3,
|
|
169
177
|
outputTokenCost: 2.5,
|
|
178
|
+
outputTokensPerSecond: 225,
|
|
170
179
|
provider: "google",
|
|
171
180
|
},
|
|
172
181
|
{
|
|
@@ -177,6 +186,7 @@ export const textModels = [
|
|
|
177
186
|
maxOutputTokens: 8192,
|
|
178
187
|
inputTokenCost: 0.1,
|
|
179
188
|
outputTokenCost: 0.4,
|
|
189
|
+
outputTokensPerSecond: 400,
|
|
180
190
|
provider: "google",
|
|
181
191
|
},
|
|
182
192
|
{
|
|
@@ -187,6 +197,7 @@ export const textModels = [
|
|
|
187
197
|
maxOutputTokens: 8192,
|
|
188
198
|
inputTokenCost: 0.1,
|
|
189
199
|
outputTokenCost: 0.4,
|
|
200
|
+
outputTokensPerSecond: 213,
|
|
190
201
|
disabled: true,
|
|
191
202
|
provider: "google",
|
|
192
203
|
},
|
|
@@ -219,6 +230,7 @@ export const textModels = [
|
|
|
219
230
|
maxOutputTokens: 8192,
|
|
220
231
|
inputTokenCost: 0.01875,
|
|
221
232
|
outputTokenCost: 0.075,
|
|
233
|
+
outputTokensPerSecond: 178,
|
|
222
234
|
costUnit: "characters",
|
|
223
235
|
provider: "google",
|
|
224
236
|
},
|
|
@@ -230,6 +242,7 @@ export const textModels = [
|
|
|
230
242
|
maxOutputTokens: 8192,
|
|
231
243
|
inputTokenCost: 0.3125,
|
|
232
244
|
outputTokenCost: 1.25,
|
|
245
|
+
outputTokensPerSecond: 59,
|
|
233
246
|
costUnit: "characters",
|
|
234
247
|
provider: "google",
|
|
235
248
|
},
|
|
@@ -252,6 +265,7 @@ export const textModels = [
|
|
|
252
265
|
maxOutputTokens: 8192,
|
|
253
266
|
inputTokenCost: 3,
|
|
254
267
|
outputTokenCost: 15,
|
|
268
|
+
outputTokensPerSecond: 78,
|
|
255
269
|
provider: "anthropic",
|
|
256
270
|
},
|
|
257
271
|
{
|
|
@@ -262,6 +276,7 @@ export const textModels = [
|
|
|
262
276
|
maxOutputTokens: 8192,
|
|
263
277
|
inputTokenCost: 0.8,
|
|
264
278
|
outputTokenCost: 4,
|
|
279
|
+
outputTokensPerSecond: 66,
|
|
265
280
|
provider: "anthropic",
|
|
266
281
|
},
|
|
267
282
|
/* {
|
|
@@ -388,6 +403,81 @@ export function isSpeechToTextModel(model) {
|
|
|
388
403
|
export function isEmbeddingsModel(model) {
|
|
389
404
|
return model.type === "embeddings";
|
|
390
405
|
}
|
|
406
|
+
export function isModelConfig(model) {
|
|
407
|
+
return typeof model === "object" && "optimizeFor" in model;
|
|
408
|
+
}
|
|
409
|
+
const WEIGHTS = {
|
|
410
|
+
1: [1],
|
|
411
|
+
2: [0.6, 0.4],
|
|
412
|
+
3: [0.5, 0.3, 0.2],
|
|
413
|
+
4: [0.4, 0.3, 0.2, 0.1],
|
|
414
|
+
};
|
|
415
|
+
function getRawMetric(model, optimization) {
|
|
416
|
+
const m = model;
|
|
417
|
+
switch (optimization) {
|
|
418
|
+
case "cost":
|
|
419
|
+
return (m.inputTokenCost ?? 0) + (m.outputTokenCost ?? 0);
|
|
420
|
+
case "speed":
|
|
421
|
+
return m.outputTokensPerSecond ?? 0;
|
|
422
|
+
case "accuracy":
|
|
423
|
+
return (m.inputTokenCost ?? 0) + (m.outputTokenCost ?? 0);
|
|
424
|
+
case "large-context":
|
|
425
|
+
return m.maxInputTokens;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
function isLowerBetter(optimization) {
|
|
429
|
+
return optimization === "cost";
|
|
430
|
+
}
|
|
431
|
+
export function pickModel(config, models = textModels) {
|
|
432
|
+
const candidates = models.filter((m) => config.providers.includes(m.provider) &&
|
|
433
|
+
!("disabled" in m && m.disabled));
|
|
434
|
+
if (candidates.length === 0) {
|
|
435
|
+
throw new SmolError("No models available for providers: " +
|
|
436
|
+
config.providers.join(", ") +
|
|
437
|
+
". Check that the providers have non-disabled models.");
|
|
438
|
+
}
|
|
439
|
+
if (candidates.length === 1) {
|
|
440
|
+
return candidates[0].modelName;
|
|
441
|
+
}
|
|
442
|
+
const optimizations = config.optimizeFor;
|
|
443
|
+
const weights = WEIGHTS[optimizations.length] ?? WEIGHTS[4];
|
|
444
|
+
const scores = new Map();
|
|
445
|
+
for (const c of candidates) {
|
|
446
|
+
scores.set(c.modelName, 0);
|
|
447
|
+
}
|
|
448
|
+
for (let i = 0; i < optimizations.length; i++) {
|
|
449
|
+
const opt = optimizations[i];
|
|
450
|
+
const weight = weights[i];
|
|
451
|
+
const rawValues = candidates.map((c) => getRawMetric(c, opt));
|
|
452
|
+
const min = Math.min(...rawValues);
|
|
453
|
+
const max = Math.max(...rawValues);
|
|
454
|
+
const range = max - min;
|
|
455
|
+
for (let j = 0; j < candidates.length; j++) {
|
|
456
|
+
const raw = rawValues[j];
|
|
457
|
+
let normalized;
|
|
458
|
+
if (range === 0) {
|
|
459
|
+
normalized = 0;
|
|
460
|
+
}
|
|
461
|
+
else if (isLowerBetter(opt)) {
|
|
462
|
+
normalized = (raw - min) / range;
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
normalized = (max - raw) / range;
|
|
466
|
+
}
|
|
467
|
+
scores.set(candidates[j].modelName, scores.get(candidates[j].modelName) + weight * normalized);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
let bestModel = candidates[0];
|
|
471
|
+
let bestScore = scores.get(candidates[0].modelName);
|
|
472
|
+
for (let i = 1; i < candidates.length; i++) {
|
|
473
|
+
const score = scores.get(candidates[i].modelName);
|
|
474
|
+
if (score < bestScore) {
|
|
475
|
+
bestScore = score;
|
|
476
|
+
bestModel = candidates[i];
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return bestModel.modelName;
|
|
480
|
+
}
|
|
391
481
|
export function calculateCost(modelName, usage) {
|
|
392
482
|
const model = getModel(modelName);
|
|
393
483
|
if (!model || !isTextModel(model)) {
|
package/dist/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { LogLevel } from "egonlog";
|
|
|
3
3
|
import { ZodType } from "zod";
|
|
4
4
|
import { Message } from "./classes/message/index.js";
|
|
5
5
|
import { ToolCall } from "./classes/ToolCall.js";
|
|
6
|
-
import { ModelName,
|
|
6
|
+
import { ModelConfig, ModelName, Provider } from "./models.js";
|
|
7
7
|
import { Result } from "./types/result.js";
|
|
8
8
|
export type PromptConfig = {
|
|
9
9
|
messages: Message[];
|
|
@@ -31,8 +31,8 @@ export type SmolConfig = {
|
|
|
31
31
|
googleApiKey?: string;
|
|
32
32
|
ollamaApiKey?: string;
|
|
33
33
|
ollamaHost?: string;
|
|
34
|
-
model: ModelName;
|
|
35
|
-
provider?:
|
|
34
|
+
model: ModelName | ModelConfig;
|
|
35
|
+
provider?: Provider;
|
|
36
36
|
logLevel?: LogLevel;
|
|
37
37
|
toolLoopDetection?: ToolLoopDetection;
|
|
38
38
|
};
|
|
@@ -42,7 +42,10 @@ export type ToolLoopDetection = {
|
|
|
42
42
|
intervention?: "remove-tool" | "remove-all-tools" | "throw-error" | "halt-execution";
|
|
43
43
|
excludeTools?: string[];
|
|
44
44
|
};
|
|
45
|
-
export type
|
|
45
|
+
export type ResolvedSmolConfig = Omit<SmolConfig, "model"> & {
|
|
46
|
+
model: ModelName;
|
|
47
|
+
};
|
|
48
|
+
export type BaseClientConfig = ResolvedSmolConfig & {};
|
|
46
49
|
export type TokenUsage = {
|
|
47
50
|
inputTokens: number;
|
|
48
51
|
outputTokens: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smoltalk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "A common interface for LLM APIs",
|
|
5
5
|
"homepage": "https://github.com/egonSchiele/smoltalk",
|
|
6
6
|
"scripts": {
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
],
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
20
21
|
"import": "./dist/index.js",
|
|
21
|
-
"require": "./dist/index.js"
|
|
22
|
-
"types": "./dist/index.d.ts"
|
|
22
|
+
"require": "./dist/index.js"
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"type": "module",
|