@promptbook/ollama 0.94.0-3 → 0.94.0-5

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/umd/index.umd.js CHANGED
@@ -1,15 +1,15 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('bottleneck'), require('colors'), require('openai'), require('spacetrim'), require('crypto')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'bottleneck', 'colors', 'openai', 'spacetrim', 'crypto'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-ollama"] = {}, global.Bottleneck, global.colors, global.OpenAI, global.spaceTrim, global.crypto));
5
- })(this, (function (exports, Bottleneck, colors, OpenAI, spaceTrim, crypto) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('spacetrim'), require('crypto'), require('bottleneck'), require('colors'), require('openai')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'spacetrim', 'crypto', 'bottleneck', 'colors', 'openai'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-ollama"] = {}, global.spaceTrim, global.crypto, global.Bottleneck, global.colors, global.OpenAI));
5
+ })(this, (function (exports, spaceTrim, crypto, Bottleneck, colors, OpenAI) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
+ var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
9
10
  var Bottleneck__default = /*#__PURE__*/_interopDefaultLegacy(Bottleneck);
10
11
  var colors__default = /*#__PURE__*/_interopDefaultLegacy(colors);
11
12
  var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
12
- var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
13
13
 
14
14
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
15
15
  /**
@@ -25,51 +25,121 @@
25
25
  * @generated
26
26
  * @see https://github.com/webgptorg/promptbook
27
27
  */
28
- const PROMPTBOOK_ENGINE_VERSION = '0.94.0-3';
28
+ const PROMPTBOOK_ENGINE_VERSION = '0.94.0-5';
29
29
  /**
30
30
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
31
31
  * Note: [💞] Ignore a discrepancy between file name and entity name
32
32
  */
33
33
 
34
34
  /**
35
- * Detects if the code is running in a browser environment in main thread (Not in a web worker)
35
+ * Freezes the given object and all its nested objects recursively
36
36
  *
37
- * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
37
+ * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
38
+ * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
38
39
  *
40
+ * @returns The same object as the input, but deeply frozen
39
41
  * @public exported from `@promptbook/utils`
40
42
  */
41
- const $isRunningInBrowser = new Function(`
42
- try {
43
- return this === window;
44
- } catch (e) {
45
- return false;
43
+ function $deepFreeze(objectValue) {
44
+ if (Array.isArray(objectValue)) {
45
+ return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
46
+ }
47
+ const propertyNames = Object.getOwnPropertyNames(objectValue);
48
+ for (const propertyName of propertyNames) {
49
+ const value = objectValue[propertyName];
50
+ if (value && typeof value === 'object') {
51
+ $deepFreeze(value);
52
+ }
53
+ }
54
+ Object.freeze(objectValue);
55
+ return objectValue;
46
56
  }
47
- `);
48
57
  /**
49
- * TODO: [🎺]
58
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
50
59
  */
51
60
 
52
61
  /**
53
- * Detects if the code is running in a web worker
62
+ * Represents the uncertain value
54
63
  *
55
- * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
64
+ * @public exported from `@promptbook/core`
65
+ */
66
+ const ZERO_VALUE = $deepFreeze({ value: 0 });
67
+ /**
68
+ * Represents the uncertain value
56
69
  *
57
- * @public exported from `@promptbook/utils`
70
+ * @public exported from `@promptbook/core`
58
71
  */
59
- const $isRunningInWebWorker = new Function(`
60
- try {
61
- if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
62
- return true;
63
- } else {
64
- return false;
65
- }
66
- } catch (e) {
67
- return false;
68
- }
69
- `);
72
+ const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
73
+ /**
74
+ * Represents the usage with no resources consumed
75
+ *
76
+ * @public exported from `@promptbook/core`
77
+ */
78
+ $deepFreeze({
79
+ price: ZERO_VALUE,
80
+ input: {
81
+ tokensCount: ZERO_VALUE,
82
+ charactersCount: ZERO_VALUE,
83
+ wordsCount: ZERO_VALUE,
84
+ sentencesCount: ZERO_VALUE,
85
+ linesCount: ZERO_VALUE,
86
+ paragraphsCount: ZERO_VALUE,
87
+ pagesCount: ZERO_VALUE,
88
+ },
89
+ output: {
90
+ tokensCount: ZERO_VALUE,
91
+ charactersCount: ZERO_VALUE,
92
+ wordsCount: ZERO_VALUE,
93
+ sentencesCount: ZERO_VALUE,
94
+ linesCount: ZERO_VALUE,
95
+ paragraphsCount: ZERO_VALUE,
96
+ pagesCount: ZERO_VALUE,
97
+ },
98
+ });
99
+ /**
100
+ * Represents the usage with unknown resources consumed
101
+ *
102
+ * @public exported from `@promptbook/core`
103
+ */
104
+ $deepFreeze({
105
+ price: UNCERTAIN_ZERO_VALUE,
106
+ input: {
107
+ tokensCount: UNCERTAIN_ZERO_VALUE,
108
+ charactersCount: UNCERTAIN_ZERO_VALUE,
109
+ wordsCount: UNCERTAIN_ZERO_VALUE,
110
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
111
+ linesCount: UNCERTAIN_ZERO_VALUE,
112
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
113
+ pagesCount: UNCERTAIN_ZERO_VALUE,
114
+ },
115
+ output: {
116
+ tokensCount: UNCERTAIN_ZERO_VALUE,
117
+ charactersCount: UNCERTAIN_ZERO_VALUE,
118
+ wordsCount: UNCERTAIN_ZERO_VALUE,
119
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
120
+ linesCount: UNCERTAIN_ZERO_VALUE,
121
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
122
+ pagesCount: UNCERTAIN_ZERO_VALUE,
123
+ },
124
+ });
125
+ /**
126
+ * Note: [💞] Ignore a discrepancy between file name and entity name
127
+ */
128
+
70
129
  /**
71
- * TODO: [🎺]
130
+ * Orders JSON object by keys
131
+ *
132
+ * @returns The same type of object as the input re-ordered
133
+ * @public exported from `@promptbook/utils`
72
134
  */
135
+ function orderJson(options) {
136
+ const { value, order } = options;
137
+ const orderedValue = {
138
+ ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
139
+ ...value,
140
+ };
141
+ return orderedValue;
142
+ }
73
143
 
74
144
  /**
75
145
  * Name for the Promptbook
@@ -260,94 +330,6 @@
260
330
  throw new WrappedError(whatWasThrown);
261
331
  }
262
332
 
263
- /**
264
- * Generates random token
265
- *
266
- * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
267
- *
268
- * @private internal helper function
269
- * @returns secure random token
270
- */
271
- function $randomToken(randomness) {
272
- return crypto.randomBytes(randomness).toString('hex');
273
- }
274
- /**
275
- * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
276
- */
277
-
278
- /**
279
- * This error indicates errors during the execution of the pipeline
280
- *
281
- * @public exported from `@promptbook/core`
282
- */
283
- class PipelineExecutionError extends Error {
284
- constructor(message) {
285
- // Added id parameter
286
- super(message);
287
- this.name = 'PipelineExecutionError';
288
- // TODO: [🐙] DRY - Maybe $randomId
289
- this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
290
- Object.setPrototypeOf(this, PipelineExecutionError.prototype);
291
- }
292
- }
293
- /**
294
- * TODO: [🧠][🌂] Add id to all errors
295
- */
296
-
297
- /**
298
- * Simple wrapper `new Date().toISOString()`
299
- *
300
- * Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
301
- *
302
- * @returns string_date branded type
303
- * @public exported from `@promptbook/utils`
304
- */
305
- function $getCurrentDate() {
306
- return new Date().toISOString();
307
- }
308
-
309
- /**
310
- * Orders JSON object by keys
311
- *
312
- * @returns The same type of object as the input re-ordered
313
- * @public exported from `@promptbook/utils`
314
- */
315
- function orderJson(options) {
316
- const { value, order } = options;
317
- const orderedValue = {
318
- ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
319
- ...value,
320
- };
321
- return orderedValue;
322
- }
323
-
324
- /**
325
- * Freezes the given object and all its nested objects recursively
326
- *
327
- * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
328
- * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
329
- *
330
- * @returns The same object as the input, but deeply frozen
331
- * @public exported from `@promptbook/utils`
332
- */
333
- function $deepFreeze(objectValue) {
334
- if (Array.isArray(objectValue)) {
335
- return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
336
- }
337
- const propertyNames = Object.getOwnPropertyNames(objectValue);
338
- for (const propertyName of propertyNames) {
339
- const value = objectValue[propertyName];
340
- if (value && typeof value === 'object') {
341
- $deepFreeze(value);
342
- }
343
- }
344
- Object.freeze(objectValue);
345
- return objectValue;
346
- }
347
- /**
348
- * TODO: [🧠] Is there a way how to meaningfully test this utility
349
- */
350
-
351
333
  /**
352
334
  * Checks if the value is [🚉] serializable as JSON
353
335
  * If not, throws an UnexpectedError with a rich error message and tracking
@@ -596,190 +578,59 @@
596
578
  */
597
579
 
598
580
  /**
599
- * This error type indicates that some limit was reached
581
+ * Generates random token
582
+ *
583
+ * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
584
+ *
585
+ * @private internal helper function
586
+ * @returns secure random token
587
+ */
588
+ function $randomToken(randomness) {
589
+ return crypto.randomBytes(randomness).toString('hex');
590
+ }
591
+ /**
592
+ * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
593
+ */
594
+
595
+ /**
596
+ * This error indicates errors during the execution of the pipeline
600
597
  *
601
598
  * @public exported from `@promptbook/core`
602
599
  */
603
- class LimitReachedError extends Error {
600
+ class PipelineExecutionError extends Error {
604
601
  constructor(message) {
602
+ // Added id parameter
605
603
  super(message);
606
- this.name = 'LimitReachedError';
607
- Object.setPrototypeOf(this, LimitReachedError.prototype);
604
+ this.name = 'PipelineExecutionError';
605
+ // TODO: [🐙] DRY - Maybe $randomId
606
+ this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
607
+ Object.setPrototypeOf(this, PipelineExecutionError.prototype);
608
608
  }
609
609
  }
610
+ /**
611
+ * TODO: [🧠][🌂] Add id to all errors
612
+ */
610
613
 
611
614
  /**
612
- * Format either small or big number
615
+ * Counts number of characters in the text
613
616
  *
614
617
  * @public exported from `@promptbook/utils`
615
618
  */
616
- function numberToString(value) {
617
- if (value === 0) {
618
- return '0';
619
- }
620
- else if (Number.isNaN(value)) {
621
- return VALUE_STRINGS.nan;
622
- }
623
- else if (value === Infinity) {
624
- return VALUE_STRINGS.infinity;
625
- }
626
- else if (value === -Infinity) {
627
- return VALUE_STRINGS.negativeInfinity;
628
- }
629
- for (let exponent = 0; exponent < 15; exponent++) {
630
- const factor = 10 ** exponent;
631
- const valueRounded = Math.round(value * factor) / factor;
632
- if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
633
- return valueRounded.toFixed(exponent);
634
- }
635
- }
636
- return value.toString();
619
+ function countCharacters(text) {
620
+ // Remove null characters
621
+ text = text.replace(/\0/g, '');
622
+ // Replace emojis (and also ZWJ sequence) with hyphens
623
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
624
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
625
+ text = text.replace(/\p{Extended_Pictographic}(\u{200D}\p{Extended_Pictographic})*/gu, '-');
626
+ return text.length;
637
627
  }
628
+ /**
629
+ * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
630
+ */
638
631
 
639
632
  /**
640
- * Function `valueToString` will convert the given value to string
641
- * This is useful and used in the `templateParameters` function
642
- *
643
- * Note: This function is not just calling `toString` method
644
- * It's more complex and can handle this conversion specifically for LLM models
645
- * See `VALUE_STRINGS`
646
- *
647
- * Note: There are 2 similar functions
648
- * - `valueToString` converts value to string for LLM models as human-readable string
649
- * - `asSerializable` converts value to string to preserve full information to be able to convert it back
650
- *
651
- * @public exported from `@promptbook/utils`
652
- */
653
- function valueToString(value) {
654
- try {
655
- if (value === '') {
656
- return VALUE_STRINGS.empty;
657
- }
658
- else if (value === null) {
659
- return VALUE_STRINGS.null;
660
- }
661
- else if (value === undefined) {
662
- return VALUE_STRINGS.undefined;
663
- }
664
- else if (typeof value === 'string') {
665
- return value;
666
- }
667
- else if (typeof value === 'number') {
668
- return numberToString(value);
669
- }
670
- else if (value instanceof Date) {
671
- return value.toISOString();
672
- }
673
- else {
674
- try {
675
- return JSON.stringify(value);
676
- }
677
- catch (error) {
678
- if (error instanceof TypeError && error.message.includes('circular structure')) {
679
- return VALUE_STRINGS.circular;
680
- }
681
- throw error;
682
- }
683
- }
684
- }
685
- catch (error) {
686
- assertsError(error);
687
- console.error(error);
688
- return VALUE_STRINGS.unserializable;
689
- }
690
- }
691
-
692
- /**
693
- * Replaces parameters in template with values from parameters object
694
- *
695
- * Note: This function is not places strings into string,
696
- * It's more complex and can handle this operation specifically for LLM models
697
- *
698
- * @param template the template with parameters in {curly} braces
699
- * @param parameters the object with parameters
700
- * @returns the template with replaced parameters
701
- * @throws {PipelineExecutionError} if parameter is not defined, not closed, or not opened
702
- * @public exported from `@promptbook/utils`
703
- */
704
- function templateParameters(template, parameters) {
705
- for (const [parameterName, parameterValue] of Object.entries(parameters)) {
706
- if (parameterValue === RESERVED_PARAMETER_MISSING_VALUE) {
707
- throw new UnexpectedError(`Parameter \`{${parameterName}}\` has missing value`);
708
- }
709
- else if (parameterValue === RESERVED_PARAMETER_RESTRICTED) {
710
- // TODO: [🍵]
711
- throw new UnexpectedError(`Parameter \`{${parameterName}}\` is restricted to use`);
712
- }
713
- }
714
- let replacedTemplates = template;
715
- let match;
716
- let loopLimit = LOOP_LIMIT;
717
- while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
718
- .exec(replacedTemplates))) {
719
- if (loopLimit-- < 0) {
720
- throw new LimitReachedError('Loop limit reached during parameters replacement in `templateParameters`');
721
- }
722
- const precol = match.groups.precol;
723
- const parameterName = match.groups.parameterName;
724
- if (parameterName === '') {
725
- // Note: Skip empty placeholders. It's used to avoid confusion with JSON-like strings
726
- continue;
727
- }
728
- if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
729
- throw new PipelineExecutionError('Parameter is already opened or not closed');
730
- }
731
- if (parameters[parameterName] === undefined) {
732
- throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
733
- }
734
- let parameterValue = parameters[parameterName];
735
- if (parameterValue === undefined) {
736
- throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
737
- }
738
- parameterValue = valueToString(parameterValue);
739
- // Escape curly braces in parameter values to prevent prompt-injection
740
- parameterValue = parameterValue.replace(/[{}]/g, '\\$&');
741
- if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
742
- parameterValue = parameterValue
743
- .split('\n')
744
- .map((line, index) => (index === 0 ? line : `${precol}${line}`))
745
- .join('\n');
746
- }
747
- replacedTemplates =
748
- replacedTemplates.substring(0, match.index + precol.length) +
749
- parameterValue +
750
- replacedTemplates.substring(match.index + precol.length + parameterName.length + 2);
751
- }
752
- // [💫] Check if there are parameters that are not closed properly
753
- if (/{\w+$/.test(replacedTemplates)) {
754
- throw new PipelineExecutionError('Parameter is not closed');
755
- }
756
- // [💫] Check if there are parameters that are not opened properly
757
- if (/^\w+}/.test(replacedTemplates)) {
758
- throw new PipelineExecutionError('Parameter is not opened');
759
- }
760
- return replacedTemplates;
761
- }
762
-
763
- /**
764
- * Counts number of characters in the text
765
- *
766
- * @public exported from `@promptbook/utils`
767
- */
768
- function countCharacters(text) {
769
- // Remove null characters
770
- text = text.replace(/\0/g, '');
771
- // Replace emojis (and also ZWJ sequence) with hyphens
772
- text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
773
- text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
774
- text = text.replace(/\p{Extended_Pictographic}(\u{200D}\p{Extended_Pictographic})*/gu, '-');
775
- return text.length;
776
- }
777
- /**
778
- * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
779
- */
780
-
781
- /**
782
- * Number of characters per standard line with 11pt Arial font size.
633
+ * Number of characters per standard line with 11pt Arial font size.
783
634
  *
784
635
  * @public exported from `@promptbook/utils`
785
636
  */
