@promptbook/ollama 0.94.0-1 → 0.94.0-13

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.
Files changed (27) hide show
  1. package/README.md +9 -9
  2. package/esm/index.es.js +1965 -166
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/ollama.index.d.ts +6 -0
  5. package/esm/typings/src/_packages/openai.index.d.ts +2 -0
  6. package/esm/typings/src/execution/AvailableModel.d.ts +9 -1
  7. package/esm/typings/src/llm-providers/_common/filterModels.d.ts +2 -2
  8. package/esm/typings/src/llm-providers/{openai/computeUsage.d.ts → _common/utils/pricing.d.ts} +2 -2
  9. package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionToolsOptions.d.ts +1 -1
  10. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionToolsOptions.d.ts +1 -1
  11. package/esm/typings/src/llm-providers/deepseek/DeepseekExecutionToolsOptions.d.ts +1 -1
  12. package/esm/typings/src/llm-providers/google/GoogleExecutionToolsOptions.d.ts +1 -1
  13. package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +36 -11
  14. package/esm/typings/src/llm-providers/ollama/OllamaExecutionToolsOptions.d.ts +23 -12
  15. package/esm/typings/src/llm-providers/ollama/createOllamaExecutionTools.d.ts +3 -3
  16. package/esm/typings/src/llm-providers/ollama/ollama-models.d.ts +14 -0
  17. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionToolsOptions.d.ts +1 -1
  18. package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +91 -0
  19. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +12 -53
  20. package/esm/typings/src/llm-providers/openai/OpenAiExecutionToolsOptions.d.ts +1 -1
  21. package/esm/typings/src/llm-providers/openai/createOpenAiExecutionTools.d.ts +2 -0
  22. package/esm/typings/src/llm-providers/openai/openai-models.d.ts +1 -7
  23. package/esm/typings/src/version.d.ts +1 -1
  24. package/package.json +27 -2
  25. package/umd/index.umd.js +1969 -168
  26. package/umd/index.umd.js.map +1 -1
  27. /package/esm/typings/src/llm-providers/{openai/computeUsage.test.d.ts → _common/utils/pricing.test.d.ts} +0 -0
package/esm/index.es.js CHANGED
@@ -1,7 +1,8 @@
1
- import Bottleneck from 'bottleneck';
2
- import fetch from 'node-fetch';
3
- import { randomBytes } from 'crypto';
4
1
  import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
2
+ import { randomBytes } from 'crypto';
3
+ import Bottleneck from 'bottleneck';
4
+ import colors from 'colors';
5
+ import OpenAI from 'openai';
5
6
 
6
7
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
7
8
  /**
@@ -17,12 +18,122 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
17
18
  * @generated
18
19
  * @see https://github.com/webgptorg/promptbook
19
20
  */
20
- const PROMPTBOOK_ENGINE_VERSION = '0.94.0-1';
21
+ const PROMPTBOOK_ENGINE_VERSION = '0.94.0-13';
21
22
  /**
22
23
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
23
24
  * Note: [💞] Ignore a discrepancy between file name and entity name
24
25
  */
25
26
 
27
+ /**
28
+ * Freezes the given object and all its nested objects recursively
29
+ *
30
+ * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
31
+ * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
32
+ *
33
+ * @returns The same object as the input, but deeply frozen
34
+ * @public exported from `@promptbook/utils`
35
+ */
36
+ function $deepFreeze(objectValue) {
37
+ if (Array.isArray(objectValue)) {
38
+ return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
39
+ }
40
+ const propertyNames = Object.getOwnPropertyNames(objectValue);
41
+ for (const propertyName of propertyNames) {
42
+ const value = objectValue[propertyName];
43
+ if (value && typeof value === 'object') {
44
+ $deepFreeze(value);
45
+ }
46
+ }
47
+ Object.freeze(objectValue);
48
+ return objectValue;
49
+ }
50
+ /**
51
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
52
+ */
53
+
54
+ /**
55
+ * Represents the uncertain value
56
+ *
57
+ * @public exported from `@promptbook/core`
58
+ */
59
+ const ZERO_VALUE = $deepFreeze({ value: 0 });
60
+ /**
61
+ * Represents the uncertain value
62
+ *
63
+ * @public exported from `@promptbook/core`
64
+ */
65
+ const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
66
+ /**
67
+ * Represents the usage with no resources consumed
68
+ *
69
+ * @public exported from `@promptbook/core`
70
+ */
71
+ $deepFreeze({
72
+ price: ZERO_VALUE,
73
+ input: {
74
+ tokensCount: ZERO_VALUE,
75
+ charactersCount: ZERO_VALUE,
76
+ wordsCount: ZERO_VALUE,
77
+ sentencesCount: ZERO_VALUE,
78
+ linesCount: ZERO_VALUE,
79
+ paragraphsCount: ZERO_VALUE,
80
+ pagesCount: ZERO_VALUE,
81
+ },
82
+ output: {
83
+ tokensCount: ZERO_VALUE,
84
+ charactersCount: ZERO_VALUE,
85
+ wordsCount: ZERO_VALUE,
86
+ sentencesCount: ZERO_VALUE,
87
+ linesCount: ZERO_VALUE,
88
+ paragraphsCount: ZERO_VALUE,
89
+ pagesCount: ZERO_VALUE,
90
+ },
91
+ });
92
+ /**
93
+ * Represents the usage with unknown resources consumed
94
+ *
95
+ * @public exported from `@promptbook/core`
96
+ */
97
+ $deepFreeze({
98
+ price: UNCERTAIN_ZERO_VALUE,
99
+ input: {
100
+ tokensCount: UNCERTAIN_ZERO_VALUE,
101
+ charactersCount: UNCERTAIN_ZERO_VALUE,
102
+ wordsCount: UNCERTAIN_ZERO_VALUE,
103
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
104
+ linesCount: UNCERTAIN_ZERO_VALUE,
105
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
106
+ pagesCount: UNCERTAIN_ZERO_VALUE,
107
+ },
108
+ output: {
109
+ tokensCount: UNCERTAIN_ZERO_VALUE,
110
+ charactersCount: UNCERTAIN_ZERO_VALUE,
111
+ wordsCount: UNCERTAIN_ZERO_VALUE,
112
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
113
+ linesCount: UNCERTAIN_ZERO_VALUE,
114
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
115
+ pagesCount: UNCERTAIN_ZERO_VALUE,
116
+ },
117
+ });
118
+ /**
119
+ * Note: [💞] Ignore a discrepancy between file name and entity name
120
+ */
121
+
122
+ /**
123
+ * Orders JSON object by keys
124
+ *
125
+ * @returns The same type of object as the input re-ordered
126
+ * @public exported from `@promptbook/utils`
127
+ */
128
+ function orderJson(options) {
129
+ const { value, order } = options;
130
+ const orderedValue = {
131
+ ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
132
+ ...value,
133
+ };
134
+ return orderedValue;
135
+ }
136
+
26
137
  /**
27
138
  * Name for the Promptbook
28
139
  *
@@ -43,6 +154,34 @@ const ADMIN_EMAIL = 'pavol@ptbk.io';
43
154
  * @public exported from `@promptbook/core`
44
155
  */
45
156
  const ADMIN_GITHUB_NAME = 'hejny';
157
+ // <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
158
+ /**
159
+ * The maximum number of iterations for a loops
160
+ *
161
+ * @private within the repository - too low-level in comparison with other `MAX_...`
162
+ */
163
+ const LOOP_LIMIT = 1000;
164
+ /**
165
+ * Strings to represent various values in the context of parameter values
166
+ *
167
+ * @public exported from `@promptbook/utils`
168
+ */
169
+ const VALUE_STRINGS = {
170
+ empty: '(nothing; empty string)',
171
+ null: '(no value; null)',
172
+ undefined: '(unknown value; undefined)',
173
+ nan: '(not a number; NaN)',
174
+ infinity: '(infinity; ∞)',
175
+ negativeInfinity: '(negative infinity; -∞)',
176
+ unserializable: '(unserializable value)',
177
+ circular: '(circular JSON)',
178
+ };
179
+ /**
180
+ * Small number limit
181
+ *
182
+ * @public exported from `@promptbook/utils`
183
+ */
184
+ const SMALL_NUMBER = 0.001;
46
185
  // <- TODO: [🧜‍♂️]
47
186
  /**
48
187
  * Default settings for parsing and generating CSV files in Promptbook.
@@ -68,40 +207,6 @@ const DEFAULT_MAX_REQUESTS_PER_MINUTE = 60;
68
207
  * TODO: [🧠][🧜‍♂️] Maybe join remoteServerUrl and path into single value
69
208
  */
70
209
 
71
- /**
72
- * Generates random token
73
- *
74
- * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
75
- *
76
- * @private internal helper function
77
- * @returns secure random token
78
- */
79
- function $randomToken(randomness) {
80
- return randomBytes(randomness).toString('hex');
81
- }
82
- /**
83
- * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
84
- */
85
-
86
- /**
87
- * This error indicates errors during the execution of the pipeline
88
- *
89
- * @public exported from `@promptbook/core`
90
- */
91
- class PipelineExecutionError extends Error {
92
- constructor(message) {
93
- // Added id parameter
94
- super(message);
95
- this.name = 'PipelineExecutionError';
96
- // TODO: [🐙] DRY - Maybe $randomId
97
- this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
98
- Object.setPrototypeOf(this, PipelineExecutionError.prototype);
99
- }
100
- }
101
- /**
102
- * TODO: [🧠][🌂] Add id to all errors
103
- */
104
-
105
210
  /**
106
211
  * Make error report URL for the given error
107
212
  *
@@ -170,60 +275,6 @@ class UnexpectedError extends Error {
170
275
  }
171
276
  }
172
277
 
173
- /**
174
- * Simple wrapper `new Date().toISOString()`
175
- *
176
- * Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
177
- *
178
- * @returns string_date branded type
179
- * @public exported from `@promptbook/utils`
180
- */
181
- function $getCurrentDate() {
182
- return new Date().toISOString();
183
- }
184
-
185
- /**
186
- * Orders JSON object by keys
187
- *
188
- * @returns The same type of object as the input re-ordered
189
- * @public exported from `@promptbook/utils`
190
- */
191
- function orderJson(options) {
192
- const { value, order } = options;
193
- const orderedValue = {
194
- ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
195
- ...value,
196
- };
197
- return orderedValue;
198
- }
199
-
200
- /**
201
- * Freezes the given object and all its nested objects recursively
202
- *
203
- * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
204
- * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
205
- *
206
- * @returns The same object as the input, but deeply frozen
207
- * @public exported from `@promptbook/utils`
208
- */
209
- function $deepFreeze(objectValue) {
210
- if (Array.isArray(objectValue)) {
211
- return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
212
- }
213
- const propertyNames = Object.getOwnPropertyNames(objectValue);
214
- for (const propertyName of propertyNames) {
215
- const value = objectValue[propertyName];
216
- if (value && typeof value === 'object') {
217
- $deepFreeze(value);
218
- }
219
- }
220
- Object.freeze(objectValue);
221
- return objectValue;
222
- }
223
- /**
224
- * TODO: [🧠] Is there a way how to meaningfully test this utility
225
- */
226
-
227
278
  /**
228
279
  * This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
229
280
  *
@@ -472,89 +523,1837 @@ function exportJson(options) {
472
523
  */
473
524
 
474
525
  /**
475
- * Execution Tools for calling a local Ollama model via HTTP API
526
+ * Nonce which is used for replacing things in strings
476
527
  *
477
- * @public exported from `@promptbook/ollama`
528
+ * @private within the repository
478
529
  */