@@ -1154,74 +1005,6 @@
1154
1005
  };
1155
1006
  }
1156
1007
 
1157
- /**
1158
- * Represents the uncertain value
1159
- *
1160
- * @public exported from `@promptbook/core`
1161
- */
1162
- const ZERO_VALUE = $deepFreeze({ value: 0 });
1163
- /**
1164
- * Represents the uncertain value
1165
- *
1166
- * @public exported from `@promptbook/core`
1167
- */
1168
- const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
1169
- /**
1170
- * Represents the usage with no resources consumed
1171
- *
1172
- * @public exported from `@promptbook/core`
1173
- */
1174
- $deepFreeze({
1175
- price: ZERO_VALUE,
1176
- input: {
1177
- tokensCount: ZERO_VALUE,
1178
- charactersCount: ZERO_VALUE,
1179
- wordsCount: ZERO_VALUE,
1180
- sentencesCount: ZERO_VALUE,
1181
- linesCount: ZERO_VALUE,
1182
- paragraphsCount: ZERO_VALUE,
1183
- pagesCount: ZERO_VALUE,
1184
- },
1185
- output: {
1186
- tokensCount: ZERO_VALUE,
1187
- charactersCount: ZERO_VALUE,
1188
- wordsCount: ZERO_VALUE,
1189
- sentencesCount: ZERO_VALUE,
1190
- linesCount: ZERO_VALUE,
1191
- paragraphsCount: ZERO_VALUE,
1192
- pagesCount: ZERO_VALUE,
1193
- },
1194
- });
1195
- /**
1196
- * Represents the usage with unknown resources consumed
1197
- *
1198
- * @public exported from `@promptbook/core`
1199
- */
1200
- $deepFreeze({
1201
- price: UNCERTAIN_ZERO_VALUE,
1202
- input: {
1203
- tokensCount: UNCERTAIN_ZERO_VALUE,
1204
- charactersCount: UNCERTAIN_ZERO_VALUE,
1205
- wordsCount: UNCERTAIN_ZERO_VALUE,
1206
- sentencesCount: UNCERTAIN_ZERO_VALUE,
1207
- linesCount: UNCERTAIN_ZERO_VALUE,
1208
- paragraphsCount: UNCERTAIN_ZERO_VALUE,
1209
- pagesCount: UNCERTAIN_ZERO_VALUE,
1210
- },
1211
- output: {
1212
- tokensCount: UNCERTAIN_ZERO_VALUE,
1213
- charactersCount: UNCERTAIN_ZERO_VALUE,
1214
- wordsCount: UNCERTAIN_ZERO_VALUE,
1215
- sentencesCount: UNCERTAIN_ZERO_VALUE,
1216
- linesCount: UNCERTAIN_ZERO_VALUE,
1217
- paragraphsCount: UNCERTAIN_ZERO_VALUE,
1218
- pagesCount: UNCERTAIN_ZERO_VALUE,
1219
- },
1220
- });
1221
- /**
1222
- * Note: [💞] Ignore a discrepancy between file name and entity name
1223
- */
1224
-
1225
1008
  /**
1226
1009
  * Make UncertainNumber
1227
1010
  *
@@ -1241,11 +1024,11 @@
1241
1024
  }
1242
1025
 
1243
1026
  /**
1244
- * Function computeUsage will create price per one token based on the string value found on openai page
1027
+ * Create price per one token based on the string value found on openai page
1245
1028
  *
1246
1029
  * @private within the repository, used only as internal helper for `OPENAI_MODELS`
1247
1030
  */
1248
- function computeUsage(value) {
1031
+ function pricing(value) {
1249
1032
  const [price, tokens] = value.split(' / ');
1250
1033
  return parseFloat(price.replace('$', '')) / parseFloat(tokens.replace('M tokens', '')) / 1000000;
1251
1034
  }
@@ -1281,8 +1064,8 @@
1281
1064
  modelName: 'davinci-002',
1282
1065
  modelDescription: 'Legacy completion model with strong performance on text generation tasks. Optimized for complex instructions and longer outputs.',
1283
1066
  pricing: {
1284
- prompt: computeUsage(`$2.00 / 1M tokens`),
1285
- output: computeUsage(`$2.00 / 1M tokens`),
1067
+ prompt: pricing(`$2.00 / 1M tokens`),
1068
+ output: pricing(`$2.00 / 1M tokens`),
1286
1069
  },
1287
1070
  },
1288
1071
  /**/
@@ -1299,8 +1082,8 @@
1299
1082
  modelName: 'gpt-3.5-turbo-16k',
1300
1083
  modelDescription: 'GPT-3.5 Turbo with extended 16k token context length for handling longer conversations and documents.',
1301
1084
  pricing: {
1302
- prompt: computeUsage(`$3.00 / 1M tokens`),
1303
- output: computeUsage(`$4.00 / 1M tokens`),
1085
+ prompt: pricing(`$3.00 / 1M tokens`),
1086
+ output: pricing(`$4.00 / 1M tokens`),
1304
1087
  },
1305
1088
  },
1306
1089
  /**/
@@ -1323,8 +1106,8 @@
1323
1106
  modelName: 'gpt-4',
1324
1107
  modelDescription: 'GPT-4 is a powerful language model with enhanced reasoning, instruction-following capabilities, and 8K context window. Optimized for complex tasks requiring deep understanding.',
1325
1108
  pricing: {
1326
- prompt: computeUsage(`$30.00 / 1M tokens`),
1327
- output: computeUsage(`$60.00 / 1M tokens`),
1109
+ prompt: pricing(`$30.00 / 1M tokens`),
1110
+ output: pricing(`$60.00 / 1M tokens`),
1328
1111
  },
1329
1112
  },
1330
1113
  /**/
@@ -1335,8 +1118,8 @@
1335
1118
  modelName: 'gpt-4-32k',
1336
1119
  modelDescription: 'Extended context version of GPT-4 with a 32K token window for processing very long inputs and generating comprehensive responses for complex tasks.',
1337
1120
  pricing: {
1338
- prompt: computeUsage(`$60.00 / 1M tokens`),
1339
- output: computeUsage(`$120.00 / 1M tokens`),
1121
+ prompt: pricing(`$60.00 / 1M tokens`),
1122
+ output: pricing(`$120.00 / 1M tokens`),
1340
1123
  },
1341
1124
  },
1342
1125
  /**/
@@ -1358,8 +1141,8 @@
1358
1141
  modelName: 'gpt-4-turbo-2024-04-09',
1359
1142
  modelDescription: 'Latest stable GPT-4 Turbo model from April 2024 with enhanced reasoning and context handling capabilities. Offers 128K context window and improved performance.',
1360
1143
  pricing: {
1361
- prompt: computeUsage(`$10.00 / 1M tokens`),
1362
- output: computeUsage(`$30.00 / 1M tokens`),
1144
+ prompt: pricing(`$10.00 / 1M tokens`),
1145
+ output: pricing(`$30.00 / 1M tokens`),
1363
1146
  },
1364
1147
  },
1365
1148
  /**/
@@ -1370,8 +1153,8 @@
1370
1153
  modelName: 'gpt-3.5-turbo-1106',
1371
1154
  modelDescription: 'November 2023 version of GPT-3.5 Turbo with improved instruction following and a 16K token context window.',
1372
1155
  pricing: {
1373
- prompt: computeUsage(`$1.00 / 1M tokens`),
1374
- output: computeUsage(`$2.00 / 1M tokens`),
1156
+ prompt: pricing(`$1.00 / 1M tokens`),
1157
+ output: pricing(`$2.00 / 1M tokens`),
1375
1158
  },
1376
1159
  },
1377
1160
  /**/
@@ -1382,8 +1165,8 @@
1382
1165
  modelName: 'gpt-4-turbo',
1383
1166
  modelDescription: 'More capable model than GPT-4 with improved instruction following, function calling and a 128K token context window for handling very large documents.',
1384
1167
  pricing: {
1385
- prompt: computeUsage(`$10.00 / 1M tokens`),
1386
- output: computeUsage(`$30.00 / 1M tokens`),
1168
+ prompt: pricing(`$10.00 / 1M tokens`),
1169
+ output: pricing(`$30.00 / 1M tokens`),
1387
1170
  },
1388
1171
  },
1389
1172
  /**/
@@ -1394,8 +1177,8 @@
1394
1177
  modelName: 'gpt-3.5-turbo-instruct-0914',
1395
1178
  modelDescription: 'September 2023 version of GPT-3.5 Turbo optimized for completion-style instruction following with a 4K context window.',
1396
1179
  pricing: {
1397
- prompt: computeUsage(`$1.50 / 1M tokens`),
1398
- output: computeUsage(`$2.00 / 1M tokens`), // <- For gpt-3.5-turbo-instruct
1180
+ prompt: pricing(`$1.50 / 1M tokens`),
1181
+ output: pricing(`$2.00 / 1M tokens`), // <- For gpt-3.5-turbo-instruct
1399
1182
  },
1400
1183
  },
1401
1184
  /**/
@@ -1406,8 +1189,8 @@
1406
1189
  modelName: 'gpt-3.5-turbo-instruct',
1407
1190
  modelDescription: 'Optimized version of GPT-3.5 for completion-style API with good instruction following and a 4K token context window.',
1408
1191
  pricing: {
1409
- prompt: computeUsage(`$1.50 / 1M tokens`),
1410
- output: computeUsage(`$2.00 / 1M tokens`),
1192
+ prompt: pricing(`$1.50 / 1M tokens`),
1193
+ output: pricing(`$2.00 / 1M tokens`),
1411
1194
  },
1412
1195
  },
1413
1196
  /**/