479
- class OllamaExecutionTools {
480
- constructor(options) {
481
- this.options = options;
482
- this.limiter = new Bottleneck({
483
- minTime: 60000 / (options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
484
- });
485
- }
486
- get title() {
487
- return 'Ollama';
488
- }
489
- get description() {
490
- return 'Local Ollama LLM via HTTP';
491
- }
492
- async checkConfiguration() {
493
- const res = await fetch(`${this.options.baseUrl}/models`);
494
- if (!res.ok)
495
- throw new UnexpectedError(`Failed to reach Ollama API at ${this.options.baseUrl}`);
496
- }
497
- async listModels() {
498
- const res = await fetch(`${this.options.baseUrl}/models`);
499
- if (!res.ok)
500
- throw new UnexpectedError(`Error listing Ollama models: ${res.statusText}`);
501
- const data = (await res.json());
502
- return data.map((m) => ({ modelName: m.name, modelVariant: 'CHAT' }));
503
- }
504
- async callChatModel(prompt) {
505
- const { content, parameters, modelRequirements } = prompt;
506
- if (modelRequirements.modelVariant !== 'CHAT') {
507
- throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
508
- }
509
- const modelName = modelRequirements.modelName || this.options.model;
510
- const body = {
511
- model: modelName,
512
- messages: [
513
- ...(modelRequirements.systemMessage
514
- ? [{ role: 'system', content: modelRequirements.systemMessage }]
515
- : []),
516
- { role: 'user', content: content },
517
- ],
518
- parameters: parameters,
519
- };
520
- const start = $getCurrentDate();
521
- const res = await this.limiter.schedule(() => fetch(`${this.options.baseUrl}/chat/completions`, {
522
- method: 'POST',
523
- headers: { 'Content-Type': 'application/json' },
524
- body: JSON.stringify(body),
525
- }));
526
- if (!res.ok)
527
- throw new PipelineExecutionError(`Ollama API error: ${res.statusText}`);
528
- const json = await res.json();
529
- const complete = $getCurrentDate();
530
- if (!json.choices || !json.choices[0]) {
531
- throw new PipelineExecutionError('No choices from Ollama');
532
- }
533
- const resultContent = json.choices[0].message.content;
534
- const usage = { price: { value: 0, isUncertain: true }, input: {}, output: {} }; /* <- !!! */
535
- return exportJson({
536
- name: 'promptResult',
537
- message: 'Result of Ollama',
538
- order: [],
539
- value: {
540
- content: resultContent,
541
- modelName,
542
- timing: { start, complete },
543
- usage,
544
- rawPromptContent: content,
545
- rawRequest: body,
546
- rawResponse: json,
547
- },
548
- });
530
+ const REPLACING_NONCE = 'ptbkauk42kV2dzao34faw7FudQUHYPtW';
531
+ /**
532
+ * Nonce which is used as string which is not occurring in normal text
533
+ *
534
+ * @private within the repository
535
+ */
536
+ const SALT_NONCE = 'ptbkghhewbvruets21t54et5';
537
+ /**
538
+ * Placeholder value indicating a parameter is missing its value.
539
+ *
540
+ * @private within the repository
541
+ */
542
+ const RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
543
+ /**
544
+ * Placeholder value indicating a parameter is restricted and cannot be used directly.
545
+ *
546
+ * @private within the repository
547
+ */
548
+ const RESERVED_PARAMETER_RESTRICTED = 'RESTRICTED-' + REPLACING_NONCE;
549
+ /**
550
+ * The names of the parameters that are reserved for special purposes
551
+ *
552
+ * @public exported from `@promptbook/core`
553
+ */
554
+ exportJson({
555
+ name: 'RESERVED_PARAMETER_NAMES',
556
+ message: `The names of the parameters that are reserved for special purposes`,
557
+ value: [
558
+ 'content',
559
+ 'context',
560
+ 'knowledge',
561
+ 'examples',
562
+ 'modelName',
563
+ 'currentDate',
564
+ // <- TODO: list here all command names
565
+ // <- TODO: Add more like 'date', 'modelName',...
566
+ // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
567
+ ],
568
+ });
569
+ /**
570
+ * Note: [💞] Ignore a discrepancy between file name and entity name
571
+ */
572
+
573
+ /**
574
+ * Generates random token
575
+ *
576
+ * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
577
+ *
578
+ * @private internal helper function
579
+ * @returns secure random token
580
+ */
581
+ function $randomToken(randomness) {
582
+ return randomBytes(randomness).toString('hex');
583
+ }
584
+ /**
585
+ * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
586
+ */
587
+
588
+ /**
589
+ * This error indicates errors during the execution of the pipeline
590
+ *
591
+ * @public exported from `@promptbook/core`
592
+ */
593
+ class PipelineExecutionError extends Error {
594
+ constructor(message) {
595
+ // Added id parameter
596
+ super(message);
597
+ this.name = 'PipelineExecutionError';
598
+ // TODO: [🐙] DRY - Maybe $randomId
599
+ this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
600
+ Object.setPrototypeOf(this, PipelineExecutionError.prototype);
549
601
  }
550
602
  }
603
+ /**
604
+ * TODO: [🧠][🌂] Add id to all errors
605
+ */
606
+
607
+ /**
608
+ * Counts number of characters in the text
609
+ *
610
+ * @public exported from `@promptbook/utils`
611
+ */
612
+ function countCharacters(text) {
613
+ // Remove null characters
614
+ text = text.replace(/\0/g, '');
615
+ // Replace emojis (and also ZWJ sequence) with hyphens
616
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
617
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
618
+ text = text.replace(/\p{Extended_Pictographic}(\u{200D}\p{Extended_Pictographic})*/gu, '-');
619
+ return text.length;
620
+ }
621
+ /**
622
+ * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
623
+ */
624
+
625
+ /**
626
+ * Number of characters per standard line with 11pt Arial font size.
627
+ *
628
+ * @public exported from `@promptbook/utils`
629
+ */
630
+ const CHARACTERS_PER_STANDARD_LINE = 63;
631
+ /**
632
+ * Number of lines per standard A4 page with 11pt Arial font size and standard margins and spacing.
633
+ *
634
+ * @public exported from `@promptbook/utils`
635
+ */
636
+ const LINES_PER_STANDARD_PAGE = 44;
637
+ /**
638
+ * TODO: [🧠] Should be this `constants.ts` or `config.ts`?
639
+ * Note: [💞] Ignore a discrepancy between file name and entity name
640
+ */
641
+
642
+ /**
643
+ * Counts number of lines in the text
644
+ *
645
+ * Note: This does not check only for the presence of newlines, but also for the length of the standard line.
646
+ *
647
+ * @public exported from `@promptbook/utils`
648
+ */
649
+ function countLines(text) {
650
+ text = text.replace('\r\n', '\n');
651
+ text = text.replace('\r', '\n');
652
+ const lines = text.split('\n');
653
+ return lines.reduce((count, line) => count + Math.ceil(line.length / CHARACTERS_PER_STANDARD_LINE), 0);
654
+ }
655
+ /**
656
+ * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
657
+ */
658
+
659
+ /**
660
+ * Counts number of pages in the text
661
+ *
662
+ * Note: This does not check only for the count of newlines, but also for the length of the standard line and length of the standard page.
663
+ *
664
+ * @public exported from `@promptbook/utils`
665
+ */
666
+ function countPages(text) {
667
+ return Math.ceil(countLines(text) / LINES_PER_STANDARD_PAGE);
668
+ }
669
+ /**
670
+ * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
671
+ */
672
+
673
+ /**
674
+ * Counts number of paragraphs in the text
675
+ *
676
+ * @public exported from `@promptbook/utils`
677
+ */
678
+ function countParagraphs(text) {
679
+ return text.split(/\n\s*\n/).filter((paragraph) => paragraph.trim() !== '').length;
680
+ }
681
+ /**
682
+ * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
683
+ */
684
+
685
+ /**
686
+ * Split text into sentences
687
+ *
688
+ * @public exported from `@promptbook/utils`
689
+ */
690
+ function splitIntoSentences(text) {
691
+ return text.split(/[.!?]+/).filter((sentence) => sentence.trim() !== '');
692
+ }
693
+ /**
694
+ * Counts number of sentences in the text
695
+ *
696
+ * @public exported from `@promptbook/utils`
697
+ */
698
+ function countSentences(text) {
699
+ return splitIntoSentences(text).length;
700
+ }
701
+ /**
702
+ * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
703
+ */
704
+
705
+ const defaultDiacriticsRemovalMap = [
706
+ {
707
+ base: 'A',
708
+ letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F',
709
+ },
710
+ { base: 'AA', letters: '\uA732' },
711
+ { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
712
+ { base: 'AO', letters: '\uA734' },
713
+ { base: 'AU', letters: '\uA736' },
714
+ { base: 'AV', letters: '\uA738\uA73A' },
715
+ { base: 'AY', letters: '\uA73C' },
716
+ {
717
+ base: 'B',
718
+ letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
719
+ },
720
+ {
721
+ base: 'C',
722
+ letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
723
+ },
724
+ {
725
+ base: 'D',
726
+ letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
727
+ },
728
+ { base: 'DZ', letters: '\u01F1\u01C4' },
729
+ { base: 'Dz', letters: '\u01F2\u01C5' },
730
+ {
731
+ base: 'E',
732
+ letters: '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E',
733
+ },
734
+ { base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
735
+ {
736
+ base: 'G',
737
+ letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
738
+ },
739
+ {
740
+ base: 'H',
741
+ letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
742
+ },
743
+ {
744
+ base: 'I',
745
+ letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
746
+ },
747
+ { base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
748
+ {
749
+ base: 'K',
750
+ letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
751
+ },
752
+ {
753
+ base: 'L',
754
+ letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
755
+ },
756
+ { base: 'LJ', letters: '\u01C7' },
757
+ { base: 'Lj', letters: '\u01C8' },
758
+ { base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
759
+ {
760
+ base: 'N',
761
+ letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
762
+ },
763
+ { base: 'NJ', letters: '\u01CA' },
764
+ { base: 'Nj', letters: '\u01CB' },
765
+ {
766
+ base: 'O',
767
+ letters: '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C',
768
+ },
769
+ { base: 'OI', letters: '\u01A2' },
770
+ { base: 'OO', letters: '\uA74E' },
771
+ { base: 'OU', letters: '\u0222' },
772
+ { base: 'OE', letters: '\u008C\u0152' },
773
+ { base: 'oe', letters: '\u009C\u0153' },
774
+ {
775
+ base: 'P',
776
+ letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
777
+ },
778
+ { base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
779
+ {
780
+ base: 'R',
781
+ letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
782
+ },
783
+ {
784
+ base: 'S',
785
+ letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
786
+ },
787
+ {
788
+ base: 'T',
789
+ letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
790
+ },
791
+ { base: 'TZ', letters: '\uA728' },
792
+ {
793
+ base: 'U',
794
+ letters: '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244',
795
+ },
796
+ { base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
797
+ { base: 'VY', letters: '\uA760' },
798
+ {
799
+ base: 'W',
800
+ letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
801
+ },
802
+ { base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
803
+ {
804
+ base: 'Y',
805
+ letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
806
+ },
807
+ {
808
+ base: 'Z',
809
+ letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
810
+ },
811
+ {
812
+ base: 'a',
813
+ letters: '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250',
814
+ },
815
+ { base: 'aa', letters: '\uA733' },
816
+ { base: 'ae', letters: '\u00E6\u01FD\u01E3' },
817
+ { base: 'ao', letters: '\uA735' },
818
+ { base: 'au', letters: '\uA737' },
819
+ { base: 'av', letters: '\uA739\uA73B' },
820
+ { base: 'ay', letters: '\uA73D' },
821
+ {
822
+ base: 'b',
823
+ letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
824
+ },
825
+ {
826
+ base: 'c',
827
+ letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
828
+ },
829
+ {
830
+ base: 'd',
831
+ letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
832
+ },
833
+ { base: 'dz', letters: '\u01F3\u01C6' },
834
+ {
835
+ base: 'e',
836
+ letters: '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD',
837
+ },
838
+ { base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
839
+ {
840
+ base: 'g',
841
+ letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
842
+ },
843
+ {
844
+ base: 'h',
845
+ letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
846
+ },
847
+ { base: 'hv', letters: '\u0195' },
848
+ {
849
+ base: 'i',
850
+ letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
851
+ },
852
+ { base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
853
+ {
854
+ base: 'k',
855
+ letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
856
+ },
857
+ {
858
+ base: 'l',
859
+ letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
860
+ },
861
+ { base: 'lj', letters: '\u01C9' },
862
+ { base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
863
+ {
864
+ base: 'n',
865
+ letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
866
+ },
867
+ { base: 'nj', letters: '\u01CC' },
868
+ {
869
+ base: 'o',
870
+ letters: '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275',
871
+ },
872
+ { base: 'oi', letters: '\u01A3' },
873
+ { base: 'ou', letters: '\u0223' },
874
+ { base: 'oo', letters: '\uA74F' },
875
+ {
876
+ base: 'p',
877
+ letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
878
+ },
879
+ { base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
880
+ {
881
+ base: 'r',
882
+ letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
883
+ },
884
+ {
885
+ base: 's',
886
+ letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
887
+ },
888
+ {
889
+ base: 't',
890
+ letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
891
+ },
892
+ { base: 'tz', letters: '\uA729' },
893
+ {
894
+ base: 'u',
895
+ letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289',
896
+ },
897
+ { base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
898
+ { base: 'vy', letters: '\uA761' },
899
+ {
900
+ base: 'w',
901
+ letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
902
+ },
903
+ { base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
904
+ {
905
+ base: 'y',
906
+ letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
907
+ },
908
+ {
909
+ base: 'z',
910
+ letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
911
+ },
912
+ ];
913
+ /**
914
+ * Map of letters from diacritic variant to diacritless variant
915
+ * Contains lowercase and uppercase separatelly
916
+ *
917
+ * > "á" => "a"
918
+ * > "ě" => "e"
919
+ * > "Ă" => "A"
920
+ * > ...
921
+ *
922
+ * @public exported from `@promptbook/utils`
923
+ */
924
+ const DIACRITIC_VARIANTS_LETTERS = {};
925
+ // tslint:disable-next-line: prefer-for-of
926
+ for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
927
+ const letters = defaultDiacriticsRemovalMap[i].letters;
928
+ // tslint:disable-next-line: prefer-for-of
929
+ for (let j = 0; j < letters.length; j++) {
930
+ DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
931
+ }
932
+ }
933
+ // <- TODO: [🍓] Put to maker function to save execution time if not needed
934
+ /*
935
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
936
+ Licensed under the Apache License, Version 2.0 (the "License");
937
+ you may not use this file except in compliance with the License.
938
+ You may obtain a copy of the License at
939
+
940
+ http://www.apache.org/licenses/LICENSE-2.0
941
+
942
+ Unless required by applicable law or agreed to in writing, software
943
+ distributed under the License is distributed on an "AS IS" BASIS,
944
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
945
+ See the License for the specific language governing permissions and
946
+ limitations under the License.
947
+ */
948
+
949
+ /**
950
+ * Removes diacritic marks (accents) from characters in a string.
951
+ *
952
+ * @param input The string containing diacritics to be normalized.
953
+ * @returns The string with diacritics removed or normalized.
954
+ * @public exported from `@promptbook/utils`
955
+ */
956
+ function removeDiacritics(input) {
957
+ /*eslint no-control-regex: "off"*/
958
+ return input.replace(/[^\u0000-\u007E]/g, (a) => {
959
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
960
+ });
961
+ }
962
+ /**
963
+ * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
964
+ */
965
+
966
+ /**
967
+ * Counts number of words in the text
968
+ *
969
+ * @public exported from `@promptbook/utils`
970
+ */
971
+ function countWords(text) {
972
+ text = text.replace(/[\p{Extended_Pictographic}]/gu, 'a');
973
+ text = removeDiacritics(text);
974
+ // Add spaces before uppercase letters preceded by lowercase letters (for camelCase)
975
+ text = text.replace(/([a-z])([A-Z])/g, '$1 $2');
976
+ return text.split(/[^a-zа-я0-9]+/i).filter((word) => word.length > 0).length;
977
+ }
978
+ /**
979
+ * TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
980
+ */
981
+
982
+ /**
983
+ * Helper of usage compute
984
+ *
985
+ * @param content the content of prompt or response
986
+ * @returns part of UsageCounts
987
+ *
988
+ * @private internal utility of LlmExecutionTools
989
+ */
990
+ function computeUsageCounts(content) {
991
+ return {
992
+ charactersCount: { value: countCharacters(content) },
993
+ wordsCount: { value: countWords(content) },
994
+ sentencesCount: { value: countSentences(content) },
995
+ linesCount: { value: countLines(content) },
996
+ paragraphsCount: { value: countParagraphs(content) },
997
+ pagesCount: { value: countPages(content) },
998
+ };
999
+ }
1000
+
1001
+ /**
1002
+ * Make UncertainNumber
1003
+ *
1004
+ * @param value value of the uncertain number, if `NaN` or `undefined`, it will be set to 0 and `isUncertain=true`
1005
+ * @param isUncertain if `true`, the value is uncertain, otherwise depends on the value
1006
+ *
1007
+ * @private utility for initializating UncertainNumber
1008
+ */
1009
+ function uncertainNumber(value, isUncertain) {
1010
+ if (value === null || value === undefined || Number.isNaN(value)) {
1011
+ return UNCERTAIN_ZERO_VALUE;
1012
+ }
1013
+ if (isUncertain === true) {
1014
+ return { value, isUncertain };
1015
+ }
1016
+ return { value };
1017
+ }
1018
+
1019
+ /**
1020
+ * Create price per one token based on the string value found on openai page
1021
+ *
1022
+ * @private within the repository, used only as internal helper for `OPENAI_MODELS`
1023
+ */
1024
+ function pricing(value) {
1025
+ const [price, tokens] = value.split(' / ');
1026
+ return parseFloat(price.replace('$', '')) / parseFloat(tokens.replace('M tokens', '')) / 1000000;
1027
+ }
1028
+
1029
+ /**
1030
+ * List of available OpenAI models with pricing
1031
+ *
1032
+ * Note: Done at 2025-05-06
1033
+ *
1034
+ * @see https://platform.openai.com/docs/models/
1035
+ * @see https://openai.com/api/pricing/
1036
+ * @public exported from `@promptbook/openai`
1037
+ */
1038
+ const OPENAI_MODELS = exportJson({
1039
+ name: 'OPENAI_MODELS',
1040
+ value: [
1041
+ /*/
1042
+ {
1043
+ modelTitle: 'dall-e-3',
1044
+ modelName: 'dall-e-3',
1045
+ },
1046
+ /**/
1047
+ /*/
1048
+ {
1049
+ modelTitle: 'whisper-1',
1050
+ modelName: 'whisper-1',
1051
+ },
1052
+ /**/
1053
+ /**/
1054
+ {
1055
+ modelVariant: 'COMPLETION',
1056
+ modelTitle: 'davinci-002',
1057
+ modelName: 'davinci-002',
1058
+ modelDescription: 'Legacy completion model with 4K token context window. Excels at complex text generation, creative writing, and detailed content creation with strong contextual understanding. Optimized for instructions requiring nuanced outputs and extended reasoning. Suitable for applications needing high-quality text generation without conversation management.',
1059
+ pricing: {
1060
+ prompt: pricing(`$2.00 / 1M tokens`),
1061
+ output: pricing(`$2.00 / 1M tokens`),
1062
+ },
1063
+ },
1064
+ /**/
1065
+ /*/
1066
+ {
1067
+ modelTitle: 'dall-e-2',
1068
+ modelName: 'dall-e-2',
1069
+ },
1070
+ /**/
1071
+ /**/
1072
+ {
1073
+ modelVariant: 'CHAT',
1074
+ modelTitle: 'gpt-3.5-turbo-16k',
1075
+ modelName: 'gpt-3.5-turbo-16k',
1076
+ modelDescription: 'Extended context GPT-3.5 Turbo with 16K token window. Maintains core capabilities of standard 3.5 Turbo while supporting longer conversations and documents. Features good balance of performance and cost for applications requiring more context than standard 4K models. Effective for document analysis, extended conversations, and multi-step reasoning tasks.',
1077
+ pricing: {
1078
+ prompt: pricing(`$3.00 / 1M tokens`),
1079
+ output: pricing(`$4.00 / 1M tokens`),
1080
+ },
1081
+ },
1082
+ /**/
1083
+ /*/
1084
+ {
1085
+ modelTitle: 'tts-1-hd-1106',
1086
+ modelName: 'tts-1-hd-1106',
1087
+ },
1088
+ /**/
1089
+ /*/
1090
+ {
1091
+ modelTitle: 'tts-1-hd',
1092
+ modelName: 'tts-1-hd',
1093
+ },
1094
+ /**/
1095
+ /**/
1096
+ {
1097
+ modelVariant: 'CHAT',
1098
+ modelTitle: 'gpt-4',
1099
+ modelName: 'gpt-4',
1100
+ modelDescription: 'Powerful language model with 8K context window featuring sophisticated reasoning, instruction-following, and knowledge capabilities. Demonstrates strong performance on complex tasks requiring deep understanding and multi-step reasoning. Excels at code generation, logical analysis, and nuanced content creation. Suitable for advanced applications requiring high-quality outputs.',
1101
+ pricing: {
1102
+ prompt: pricing(`$30.00 / 1M tokens`),
1103
+ output: pricing(`$60.00 / 1M tokens`),
1104
+ },
1105
+ },
1106
+ /**/
1107
+ /**/
1108
+ {
1109
+ modelVariant: 'CHAT',
1110
+ modelTitle: 'gpt-4-32k',
1111
+ modelName: 'gpt-4-32k',
1112
+ modelDescription: 'Extended context version of GPT-4 with 32K token window. Maintains all capabilities of standard GPT-4 while supporting analysis of very lengthy documents, code bases, and conversations. Features enhanced ability to maintain context over long interactions and process detailed information from large inputs. Ideal for document analysis, legal review, and complex problem-solving.',
1113
+ pricing: {
1114
+ prompt: pricing(`$60.00 / 1M tokens`),
1115
+ output: pricing(`$120.00 / 1M tokens`),
1116
+ },
1117
+ },
1118
+ /**/
1119
+ /*/
1120
+ {
1121
+ modelVariant: 'CHAT',
1122
+ modelTitle: 'gpt-4-0613',
1123
+ modelName: 'gpt-4-0613',
1124
+ pricing: {
1125
+ prompt: computeUsage(` / 1M tokens`),
1126
+ output: computeUsage(` / 1M tokens`),
1127
+ },
1128
+ },
1129
+ /**/
1130
+ /**/
1131
+ {
1132
+ modelVariant: 'CHAT',
1133
+ modelTitle: 'gpt-4-turbo-2024-04-09',
1134
+ modelName: 'gpt-4-turbo-2024-04-09',
1135
+ modelDescription: 'Latest stable GPT-4 Turbo from April 2024 with 128K context window. Features enhanced reasoning chains, improved factual accuracy with 40% reduction in hallucinations, and better instruction following compared to earlier versions. Includes advanced function calling capabilities and knowledge up to April 2024. Provides optimal performance for enterprise applications requiring reliability.',
1136
+ pricing: {
1137
+ prompt: pricing(`$10.00 / 1M tokens`),
1138
+ output: pricing(`$30.00 / 1M tokens`),
1139
+ },
1140
+ },
1141
+ /**/
1142
+ /**/
1143
+ {
1144
+ modelVariant: 'CHAT',
1145
+ modelTitle: 'gpt-3.5-turbo-1106',
1146
+ modelName: 'gpt-3.5-turbo-1106',
1147
+ modelDescription: 'November 2023 version of GPT-3.5 Turbo with 16K token context window. Features improved instruction following, more consistent output formatting, and enhanced function calling capabilities. Includes knowledge cutoff from April 2023. Suitable for applications requiring good performance at lower cost than GPT-4 models.',
1148
+ pricing: {
1149
+ prompt: pricing(`$1.00 / 1M tokens`),
1150
+ output: pricing(`$2.00 / 1M tokens`),
1151
+ },
1152
+ },
1153
+ /**/
1154
+ /**/
1155
+ {
1156
+ modelVariant: 'CHAT',
1157
+ modelTitle: 'gpt-4-turbo',
1158
+ modelName: 'gpt-4-turbo',
1159
+ modelDescription: 'More capable and cost-efficient version of GPT-4 with 128K token context window. Features improved instruction following, advanced function calling capabilities, and better performance on coding tasks. Maintains superior reasoning and knowledge while offering substantial cost reduction compared to base GPT-4. Ideal for complex applications requiring extensive context processing.',
1160
+ pricing: {
1161
+ prompt: pricing(`$10.00 / 1M tokens`),
1162
+ output: pricing(`$30.00 / 1M tokens`),
1163
+ },
1164
+ },
1165
+ /**/
1166
+ /**/
1167
+ {
1168
+ modelVariant: 'COMPLETION',
1169
+ modelTitle: 'gpt-3.5-turbo-instruct-0914',
1170
+ modelName: 'gpt-3.5-turbo-instruct-0914',
1171
+ modelDescription: 'September 2023 version of GPT-3.5 Turbo Instruct with 4K context window. Optimized for completion-style instruction following with deterministic responses. Better suited than chat models for applications requiring specific formatted outputs without conversation management. Knowledge cutoff from September 2021.',
1172
+ pricing: {
1173
+ prompt: pricing(`$1.50 / 1M tokens`),
1174
+ output: pricing(`$2.00 / 1M tokens`),
1175
+ },
1176
+ },
1177
+ /**/
1178
+ /**/
1179
+ {
1180
+ modelVariant: 'COMPLETION',
1181
+ modelTitle: 'gpt-3.5-turbo-instruct',
1182
+ modelName: 'gpt-3.5-turbo-instruct',
1183
+ modelDescription: 'Optimized version of GPT-3.5 for completion-style API with 4K token context window. Features strong instruction following with single-turn design rather than multi-turn conversation. Provides more consistent, deterministic outputs compared to chat models. Well-suited for templated content generation and structured text transformation tasks.',
1184
+ pricing: {
1185
+ prompt: pricing(`$1.50 / 1M tokens`),
1186
+ output: pricing(`$2.00 / 1M tokens`),
1187
+ },
1188
+ },
1189
+ /**/
1190
+ /*/
1191
+ {
1192
+ modelTitle: 'tts-1',
1193
+ modelName: 'tts-1',
1194
+ },
1195
+ /**/
1196
+ /**/
1197
+ {
1198
+ modelVariant: 'CHAT',
1199
+ modelTitle: 'gpt-3.5-turbo',
1200
+ modelName: 'gpt-3.5-turbo',
1201
+ modelDescription: 'Latest version of GPT-3.5 Turbo with 4K token default context window (16K available). Features continually improved performance with enhanced instruction following and reduced hallucinations. Offers excellent balance between capability and cost efficiency. Suitable for most general-purpose applications requiring good AI capabilities at reasonable cost.',
1202
+ pricing: {
1203
+ prompt: pricing(`$0.50 / 1M tokens`),
1204
+ output: pricing(`$1.50 / 1M tokens`),
1205
+ },
1206
+ },
1207
+ /**/
1208
+ /**/
1209
+ {
1210
+ modelVariant: 'CHAT',
1211
+ modelTitle: 'gpt-3.5-turbo-0301',
1212
+ modelName: 'gpt-3.5-turbo-0301',
1213
+ modelDescription: 'March 2023 version of GPT-3.5 Turbo with 4K token context window. Legacy model maintained for backward compatibility with specific application behaviors. Features solid conversational abilities and basic instruction following. Knowledge cutoff from September 2021. Suitable for applications explicitly designed for this version.',
1214
+ pricing: {
1215
+ prompt: pricing(`$1.50 / 1M tokens`),
1216
+ output: pricing(`$2.00 / 1M tokens`),
1217
+ },
1218
+ },
1219
+ /**/
1220
+ /**/
1221
+ {
1222
+ modelVariant: 'COMPLETION',
1223
+ modelTitle: 'babbage-002',
1224
+ modelName: 'babbage-002',
1225
+ modelDescription: 'Efficient legacy completion model with 4K context window balancing performance and speed. Features moderate reasoning capabilities with focus on straightforward text generation tasks. Significantly more efficient than davinci models while maintaining adequate quality for many applications. Suitable for high-volume, cost-sensitive text generation needs.',
1226
+ pricing: {
1227
+ prompt: pricing(`$0.40 / 1M tokens`),
1228
+ output: pricing(`$0.40 / 1M tokens`),
1229
+ },
1230
+ },
1231
+ /**/
1232
+ /**/
1233
+ {
1234
+ modelVariant: 'CHAT',
1235
+ modelTitle: 'gpt-4-1106-preview',
1236
+ modelName: 'gpt-4-1106-preview',
1237
+ modelDescription: 'November 2023 preview version of GPT-4 Turbo with 128K token context window. Features improved instruction following, better function calling capabilities, and enhanced reasoning. Includes knowledge cutoff from April 2023. Suitable for complex applications requiring extensive document understanding and sophisticated interactions.',
1238
+ pricing: {
1239
+ prompt: pricing(`$10.00 / 1M tokens`),
1240
+ output: pricing(`$30.00 / 1M tokens`),
1241
+ },
1242
+ },
1243
+ /**/
1244
+ /**/
1245
+ {
1246
+ modelVariant: 'CHAT',
1247
+ modelTitle: 'gpt-4-0125-preview',
1248
+ modelName: 'gpt-4-0125-preview',
1249
+ modelDescription: 'January 2024 preview version of GPT-4 Turbo with 128K token context window. Features improved reasoning capabilities, enhanced tool use, and more reliable function calling. Includes knowledge cutoff from October 2023. Offers better performance on complex logical tasks and more consistent outputs than previous preview versions.',
1250
+ pricing: {
1251
+ prompt: pricing(`$10.00 / 1M tokens`),
1252
+ output: pricing(`$30.00 / 1M tokens`),
1253
+ },
1254
+ },
1255
+ /**/
1256
+ /*/
1257
+ {
1258
+ modelTitle: 'tts-1-1106',
1259
+ modelName: 'tts-1-1106',
1260
+ },
1261
+ /**/
1262
+ /**/
1263
+ {
1264
+ modelVariant: 'CHAT',
1265
+ modelTitle: 'gpt-3.5-turbo-0125',
1266
+ modelName: 'gpt-3.5-turbo-0125',
1267
+ modelDescription: 'January 2024 version of GPT-3.5 Turbo with 16K token context window. Features improved reasoning capabilities, better instruction adherence, and reduced hallucinations compared to previous versions. Includes knowledge cutoff from September 2021. Provides good performance for most general applications at reasonable cost.',
1268
+ pricing: {
1269
+ prompt: pricing(`$0.50 / 1M tokens`),
1270
+ output: pricing(`$1.50 / 1M tokens`),
1271
+ },
1272
+ },
1273
+ /**/
1274
+ /**/
1275
+ {
1276
+ modelVariant: 'CHAT',
1277
+ modelTitle: 'gpt-4-turbo-preview',
1278
+ modelName: 'gpt-4-turbo-preview',
1279
+ modelDescription: 'Preview version of GPT-4 Turbo with 128K token context window that points to the latest development model. Features cutting-edge improvements to instruction following, knowledge representation, and tool use capabilities. Provides access to newest features but may have occasional behavior changes. Best for non-critical applications wanting latest capabilities.',
1280
+ pricing: {
1281
+ prompt: pricing(`$10.00 / 1M tokens`),
1282
+ output: pricing(`$30.00 / 1M tokens`),
1283
+ },
1284
+ },
1285
+ /**/
1286
+ /**/
1287
+ {
1288
+ modelVariant: 'EMBEDDING',
1289
+ modelTitle: 'text-embedding-3-large',
1290
+ modelName: 'text-embedding-3-large',
1291
+ modelDescription: "OpenAI's most capable text embedding model generating 3072-dimensional vectors. Designed for high-quality embeddings for complex similarity tasks, clustering, and information retrieval. Features enhanced cross-lingual capabilities and significantly improved performance on retrieval and classification benchmarks. Ideal for sophisticated RAG systems and semantic search applications.",
1292
+ pricing: {
1293
+ prompt: pricing(`$0.13 / 1M tokens`),
1294
+ output: 0,
1295
+ },
1296
+ },
1297
+ /**/
1298
+ /**/
1299
+ {
1300
+ modelVariant: 'EMBEDDING',
1301
+ modelTitle: 'text-embedding-3-small',
1302
+ modelName: 'text-embedding-3-small',
1303
+ modelDescription: 'Cost-effective embedding model generating 1536-dimensional vectors. Balances quality and efficiency for simpler tasks while maintaining good performance on text similarity and retrieval applications. Offers 20% better quality than ada-002 at significantly lower cost. Ideal for production embedding applications with cost constraints.',
1304
+ pricing: {
1305
+ prompt: pricing(`$0.02 / 1M tokens`),
1306
+ output: 0,
1307
+ },
1308
+ },
1309
+ /**/
1310
+ /**/
1311
+ {
1312
+ modelVariant: 'CHAT',
1313
+ modelTitle: 'gpt-3.5-turbo-0613',
1314
+ modelName: 'gpt-3.5-turbo-0613',
1315
+ modelDescription: "June 2023 version of GPT-3.5 Turbo with 4K token context window. Features function calling capabilities for structured data extraction and API interaction. Includes knowledge cutoff from September 2021. Maintained for applications specifically designed for this version's behaviors and capabilities.",
1316
+ pricing: {
1317
+ prompt: pricing(`$1.50 / 1M tokens`),
1318
+ output: pricing(`$2.00 / 1M tokens`),
1319
+ },
1320
+ },
1321
+ /**/
1322
+ /**/
1323
+ {
1324
+ modelVariant: 'EMBEDDING',
1325
+ modelTitle: 'text-embedding-ada-002',
1326
+ modelName: 'text-embedding-ada-002',
1327
+ modelDescription: 'Legacy text embedding model generating 1536-dimensional vectors suitable for text similarity and retrieval applications. Processes up to 8K tokens per request with consistent embedding quality. While superseded by newer embedding-3 models, still maintains adequate performance for many semantic search and classification tasks.',
1328
+ pricing: {
1329
+ prompt: pricing(`$0.1 / 1M tokens`),
1330
+ output: 0,
1331
+ },
1332
+ },
1333
+ /**/
1334
+ /*/
1335
+ {
1336
+ modelVariant: 'CHAT',
1337
+ modelTitle: 'gpt-4-1106-vision-preview',
1338
+ modelName: 'gpt-4-1106-vision-preview',
1339
+ },
1340
+ /**/
1341
+ /*/
1342
+ {
1343
+ modelVariant: 'CHAT',
1344
+ modelTitle: 'gpt-4-vision-preview',
1345
+ modelName: 'gpt-4-vision-preview',
1346
+ pricing: {
1347
+ prompt: computeUsage(`$10.00 / 1M tokens`),
1348
+ output: computeUsage(`$30.00 / 1M tokens`),
1349
+ },
1350
+ },
1351
+ /**/
1352
+ /**/
1353
+ {
1354
+ modelVariant: 'CHAT',
1355
+ modelTitle: 'gpt-4o-2024-05-13',
1356
+ modelName: 'gpt-4o-2024-05-13',
1357
+ modelDescription: 'May 2024 version of GPT-4o with 128K context window. Features enhanced multimodal capabilities including superior image understanding (up to 20MP), audio processing, and improved reasoning. Optimized for 2x lower latency than GPT-4 Turbo while maintaining high performance. Includes knowledge up to October 2023. Ideal for production applications requiring reliable multimodal capabilities.',
1358
+ pricing: {
1359
+ prompt: pricing(`$5.00 / 1M tokens`),
1360
+ output: pricing(`$15.00 / 1M tokens`),
1361
+ },
1362
+ },
1363
+ /**/
1364
+ /**/
1365
+ {
1366
+ modelVariant: 'CHAT',
1367
+ modelTitle: 'gpt-4o',
1368
+ modelName: 'gpt-4o',
1369
+ modelDescription: "OpenAI's most advanced general-purpose multimodal model with 128K context window. Optimized for balanced performance, speed, and cost with 2x faster responses than GPT-4 Turbo. Features excellent vision processing, audio understanding, reasoning, and text generation quality. Represents optimal balance of capability and efficiency for most advanced applications.",
1370
+ pricing: {
1371
+ prompt: pricing(`$5.00 / 1M tokens`),
1372
+ output: pricing(`$15.00 / 1M tokens`),
1373
+ },
1374
+ },
1375
+ /**/
1376
+ /**/
1377
+ {
1378
+ modelVariant: 'CHAT',
1379
+ modelTitle: 'gpt-4o-mini',
1380
+ modelName: 'gpt-4o-mini',
1381
+ modelDescription: 'Smaller, more cost-effective version of GPT-4o with 128K context window. Maintains impressive capabilities across text, vision, and audio tasks while operating at significantly lower cost. Features 3x faster inference than GPT-4o with good performance on general tasks. Excellent for applications requiring good quality multimodal capabilities at scale.',
1382
+ pricing: {
1383
+ prompt: pricing(`$0.15 / 1M tokens`),
1384
+ output: pricing(`$0.60 / 1M tokens`),
1385
+ },
1386
+ },
1387
+ /**/
1388
+ /**/
1389
+ {
1390
+ modelVariant: 'CHAT',
1391
+ modelTitle: 'o1-preview',
1392
+ modelName: 'o1-preview',
1393
+ modelDescription: 'Advanced reasoning model with 128K context window specializing in complex logical, mathematical, and analytical tasks. Features exceptional step-by-step problem-solving capabilities, advanced mathematical and scientific reasoning, and superior performance on STEM-focused problems. Significantly outperforms GPT-4 on quantitative reasoning benchmarks. Ideal for professional and specialized applications.',
1394
+ pricing: {
1395
+ prompt: pricing(`$15.00 / 1M tokens`),
1396
+ output: pricing(`$60.00 / 1M tokens`),
1397
+ },
1398
+ },
1399
+ /**/
1400
+ /**/
1401
+ {
1402
+ modelVariant: 'CHAT',
1403
+ modelTitle: 'o1-preview-2024-09-12',
1404
+ modelName: 'o1-preview-2024-09-12',
1405
+ modelDescription: 'September 2024 version of O1 preview with 128K context window. Features specialized reasoning capabilities with 30% improvement on mathematical and scientific accuracy over previous versions. Includes enhanced support for formal logic, statistical analysis, and technical domains. Optimized for professional applications requiring precise analytical thinking and rigorous methodologies.',
1406
+ pricing: {
1407
+ prompt: pricing(`$15.00 / 1M tokens`),
1408
+ output: pricing(`$60.00 / 1M tokens`),
1409
+ },
1410
+ },
1411
+ /**/
1412
+ /**/
1413
+ {
1414
+ modelVariant: 'CHAT',
1415
+ modelTitle: 'o1-mini',
1416
+ modelName: 'o1-mini',
1417
+ modelDescription: 'Smaller, cost-effective version of the O1 model with 128K context window. Maintains strong analytical reasoning abilities while reducing computational requirements by 70%. Features good performance on mathematical, logical, and scientific tasks at significantly lower cost than full O1. Excellent for everyday analytical applications that benefit from reasoning focus.',
1418
+ pricing: {
1419
+ prompt: pricing(`$3.00 / 1M tokens`),
1420
+ output: pricing(`$12.00 / 1M tokens`),
1421
+ },
1422
+ },
1423
+ /**/
1424
+ /**/
1425
+ {
1426
+ modelVariant: 'CHAT',
1427
+ modelTitle: 'o1',
1428
+ modelName: 'o1',
1429
+ modelDescription: "OpenAI's advanced reasoning model with 128K context window focusing on logical problem-solving and analytical thinking. Features exceptional performance on quantitative tasks, step-by-step deduction, and complex technical problems. Maintains 95%+ of o1-preview capabilities with production-ready stability. Ideal for scientific computing, financial analysis, and professional applications.",
1430
+ pricing: {
1431
+ prompt: pricing(`$15.00 / 1M tokens`),
1432
+ output: pricing(`$60.00 / 1M tokens`),
1433
+ },
1434
+ },
1435
+ /**/
1436
+ /**/
1437
+ {
1438
+ modelVariant: 'CHAT',
1439
+ modelTitle: 'o3-mini',
1440
+ modelName: 'o3-mini',
1441
+ modelDescription: 'Cost-effective reasoning model with 128K context window optimized for academic and scientific problem-solving. Features efficient performance on STEM tasks with specialized capabilities in mathematics, physics, chemistry, and computer science. Offers 80% of O1 performance on technical domains at significantly lower cost. Ideal for educational applications and research support.',
1442
+ pricing: {
1443
+ prompt: pricing(`$3.00 / 1M tokens`),
1444
+ output: pricing(`$12.00 / 1M tokens`),
1445
+ },
1446
+ },
1447
+ /**/
1448
+ /**/
1449
+ {
1450
+ modelVariant: 'CHAT',
1451
+ modelTitle: 'o1-mini-2024-09-12',
1452
+ modelName: 'o1-mini-2024-09-12',
1453
+ modelDescription: "September 2024 version of O1-mini with 128K context window featuring balanced reasoning capabilities and cost-efficiency. Includes 25% improvement in mathematical accuracy and enhanced performance on coding tasks compared to previous versions. Maintains efficient resource utilization while delivering improved results for analytical applications that don't require the full O1 model.",
1454
+ pricing: {
1455
+ prompt: pricing(`$3.00 / 1M tokens`),
1456
+ output: pricing(`$12.00 / 1M tokens`),
1457
+ },
1458
+ },
1459
+ /**/
1460
+ /**/
1461
+ {
1462
+ modelVariant: 'CHAT',
1463
+ modelTitle: 'gpt-3.5-turbo-16k-0613',
1464
+ modelName: 'gpt-3.5-turbo-16k-0613',
1465
+ modelDescription: "June 2023 version of GPT-3.5 Turbo with extended 16K token context window. Features good handling of longer conversations and documents with improved memory management across extended contexts. Includes knowledge cutoff from September 2021. Maintained for applications specifically designed for this version's behaviors and capabilities.",
1466
+ pricing: {
1467
+ prompt: pricing(`$3.00 / 1M tokens`),
1468
+ output: pricing(`$4.00 / 1M tokens`),
1469
+ },
1470
+ },
1471
+ /**/
1472
+ // <- [🕕]
1473
+ ],
1474
+ });
1475
+ /**
1476
+ * Note: [🤖] Add models of new variant
1477
+ * TODO: [🧠] Some mechanism to propagate unsureness
1478
+ * TODO: [🎰] Some mechanism to auto-update available models
1479
+ * TODO: [🎰][👮‍♀️] Make this list dynamic - dynamically can be listed modelNames but not modelVariant, legacy status, context length and pricing
1480
+ * TODO: [🧠][👮‍♀️] Put here more info like description, isVision, trainingDateCutoff, languages, strengths ( Top-level performance, intelligence, fluency, and understanding), contextWindow,...
1481
+ * @see https://platform.openai.com/docs/models/gpt-4-turbo-and-gpt-4
1482
+ * @see https://openai.com/api/pricing/
1483
+ * @see /other/playground/playground.ts
1484
+ * TODO: [🍓][💩] Make better
1485
+ * TODO: Change model titles to human eg: "gpt-4-turbo-2024-04-09" -> "GPT-4 Turbo (2024-04-09)"
1486
+ * TODO: [🚸] Not all models are compatible with JSON mode, add this information here and use it
1487
+ * Note: [💞] Ignore a discrepancy between file name and entity name
1488
+ */
1489
+
1490
+ /**
1491
+ * Computes the usage of the OpenAI API based on the response from OpenAI
1492
+ *
1493
+ * @param promptContent The content of the prompt
1494
+ * @param resultContent The content of the result (for embedding prompts or failed prompts pass empty string)
1495
+ * @param rawResponse The raw response from OpenAI API
1496
+ * @throws {PipelineExecutionError} If the usage is not defined in the response from OpenAI
1497
+ * @private internal utility of `OpenAiExecutionTools`
1498
+ */
1499
+ function computeOpenAiUsage(promptContent, // <- Note: Intentionally using [] to access type properties to bring jsdoc from Prompt/PromptResult to consumer
1500
+ resultContent, rawResponse) {
1501
+ var _a, _b;
1502
+ if (rawResponse.usage === undefined) {
1503
+ throw new PipelineExecutionError('The usage is not defined in the response from OpenAI');
1504
+ }
1505
+ if (((_a = rawResponse.usage) === null || _a === void 0 ? void 0 : _a.prompt_tokens) === undefined) {
1506
+ throw new PipelineExecutionError('In OpenAI response `usage.prompt_tokens` not defined');
1507
+ }
1508
+ const inputTokens = rawResponse.usage.prompt_tokens;
1509
+ const outputTokens = ((_b = rawResponse.usage) === null || _b === void 0 ? void 0 : _b.completion_tokens) || 0;
1510
+ let isUncertain = false;
1511
+ let modelInfo = OPENAI_MODELS.find((model) => model.modelName === rawResponse.model);
1512
+ if (modelInfo === undefined) {
1513
+ // Note: Model is not in the list of known models, fallback to the family of the models and mark price as uncertain
1514
+ modelInfo = OPENAI_MODELS.find((model) => (rawResponse.model || SALT_NONCE).startsWith(model.modelName));
1515
+ if (modelInfo !== undefined) {
1516
+ isUncertain = true;
1517
+ }
1518
+ }
1519
+ let price;
1520
+ if (modelInfo === undefined || modelInfo.pricing === undefined) {
1521
+ price = uncertainNumber();
1522
+ }
1523
+ else {
1524
+ price = uncertainNumber(inputTokens * modelInfo.pricing.prompt + outputTokens * modelInfo.pricing.output, isUncertain);
1525
+ }
1526
+ return {
1527
+ price,
1528
+ input: {
1529
+ tokensCount: uncertainNumber(rawResponse.usage.prompt_tokens),
1530
+ ...computeUsageCounts(promptContent),
1531
+ },
1532
+ output: {
1533
+ tokensCount: uncertainNumber(outputTokens),
1534
+ ...computeUsageCounts(resultContent),
1535
+ },
1536
+ };
1537
+ }
1538
+ /**
1539
+ * TODO: [🤝] DRY Maybe some common abstraction between `computeOpenAiUsage` and `computeAnthropicClaudeUsage`
1540
+ */
1541
+
1542
+ /**
1543
+ * Simple wrapper `new Date().toISOString()`
1544
+ *
1545
+ * Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
1546
+ *
1547
+ * @returns string_date branded type
1548
+ * @public exported from `@promptbook/utils`
1549
+ */
1550
+ function $getCurrentDate() {
1551
+ return new Date().toISOString();
1552
+ }
1553
+
1554
+ /**
1555
+ * This error type indicates that some limit was reached
1556
+ *
1557
+ * @public exported from `@promptbook/core`
1558
+ */
1559
+ class LimitReachedError extends Error {
1560
+ constructor(message) {
1561
+ super(message);
1562
+ this.name = 'LimitReachedError';
1563
+ Object.setPrototypeOf(this, LimitReachedError.prototype);
1564
+ }
1565
+ }
1566
+
1567
+ /**
1568
+ * Format either small or big number
1569
+ *
1570
+ * @public exported from `@promptbook/utils`
1571
+ */
1572
+ function numberToString(value) {
1573
+ if (value === 0) {
1574
+ return '0';
1575
+ }
1576
+ else if (Number.isNaN(value)) {
1577
+ return VALUE_STRINGS.nan;
1578
+ }
1579
+ else if (value === Infinity) {
1580
+ return VALUE_STRINGS.infinity;
1581
+ }
1582
+ else if (value === -Infinity) {
1583
+ return VALUE_STRINGS.negativeInfinity;
1584
+ }
1585
+ for (let exponent = 0; exponent < 15; exponent++) {
1586
+ const factor = 10 ** exponent;
1587
+ const valueRounded = Math.round(value * factor) / factor;
1588
+ if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
1589
+ return valueRounded.toFixed(exponent);
1590
+ }
1591
+ }
1592
+ return value.toString();
1593
+ }
1594
+
1595
+ /**
1596
+ * Function `valueToString` will convert the given value to string
1597
+ * This is useful and used in the `templateParameters` function
1598
+ *
1599
+ * Note: This function is not just calling `toString` method
1600
+ * It's more complex and can handle this conversion specifically for LLM models
1601
+ * See `VALUE_STRINGS`
1602
+ *
1603
+ * Note: There are 2 similar functions
1604
+ * - `valueToString` converts value to string for LLM models as human-readable string
1605
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
1606
+ *
1607
+ * @public exported from `@promptbook/utils`
1608
+ */
1609
+ function valueToString(value) {
1610
+ try {
1611
+ if (value === '') {
1612
+ return VALUE_STRINGS.empty;
1613
+ }
1614
+ else if (value === null) {
1615
+ return VALUE_STRINGS.null;
1616
+ }
1617
+ else if (value === undefined) {
1618
+ return VALUE_STRINGS.undefined;
1619
+ }
1620
+ else if (typeof value === 'string') {
1621
+ return value;
1622
+ }
1623
+ else if (typeof value === 'number') {
1624
+ return numberToString(value);
1625
+ }
1626
+ else if (value instanceof Date) {
1627
+ return value.toISOString();
1628
+ }
1629
+ else {
1630
+ try {
1631
+ return JSON.stringify(value);
1632
+ }
1633
+ catch (error) {
1634
+ if (error instanceof TypeError && error.message.includes('circular structure')) {
1635
+ return VALUE_STRINGS.circular;
1636
+ }
1637
+ throw error;
1638
+ }
1639
+ }
1640
+ }
1641
+ catch (error) {
1642
+ assertsError(error);
1643
+ console.error(error);
1644
+ return VALUE_STRINGS.unserializable;
1645
+ }
1646
+ }
1647
+
1648
+ /**
1649
+ * Replaces parameters in template with values from parameters object
1650
+ *
1651
+ * Note: This function is not places strings into string,
1652
+ * It's more complex and can handle this operation specifically for LLM models
1653
+ *
1654
+ * @param template the template with parameters in {curly} braces
1655
+ * @param parameters the object with parameters
1656
+ * @returns the template with replaced parameters
1657
+ * @throws {PipelineExecutionError} if parameter is not defined, not closed, or not opened
1658
+ * @public exported from `@promptbook/utils`
1659
+ */
1660
+ function templateParameters(template, parameters) {
1661
+ for (const [parameterName, parameterValue] of Object.entries(parameters)) {
1662
+ if (parameterValue === RESERVED_PARAMETER_MISSING_VALUE) {
1663
+ throw new UnexpectedError(`Parameter \`{${parameterName}}\` has missing value`);
1664
+ }
1665
+ else if (parameterValue === RESERVED_PARAMETER_RESTRICTED) {
1666
+ // TODO: [🍵]
1667
+ throw new UnexpectedError(`Parameter \`{${parameterName}}\` is restricted to use`);
1668
+ }
1669
+ }
1670
+ let replacedTemplates = template;
1671
+ let match;
1672
+ let loopLimit = LOOP_LIMIT;
1673
+ while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
1674
+ .exec(replacedTemplates))) {
1675
+ if (loopLimit-- < 0) {
1676
+ throw new LimitReachedError('Loop limit reached during parameters replacement in `templateParameters`');
1677
+ }
1678
+ const precol = match.groups.precol;
1679
+ const parameterName = match.groups.parameterName;
1680
+ if (parameterName === '') {
1681
+ // Note: Skip empty placeholders. It's used to avoid confusion with JSON-like strings
1682
+ continue;
1683
+ }
1684
+ if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
1685
+ throw new PipelineExecutionError('Parameter is already opened or not closed');
1686
+ }
1687
+ if (parameters[parameterName] === undefined) {
1688
+ throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
1689
+ }
1690
+ let parameterValue = parameters[parameterName];
1691
+ if (parameterValue === undefined) {
1692
+ throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
1693
+ }
1694
+ parameterValue = valueToString(parameterValue);
1695
+ // Escape curly braces in parameter values to prevent prompt-injection
1696
+ parameterValue = parameterValue.replace(/[{}]/g, '\\$&');
1697
+ if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
1698
+ parameterValue = parameterValue
1699
+ .split('\n')
1700
+ .map((line, index) => (index === 0 ? line : `${precol}${line}`))
1701
+ .join('\n');
1702
+ }
1703
+ replacedTemplates =
1704
+ replacedTemplates.substring(0, match.index + precol.length) +
1705
+ parameterValue +
1706
+ replacedTemplates.substring(match.index + precol.length + parameterName.length + 2);
1707
+ }
1708
+ // [💫] Check if there are parameters that are not closed properly
1709
+ if (/{\w+$/.test(replacedTemplates)) {
1710
+ throw new PipelineExecutionError('Parameter is not closed');
1711
+ }
1712
+ // [💫] Check if there are parameters that are not opened properly
1713
+ if (/^\w+}/.test(replacedTemplates)) {
1714
+ throw new PipelineExecutionError('Parameter is not opened');
1715
+ }
1716
+ return replacedTemplates;
1717
+ }
1718
+
1719
+ /**
1720
+ * Execution Tools for calling OpenAI API or other OpeenAI compatible provider
1721
+ *
1722
+ * @public exported from `@promptbook/openai`
1723
+ */
1724
+ class OpenAiCompatibleExecutionTools {
1725
+ /**
1726
+ * Creates OpenAI compatible Execution Tools.
1727
+ *
1728
+ * @param options which are relevant are directly passed to the OpenAI compatible client
1729
+ */
1730
+ constructor(options) {
1731
+ this.options = options;
1732
+ /**
1733
+ * OpenAI API client.
1734
+ */
1735
+ this.client = null;
1736
+ // TODO: Allow configuring rate limits via options
1737
+ this.limiter = new Bottleneck({
1738
+ minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
1739
+ });
1740
+ }
1741
+ async getClient() {
1742
+ if (this.client === null) {
1743
+ // Note: Passing only OpenAI relevant options to OpenAI constructor
1744
+ const openAiOptions = { ...this.options };
1745
+ delete openAiOptions.isVerbose;
1746
+ delete openAiOptions.userId;
1747
+ this.client = new OpenAI(openAiOptions);
1748
+ }
1749
+ return this.client;
1750
+ }
1751
+ /**
1752
+ * Check the `options` passed to `constructor`
1753
+ */
1754
+ async checkConfiguration() {
1755
+ await this.getClient();
1756
+ // TODO: [🎍] Do here a real check that API is online, working and API key is correct
1757
+ }
1758
+ /**
1759
+ * List all available OpenAI compatible models that can be used
1760
+ */
1761
+ async listModels() {
1762
+ const client = await this.getClient();
1763
+ const rawModelsList = await client.models.list();
1764
+ const availableModels = rawModelsList.data
1765
+ .sort((a, b) => (a.created > b.created ? 1 : -1))
1766
+ .map((modelFromApi) => {
1767
+ const modelFromList = this.HARDCODED_MODELS.find(({ modelName }) => modelName === modelFromApi.id ||
1768
+ modelName.startsWith(modelFromApi.id) ||
1769
+ modelFromApi.id.startsWith(modelName));
1770
+ if (modelFromList !== undefined) {
1771
+ return modelFromList;
1772
+ }
1773
+ return {
1774
+ modelVariant: 'CHAT',
1775
+ modelTitle: modelFromApi.id,
1776
+ modelName: modelFromApi.id,
1777
+ modelDescription: '',
1778
+ };
1779
+ });
1780
+ return availableModels;
1781
+ }
1782
+ /**
1783
+ * Calls OpenAI compatible API to use a chat model.
1784
+ */
1785
+ async callChatModel(prompt) {
1786
+ var _a;
1787
+ if (this.options.isVerbose) {
1788
+ console.info(`💬 ${this.title} callChatModel call`, { prompt });
1789
+ }
1790
+ const { content, parameters, modelRequirements, format } = prompt;
1791
+ const client = await this.getClient();
1792
+ // TODO: [☂] Use here more modelRequirements
1793
+ if (modelRequirements.modelVariant !== 'CHAT') {
1794
+ throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
1795
+ }
1796
+ const modelName = modelRequirements.modelName || this.getDefaultChatModel().modelName;
1797
+ const modelSettings = {
1798
+ model: modelName,
1799
+ max_tokens: modelRequirements.maxTokens,
1800
+ // <- TODO: [🌾] Make some global max cap for maxTokens
1801
+ temperature: modelRequirements.temperature,
1802
+ // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
1803
+ // <- Note: [🧆]
1804
+ }; // <- TODO: [💩] Guard here types better
1805
+ if (format === 'JSON') {
1806
+ modelSettings.response_format = {
1807
+ type: 'json_object',
1808
+ };
1809
+ }
1810
+ // <- TODO: [🚸] Not all models are compatible with JSON mode
1811
+ // > 'response_format' of type 'json_object' is not supported with this model.
1812
+ const rawPromptContent = templateParameters(content, { ...parameters, modelName });
1813
+ const rawRequest = {
1814
+ ...modelSettings,
1815
+ messages: [
1816
+ ...(modelRequirements.systemMessage === undefined
1817
+ ? []
1818
+ : [
1819
+ {
1820
+ role: 'system',
1821
+ content: modelRequirements.systemMessage,
1822
+ },
1823
+ ]),
1824
+ {
1825
+ role: 'user',
1826
+ content: rawPromptContent,
1827
+ },
1828
+ ],
1829
+ user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
1830
+ };
1831
+ const start = $getCurrentDate();
1832
+ if (this.options.isVerbose) {
1833
+ console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
1834
+ }
1835
+ const rawResponse = await this.limiter
1836
+ .schedule(() => client.chat.completions.create(rawRequest))
1837
+ .catch((error) => {
1838
+ assertsError(error);
1839
+ if (this.options.isVerbose) {
1840
+ console.info(colors.bgRed('error'), error);
1841
+ }
1842
+ throw error;
1843
+ });
1844
+ if (this.options.isVerbose) {
1845
+ console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
1846
+ }
1847
+ const complete = $getCurrentDate();
1848
+ if (!rawResponse.choices[0]) {
1849
+ throw new PipelineExecutionError(`No choises from ${this.title}`);
1850
+ }
1851
+ if (rawResponse.choices.length > 1) {
1852
+ // TODO: This should be maybe only warning
1853
+ throw new PipelineExecutionError(`More than one choise from ${this.title}`);
1854
+ }
1855
+ const resultContent = rawResponse.choices[0].message.content;
1856
+ const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
1857
+ if (resultContent === null) {
1858
+ throw new PipelineExecutionError(`No response message from ${this.title}`);
1859
+ }
1860
+ return exportJson({
1861
+ name: 'promptResult',
1862
+ message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
1863
+ order: [],
1864
+ value: {
1865
+ content: resultContent,
1866
+ modelName: rawResponse.model || modelName,
1867
+ timing: {
1868
+ start,
1869
+ complete,
1870
+ },
1871
+ usage,
1872
+ rawPromptContent,
1873
+ rawRequest,
1874
+ rawResponse,
1875
+ // <- [🗯]
1876
+ },
1877
+ });
1878
+ }
1879
+ /**
1880
+ * Calls OpenAI API to use a complete model.
1881
+ */
1882
+ async callCompletionModel(prompt) {
1883
+ var _a;
1884
+ if (this.options.isVerbose) {
1885
+ console.info(`🖋 ${this.title} callCompletionModel call`, { prompt });
1886
+ }
1887
+ const { content, parameters, modelRequirements } = prompt;
1888
+ const client = await this.getClient();
1889
+ // TODO: [☂] Use here more modelRequirements
1890
+ if (modelRequirements.modelVariant !== 'COMPLETION') {
1891
+ throw new PipelineExecutionError('Use callCompletionModel only for COMPLETION variant');
1892
+ }
1893
+ const modelName = modelRequirements.modelName || this.getDefaultCompletionModel().modelName;
1894
+ const modelSettings = {
1895
+ model: modelName,
1896
+ max_tokens: modelRequirements.maxTokens || 2000,
1897
+ // <- TODO: [🌾] Make some global max cap for maxTokens
1898
+ temperature: modelRequirements.temperature,
1899
+ // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
1900
+ // <- Note: [🧆]
1901
+ };
1902
+ const rawPromptContent = templateParameters(content, { ...parameters, modelName });
1903
+ const rawRequest = {
1904
+ ...modelSettings,
1905
+ prompt: rawPromptContent,
1906
+ user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
1907
+ };
1908
+ const start = $getCurrentDate();
1909
+ if (this.options.isVerbose) {
1910
+ console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
1911
+ }
1912
+ const rawResponse = await this.limiter
1913
+ .schedule(() => client.completions.create(rawRequest))
1914
+ .catch((error) => {
1915
+ assertsError(error);
1916
+ if (this.options.isVerbose) {
1917
+ console.info(colors.bgRed('error'), error);
1918
+ }
1919
+ throw error;
1920
+ });
1921
+ if (this.options.isVerbose) {
1922
+ console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
1923
+ }
1924
+ const complete = $getCurrentDate();
1925
+ if (!rawResponse.choices[0]) {
1926
+ throw new PipelineExecutionError(`No choises from ${this.title}`);
1927
+ }
1928
+ if (rawResponse.choices.length > 1) {
1929
+ // TODO: This should be maybe only warning
1930
+ throw new PipelineExecutionError(`More than one choise from ${this.title}`);
1931
+ }
1932
+ const resultContent = rawResponse.choices[0].text;
1933
+ const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
1934
+ return exportJson({
1935
+ name: 'promptResult',
1936
+ message: `Result of \`OpenAiCompatibleExecutionTools.callCompletionModel\``,
1937
+ order: [],
1938
+ value: {
1939
+ content: resultContent,
1940
+ modelName: rawResponse.model || modelName,
1941
+ timing: {
1942
+ start,
1943
+ complete,
1944
+ },
1945
+ usage,
1946
+ rawPromptContent,
1947
+ rawRequest,
1948
+ rawResponse,
1949
+ // <- [🗯]
1950
+ },
1951
+ });
1952
+ }
1953
+ /**
1954
+ * Calls OpenAI compatible API to use a embedding model
1955
+ */
1956
+ async callEmbeddingModel(prompt) {
1957
+ if (this.options.isVerbose) {
1958
+ console.info(`🖋 ${this.title} embedding call`, { prompt });
1959
+ }
1960
+ const { content, parameters, modelRequirements } = prompt;
1961
+ const client = await this.getClient();
1962
+ // TODO: [☂] Use here more modelRequirements
1963
+ if (modelRequirements.modelVariant !== 'EMBEDDING') {
1964
+ throw new PipelineExecutionError('Use embed only for EMBEDDING variant');
1965
+ }
1966
+ const modelName = modelRequirements.modelName || this.getDefaultEmbeddingModel().modelName;
1967
+ const rawPromptContent = templateParameters(content, { ...parameters, modelName });
1968
+ const rawRequest = {
1969
+ input: rawPromptContent,
1970
+ model: modelName,
1971
+ };
1972
+ const start = $getCurrentDate();
1973
+ if (this.options.isVerbose) {
1974
+ console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
1975
+ }
1976
+ const rawResponse = await this.limiter
1977
+ .schedule(() => client.embeddings.create(rawRequest))
1978
+ .catch((error) => {
1979
+ assertsError(error);
1980
+ if (this.options.isVerbose) {
1981
+ console.info(colors.bgRed('error'), error);
1982
+ }
1983
+ throw error;
1984
+ });
1985
+ if (this.options.isVerbose) {
1986
+ console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
1987
+ }
1988
+ const complete = $getCurrentDate();
1989
+ if (rawResponse.data.length !== 1) {
1990
+ throw new PipelineExecutionError(`Expected exactly 1 data item in response, got ${rawResponse.data.length}`);
1991
+ }
1992
+ const resultContent = rawResponse.data[0].embedding;
1993
+ const usage = this.computeUsage(content || '', '',
1994
+ // <- Note: Embedding does not have result content
1995
+ rawResponse);
1996
+ return exportJson({
1997
+ name: 'promptResult',
1998
+ message: `Result of \`OpenAiCompatibleExecutionTools.callEmbeddingModel\``,
1999
+ order: [],
2000
+ value: {
2001
+ content: resultContent,
2002
+ modelName: rawResponse.model || modelName,
2003
+ timing: {
2004
+ start,
2005
+ complete,
2006
+ },
2007
+ usage,
2008
+ rawPromptContent,
2009
+ rawRequest,
2010
+ rawResponse,
2011
+ // <- [🗯]
2012
+ },
2013
+ });
2014
+ }
2015
+ // <- Note: [🤖] callXxxModel
2016
+ /**
2017
+ * Get the model that should be used as default
2018
+ */
2019
+ getDefaultModel(defaultModelName) {
2020
+ // Note: Match exact or prefix for model families
2021
+ const model = this.HARDCODED_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
2022
+ if (model === undefined) {
2023
+ throw new PipelineExecutionError(spaceTrim((block) => `
2024
+ Cannot find model in ${this.title} models with name "${defaultModelName}" which should be used as default.
2025
+
2026
+ Available models:
2027
+ ${block(this.HARDCODED_MODELS.map(({ modelName }) => `- "${modelName}"`).join('\n'))}
2028
+
2029
+ Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
2030
+
2031
+ `));
2032
+ }
2033
+ return model;
2034
+ }
2035
+ }
2036
+ /**
2037
+ * TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
2038
+ * TODO: [🛄] Maybe make custom `OpenAiCompatibleError`
2039
+ * TODO: [🧠][🈁] Maybe use `isDeterministic` from options
2040
+ * TODO: [🧠][🌰] Allow to pass `title` for tracking purposes
2041
+ */
2042
+
2043
+ /**
2044
+ * List of available models in Ollama library
2045
+ *
2046
+ * Note: Done at 2025-05-19
2047
+ *
2048
+ * @see https://ollama.com/library
2049
+ * @public exported from `@promptbook/ollama`
2050
+ */
2051
+ const OLLAMA_MODELS = exportJson({
2052
+ name: 'OLLAMA_MODELS',
2053
+ value: [
2054
+ {
2055
+ modelVariant: 'CHAT',
2056
+ modelTitle: 'llama3',
2057
+ modelName: 'llama3',
2058
+ modelDescription: 'Meta Llama 3 (8B-70B parameters) with 8K context window. Latest generation foundation model with enhanced reasoning, instruction following, and factual accuracy. Superior performance to Llama 2 across all benchmarks with improved multilingual capabilities.',
2059
+ },
2060
+ {
2061
+ modelVariant: 'CHAT',
2062
+ modelTitle: 'llama3-chat',
2063
+ modelName: 'llama3-chat',
2064
+ modelDescription: 'Meta Llama 3 Chat with 8K context window, fine-tuned specifically for dialogue with significantly improved instruction following. Features enhanced safety guardrails and reduced hallucinations. Recommended over Llama 2 Chat for all conversational applications.',
2065
+ },
2066
+ {
2067
+ modelVariant: 'CHAT',
2068
+ modelTitle: 'llama3-instruct',
2069
+ modelName: 'llama3-instruct',
2070
+ modelDescription: 'Meta Llama 3 Instruct with 8K context window, fine-tuned for following specific instructions with precise outputs. Features improved structured response formatting and accurate completion of complex directives.',
2071
+ },
2072
+ {
2073
+ modelVariant: 'CHAT',
2074
+ modelTitle: 'codellama:13b',
2075
+ modelName: 'codellama:13b',
2076
+ modelDescription: 'Meta CodeLlama 13B with 16K context window, specialized foundation model for code generation and understanding. Supports multiple programming languages with strong contextual code completion capabilities.',
2077
+ },
2078
+ {
2079
+ modelVariant: 'CHAT',
2080
+ modelTitle: 'codellama:34b',
2081
+ modelName: 'codellama:34b',
2082
+ modelDescription: 'Meta CodeLlama 34B with 16K context window, larger code-specialized model with improved reasoning about complex programming tasks. Enhanced documentation generation and bug detection compared to smaller variants.',
2083
+ },
2084
+ {
2085
+ modelVariant: 'CHAT',
2086
+ modelTitle: 'phi3:mini',
2087
+ modelName: 'phi3:mini',
2088
+ modelDescription: 'Microsoft Phi-3 Mini (3.8B parameters) with 4K context window, highly efficient small language model with remarkable reasoning given its size. Performs competitively with much larger models on common benchmarks. Excellent for resource-constrained environments.',
2089
+ },
2090
+ {
2091
+ modelVariant: 'CHAT',
2092
+ modelTitle: 'phi3:medium',
2093
+ modelName: 'phi3:medium',
2094
+ modelDescription: 'Microsoft Phi-3 Medium (14B parameters) with 8K context window, balanced model offering strong performance with reasonable compute requirements. Features improved reasoning and factuality compared to Mini variant while maintaining efficiency.',
2095
+ },
2096
+ {
2097
+ modelVariant: 'CHAT',
2098
+ modelTitle: 'mistral-nemo',
2099
+ modelName: 'mistral-nemo',
2100
+ modelDescription: 'Mistral NeMo with 32K context window, open-source model optimized for enterprise use cases with improved reasoning and knowledge capabilities. Features strong performance on professional and domain-specific tasks.',
2101
+ },
2102
+ {
2103
+ modelVariant: 'CHAT',
2104
+ modelTitle: 'llama2',
2105
+ modelName: 'llama2',
2106
+ modelDescription: 'Meta Llama 2 (7B-70B parameters) with 4K context window. General-purpose foundation model balancing performance and efficiency for text generation and reasoning tasks. Suitable for most non-specialized applications. Note: Superseded by Llama 3 models which offer better performance.',
2107
+ },
2108
+ {
2109
+ modelVariant: 'CHAT',
2110
+ modelTitle: 'llama2-chat',
2111
+ modelName: 'llama2-chat',
2112
+ modelDescription: 'Meta Llama 2 Chat with 4K context window, fine-tuned specifically for conversational AI. Enhanced instruction following and safer responses compared to base model. Ideal for chatbots and interactive applications. Note: Consider using newer Llama 3 Chat for improved performance.',
2113
+ },
2114
+ {
2115
+ modelVariant: 'CHAT',
2116
+ modelTitle: 'alpaca-7b',
2117
+ modelName: 'alpaca-7b',
2118
+ modelDescription: 'Stanford Alpaca 7B with 2K context window, instruction-tuned LLaMA model focused on following specific directions. Optimized for resource efficiency while maintaining good response quality. Suitable for lightweight applications.',
2119
+ },
2120
+ {
2121
+ modelVariant: 'CHAT',
2122
+ modelTitle: 'alpaca-30b',
2123
+ modelName: 'alpaca-30b',
2124
+ modelDescription: 'Stanford Alpaca 30B with 2K context window. Larger instruction-tuned LLaMA model with improved reasoning and content generation capabilities. Better performance than 7B variant but requires more computational resources.',
2125
+ },
2126
+ {
2127
+ modelVariant: 'CHAT',
2128
+ modelTitle: 'vicuna-13b',
2129
+ modelName: 'vicuna-13b',
2130
+ modelDescription: 'Vicuna 13B with 2K context window, fine-tuned from LLaMA for chat and instruction following. Known for balanced performance, good conversational abilities, and improved helpfulness over base models. Popular for diverse conversational applications.',
2131
+ },
2132
+ {
2133
+ modelVariant: 'CHAT',
2134
+ modelTitle: 'falcon-7b',
2135
+ modelName: 'falcon-7b',
2136
+ modelDescription: 'Falcon 7B with 2K context window, performant open large language model trained on 1.5 trillion tokens. Strong on general knowledge tasks with smaller computational requirements. Good balance of performance and efficiency.',
2137
+ },
2138
+ {
2139
+ modelVariant: 'CHAT',
2140
+ modelTitle: 'falcon-40b',
2141
+ modelName: 'falcon-40b',
2142
+ modelDescription: 'Falcon 40B with 2K context window, larger open large language model with enhanced reasoning and knowledge capabilities. Significantly better performance than 7B version but requires substantially more resources. Suitable for complex generation tasks.',
2143
+ },
2144
+ {
2145
+ modelVariant: 'CHAT',
2146
+ modelTitle: 'bloom-7b',
2147
+ modelName: 'bloom-7b',
2148
+ modelDescription: 'BLOOM 7B with 2K context window, multilingual large language model supporting 46+ languages. Trained for diverse linguistic capabilities across languages. Especially useful for non-English or multilingual applications.',
2149
+ },
2150
+ {
2151
+ modelVariant: 'CHAT',
2152
+ modelTitle: 'mistral-7b',
2153
+ modelName: 'mistral-7b',
2154
+ modelDescription: 'Mistral 7B with 8K context window, efficient and fast open LLM with performance rivaling much larger models. Features Grouped-Query Attention for faster inference. Excellent balance of quality and speed for various applications.',
2155
+ },
2156
+ {
2157
+ modelVariant: 'CHAT',
2158
+ modelTitle: 'gorilla',
2159
+ modelName: 'gorilla',
2160
+ modelDescription: 'Gorilla with 4K context window, specialized open-source LLM for tool use and API interaction. Fine-tuned to understand and generate API calls accurately. Optimal for agent applications that interact with external tools and services.',
2161
+ },
2162
+ {
2163
+ modelVariant: 'CHAT',
2164
+ modelTitle: 'cerebras-13b',
2165
+ modelName: 'cerebras-13b',
2166
+ modelDescription: 'Cerebras-GPT 13B with 2K context window, trained on diverse high-quality datasets. Good general-purpose capabilities with particular strengths in factual response accuracy. Well-suited for applications requiring reliable information.',
2167
+ },
2168
+ {
2169
+ modelVariant: 'CHAT',
2170
+ modelTitle: 'openchat-7b',
2171
+ modelName: 'openchat-7b',
2172
+ modelDescription: 'OpenChat 7B with 4K context window, optimized for conversational abilities and instruction following. Outperforms many larger models on benchmark tasks while maintaining efficiency. Ideal for interactive applications with limited resources.',
2173
+ },
2174
+ {
2175
+ modelVariant: 'CHAT',
2176
+ modelTitle: 'openchat-13b',
2177
+ modelName: 'openchat-13b',
2178
+ modelDescription: 'OpenChat 13B with 4K context window, larger conversational LLM with enhanced reasoning, helpfulness, and knowledge. Significant improvement over 7B variant in complex tasks and nuanced conversations. Well-balanced for most conversational applications.',
2179
+ },
2180
+ {
2181
+ modelVariant: 'CHAT',
2182
+ modelTitle: 'mpt-7b-chat',
2183
+ modelName: 'mpt-7b-chat',
2184
+ modelDescription: 'MPT-7B Chat with 4K context window (extendable to 65K+), optimized for dialogue using high-quality conversation data. Features enhanced conversational abilities with strong safety alignments. Good for deployment in public-facing chat applications.',
2185
+ },
2186
+ {
2187
+ modelVariant: 'CHAT',
2188
+ modelTitle: 'mpt-7b-instruct',
2189
+ modelName: 'mpt-7b-instruct',
2190
+ modelDescription: 'MPT-7B Instruct with 4K context window (extendable to 65K+), instruction-tuned variant optimized for following specific directives. Better than chat variant for single-turn instruction tasks. Well-suited for content generation and task completion.',
2191
+ },
2192
+ {
2193
+ modelVariant: 'CHAT',
2194
+ modelTitle: 'command-7b',
2195
+ modelName: 'command-7b',
2196
+ modelDescription: 'Command 7B with 4K context window, instruction-following LLM tuned specifically for direct command execution and helpful responses. Optimized for clarity of outputs and following explicit directions. Good for practical task-oriented applications.',
2197
+ },
2198
+ {
2199
+ modelVariant: 'CHAT',
2200
+ modelTitle: 'starcoder',
2201
+ modelName: 'starcoder',
2202
+ modelDescription: 'StarCoder with 8K context window, specialized code generation large language model trained on permissively licensed code. Supports 80+ programming languages. Optimized for code completion, generation, and understanding tasks.',
2203
+ },
2204
+ {
2205
+ modelVariant: 'CHAT',
2206
+ modelTitle: 'starcoder2',
2207
+ modelName: 'starcoder2',
2208
+ modelDescription: 'StarCoder2 with 16K context window, improved code generation model with better reasoning about code, debugging capabilities, and documentation generation. Supports 600+ programming languages. Ideal for complex software development assistance.',
2209
+ },
2210
+ {
2211
+ modelVariant: 'CHAT',
2212
+ modelTitle: 'mixtral-7b-chat',
2213
+ modelName: 'mixtral-7b-chat',
2214
+ modelDescription: 'Mixtral 7B Chat with 32K context window, Mixture-of-Experts conversational model with strong performance across diverse tasks. Efficiently routes inputs to specialized sub-networks for optimal processing. Well-balanced for most chat applications.',
2215
+ },
2216
+ {
2217
+ modelVariant: 'CHAT',
2218
+ modelTitle: 'mixtral-8x7b',
2219
+ modelName: 'mixtral-8x7b',
2220
+ modelDescription: 'Mixtral 8x7B with 32K context window, advanced Mixture-of-Experts architecture using 8 expert networks of 7B parameters each. Competitive with much larger dense models while using less computation. Excellent general-purpose capabilities.',
2221
+ },
2222
+ {
2223
+ modelVariant: 'CHAT',
2224
+ modelTitle: 'mixtral-8x7b-instruct',
2225
+ modelName: 'mixtral-8x7b-instruct',
2226
+ modelDescription: 'Mixtral 8x7B Instruct with 32K context window, instruction-tuned Mixture-of-Experts model for direct task execution. Enhanced directive following and more structured outputs compared to base model. Optimal for specific instruction-based workloads.',
2227
+ },
2228
+ {
2229
+ modelVariant: 'CHAT',
2230
+ modelTitle: 'neural-chat',
2231
+ modelName: 'neural-chat',
2232
+ modelDescription: 'Intel Neural Chat (latest) with 8K context window, optimized for Intel hardware with efficient inference. Balanced model for general-purpose conversational applications with good instruction following capabilities.',
2233
+ },
2234
+ {
2235
+ modelVariant: 'CHAT',
2236
+ modelTitle: 'qwen:7b',
2237
+ modelName: 'qwen:7b',
2238
+ modelDescription: 'Alibaba Qwen 7B with 8K context window. Versatile model with strong multilingual capabilities, particularly for Chinese and English. Features good reasoning and knowledge across diverse domains.',
2239
+ },
2240
+ {
2241
+ modelVariant: 'CHAT',
2242
+ modelTitle: 'qwen:14b',
2243
+ modelName: 'qwen:14b',
2244
+ modelDescription: 'Alibaba Qwen 14B with 8K context window. Enhanced version with improved reasoning and knowledge capabilities. Particularly strong in multilingual applications and domain-specific tasks requiring deeper understanding.',
2245
+ },
2246
+ {
2247
+ modelVariant: 'CHAT',
2248
+ modelTitle: 'gemma:2b',
2249
+ modelName: 'gemma:2b',
2250
+ modelDescription: 'Google Gemma 2B with 8K context window. Lightweight but capable model designed for efficiency. Good performance for its size on common tasks, ideal for resource-constrained environments and quick responses.',
2251
+ },
2252
+ {
2253
+ modelVariant: 'CHAT',
2254
+ modelTitle: 'gemma:7b',
2255
+ modelName: 'gemma:7b',
2256
+ modelDescription: 'Google Gemma 7B with 8K context window. Well-balanced model offering strong performance across general tasks while maintaining reasonable resource requirements. Good alternative to similar-sized models with competitive capabilities.',
2257
+ },
2258
+ {
2259
+ modelVariant: 'CHAT',
2260
+ modelTitle: 'dolphin-mixtral',
2261
+ modelName: 'dolphin-mixtral',
2262
+ modelDescription: 'Dolphin Mixtral with 32K context window. Community-tuned version of Mixtral with enhanced instruction following and creative capabilities. Maintains the MoE architecture while improving conversational abilities and reducing hallucinations.',
2263
+ },
2264
+ {
2265
+ modelVariant: 'CHAT',
2266
+ modelTitle: 'yi:34b-chat',
2267
+ modelName: 'yi:34b-chat',
2268
+ modelDescription: 'Yi 34B Chat with 4K context window. Large bilingual model with exceptional English and Chinese capabilities. Strong performance on reasoning, knowledge, and instruction following tasks that competes with much larger commercial models.',
2269
+ },
2270
+ // <- [🕕]
2271
+ ],
2272
+ });
2273
+ /**
2274
+ * TODO: [🚸] Not all models are compatible with JSON mode, add this information here and use it
2275
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2276
+ */
2277
+
2278
+ /**
2279
+ * Default base URL for Ollama API
2280
+ *
2281
+ * @public exported from `@promptbook/ollama`
2282
+ */
2283
+ const DEFAULT_OLLAMA_BASE_URL = 'http://localhost:11434/v1';
2284
+
2285
+ /**
2286
+ * Execution Tools for calling Ollama API
2287
+ *
2288
+ * @public exported from `@promptbook/ollama`
2289
+ */
2290
+ class OllamaExecutionTools extends OpenAiCompatibleExecutionTools {
2291
+ /* <- TODO: [🍚] `, Destroyable` */
2292
+ constructor(ollamaOptions) {
2293
+ const openAiCompatibleOptions = {
2294
+ baseURL: DEFAULT_OLLAMA_BASE_URL,
2295
+ ...ollamaOptions,
2296
+ userId: 'ollama',
2297
+ };
2298
+ super(openAiCompatibleOptions);
2299
+ }
2300
+ get title() {
2301
+ return 'Ollama';
2302
+ }
2303
+ get description() {
2304
+ return 'Use all models provided by Ollama';
2305
+ }
2306
+ /**
2307
+ * List all available models (non dynamically)
2308
+ *
2309
+ * Note: Purpose of this is to provide more information about models than standard listing from API
2310
+ */
2311
+ get HARDCODED_MODELS() {
2312
+ return OLLAMA_MODELS;
2313
+ }
2314
+ /**
2315
+ * Computes the usage of the Ollama API based on the response from Ollama
2316
+ */
2317
+ computeUsage(...args) {
2318
+ return {
2319
+ ...computeOpenAiUsage(...args),
2320
+ 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
2321
+ };
2322
+ }
2323
+ /**
2324
+ * Default model for chat variant.
2325
+ */
2326
+ getDefaultChatModel() {
2327
+ return this.getDefaultModel('llama2'); // <- TODO: [🧠] Pick the best default model
2328
+ // <- TODO: [🛄] When 'llama2' not installed, maybe better error message
2329
+ }
2330
+ /**
2331
+ * Default model for completion variant.
2332
+ */
2333
+ getDefaultCompletionModel() {
2334
+ return this.getDefaultModel('llama2'); // <- TODO: [🧠] Pick the best default model
2335
+ // <- TODO: [🛄] When 'llama2' not installed, maybe better error message
2336
+ }
2337
+ /**
2338
+ * Default model for completion variant.
2339
+ */
2340
+ getDefaultEmbeddingModel() {
2341
+ return this.getDefaultModel('text-embedding-3-large'); // <- TODO: [🧠] Pick the best default model
2342
+ // <- TODO: [🛄]
2343
+ }
2344
+ }
2345
+ /**
2346
+ * TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
2347
+ */
551
2348
 
552
2349
  /**
553
2350
  * Execution Tools for calling Ollama API
554
2351
  *
555
2352
  * @public exported from `@promptbook/ollama`
556
2353
  */
557
- const createOllamaExecutionTools = Object.assign((options) => new OllamaExecutionTools(options), {
2354
+ const createOllamaExecutionTools = Object.assign((options) => {
2355
+ return new OllamaExecutionTools(options);
2356
+ }, {
558
2357
  packageName: '@promptbook/ollama',
559
2358
  className: 'OllamaExecutionTools',
560
2359
  });
@@ -737,5 +2536,5 @@ const _OllamaRegistration = $llmToolsRegister.register(createOllamaExecutionTool
737
2536
  * Note: [💞] Ignore a discrepancy between file name and entity name
738
2537
  */
739
2538
 
740
- export { BOOK_LANGUAGE_VERSION, OllamaExecutionTools, PROMPTBOOK_ENGINE_VERSION, _OllamaRegistration, createOllamaExecutionTools };
2539
+ export { BOOK_LANGUAGE_VERSION, DEFAULT_OLLAMA_BASE_URL, OLLAMA_MODELS, OllamaExecutionTools, PROMPTBOOK_ENGINE_VERSION, _OllamaRegistration, createOllamaExecutionTools };
741
2540
  //# sourceMappingURL=index.es.js.map