@@ -1424,8 +1207,8 @@
1424
1207
  modelName: 'gpt-3.5-turbo',
1425
1208
  modelDescription: 'Latest version of GPT-3.5 Turbo with improved performance and instruction following capabilities. Default 4K context window with options for 16K.',
1426
1209
  pricing: {
1427
- prompt: computeUsage(`$0.50 / 1M tokens`),
1428
- output: computeUsage(`$1.50 / 1M tokens`),
1210
+ prompt: pricing(`$0.50 / 1M tokens`),
1211
+ output: pricing(`$1.50 / 1M tokens`),
1429
1212
  },
1430
1213
  },
1431
1214
  /**/
@@ -1436,8 +1219,8 @@
1436
1219
  modelName: 'gpt-3.5-turbo-0301',
1437
1220
  modelDescription: 'March 2023 version of GPT-3.5 Turbo with a 4K token context window. Legacy model maintained for backward compatibility.',
1438
1221
  pricing: {
1439
- prompt: computeUsage(`$1.50 / 1M tokens`),
1440
- output: computeUsage(`$2.00 / 1M tokens`),
1222
+ prompt: pricing(`$1.50 / 1M tokens`),
1223
+ output: pricing(`$2.00 / 1M tokens`),
1441
1224
  },
1442
1225
  },
1443
1226
  /**/
@@ -1448,8 +1231,8 @@
1448
1231
  modelName: 'babbage-002',
1449
1232
  modelDescription: 'Efficient legacy completion model with a good balance of performance and speed. Suitable for straightforward text generation tasks.',
1450
1233
  pricing: {
1451
- prompt: computeUsage(`$0.40 / 1M tokens`),
1452
- output: computeUsage(`$0.40 / 1M tokens`),
1234
+ prompt: pricing(`$0.40 / 1M tokens`),
1235
+ output: pricing(`$0.40 / 1M tokens`),
1453
1236
  },
1454
1237
  },
1455
1238
  /**/
@@ -1460,8 +1243,8 @@
1460
1243
  modelName: 'gpt-4-1106-preview',
1461
1244
  modelDescription: 'November 2023 preview version of GPT-4 Turbo with improved instruction following and a 128K token context window.',
1462
1245
  pricing: {
1463
- prompt: computeUsage(`$10.00 / 1M tokens`),
1464
- output: computeUsage(`$30.00 / 1M tokens`),
1246
+ prompt: pricing(`$10.00 / 1M tokens`),
1247
+ output: pricing(`$30.00 / 1M tokens`),
1465
1248
  },
1466
1249
  },
1467
1250
  /**/
@@ -1472,8 +1255,8 @@
1472
1255
  modelName: 'gpt-4-0125-preview',
1473
1256
  modelDescription: 'January 2024 preview version of GPT-4 Turbo with improved reasoning capabilities and a 128K token context window.',
1474
1257
  pricing: {
1475
- prompt: computeUsage(`$10.00 / 1M tokens`),
1476
- output: computeUsage(`$30.00 / 1M tokens`),
1258
+ prompt: pricing(`$10.00 / 1M tokens`),
1259
+ output: pricing(`$30.00 / 1M tokens`),
1477
1260
  },
1478
1261
  },
1479
1262
  /**/
@@ -1490,8 +1273,8 @@
1490
1273
  modelName: 'gpt-3.5-turbo-0125',
1491
1274
  modelDescription: 'January 2024 version of GPT-3.5 Turbo with improved reasoning capabilities and a 16K token context window.',
1492
1275
  pricing: {
1493
- prompt: computeUsage(`$0.50 / 1M tokens`),
1494
- output: computeUsage(`$1.50 / 1M tokens`),
1276
+ prompt: pricing(`$0.50 / 1M tokens`),
1277
+ output: pricing(`$1.50 / 1M tokens`),
1495
1278
  },
1496
1279
  },
1497
1280
  /**/
@@ -1502,8 +1285,8 @@
1502
1285
  modelName: 'gpt-4-turbo-preview',
1503
1286
  modelDescription: 'Preview version of GPT-4 Turbo that points to the latest model version. Features improved instruction following, 128K token context window and lower latency.',
1504
1287
  pricing: {
1505
- prompt: computeUsage(`$10.00 / 1M tokens`),
1506
- output: computeUsage(`$30.00 / 1M tokens`),
1288
+ prompt: pricing(`$10.00 / 1M tokens`),
1289
+ output: pricing(`$30.00 / 1M tokens`),
1507
1290
  },
1508
1291
  },
1509
1292
  /**/
@@ -1514,7 +1297,7 @@
1514
1297
  modelName: 'text-embedding-3-large',
1515
1298
  modelDescription: "OpenAI's most capable text embedding model designed for high-quality embeddings for complex similarity tasks and information retrieval.",
1516
1299
  pricing: {
1517
- prompt: computeUsage(`$0.13 / 1M tokens`),
1300
+ prompt: pricing(`$0.13 / 1M tokens`),
1518
1301
  // TODO: [🏏] Leverage the batch API @see https://platform.openai.com/docs/guides/batch
1519
1302
  output: 0, // <- Note: [🆖] In Embedding models you dont pay for output
1520
1303
  },
@@ -1527,7 +1310,7 @@
1527
1310
  modelName: 'text-embedding-3-small',
1528
1311
  modelDescription: 'Cost-effective embedding model with good performance for simpler tasks like text similarity and retrieval. Good balance of quality and efficiency.',
1529
1312
  pricing: {
1530
- prompt: computeUsage(`$0.02 / 1M tokens`),
1313
+ prompt: pricing(`$0.02 / 1M tokens`),
1531
1314
  // TODO: [🏏] Leverage the batch API @see https://platform.openai.com/docs/guides/batch
1532
1315
  output: 0, // <- Note: [🆖] In Embedding models you dont pay for output
1533
1316
  },
@@ -1540,8 +1323,8 @@
1540
1323
  modelName: 'gpt-3.5-turbo-0613',
1541
1324
  modelDescription: 'June 2023 version of GPT-3.5 Turbo with function calling capabilities and a 4K token context window.',
1542
1325
  pricing: {
1543
- prompt: computeUsage(`$1.50 / 1M tokens`),
1544
- output: computeUsage(`$2.00 / 1M tokens`),
1326
+ prompt: pricing(`$1.50 / 1M tokens`),
1327
+ output: pricing(`$2.00 / 1M tokens`),
1545
1328
  },
1546
1329
  },
1547
1330
  /**/
@@ -1552,7 +1335,7 @@
1552
1335
  modelName: 'text-embedding-ada-002',
1553
1336
  modelDescription: 'Legacy text embedding model suitable for text similarity and retrieval augmented generation use cases. Replaced by newer embedding-3 models.',
1554
1337
  pricing: {
1555
- prompt: computeUsage(`$0.1 / 1M tokens`),
1338
+ prompt: pricing(`$0.1 / 1M tokens`),
1556
1339
  // TODO: [🏏] Leverage the batch API @see https://platform.openai.com/docs/guides/batch
1557
1340
  output: 0, // <- Note: [🆖] In Embedding models you dont pay for output
1558
1341
  },
@@ -1583,8 +1366,8 @@
1583
1366
  modelName: 'gpt-4o-2024-05-13',
1584
1367
  modelDescription: 'May 2024 version of GPT-4o with enhanced multimodal capabilities, improved reasoning, and optimized for vision, audio and chat at lower latencies.',
1585
1368
  pricing: {
1586
- prompt: computeUsage(`$5.00 / 1M tokens`),
1587
- output: computeUsage(`$15.00 / 1M tokens`),
1369
+ prompt: pricing(`$5.00 / 1M tokens`),
1370
+ output: pricing(`$15.00 / 1M tokens`),
1588
1371
  },
1589
1372
  },
1590
1373
  /**/
@@ -1595,8 +1378,8 @@
1595
1378
  modelName: 'gpt-4o',
1596
1379
  modelDescription: "OpenAI's most advanced multimodal model optimized for performance, speed, and cost. Capable of vision, reasoning, and high quality text generation.",
1597
1380
  pricing: {
1598
- prompt: computeUsage(`$5.00 / 1M tokens`),
1599
- output: computeUsage(`$15.00 / 1M tokens`),
1381
+ prompt: pricing(`$5.00 / 1M tokens`),
1382
+ output: pricing(`$15.00 / 1M tokens`),
1600
1383
  },
1601
1384
  },
1602
1385
  /**/
@@ -1607,8 +1390,8 @@
1607
1390
  modelName: 'gpt-4o-mini',
1608
1391
  modelDescription: 'Smaller, more cost-effective version of GPT-4o with good performance across text, vision, and audio tasks at reduced complexity.',
1609
1392
  pricing: {
1610
- prompt: computeUsage(`$0.15 / 1M tokens`),
1611
- output: computeUsage(`$0.60 / 1M tokens`),
1393
+ prompt: pricing(`$0.15 / 1M tokens`),
1394
+ output: pricing(`$0.60 / 1M tokens`),
1612
1395
  },
1613
1396
  },
1614
1397
  /**/
@@ -1619,8 +1402,8 @@
1619
1402
  modelName: 'o1-preview',
1620
1403
  modelDescription: 'Advanced reasoning model with exceptional performance on complex logical, mathematical, and analytical tasks. Built for deep reasoning and specialized professional tasks.',
1621
1404
  pricing: {
1622
- prompt: computeUsage(`$15.00 / 1M tokens`),
1623
- output: computeUsage(`$60.00 / 1M tokens`),
1405
+ prompt: pricing(`$15.00 / 1M tokens`),
1406
+ output: pricing(`$60.00 / 1M tokens`),
1624
1407
  },
1625
1408
  },
1626
1409
  /**/
@@ -1632,8 +1415,8 @@
1632
1415
  modelDescription: 'September 2024 version of O1 preview with specialized reasoning capabilities for complex tasks requiring precise analytical thinking.',
1633
1416
  // <- TODO: [💩] Some better system to organize these date suffixes and versions
1634
1417
  pricing: {
1635
- prompt: computeUsage(`$15.00 / 1M tokens`),
1636
- output: computeUsage(`$60.00 / 1M tokens`),
1418
+ prompt: pricing(`$15.00 / 1M tokens`),
1419
+ output: pricing(`$60.00 / 1M tokens`),
1637
1420
  },
1638
1421
  },
1639
1422
  /**/
@@ -1644,8 +1427,8 @@
1644
1427
  modelName: 'o1-mini',
1645
1428
  modelDescription: 'Smaller, cost-effective version of the O1 model with good performance on reasoning tasks while maintaining efficiency for everyday analytical use.',
1646
1429
  pricing: {
1647
- prompt: computeUsage(`$3.00 / 1M tokens`),
1648
- output: computeUsage(`$12.00 / 1M tokens`),
1430
+ prompt: pricing(`$3.00 / 1M tokens`),
1431
+ output: pricing(`$12.00 / 1M tokens`),
1649
1432
  },
1650
1433
  },
1651
1434
  /**/
@@ -1656,8 +1439,8 @@
1656
1439
  modelName: 'o1',
1657
1440
  modelDescription: "OpenAI's advanced reasoning model focused on logic and problem-solving. Designed for complex analytical tasks with rigorous step-by-step reasoning. 128K context window.",
1658
1441
  pricing: {
1659
- prompt: computeUsage(`$15.00 / 1M tokens`),
1660
- output: computeUsage(`$60.00 / 1M tokens`),
1442
+ prompt: pricing(`$15.00 / 1M tokens`),
1443
+ output: pricing(`$60.00 / 1M tokens`),
1661
1444
  },
1662
1445
  },
1663
1446
  /**/
@@ -1668,8 +1451,8 @@
1668
1451
  modelName: 'o3-mini',
1669
1452
  modelDescription: 'Cost-effective reasoning model optimized for academic and scientific problem-solving. Efficient performance on STEM tasks with deep mathematical and scientific knowledge. 128K context window.',
1670
1453
  pricing: {
1671
- prompt: computeUsage(`$3.00 / 1M tokens`),
1672
- output: computeUsage(`$12.00 / 1M tokens`),
1454
+ prompt: pricing(`$3.00 / 1M tokens`),
1455
+ output: pricing(`$12.00 / 1M tokens`),
1673
1456
  // <- TODO: !! Unsure, check the pricing
1674
1457
  },
1675
1458
  },
@@ -1681,8 +1464,8 @@
1681
1464
  modelName: 'o1-mini-2024-09-12',
1682
1465
  modelDescription: "September 2024 version of O1-mini with balanced reasoning capabilities and cost-efficiency. Good for analytical tasks that don't require the full O1 model.",
1683
1466
  pricing: {
1684
- prompt: computeUsage(`$3.00 / 1M tokens`),
1685
- output: computeUsage(`$12.00 / 1M tokens`),
1467
+ prompt: pricing(`$3.00 / 1M tokens`),
1468
+ output: pricing(`$12.00 / 1M tokens`),
1686
1469
  },
1687
1470
  },
1688
1471
  /**/
@@ -1693,8 +1476,8 @@
1693
1476
  modelName: 'gpt-3.5-turbo-16k-0613',
1694
1477
  modelDescription: 'June 2023 version of GPT-3.5 Turbo with extended 16k token context window for processing longer conversations and documents.',
1695
1478
  pricing: {
1696
- prompt: computeUsage(`$3.00 / 1M tokens`),
1697
- output: computeUsage(`$4.00 / 1M tokens`),
1479
+ prompt: pricing(`$3.00 / 1M tokens`),
1480
+ output: pricing(`$4.00 / 1M tokens`),
1698
1481
  },
1699
1482
  },
1700
1483
  /**/
@@ -1769,36 +1552,207 @@
1769
1552
  */
1770
1553
 
1771
1554
  /**
1772
- * Execution Tools for calling OpenAI API
1555
+ * Simple wrapper `new Date().toISOString()`
1773
1556
  *
1774
- * @public exported from `@promptbook/openai`
1557
+ * Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
1558
+ *
1559
+ * @returns string_date branded type
1560
+ * @public exported from `@promptbook/utils`
1775
1561
  */
1776
- class OpenAiExecutionTools {
1777
- /**
1778
- * Creates OpenAI Execution Tools.
1779
- *
1780
- * @param options which are relevant are directly passed to the OpenAI client
1781
- */
1782
- constructor(options) {
1783
- this.options = options;
1784
- /**
1785
- * OpenAI API client.
1786
- */
1787
- this.client = null;
1788
- // TODO: Allow configuring rate limits via options
1789
- this.limiter = new Bottleneck__default["default"]({
1790
- minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
1791
- });
1562
+ function $getCurrentDate() {
1563
+ return new Date().toISOString();
1564
+ }
1565
+
1566
+ /**
1567
+ * This error type indicates that some limit was reached
1568
+ *
1569
+ * @public exported from `@promptbook/core`
1570
+ */
1571
+ class LimitReachedError extends Error {
1572
+ constructor(message) {
1573
+ super(message);
1574
+ this.name = 'LimitReachedError';
1575
+ Object.setPrototypeOf(this, LimitReachedError.prototype);
1792
1576
  }
1793
- get title() {
1794
- return 'OpenAI';
1577
+ }
1578
+
1579
+ /**
1580
+ * Format either small or big number
1581
+ *
1582
+ * @public exported from `@promptbook/utils`
1583
+ */
1584
+ function numberToString(value) {
1585
+ if (value === 0) {
1586
+ return '0';
1795
1587
  }
1796
- get description() {
1797
- return 'Use all models provided by OpenAI';
1588
+ else if (Number.isNaN(value)) {
1589
+ return VALUE_STRINGS.nan;
1798
1590
  }
1799
- async getClient() {
1800
- if (this.client === null) {
1801
- // Note: Passing only OpenAI relevant options to OpenAI constructor
1591
+ else if (value === Infinity) {
1592
+ return VALUE_STRINGS.infinity;
1593
+ }
1594
+ else if (value === -Infinity) {
1595
+ return VALUE_STRINGS.negativeInfinity;
1596
+ }
1597
+ for (let exponent = 0; exponent < 15; exponent++) {
1598
+ const factor = 10 ** exponent;
1599
+ const valueRounded = Math.round(value * factor) / factor;
1600
+ if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
1601
+ return valueRounded.toFixed(exponent);
1602
+ }
1603
+ }
1604
+ return value.toString();
1605
+ }
1606
+
1607
+ /**
1608
+ * Function `valueToString` will convert the given value to string
1609
+ * This is useful and used in the `templateParameters` function
1610
+ *
1611
+ * Note: This function is not just calling `toString` method
1612
+ * It's more complex and can handle this conversion specifically for LLM models
1613
+ * See `VALUE_STRINGS`
1614
+ *
1615
+ * Note: There are 2 similar functions
1616
+ * - `valueToString` converts value to string for LLM models as human-readable string
1617
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
1618
+ *
1619
+ * @public exported from `@promptbook/utils`
1620
+ */
1621
+ function valueToString(value) {
1622
+ try {
1623
+ if (value === '') {
1624
+ return VALUE_STRINGS.empty;
1625
+ }
1626
+ else if (value === null) {
1627
+ return VALUE_STRINGS.null;
1628
+ }
1629
+ else if (value === undefined) {
1630
+ return VALUE_STRINGS.undefined;
1631
+ }
1632
+ else if (typeof value === 'string') {
1633
+ return value;
1634
+ }
1635
+ else if (typeof value === 'number') {
1636
+ return numberToString(value);
1637
+ }
1638
+ else if (value instanceof Date) {
1639
+ return value.toISOString();
1640
+ }
1641
+ else {
1642
+ try {
1643
+ return JSON.stringify(value);
1644
+ }
1645
+ catch (error) {
1646
+ if (error instanceof TypeError && error.message.includes('circular structure')) {
1647
+ return VALUE_STRINGS.circular;
1648
+ }
1649
+ throw error;
1650
+ }
1651
+ }
1652
+ }
1653
+ catch (error) {
1654
+ assertsError(error);
1655
+ console.error(error);
1656
+ return VALUE_STRINGS.unserializable;
1657
+ }
1658
+ }
1659
+
1660
+ /**
1661
+ * Replaces parameters in template with values from parameters object
1662
+ *
1663
+ * Note: This function is not places strings into string,
1664
+ * It's more complex and can handle this operation specifically for LLM models
1665
+ *
1666
+ * @param template the template with parameters in {curly} braces
1667
+ * @param parameters the object with parameters
1668
+ * @returns the template with replaced parameters
1669
+ * @throws {PipelineExecutionError} if parameter is not defined, not closed, or not opened
1670
+ * @public exported from `@promptbook/utils`
1671
+ */
1672
+ function templateParameters(template, parameters) {
1673
+ for (const [parameterName, parameterValue] of Object.entries(parameters)) {
1674
+ if (parameterValue === RESERVED_PARAMETER_MISSING_VALUE) {
1675
+ throw new UnexpectedError(`Parameter \`{${parameterName}}\` has missing value`);
1676
+ }
1677
+ else if (parameterValue === RESERVED_PARAMETER_RESTRICTED) {
1678
+ // TODO: [🍵]
1679
+ throw new UnexpectedError(`Parameter \`{${parameterName}}\` is restricted to use`);
1680
+ }
1681
+ }
1682
+ let replacedTemplates = template;
1683
+ let match;
1684
+ let loopLimit = LOOP_LIMIT;
1685
+ while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
1686
+ .exec(replacedTemplates))) {
1687
+ if (loopLimit-- < 0) {
1688
+ throw new LimitReachedError('Loop limit reached during parameters replacement in `templateParameters`');
1689
+ }
1690
+ const precol = match.groups.precol;
1691
+ const parameterName = match.groups.parameterName;
1692
+ if (parameterName === '') {
1693
+ // Note: Skip empty placeholders. It's used to avoid confusion with JSON-like strings
1694
+ continue;
1695
+ }
1696
+ if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
1697
+ throw new PipelineExecutionError('Parameter is already opened or not closed');
1698
+ }
1699
+ if (parameters[parameterName] === undefined) {
1700
+ throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
1701
+ }
1702
+ let parameterValue = parameters[parameterName];
1703
+ if (parameterValue === undefined) {
1704
+ throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
1705
+ }
1706
+ parameterValue = valueToString(parameterValue);
1707
+ // Escape curly braces in parameter values to prevent prompt-injection
1708
+ parameterValue = parameterValue.replace(/[{}]/g, '\\$&');
1709
+ if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
1710
+ parameterValue = parameterValue
1711
+ .split('\n')
1712
+ .map((line, index) => (index === 0 ? line : `${precol}${line}`))
1713
+ .join('\n');
1714
+ }
1715
+ replacedTemplates =
1716
+ replacedTemplates.substring(0, match.index + precol.length) +
1717
+ parameterValue +
1718
+ replacedTemplates.substring(match.index + precol.length + parameterName.length + 2);
1719
+ }
1720
+ // [💫] Check if there are parameters that are not closed properly
1721
+ if (/{\w+$/.test(replacedTemplates)) {
1722
+ throw new PipelineExecutionError('Parameter is not closed');
1723
+ }
1724
+ // [💫] Check if there are parameters that are not opened properly
1725
+ if (/^\w+}/.test(replacedTemplates)) {
1726
+ throw new PipelineExecutionError('Parameter is not opened');
1727
+ }
1728
+ return replacedTemplates;
1729
+ }
1730
+
1731
+ /**
1732
+ * Execution Tools for calling OpenAI API or other OpeenAI compatible provider
1733
+ *
1734
+ * @public exported from `@promptbook/openai`
1735
+ */
1736
+ class OpenAiCompatibleExecutionTools {
1737
+ /**
1738
+ * Creates OpenAI compatible Execution Tools.
1739
+ *
1740
+ * @param options which are relevant are directly passed to the OpenAI compatible client
1741
+ */
1742
+ constructor(options) {
1743
+ this.options = options;
1744
+ /**
1745
+ * OpenAI API client.
1746
+ */
1747
+ this.client = null;
1748
+ // TODO: Allow configuring rate limits via options
1749
+ this.limiter = new Bottleneck__default["default"]({
1750
+ minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
1751
+ });
1752
+ }
1753
+ async getClient() {
1754
+ if (this.client === null) {
1755
+ // Note: Passing only OpenAI relevant options to OpenAI constructor
1802
1756
  const openAiOptions = { ...this.options };
1803
1757
  delete openAiOptions.isVerbose;
1804
1758
  delete openAiOptions.userId;
@@ -1806,18 +1760,6 @@
1806
1760
  }
1807
1761
  return this.client;
1808
1762
  }
1809
- /*
1810
- Note: Commenting this out to avoid circular dependency
1811
- /**
1812
- * Create (sub)tools for calling OpenAI API Assistants
1813
- *
1814
- * @param assistantId Which assistant to use
1815
- * @returns Tools for calling OpenAI API Assistants with same token
1816
- * /
1817
- public createAssistantSubtools(assistantId: string_token): OpenAiAssistantExecutionTools {
1818
- return new OpenAiAssistantExecutionTools({ ...this.options, assistantId });
1819
- }
1820
- */
1821
1763
  /**
1822
1764
  * Check the `options` passed to `constructor`
1823
1765
  */
@@ -1826,23 +1768,15 @@
1826
1768
  // TODO: [🎍] Do here a real check that API is online, working and API key is correct
1827
1769
  }
1828
1770
  /**
1829
- * List all available OpenAI models that can be used
1771
+ * List all available OpenAI compatible models that can be used
1830
1772
  */
1831
1773
  async listModels() {
1832
- /*
1833
- Note: Dynamic lising of the models
1834
- const models = await this.openai.models.list({});
1835
-
1836
- console.log({ models });
1837
- console.log(models.data);
1838
- */
1839
1774
  const client = await this.getClient();
1840
1775
  const rawModelsList = await client.models.list();
1841
1776
  const availableModels = rawModelsList.data
1842
1777
  .sort((a, b) => (a.created > b.created ? 1 : -1))
1843
1778
  .map((modelFromApi) => {
1844
- // TODO: !!!! What about other model compatibilities?
1845
- const modelFromList = OPENAI_MODELS.find(({ modelName }) => modelName === modelFromApi.id ||
1779
+ const modelFromList = this.HARDCODED_MODELS.find(({ modelName }) => modelName === modelFromApi.id ||
1846
1780
  modelName.startsWith(modelFromApi.id) ||
1847
1781
  modelFromApi.id.startsWith(modelName));
1848
1782
  if (modelFromList !== undefined) {
@@ -1858,12 +1792,12 @@
1858
1792
  return availableModels;
1859
1793
  }
1860
1794
  /**
1861
- * Calls OpenAI API to use a chat model.
1795
+ * Calls OpenAI compatible API to use a chat model.
1862
1796
  */
1863
1797
  async callChatModel(prompt) {
1864
1798
  var _a;
1865
1799
  if (this.options.isVerbose) {
1866
- console.info('💬 OpenAI callChatModel call', { prompt });
1800
+ console.info(`💬 ${this.title} callChatModel call`, { prompt });
1867
1801
  }
1868
1802
  const { content, parameters, modelRequirements, format } = prompt;
1869
1803
  const client = await this.getClient();
@@ -1924,20 +1858,20 @@
1924
1858
  }
1925
1859
  const complete = $getCurrentDate();
1926
1860
  if (!rawResponse.choices[0]) {
1927
- throw new PipelineExecutionError('No choises from OpenAI');
1861
+ throw new PipelineExecutionError(`No choises from ${this.title}`);
1928
1862
  }
1929
1863
  if (rawResponse.choices.length > 1) {
1930
1864
  // TODO: This should be maybe only warning
1931
- throw new PipelineExecutionError('More than one choise from OpenAI');
1865
+ throw new PipelineExecutionError(`More than one choise from ${this.title}`);
1932
1866
  }
1933
1867
  const resultContent = rawResponse.choices[0].message.content;
1934
- const usage = computeOpenAiUsage(content || '', resultContent || '', rawResponse);
1868
+ const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
1935
1869
  if (resultContent === null) {
1936
- throw new PipelineExecutionError('No response message from OpenAI');
1870
+ throw new PipelineExecutionError(`No response message from ${this.title}`);
1937
1871
  }
1938
1872
  return exportJson({
1939
1873
  name: 'promptResult',
1940
- message: `Result of \`OpenAiExecutionTools.callChatModel\``,
1874
+ message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
1941
1875
  order: [],
1942
1876
  value: {
1943
1877
  content: resultContent,
@@ -1960,7 +1894,7 @@
1960
1894
  async callCompletionModel(prompt) {
1961
1895
  var _a;
1962
1896
  if (this.options.isVerbose) {
1963
- console.info('🖋 OpenAI callCompletionModel call', { prompt });
1897
+ console.info(`🖋 ${this.title} callCompletionModel call`, { prompt });
1964
1898
  }
1965
1899
  const { content, parameters, modelRequirements } = prompt;
1966
1900
  const client = await this.getClient();
@@ -2001,17 +1935,17 @@
2001
1935
  }
2002
1936
  const complete = $getCurrentDate();
2003
1937
  if (!rawResponse.choices[0]) {
2004
- throw new PipelineExecutionError('No choises from OpenAI');
1938
+ throw new PipelineExecutionError(`No choises from ${this.title}`);
2005
1939
  }
2006
1940
  if (rawResponse.choices.length > 1) {
2007
1941
  // TODO: This should be maybe only warning
2008
- throw new PipelineExecutionError('More than one choise from OpenAI');
1942
+ throw new PipelineExecutionError(`More than one choise from ${this.title}`);
2009
1943
  }
2010
1944
  const resultContent = rawResponse.choices[0].text;
2011
- const usage = computeOpenAiUsage(content || '', resultContent || '', rawResponse);
1945
+ const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
2012
1946
  return exportJson({
2013
1947
  name: 'promptResult',
2014
- message: `Result of \`OpenAiExecutionTools.callCompletionModel\``,
1948
+ message: `Result of \`OpenAiCompatibleExecutionTools.callCompletionModel\``,
2015
1949
  order: [],
2016
1950
  value: {
2017
1951
  content: resultContent,
@@ -2029,11 +1963,11 @@
2029
1963
  });
2030
1964
  }
2031
1965
  /**
2032
- * Calls OpenAI API to use a embedding model
1966
+ * Calls OpenAI compatible API to use a embedding model
2033
1967
  */
2034
1968
  async callEmbeddingModel(prompt) {
2035
1969
  if (this.options.isVerbose) {
2036
- console.info('🖋 OpenAI embedding call', { prompt });
1970
+ console.info(`🖋 ${this.title} embedding call`, { prompt });
2037
1971
  }
2038
1972
  const { content, parameters, modelRequirements } = prompt;
2039
1973
  const client = await this.getClient();
@@ -2068,12 +2002,12 @@
2068
2002
  throw new PipelineExecutionError(`Expected exactly 1 data item in response, got ${rawResponse.data.length}`);
2069
2003
  }
2070
2004
  const resultContent = rawResponse.data[0].embedding;
2071
- const usage = computeOpenAiUsage(content || '', '',
2005
+ const usage = this.computeUsage(content || '', '',
2072
2006
  // <- Note: Embedding does not have result content
2073
2007
  rawResponse);
2074
2008
  return exportJson({
2075
2009
  name: 'promptResult',
2076
- message: `Result of \`OpenAiExecutionTools.callEmbeddingModel\``,
2010
+ message: `Result of \`OpenAiCompatibleExecutionTools.callEmbeddingModel\``,
2077
2011
  order: [],
2078
2012
  value: {
2079
2013
  content: resultContent,
@@ -2096,65 +2030,171 @@
2096
2030
  */
2097
2031
  getDefaultModel(defaultModelName) {
2098
2032
  // Note: Match exact or prefix for model families
2099
- const model = OPENAI_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
2033
+ const model = this.HARDCODED_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
2100
2034
  if (model === undefined) {
2101
- throw new UnexpectedError(spaceTrim__default["default"]((block) => `
2102
- Cannot find model in OpenAI models with name "${defaultModelName}" which should be used as default.
2035
+ throw new PipelineExecutionError(spaceTrim__default["default"]((block) => `
2036
+ Cannot find model in ${this.title} models with name "${defaultModelName}" which should be used as default.
2103
2037
 
2104
2038
  Available models:
2105
- ${block(OPENAI_MODELS.map(({ modelName }) => `- "${modelName}"`).join('\n'))}
2039
+ ${block(this.HARDCODED_MODELS.map(({ modelName }) => `- "${modelName}"`).join('\n'))}
2040
+
2041
+ Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
2106
2042
 
2107
2043
  `));
2108
2044
  }
2109
2045
  return model;
2110
2046
  }
2111
- /**
2112
- * Default model for chat variant.
2113
- */
2114
- getDefaultChatModel() {
2115
- return this.getDefaultModel('gpt-4o');
2116
- }
2117
- /**
2118
- * Default model for completion variant.
2119
- */
2120
- getDefaultCompletionModel() {
2121
- return this.getDefaultModel('gpt-3.5-turbo-instruct');
2122
- }
2123
- /**
2124
- * Default model for completion variant.
2125
- */
2126
- getDefaultEmbeddingModel() {
2127
- return this.getDefaultModel('text-embedding-3-large');
2128
- }
2129
2047
  }
2130
2048
  /**
2131
- * TODO: [🧠][🧙‍♂️] Maybe there can be some wizzard for thoose who want to use just OpenAI
2132
- * TODO: Maybe Create some common util for callChatModel and callCompletionModel
2133
- * TODO: Maybe make custom OpenAiError
2049
+ * TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
2050
+ * TODO: [🛄] Maybe make custom `OpenAiCompatibleError`
2134
2051
  * TODO: [🧠][🈁] Maybe use `isDeterministic` from options
2135
2052
  * TODO: [🧠][🌰] Allow to pass `title` for tracking purposes
2136
2053
  */
2137
2054
 
2138
2055
  /**
2139
- * Execution Tools for calling OpenAI API
2056
+ * List of available models in Ollama library
2140
2057
  *
2141
- * Note: This can be also used for other OpenAI compatible APIs, like Ollama
2058
+ * Note: Done at 2025-05-19
2142
2059
  *
2143
- * @public exported from `@promptbook/openai`
2060
+ * @see https://ollama.com/library
2061
+ * @public exported from `@promptbook/ollama`
2144
2062
  */
2145
- const createOpenAiExecutionTools = Object.assign((options) => {
2146
- // TODO: [🧠][main] !!4 If browser, auto add `dangerouslyAllowBrowser`
2147
- if (($isRunningInBrowser() || $isRunningInWebWorker()) && !options.dangerouslyAllowBrowser) {
2148
- options = { ...options, dangerouslyAllowBrowser: true };
2149
- }
2150
- return new OpenAiExecutionTools(options);
2151
- }, {
2152
- packageName: '@promptbook/openai',
2153
- className: 'OpenAiExecutionTools',
2063
+ const OLLAMA_MODELS = exportJson({
2064
+ name: 'OLLAMA_MODELS',
2065
+ value: [
2066
+ {
2067
+ modelVariant: 'CHAT',
2068
+ modelTitle: 'llama2',
2069
+ modelName: 'llama2',
2070
+ modelDescription: 'Meta Llama 2, a general-purpose large language model.',
2071
+ },
2072
+ {
2073
+ modelVariant: 'CHAT',
2074
+ modelTitle: 'llama2-chat',
2075
+ modelName: 'llama2-chat',
2076
+ modelDescription: 'Meta Llama 2 Chat, optimized for conversational tasks.',
2077
+ },
2078
+ {
2079
+ modelVariant: 'CHAT',
2080
+ modelTitle: 'alpaca-7b',
2081
+ modelName: 'alpaca-7b',
2082
+ modelDescription: 'Stanford Alpaca 7B, instruction-tuned LLaMA model.',
2083
+ },
2084
+ {
2085
+ modelVariant: 'CHAT',
2086
+ modelTitle: 'alpaca-30b',
2087
+ modelName: 'alpaca-30b',
2088
+ modelDescription: 'Stanford Alpaca 30B, larger instruction-tuned LLaMA model.',
2089
+ },
2090
+ {
2091
+ modelVariant: 'CHAT',
2092
+ modelTitle: 'vicuna-13b',
2093
+ modelName: 'vicuna-13b',
2094
+ modelDescription: 'Vicuna 13B, fine-tuned LLaMA for chat and instruction.',
2095
+ },
2096
+ {
2097
+ modelVariant: 'CHAT',
2098
+ modelTitle: 'falcon-7b',
2099
+ modelName: 'falcon-7b',
2100
+ modelDescription: 'Falcon 7B, a performant open large language model.',
2101
+ },
2102
+ {
2103
+ modelVariant: 'CHAT',
2104
+ modelTitle: 'falcon-40b',
2105
+ modelName: 'falcon-40b',
2106
+ modelDescription: 'Falcon 40B, a larger open large language model.',
2107
+ },
2108
+ {
2109
+ modelVariant: 'CHAT',
2110
+ modelTitle: 'bloom-7b',
2111
+ modelName: 'bloom-7b',
2112
+ modelDescription: 'BLOOM 7B, multilingual large language model.',
2113
+ },
2114
+ {
2115
+ modelVariant: 'CHAT',
2116
+ modelTitle: 'mistral-7b',
2117
+ modelName: 'mistral-7b',
2118
+ modelDescription: 'Mistral 7B, efficient and fast open LLM.',
2119
+ },
2120
+ {
2121
+ modelVariant: 'CHAT',
2122
+ modelTitle: 'gorilla',
2123
+ modelName: 'gorilla',
2124
+ modelDescription: 'Gorilla, open-source LLM for tool use and APIs.',
2125
+ },
2126
+ {
2127
+ modelVariant: 'CHAT',
2128
+ modelTitle: 'cerebras-13b',
2129
+ modelName: 'cerebras-13b',
2130
+ modelDescription: 'Cerebras-GPT 13B, open large language model.',
2131
+ },
2132
+ {
2133
+ modelVariant: 'CHAT',
2134
+ modelTitle: 'openchat-7b',
2135
+ modelName: 'openchat-7b',
2136
+ modelDescription: 'OpenChat 7B, fine-tuned for conversational tasks.',
2137
+ },
2138
+ {
2139
+ modelVariant: 'CHAT',
2140
+ modelTitle: 'openchat-13b',
2141
+ modelName: 'openchat-13b',
2142
+ modelDescription: 'OpenChat 13B, larger conversational LLM.',
2143
+ },
2144
+ {
2145
+ modelVariant: 'CHAT',
2146
+ modelTitle: 'mpt-7b-chat',
2147
+ modelName: 'mpt-7b-chat',
2148
+ modelDescription: 'MPT-7B Chat, optimized for dialogue and chat.',
2149
+ },
2150
+ {
2151
+ modelVariant: 'CHAT',
2152
+ modelTitle: 'mpt-7b-instruct',
2153
+ modelName: 'mpt-7b-instruct',
2154
+ modelDescription: 'MPT-7B Instruct, instruction-tuned variant.',
2155
+ },
2156
+ {
2157
+ modelVariant: 'CHAT',
2158
+ modelTitle: 'command-7b',
2159
+ modelName: 'command-7b',
2160
+ modelDescription: 'Command 7B, instruction-following LLM.',
2161
+ },
2162
+ {
2163
+ modelVariant: 'CHAT',
2164
+ modelTitle: 'starcoder',
2165
+ modelName: 'starcoder',
2166
+ modelDescription: 'StarCoder, code generation large language model.',
2167
+ },
2168
+ {
2169
+ modelVariant: 'CHAT',
2170
+ modelTitle: 'starcoder2',
2171
+ modelName: 'starcoder2',
2172
+ modelDescription: 'StarCoder2, improved code generation model.',
2173
+ },
2174
+ {
2175
+ modelVariant: 'CHAT',
2176
+ modelTitle: 'mixtral-7b-chat',
2177
+ modelName: 'mixtral-7b-chat',
2178
+ modelDescription: 'Mixtral 7B Chat, Mixture-of-Experts conversational model.',
2179
+ },
2180
+ {
2181
+ modelVariant: 'CHAT',
2182
+ modelTitle: 'mixtral-8x7b',
2183
+ modelName: 'mixtral-8x7b',
2184
+ modelDescription: 'Mixtral 8x7B, Mixture-of-Experts large language model.',
2185
+ },
2186
+ {
2187
+ modelVariant: 'CHAT',
2188
+ modelTitle: 'mixtral-8x7b-instruct',
2189
+ modelName: 'mixtral-8x7b-instruct',
2190
+ modelDescription: 'Mixtral 8x7B Instruct, instruction-tuned Mixture-of-Experts model.',
2191
+ },
2192
+ // <- [🕕]
2193
+ ],
2154
2194
  });
2155
2195
  /**
2156
- * TODO: [🦺] Is there some way how to put `packageName` and `className` on top and function definition on bottom?
2157
- * TODO: [🎶] Naming "constructor" vs "creator" vs "factory"
2196
+ * TODO: [🚸] Not all models are compatible with JSON mode, add this information here and use it
2197
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2158
2198
  */
2159
2199
 
2160
2200
  /**
@@ -2162,22 +2202,79 @@
2162
2202
  *
2163
2203
  * @public exported from `@promptbook/ollama`
2164
2204
  */
2165
- const DEFAULT_OLLAMA_BASE_URL = 'http://localhost:11434'; // <- TODO: !!!! What is the correct base URL? /v1?
2205
+ const DEFAULT_OLLAMA_BASE_URL = 'http://localhost:11434/v1';
2166
2206
 
2167
2207
  /**
2168
2208
  * Execution Tools for calling Ollama API
2169
2209
  *
2170
2210
  * @public exported from `@promptbook/ollama`
2171
2211
  */
2172
- const createOllamaExecutionTools = Object.assign((ollamaOptions) => {
2173
- const openAiCompatibleOptions = {
2174
- baseURL: DEFAULT_OLLAMA_BASE_URL,
2175
- ...ollamaOptions,
2176
- userId: 'ollama',
2177
- };
2178
- // TODO: !!!! Listing the models - do it dynamically in OpenAiExecutionTools
2179
- // TODO: !!!! Do not allow to create Assistant from OpenAi compatible tools
2180
- return createOpenAiExecutionTools(openAiCompatibleOptions);
2212
+ class OllamaExecutionTools extends OpenAiCompatibleExecutionTools {
2213
+ /* <- TODO: [🍚] `, Destroyable` */
2214
+ constructor(ollamaOptions) {
2215
+ const openAiCompatibleOptions = {
2216
+ baseURL: DEFAULT_OLLAMA_BASE_URL,
2217
+ ...ollamaOptions,
2218
+ userId: 'ollama',
2219
+ };
2220
+ super(openAiCompatibleOptions);
2221
+ }
2222
+ get title() {
2223
+ return 'Ollama';
2224
+ }
2225
+ get description() {
2226
+ return 'Use all models provided by Ollama';
2227
+ }
2228
+ /**
2229
+ * List all available models (non dynamically)
2230
+ *
2231
+ * Note: Purpose of this is to provide more information about models than standard listing from API
2232
+ */
2233
+ get HARDCODED_MODELS() {
2234
+ return OLLAMA_MODELS;
2235
+ }
2236
+ /**
2237
+ * Computes the usage of the Ollama API based on the response from Ollama
2238
+ */
2239
+ computeUsage(...args) {
2240
+ return {
2241
+ ...computeOpenAiUsage(...args),
2242
+ price: ZERO_VALUE, // <- Note: Running on local model, so no price, maybe in the future we can add a way to calculate price based on electricity usage
2243
+ };
2244
+ }
2245
+ /**
2246
+ * Default model for chat variant.
2247
+ */
2248
+ getDefaultChatModel() {
2249
+ return this.getDefaultModel('llama2'); // <- TODO: [🧠] Pick the best default model
2250
+ // <- TODO: [🛄] When 'llama2' not installed, maybe better error message
2251
+ }
2252
+ /**
2253
+ * Default model for completion variant.
2254
+ */
2255
+ getDefaultCompletionModel() {
2256
+ return this.getDefaultModel('llama2'); // <- TODO: [🧠] Pick the best default model
2257
+ // <- TODO: [🛄] When 'llama2' not installed, maybe better error message
2258
+ }
2259
+ /**
2260
+ * Default model for completion variant.
2261
+ */
2262
+ getDefaultEmbeddingModel() {
2263
+ return this.getDefaultModel('text-embedding-3-large'); // <- TODO: [🧠] Pick the best default model
2264
+ // <- TODO: [🛄]
2265
+ }
2266
+ }
2267
+ /**
2268
+ * TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
2269
+ */
2270
+
2271
+ /**
2272
+ * Execution Tools for calling Ollama API
2273
+ *
2274
+ * @public exported from `@promptbook/ollama`
2275
+ */
2276
+ const createOllamaExecutionTools = Object.assign((options) => {
2277
+ return new OllamaExecutionTools(options);
2181
2278
  }, {
2182
2279
  packageName: '@promptbook/ollama',
2183
2280
  className: 'OllamaExecutionTools',
@@ -2363,6 +2460,8 @@
2363
2460
 
2364
2461
  exports.BOOK_LANGUAGE_VERSION = BOOK_LANGUAGE_VERSION;
2365
2462
  exports.DEFAULT_OLLAMA_BASE_URL = DEFAULT_OLLAMA_BASE_URL;
2463
+ exports.OLLAMA_MODELS = OLLAMA_MODELS;
2464
+ exports.OllamaExecutionTools = OllamaExecutionTools;
2366
2465
  exports.PROMPTBOOK_ENGINE_VERSION = PROMPTBOOK_ENGINE_VERSION;
2367
2466
  exports._OllamaRegistration = _OllamaRegistration;
2368
2467
  exports.createOllamaExecutionTools = createOllamaExecutionTools;