@promptbook/cli 0.89.0 → 0.92.0-10

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 +4 -0
  2. package/esm/index.es.js +944 -94
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/core.index.d.ts +6 -0
  5. package/esm/typings/src/_packages/deepseek.index.d.ts +2 -0
  6. package/esm/typings/src/_packages/google.index.d.ts +2 -0
  7. package/esm/typings/src/_packages/utils.index.d.ts +2 -0
  8. package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +1 -1
  9. package/esm/typings/src/conversion/archive/loadArchive.d.ts +2 -2
  10. package/esm/typings/src/execution/CommonToolsOptions.d.ts +4 -0
  11. package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTask.d.ts +12 -0
  12. package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTask.d.ts +5 -0
  13. package/esm/typings/src/formats/csv/utils/csvParse.d.ts +12 -0
  14. package/esm/typings/src/formats/json/utils/jsonParse.d.ts +11 -0
  15. package/esm/typings/src/llm-providers/_common/filterModels.d.ts +15 -0
  16. package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +43 -0
  17. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +4 -0
  18. package/esm/typings/src/llm-providers/deepseek/deepseek-models.d.ts +23 -0
  19. package/esm/typings/src/llm-providers/google/google-models.d.ts +23 -0
  20. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
  21. package/esm/typings/src/personas/preparePersona.d.ts +1 -1
  22. package/esm/typings/src/pipeline/PipelineJson/PersonaJson.d.ts +4 -2
  23. package/esm/typings/src/remote-server/openapi-types.d.ts +348 -6
  24. package/esm/typings/src/remote-server/openapi.d.ts +397 -3
  25. package/package.json +2 -1
  26. package/umd/index.umd.js +948 -98
  27. package/umd/index.umd.js.map +1 -1
package/umd/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('commander'), require('spacetrim'), require('waitasecond'), require('prompts'), require('path'), require('fs/promises'), require('dotenv'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('crypto'), require('socket.io-client'), require('rxjs'), require('child_process'), require('jszip'), require('prettier'), require('prettier/parser-html'), require('papaparse'), require('crypto-js'), require('mime-types'), require('glob-promise'), require('moment'), require('express'), require('http'), require('socket.io'), require('express-openapi-validator'), require('swagger-ui-express'), require('@anthropic-ai/sdk'), require('@azure/openai'), require('openai'), require('@mozilla/readability'), require('jsdom'), require('showdown')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'colors', 'commander', 'spacetrim', 'waitasecond', 'prompts', 'path', 'fs/promises', 'dotenv', 'crypto-js/enc-hex', 'crypto-js/sha256', 'crypto', 'socket.io-client', 'rxjs', 'child_process', 'jszip', 'prettier', 'prettier/parser-html', 'papaparse', 'crypto-js', 'mime-types', 'glob-promise', 'moment', 'express', 'http', 'socket.io', 'express-openapi-validator', 'swagger-ui-express', '@anthropic-ai/sdk', '@azure/openai', 'openai', '@mozilla/readability', 'jsdom', 'showdown'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global.spaceTrim, global.waitasecond, global.prompts, global.path, global.promises, global.dotenv, global.hexEncoder, global.sha256, global.crypto, global.socket_ioClient, global.rxjs, global.child_process, global.JSZip, global.prettier, global.parserHtml, global.papaparse, global.cryptoJs, global.mimeTypes, global.glob, global.moment, global.express, global.http, global.socket_io, global.OpenApiValidator, global.swaggerUi, global.Anthropic, global.openai, global.OpenAI, global.readability, global.jsdom, global.showdown));
5
- })(this, (function (exports, colors, commander, spaceTrim, waitasecond, prompts, path, promises, dotenv, hexEncoder, sha256, crypto, socket_ioClient, rxjs, child_process, JSZip, prettier, parserHtml, papaparse, cryptoJs, mimeTypes, glob, moment, express, http, socket_io, OpenApiValidator, swaggerUi, Anthropic, openai, OpenAI, readability, jsdom, showdown) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('commander'), require('spacetrim'), require('waitasecond'), require('prompts'), require('path'), require('fs/promises'), require('dotenv'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('crypto'), require('socket.io-client'), require('rxjs'), require('child_process'), require('jszip'), require('prettier'), require('prettier/parser-html'), require('papaparse'), require('crypto-js'), require('mime-types'), require('glob-promise'), require('moment'), require('express'), require('http'), require('socket.io'), require('express-openapi-validator'), require('swagger-ui-express'), require('@anthropic-ai/sdk'), require('@azure/openai'), require('bottleneck'), require('openai'), require('@mozilla/readability'), require('jsdom'), require('showdown')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'colors', 'commander', 'spacetrim', 'waitasecond', 'prompts', 'path', 'fs/promises', 'dotenv', 'crypto-js/enc-hex', 'crypto-js/sha256', 'crypto', 'socket.io-client', 'rxjs', 'child_process', 'jszip', 'prettier', 'prettier/parser-html', 'papaparse', 'crypto-js', 'mime-types', 'glob-promise', 'moment', 'express', 'http', 'socket.io', 'express-openapi-validator', 'swagger-ui-express', '@anthropic-ai/sdk', '@azure/openai', 'bottleneck', 'openai', '@mozilla/readability', 'jsdom', 'showdown'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global.spaceTrim, global.waitasecond, global.prompts, global.path, global.promises, global.dotenv, global.hexEncoder, global.sha256, global.crypto, global.socket_ioClient, global.rxjs, global.child_process, global.JSZip, global.prettier, global.parserHtml, global.papaparse, global.cryptoJs, global.mimeTypes, global.glob, global.moment, global.express, global.http, global.socket_io, global.OpenApiValidator, global.swaggerUi, global.Anthropic, global.openai, global.Bottleneck, global.OpenAI, global.readability, global.jsdom, global.showdown));
5
+ })(this, (function (exports, colors, commander, spaceTrim, waitasecond, prompts, path, promises, dotenv, hexEncoder, sha256, crypto, socket_ioClient, rxjs, child_process, JSZip, prettier, parserHtml, papaparse, cryptoJs, mimeTypes, glob, moment, express, http, socket_io, OpenApiValidator, swaggerUi, Anthropic, openai, Bottleneck, OpenAI, readability, jsdom, showdown) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
@@ -40,6 +40,7 @@
40
40
  var OpenApiValidator__namespace = /*#__PURE__*/_interopNamespace(OpenApiValidator);
41
41
  var swaggerUi__default = /*#__PURE__*/_interopDefaultLegacy(swaggerUi);
42
42
  var Anthropic__default = /*#__PURE__*/_interopDefaultLegacy(Anthropic);
43
+ var Bottleneck__default = /*#__PURE__*/_interopDefaultLegacy(Bottleneck);
43
44
  var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
44
45
 
45
46
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
@@ -56,7 +57,7 @@
56
57
  * @generated
57
58
  * @see https://github.com/webgptorg/promptbook
58
59
  */
59
- const PROMPTBOOK_ENGINE_VERSION = '0.89.0';
60
+ const PROMPTBOOK_ENGINE_VERSION = '0.92.0-10';
60
61
  /**
61
62
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
62
63
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1014,6 +1015,45 @@
1014
1015
  keepUnused(...sideEffectSubjects);
1015
1016
  }
1016
1017
 
1018
+ /**
1019
+ * Converts a JavaScript Object Notation (JSON) string into an object.
1020
+ *
1021
+ * Note: This is wrapper around `JSON.parse()` with better error and type handling
1022
+ *
1023
+ * @public exported from `@promptbook/utils`
1024
+ */
1025
+ function jsonParse(value) {
1026
+ if (value === undefined) {
1027
+ throw new Error(`Can not parse JSON from undefined value.`);
1028
+ }
1029
+ else if (typeof value !== 'string') {
1030
+ console.error('Can not parse JSON from non-string value.', { text: value });
1031
+ throw new Error(spaceTrim__default["default"](`
1032
+ Can not parse JSON from non-string value.
1033
+
1034
+ The value type: ${typeof value}
1035
+ See more in console.
1036
+ `));
1037
+ }
1038
+ try {
1039
+ return JSON.parse(value);
1040
+ }
1041
+ catch (error) {
1042
+ if (!(error instanceof Error)) {
1043
+ throw error;
1044
+ }
1045
+ throw new Error(spaceTrim__default["default"]((block) => `
1046
+ ${block(error.message)}
1047
+
1048
+ The JSON text:
1049
+ ${block(value)}
1050
+ `));
1051
+ }
1052
+ }
1053
+ /**
1054
+ * TODO: !!!! Use in Promptbook.studio
1055
+ */
1056
+
1017
1057
  /**
1018
1058
  * Convert identification to Promptbook token
1019
1059
  *
@@ -2095,7 +2135,7 @@
2095
2135
  return null;
2096
2136
  }
2097
2137
  const fileContent = await promises.readFile(filename, 'utf-8');
2098
- const value = JSON.parse(fileContent);
2138
+ const value = jsonParse(fileContent);
2099
2139
  // TODO: [🌗]
2100
2140
  return value;
2101
2141
  }
@@ -3430,7 +3470,7 @@
3430
3470
  password,
3431
3471
  }),
3432
3472
  });
3433
- const { isSuccess, message, error, identification } = (await response.json());
3473
+ const { isSuccess, message, error, identification } = jsonParse(await response.text());
3434
3474
  if (message) {
3435
3475
  if (isSuccess) {
3436
3476
  console.log(colors__default["default"].green(message));
@@ -4461,7 +4501,7 @@
4461
4501
  if (!indexFile) {
4462
4502
  throw new UnexpectedError(`Archive does not contain 'index.book.json' file`);
4463
4503
  }
4464
- const collectionJson = JSON.parse(await indexFile.async('text'));
4504
+ const collectionJson = jsonParse(await indexFile.async('text'));
4465
4505
  for (const pipeline of collectionJson) {
4466
4506
  validatePipeline(pipeline);
4467
4507
  }
@@ -4471,7 +4511,7 @@
4471
4511
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
4472
4512
  */
4473
4513
 
4474
- var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
4514
+ var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModels",description:"List of available model names together with their descriptions as JSON",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelsRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n```json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n```\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nHere are the available models:\n\n```json\n{availableModels}\n```\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelsRequirements",format:"JSON",dependentParameterNames:["availableModels","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModels}` List of available model names together with their descriptions as JSON\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelsRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n\\`\\`\\`json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nHere are the available models:\n\n\\`\\`\\`json\n{availableModels}\n\\`\\`\\`\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelsRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
4475
4515
 
4476
4516
  /**
4477
4517
  * Function isValidJsonString will tell you if the string is valid JSON or not
@@ -4732,7 +4772,7 @@
4732
4772
  */
4733
4773
  function unpreparePipeline(pipeline) {
4734
4774
  let { personas, knowledgeSources, tasks } = pipeline;
4735
- personas = personas.map((persona) => ({ ...persona, modelRequirements: undefined, preparationIds: undefined }));
4775
+ personas = personas.map((persona) => ({ ...persona, modelsRequirements: undefined, preparationIds: undefined }));
4736
4776
  knowledgeSources = knowledgeSources.map((knowledgeSource) => ({ ...knowledgeSource, preparationIds: undefined }));
4737
4777
  tasks = tasks.map((task) => {
4738
4778
  let { dependentParameterNames } = task;
@@ -4890,7 +4930,7 @@
4890
4930
  if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
4891
4931
  return false;
4892
4932
  }
4893
- if (!pipeline.personas.every((persona) => persona.modelRequirements !== undefined)) {
4933
+ if (!pipeline.personas.every((persona) => persona.modelsRequirements !== undefined)) {
4894
4934
  return false;
4895
4935
  }
4896
4936
  if (!pipeline.knowledgeSources.every((knowledgeSource) => knowledgeSource.preparationIds !== undefined)) {
@@ -4932,7 +4972,7 @@
4932
4972
  const newObject = { ...object };
4933
4973
  for (const [key, value] of Object.entries(object)) {
4934
4974
  if (typeof value === 'string' && isValidJsonString(value)) {
4935
- newObject[key] = JSON.parse(value);
4975
+ newObject[key] = jsonParse(value);
4936
4976
  }
4937
4977
  else {
4938
4978
  newObject[key] = jsonStringsToJsons(value);
@@ -5385,6 +5425,24 @@
5385
5425
  }
5386
5426
  }
5387
5427
 
5428
+ /**
5429
+ * Converts a CSV string into an object
5430
+ *
5431
+ * Note: This is wrapper around `papaparse.parse()` with better autohealing
5432
+ *
5433
+ * @private - for now until `@promptbook/csv` is released
5434
+ */
5435
+ function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO: Make CSV Schemas */) {
5436
+ settings = { ...settings, ...MANDATORY_CSV_SETTINGS };
5437
+ // Note: Autoheal invalid '\n' characters
5438
+ if (settings.newline && !settings.newline.includes('\r') && value.includes('\r')) {
5439
+ console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
5440
+ value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
5441
+ }
5442
+ const csv = papaparse.parse(value, settings);
5443
+ return csv;
5444
+ }
5445
+
5388
5446
  /**
5389
5447
  * Definition for CSV spreadsheet
5390
5448
  *
@@ -5407,8 +5465,7 @@
5407
5465
  {
5408
5466
  subvalueName: 'ROW',
5409
5467
  async mapValues(value, outputParameterName, settings, mapCallback) {
5410
- // TODO: [👨🏾‍🤝‍👨🏼] DRY csv parsing
5411
- const csv = papaparse.parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
5468
+ const csv = csvParse(value, settings);
5412
5469
  if (csv.errors.length !== 0) {
5413
5470
  throw new CsvFormatError(spaceTrim__default["default"]((block) => `
5414
5471
  CSV parsing error
@@ -5438,8 +5495,7 @@
5438
5495
  {
5439
5496
  subvalueName: 'CELL',
5440
5497
  async mapValues(value, outputParameterName, settings, mapCallback) {
5441
- // TODO: [👨🏾‍🤝‍👨🏼] DRY csv parsing
5442
- const csv = papaparse.parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
5498
+ const csv = csvParse(value, settings);
5443
5499
  if (csv.errors.length !== 0) {
5444
5500
  throw new CsvFormatError(spaceTrim__default["default"]((block) => `
5445
5501
  CSV parsing error
@@ -6487,13 +6543,79 @@
6487
6543
  /**
6488
6544
  * @@@
6489
6545
  *
6546
+ * Here is the place where RAG (retrieval-augmented generation) happens
6547
+ *
6490
6548
  * @private internal utility of `createPipelineExecutor`
6491
6549
  */
6492
6550
  async function getKnowledgeForTask(options) {
6493
- const { preparedPipeline, task } = options;
6494
- return preparedPipeline.knowledgePieces.map(({ content }) => `- ${content}`).join('\n');
6551
+ const { tools, preparedPipeline, task } = options;
6552
+ const firstKnowlegePiece = preparedPipeline.knowledgePieces[0];
6553
+ const firstKnowlegeIndex = firstKnowlegePiece === null || firstKnowlegePiece === void 0 ? void 0 : firstKnowlegePiece.index[0];
6554
+ // <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
6555
+ if (firstKnowlegePiece === undefined || firstKnowlegeIndex === undefined) {
6556
+ return 'No knowledge pieces found';
6557
+ }
6558
+ // TODO: [🚐] Make arrayable LLMs -> single LLM DRY
6559
+ const _llms = arrayableToArray(tools.llm);
6560
+ const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
6561
+ const taskEmbeddingPrompt = {
6562
+ title: 'Knowledge Search',
6563
+ modelRequirements: {
6564
+ modelVariant: 'EMBEDDING',
6565
+ modelName: firstKnowlegeIndex.modelName,
6566
+ },
6567
+ content: task.content,
6568
+ parameters: {
6569
+ /* !!!!!!!! */
6570
+ },
6571
+ };
6572
+ const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
6573
+ const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
6574
+ const { index } = knowledgePiece;
6575
+ const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
6576
+ // <- TODO: Do not use just first knowledge piece and first index to determine embedding model
6577
+ if (knowledgePieceIndex === undefined) {
6578
+ return {
6579
+ content: knowledgePiece.content,
6580
+ relevance: 0,
6581
+ };
6582
+ }
6583
+ const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
6584
+ return {
6585
+ content: knowledgePiece.content,
6586
+ relevance,
6587
+ };
6588
+ });
6589
+ const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
6590
+ const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
6591
+ console.log('!!! Embedding', {
6592
+ task,
6593
+ taskEmbeddingPrompt,
6594
+ taskEmbeddingResult,
6595
+ firstKnowlegePiece,
6596
+ firstKnowlegeIndex,
6597
+ knowledgePiecesWithRelevance,
6598
+ knowledgePiecesSorted,
6599
+ knowledgePiecesLimited,
6600
+ });
6601
+ return knowledgePiecesLimited.map(({ content }) => `- ${content}`).join('\n');
6495
6602
  // <- TODO: [🧠] Some smart aggregation of knowledge pieces, single-line vs multi-line vs mixed
6496
6603
  }
6604
+ // TODO: !!!!!! Annotate + to new file
6605
+ function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
6606
+ if (embeddingVector1.length !== embeddingVector2.length) {
6607
+ throw new TypeError('Embedding vectors must have the same length');
6608
+ }
6609
+ const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
6610
+ const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
6611
+ const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
6612
+ return 1 - dotProduct / (magnitude1 * magnitude2);
6613
+ }
6614
+ /**
6615
+ * TODO: !!!! Verify if this is working
6616
+ * TODO: [♨] Implement Better - use keyword search
6617
+ * TODO: [♨] Examples of values
6618
+ */
6497
6619
 
6498
6620
  /**
6499
6621
  * @@@
@@ -6501,9 +6623,9 @@
6501
6623
  * @private internal utility of `createPipelineExecutor`
6502
6624
  */
6503
6625
  async function getReservedParametersForTask(options) {
6504
- const { preparedPipeline, task, pipelineIdentification } = options;
6626
+ const { tools, preparedPipeline, task, pipelineIdentification } = options;
6505
6627
  const context = await getContextForTask(); // <- [🏍]
6506
- const knowledge = await getKnowledgeForTask({ preparedPipeline, task });
6628
+ const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task });
6507
6629
  const examples = await getExamplesForTask();
6508
6630
  const currentDate = new Date().toISOString(); // <- TODO: [🧠][💩] Better
6509
6631
  const modelName = RESERVED_PARAMETER_MISSING_VALUE;
@@ -6565,6 +6687,7 @@
6565
6687
  }
6566
6688
  const definedParameters = Object.freeze({
6567
6689
  ...(await getReservedParametersForTask({
6690
+ tools,
6568
6691
  preparedPipeline,
6569
6692
  task: currentTask,
6570
6693
  pipelineIdentification,
@@ -7050,27 +7173,48 @@
7050
7173
  pipeline: await collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.book'),
7051
7174
  tools,
7052
7175
  });
7053
- // TODO: [🚐] Make arrayable LLMs -> single LLM DRY
7054
7176
  const _llms = arrayableToArray(tools.llm);
7055
7177
  const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
7056
- const availableModels = await llmTools.listModels();
7057
- const availableModelNames = availableModels
7178
+ const availableModels = (await llmTools.listModels())
7058
7179
  .filter(({ modelVariant }) => modelVariant === 'CHAT')
7059
- .map(({ modelName }) => modelName)
7060
- .join(',');
7061
- const result = await preparePersonaExecutor({ availableModelNames, personaDescription }).asPromise();
7180
+ .map(({ modelName, modelDescription }) => ({
7181
+ modelName,
7182
+ modelDescription,
7183
+ // <- Note: `modelTitle` and `modelVariant` is not relevant for this task
7184
+ }));
7185
+ const result = await preparePersonaExecutor({
7186
+ availableModels /* <- Note: Passing as JSON */,
7187
+ personaDescription,
7188
+ }).asPromise();
7062
7189
  const { outputParameters } = result;
7063
- const { modelRequirements: modelRequirementsRaw } = outputParameters;
7064
- const modelRequirements = JSON.parse(modelRequirementsRaw);
7190
+ const { modelsRequirements: modelsRequirementsJson } = outputParameters;
7191
+ let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
7065
7192
  if (isVerbose) {
7066
- console.info(`PERSONA ${personaDescription}`, modelRequirements);
7193
+ console.info(`PERSONA ${personaDescription}`, modelsRequirementsUnchecked);
7067
7194
  }
7068
- const { modelName, systemMessage, temperature } = modelRequirements;
7069
- return {
7195
+ if (!Array.isArray(modelsRequirementsUnchecked)) {
7196
+ // <- TODO: Book should have syntax and system to enforce shape of JSON
7197
+ modelsRequirementsUnchecked = [modelsRequirementsUnchecked];
7198
+ /*
7199
+ throw new UnexpectedError(
7200
+ spaceTrim(
7201
+ (block) => `
7202
+ Invalid \`modelsRequirements\`:
7203
+
7204
+ \`\`\`json
7205
+ ${block(JSON.stringify(modelsRequirementsUnchecked, null, 4))}
7206
+ \`\`\`
7207
+ `,
7208
+ ),
7209
+ );
7210
+ */
7211
+ }
7212
+ const modelsRequirements = modelsRequirementsUnchecked.map((modelRequirements) => ({
7070
7213
  modelVariant: 'CHAT',
7071
- modelName,
7072
- systemMessage,
7073
- temperature,
7214
+ ...modelRequirements,
7215
+ }));
7216
+ return {
7217
+ modelsRequirements,
7074
7218
  };
7075
7219
  }
7076
7220
  /**
@@ -7239,7 +7383,7 @@
7239
7383
  > },
7240
7384
  */
7241
7385
  async asJson() {
7242
- return JSON.parse(await tools.fs.readFile(filename, 'utf-8'));
7386
+ return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
7243
7387
  },
7244
7388
  async asText() {
7245
7389
  return await tools.fs.readFile(filename, 'utf-8');
@@ -7497,14 +7641,14 @@
7497
7641
  // TODO: [🖌][🧠] Implement some `mapAsync` function
7498
7642
  const preparedPersonas = new Array(personas.length);
7499
7643
  await forEachAsync(personas, { maxParallelCount /* <- TODO: [🪂] When there are subtasks, this maximul limit can be broken */ }, async (persona, index) => {
7500
- const modelRequirements = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
7644
+ const { modelsRequirements } = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
7501
7645
  rootDirname,
7502
7646
  maxParallelCount /* <- TODO: [🪂] */,
7503
7647
  isVerbose,
7504
7648
  });
7505
7649
  const preparedPersona = {
7506
7650
  ...persona,
7507
- modelRequirements,
7651
+ modelsRequirements,
7508
7652
  preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id],
7509
7653
  // <- TODO: [🍙] Make some standard order of json properties
7510
7654
  };
@@ -12944,7 +13088,7 @@
12944
13088
  }
12945
13089
  let inputParameters = {};
12946
13090
  if (json) {
12947
- inputParameters = JSON.parse(json);
13091
+ inputParameters = jsonParse(json);
12948
13092
  // <- TODO: Maybe check shape of passed JSON and if its valid parameters Record
12949
13093
  }
12950
13094
  // TODO: DRY [◽]
@@ -13175,7 +13319,7 @@
13175
13319
  const openapiJson = {
13176
13320
  openapi: '3.0.0',
13177
13321
  info: {
13178
- title: 'Promptbook Remote Server API (!!!! From TS)',
13322
+ title: 'Promptbook Remote Server API (!!!! From YML)',
13179
13323
  version: '1.0.0',
13180
13324
  description: 'API documentation for the Promptbook Remote Server',
13181
13325
  },
@@ -13187,6 +13331,13 @@
13187
13331
  responses: {
13188
13332
  '200': {
13189
13333
  description: 'Server details in markdown format.',
13334
+ content: {
13335
+ 'text/markdown': {
13336
+ schema: {
13337
+ type: 'string',
13338
+ },
13339
+ },
13340
+ },
13190
13341
  },
13191
13342
  },
13192
13343
  },
@@ -13217,13 +13368,22 @@
13217
13368
  },
13218
13369
  },
13219
13370
  responses: {
13220
- '200': {
13371
+ '201': {
13221
13372
  description: 'Successful login',
13222
13373
  content: {
13223
13374
  'application/json': {
13224
13375
  schema: {
13225
13376
  type: 'object',
13226
13377
  properties: {
13378
+ isSuccess: {
13379
+ type: 'boolean',
13380
+ },
13381
+ message: {
13382
+ type: 'string',
13383
+ },
13384
+ error: {
13385
+ type: 'object',
13386
+ },
13227
13387
  identification: {
13228
13388
  type: 'object',
13229
13389
  },
@@ -13232,6 +13392,43 @@
13232
13392
  },
13233
13393
  },
13234
13394
  },
13395
+ '400': {
13396
+ description: 'Bad request or login failed',
13397
+ content: {
13398
+ 'application/json': {
13399
+ schema: {
13400
+ type: 'object',
13401
+ properties: {
13402
+ error: {
13403
+ type: 'object',
13404
+ },
13405
+ },
13406
+ },
13407
+ },
13408
+ },
13409
+ },
13410
+ '401': {
13411
+ description: 'Authentication error',
13412
+ content: {
13413
+ 'application/json': {
13414
+ schema: {
13415
+ type: 'object',
13416
+ properties: {
13417
+ isSuccess: {
13418
+ type: 'boolean',
13419
+ enum: [false],
13420
+ },
13421
+ message: {
13422
+ type: 'string',
13423
+ },
13424
+ error: {
13425
+ type: 'object',
13426
+ },
13427
+ },
13428
+ },
13429
+ },
13430
+ },
13431
+ },
13235
13432
  },
13236
13433
  },
13237
13434
  },
@@ -13253,6 +13450,16 @@
13253
13450
  },
13254
13451
  },
13255
13452
  },
13453
+ '500': {
13454
+ description: 'No collection available',
13455
+ content: {
13456
+ 'text/plain': {
13457
+ schema: {
13458
+ type: 'string',
13459
+ },
13460
+ },
13461
+ },
13462
+ },
13256
13463
  },
13257
13464
  },
13258
13465
  },
@@ -13284,6 +13491,28 @@
13284
13491
  },
13285
13492
  '404': {
13286
13493
  description: 'Book not found.',
13494
+ content: {
13495
+ 'application/json': {
13496
+ schema: {
13497
+ type: 'object',
13498
+ properties: {
13499
+ error: {
13500
+ type: 'object',
13501
+ },
13502
+ },
13503
+ },
13504
+ },
13505
+ },
13506
+ },
13507
+ '500': {
13508
+ description: 'No collection available',
13509
+ content: {
13510
+ 'text/plain': {
13511
+ schema: {
13512
+ type: 'string',
13513
+ },
13514
+ },
13515
+ },
13287
13516
  },
13288
13517
  },
13289
13518
  },
@@ -13301,6 +13530,28 @@
13301
13530
  type: 'array',
13302
13531
  items: {
13303
13532
  type: 'object',
13533
+ properties: {
13534
+ nonce: {
13535
+ type: 'string',
13536
+ },
13537
+ taskId: {
13538
+ type: 'string',
13539
+ },
13540
+ taskType: {
13541
+ type: 'string',
13542
+ },
13543
+ status: {
13544
+ type: 'string',
13545
+ },
13546
+ createdAt: {
13547
+ type: 'string',
13548
+ format: 'date-time',
13549
+ },
13550
+ updatedAt: {
13551
+ type: 'string',
13552
+ format: 'date-time',
13553
+ },
13554
+ },
13304
13555
  },
13305
13556
  },
13306
13557
  },
@@ -13309,6 +13560,147 @@
13309
13560
  },
13310
13561
  },
13311
13562
  },
13563
+ '/executions/last': {
13564
+ get: {
13565
+ summary: 'Get the last execution',
13566
+ description: 'Returns details of the last execution task.',
13567
+ responses: {
13568
+ '200': {
13569
+ description: 'The last execution task with full details.',
13570
+ content: {
13571
+ 'application/json': {
13572
+ schema: {
13573
+ type: 'object',
13574
+ properties: {
13575
+ nonce: {
13576
+ type: 'string',
13577
+ },
13578
+ taskId: {
13579
+ type: 'string',
13580
+ },
13581
+ taskType: {
13582
+ type: 'string',
13583
+ },
13584
+ status: {
13585
+ type: 'string',
13586
+ },
13587
+ errors: {
13588
+ type: 'array',
13589
+ items: {
13590
+ type: 'object',
13591
+ },
13592
+ },
13593
+ warnings: {
13594
+ type: 'array',
13595
+ items: {
13596
+ type: 'object',
13597
+ },
13598
+ },
13599
+ createdAt: {
13600
+ type: 'string',
13601
+ format: 'date-time',
13602
+ },
13603
+ updatedAt: {
13604
+ type: 'string',
13605
+ format: 'date-time',
13606
+ },
13607
+ currentValue: {
13608
+ type: 'object',
13609
+ },
13610
+ },
13611
+ },
13612
+ },
13613
+ },
13614
+ },
13615
+ '404': {
13616
+ description: 'No execution tasks found.',
13617
+ content: {
13618
+ 'text/plain': {
13619
+ schema: {
13620
+ type: 'string',
13621
+ },
13622
+ },
13623
+ },
13624
+ },
13625
+ },
13626
+ },
13627
+ },
13628
+ '/executions/{taskId}': {
13629
+ get: {
13630
+ summary: 'Get specific execution',
13631
+ description: 'Returns details of a specific execution task.',
13632
+ parameters: [
13633
+ {
13634
+ in: 'path',
13635
+ name: 'taskId',
13636
+ required: true,
13637
+ schema: {
13638
+ type: 'string',
13639
+ },
13640
+ description: 'The ID of the execution task to retrieve.',
13641
+ },
13642
+ ],
13643
+ responses: {
13644
+ '200': {
13645
+ description: 'The execution task with full details.',
13646
+ content: {
13647
+ 'application/json': {
13648
+ schema: {
13649
+ type: 'object',
13650
+ properties: {
13651
+ nonce: {
13652
+ type: 'string',
13653
+ },
13654
+ taskId: {
13655
+ type: 'string',
13656
+ },
13657
+ taskType: {
13658
+ type: 'string',
13659
+ },
13660
+ status: {
13661
+ type: 'string',
13662
+ },
13663
+ errors: {
13664
+ type: 'array',
13665
+ items: {
13666
+ type: 'object',
13667
+ },
13668
+ },
13669
+ warnings: {
13670
+ type: 'array',
13671
+ items: {
13672
+ type: 'object',
13673
+ },
13674
+ },
13675
+ createdAt: {
13676
+ type: 'string',
13677
+ format: 'date-time',
13678
+ },
13679
+ updatedAt: {
13680
+ type: 'string',
13681
+ format: 'date-time',
13682
+ },
13683
+ currentValue: {
13684
+ type: 'object',
13685
+ },
13686
+ },
13687
+ },
13688
+ },
13689
+ },
13690
+ },
13691
+ '404': {
13692
+ description: 'Execution task not found.',
13693
+ content: {
13694
+ 'text/plain': {
13695
+ schema: {
13696
+ type: 'string',
13697
+ },
13698
+ },
13699
+ },
13700
+ },
13701
+ },
13702
+ },
13703
+ },
13312
13704
  '/executions/new': {
13313
13705
  post: {
13314
13706
  summary: 'Start a new execution',
@@ -13322,12 +13714,19 @@
13322
13714
  properties: {
13323
13715
  pipelineUrl: {
13324
13716
  type: 'string',
13717
+ description: 'URL of the pipeline to execute',
13718
+ },
13719
+ book: {
13720
+ type: 'string',
13721
+ description: 'Alternative field for pipelineUrl',
13325
13722
  },
13326
13723
  inputParameters: {
13327
13724
  type: 'object',
13725
+ description: 'Parameters for pipeline execution',
13328
13726
  },
13329
13727
  identification: {
13330
13728
  type: 'object',
13729
+ description: 'User identification data',
13331
13730
  },
13332
13731
  },
13333
13732
  },
@@ -13347,13 +13746,164 @@
13347
13746
  },
13348
13747
  '400': {
13349
13748
  description: 'Invalid input.',
13749
+ content: {
13750
+ 'application/json': {
13751
+ schema: {
13752
+ type: 'object',
13753
+ properties: {
13754
+ error: {
13755
+ type: 'object',
13756
+ },
13757
+ },
13758
+ },
13759
+ },
13760
+ },
13761
+ },
13762
+ '404': {
13763
+ description: 'Pipeline not found.',
13764
+ content: {
13765
+ 'text/plain': {
13766
+ schema: {
13767
+ type: 'string',
13768
+ },
13769
+ },
13770
+ },
13771
+ },
13772
+ },
13773
+ },
13774
+ },
13775
+ '/api-docs': {
13776
+ get: {
13777
+ summary: 'API documentation UI',
13778
+ description: 'Swagger UI for API documentation',
13779
+ responses: {
13780
+ '200': {
13781
+ description: 'HTML Swagger UI',
13782
+ },
13783
+ },
13784
+ },
13785
+ },
13786
+ '/swagger': {
13787
+ get: {
13788
+ summary: 'API documentation UI (alternative path)',
13789
+ description: 'Swagger UI for API documentation',
13790
+ responses: {
13791
+ '200': {
13792
+ description: 'HTML Swagger UI',
13793
+ },
13794
+ },
13795
+ },
13796
+ },
13797
+ '/openapi': {
13798
+ get: {
13799
+ summary: 'OpenAPI specification',
13800
+ description: 'Returns the OpenAPI JSON specification',
13801
+ responses: {
13802
+ '200': {
13803
+ description: 'OpenAPI specification',
13804
+ content: {
13805
+ 'application/json': {
13806
+ schema: {
13807
+ type: 'object',
13808
+ },
13809
+ },
13810
+ },
13350
13811
  },
13351
13812
  },
13352
13813
  },
13353
13814
  },
13354
13815
  },
13355
- components: {},
13356
- tags: [],
13816
+ components: {
13817
+ schemas: {
13818
+ Error: {
13819
+ type: 'object',
13820
+ properties: {
13821
+ error: {
13822
+ type: 'object',
13823
+ },
13824
+ },
13825
+ },
13826
+ ExecutionTaskSummary: {
13827
+ type: 'object',
13828
+ properties: {
13829
+ nonce: {
13830
+ type: 'string',
13831
+ },
13832
+ taskId: {
13833
+ type: 'string',
13834
+ },
13835
+ taskType: {
13836
+ type: 'string',
13837
+ },
13838
+ status: {
13839
+ type: 'string',
13840
+ },
13841
+ createdAt: {
13842
+ type: 'string',
13843
+ format: 'date-time',
13844
+ },
13845
+ updatedAt: {
13846
+ type: 'string',
13847
+ format: 'date-time',
13848
+ },
13849
+ },
13850
+ },
13851
+ ExecutionTaskFull: {
13852
+ type: 'object',
13853
+ properties: {
13854
+ nonce: {
13855
+ type: 'string',
13856
+ },
13857
+ taskId: {
13858
+ type: 'string',
13859
+ },
13860
+ taskType: {
13861
+ type: 'string',
13862
+ },
13863
+ status: {
13864
+ type: 'string',
13865
+ },
13866
+ errors: {
13867
+ type: 'array',
13868
+ items: {
13869
+ type: 'object',
13870
+ },
13871
+ },
13872
+ warnings: {
13873
+ type: 'array',
13874
+ items: {
13875
+ type: 'object',
13876
+ },
13877
+ },
13878
+ createdAt: {
13879
+ type: 'string',
13880
+ format: 'date-time',
13881
+ },
13882
+ updatedAt: {
13883
+ type: 'string',
13884
+ format: 'date-time',
13885
+ },
13886
+ currentValue: {
13887
+ type: 'object',
13888
+ },
13889
+ },
13890
+ },
13891
+ },
13892
+ },
13893
+ tags: [
13894
+ {
13895
+ name: 'Books',
13896
+ description: 'Operations related to books and pipelines',
13897
+ },
13898
+ {
13899
+ name: 'Executions',
13900
+ description: 'Operations related to execution tasks',
13901
+ },
13902
+ {
13903
+ name: 'Authentication',
13904
+ description: 'Authentication operations',
13905
+ },
13906
+ ],
13357
13907
  };
13358
13908
  /**
13359
13909
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -13998,7 +14548,7 @@
13998
14548
  }
13999
14549
  }
14000
14550
  if (filename.endsWith('.bookc')) {
14001
- pipeline = JSON.parse(await promises.readFile(filename, 'utf-8'));
14551
+ pipeline = jsonParse(await promises.readFile(filename, 'utf-8'));
14002
14552
  }
14003
14553
  else {
14004
14554
  if (isVerbose) {
@@ -14107,6 +14657,37 @@
14107
14657
  * Note: [🟡] Code in this file should never be published outside of `@promptbook/cli`
14108
14658
  */
14109
14659
 
14660
+ /**
14661
+ * How is the model provider trusted?
14662
+ *
14663
+ * @public exported from `@promptbook/core`
14664
+ */
14665
+ // <- TODO: Maybe do better levels of trust
14666
+ /**
14667
+ * How is the model provider important?
14668
+ *
14669
+ * @public exported from `@promptbook/core`
14670
+ */
14671
+ const MODEL_ORDER = {
14672
+ /**
14673
+ * Top-tier models, e.g. OpenAI, Anthropic,...
14674
+ */
14675
+ TOP_TIER: 333,
14676
+ /**
14677
+ * Mid-tier models, e.g. Llama, Mistral, etc.
14678
+ */
14679
+ NORMAL: 100,
14680
+ /**
14681
+ * Low-tier models, e.g. Phi, Tiny, etc.
14682
+ */
14683
+ LOW_TIER: 0,
14684
+ };
14685
+ /**
14686
+ * TODO: Add configuration schema and maybe some documentation link
14687
+ * TODO: Maybe constrain LlmToolsConfiguration[number] by generic to ensure that `createConfigurationFromEnv` and `getBoilerplateConfiguration` always create same `packageName` and `className`
14688
+ * TODO: [®] DRY Register logic
14689
+ */
14690
+
14110
14691
  /**
14111
14692
  * Registration of LLM provider metadata
14112
14693
  *
@@ -14121,9 +14702,11 @@
14121
14702
  packageName: '@promptbook/anthropic-claude',
14122
14703
  className: 'AnthropicClaudeExecutionTools',
14123
14704
  envVariables: ['ANTHROPIC_CLAUDE_API_KEY'],
14705
+ trustLevel: 'CLOSED',
14706
+ order: MODEL_ORDER.TOP_TIER,
14124
14707
  getBoilerplateConfiguration() {
14125
14708
  return {
14126
- title: 'Anthropic Claude (boilerplate)',
14709
+ title: 'Anthropic Claude',
14127
14710
  packageName: '@promptbook/anthropic-claude',
14128
14711
  className: 'AnthropicClaudeExecutionTools',
14129
14712
  options: {
@@ -14177,6 +14760,7 @@
14177
14760
  modelVariant: 'CHAT',
14178
14761
  modelTitle: 'Claude 3.5 Sonnet',
14179
14762
  modelName: 'claude-3-5-sonnet-20240620',
14763
+ modelDescription: 'Latest Claude model with great reasoning, coding, and language understanding capabilities. 200K context window. Optimized balance of intelligence and speed.',
14180
14764
  pricing: {
14181
14765
  prompt: computeUsage(`$3.00 / 1M tokens`),
14182
14766
  output: computeUsage(`$15.00 / 1M tokens`),
@@ -14186,6 +14770,7 @@
14186
14770
  modelVariant: 'CHAT',
14187
14771
  modelTitle: 'Claude 3 Opus',
14188
14772
  modelName: 'claude-3-opus-20240229',
14773
+ modelDescription: 'Most capable Claude model excelling at complex reasoning, coding, and detailed instruction following. 200K context window. Best for sophisticated tasks requiring nuanced understanding.',
14189
14774
  pricing: {
14190
14775
  prompt: computeUsage(`$15.00 / 1M tokens`),
14191
14776
  output: computeUsage(`$75.00 / 1M tokens`),
@@ -14195,6 +14780,7 @@
14195
14780
  modelVariant: 'CHAT',
14196
14781
  modelTitle: 'Claude 3 Sonnet',
14197
14782
  modelName: 'claude-3-sonnet-20240229',
14783
+ modelDescription: 'Strong general-purpose model with excellent performance across reasoning, conversation, and coding tasks. 200K context window. Good balance of intelligence and cost-efficiency.',
14198
14784
  pricing: {
14199
14785
  prompt: computeUsage(`$3.00 / 1M tokens`),
14200
14786
  output: computeUsage(`$15.00 / 1M tokens`),
@@ -14204,6 +14790,7 @@
14204
14790
  modelVariant: 'CHAT',
14205
14791
  modelTitle: 'Claude 3 Haiku',
14206
14792
  modelName: ' claude-3-haiku-20240307',
14793
+ modelDescription: 'Fastest and most compact Claude model optimized for responsiveness in interactive applications. 200K context window. Excellent for quick responses and lightweight applications.',
14207
14794
  pricing: {
14208
14795
  prompt: computeUsage(`$0.25 / 1M tokens`),
14209
14796
  output: computeUsage(`$1.25 / 1M tokens`),
@@ -14213,6 +14800,7 @@
14213
14800
  modelVariant: 'CHAT',
14214
14801
  modelTitle: 'Claude 2.1',
14215
14802
  modelName: 'claude-2.1',
14803
+ modelDescription: 'Improved version of Claude 2 with better performance across reasoning and truthfulness. 100K context window. Legacy model with strong reliability.',
14216
14804
  pricing: {
14217
14805
  prompt: computeUsage(`$8.00 / 1M tokens`),
14218
14806
  output: computeUsage(`$24.00 / 1M tokens`),
@@ -14222,6 +14810,7 @@
14222
14810
  modelVariant: 'CHAT',
14223
14811
  modelTitle: 'Claude 2',
14224
14812
  modelName: 'claude-2.0',
14813
+ modelDescription: 'Legacy model with strong general reasoning and language capabilities. 100K context window. Superseded by newer Claude 3 models.',
14225
14814
  pricing: {
14226
14815
  prompt: computeUsage(`$8.00 / 1M tokens`),
14227
14816
  output: computeUsage(`$24.00 / 1M tokens`),
@@ -14229,8 +14818,9 @@
14229
14818
  },
14230
14819
  {
14231
14820
  modelVariant: 'CHAT',
14232
- modelTitle: ' Claude Instant 1.2',
14821
+ modelTitle: 'Claude Instant 1.2',
14233
14822
  modelName: 'claude-instant-1.2',
14823
+ modelDescription: 'Older, faster Claude model optimized for high throughput applications. Lower cost but less capable than newer models. 100K context window.',
14234
14824
  pricing: {
14235
14825
  prompt: computeUsage(`$0.80 / 1M tokens`),
14236
14826
  output: computeUsage(`$2.40 / 1M tokens`),
@@ -14240,6 +14830,7 @@
14240
14830
  modelVariant: 'CHAT',
14241
14831
  modelTitle: 'Claude 3.7 Sonnet',
14242
14832
  modelName: 'claude-3-7-sonnet-20250219',
14833
+ modelDescription: 'Latest generation Claude model with advanced reasoning and language understanding. Enhanced capabilities over 3.5 with improved domain knowledge. 200K context window.',
14243
14834
  pricing: {
14244
14835
  prompt: computeUsage(`$3.00 / 1M tokens`),
14245
14836
  output: computeUsage(`$15.00 / 1M tokens`),
@@ -14249,6 +14840,7 @@
14249
14840
  modelVariant: 'CHAT',
14250
14841
  modelTitle: 'Claude 3.5 Haiku',
14251
14842
  modelName: 'claude-3-5-haiku-20241022',
14843
+ modelDescription: 'Fast and efficient Claude 3.5 variant optimized for speed and cost-effectiveness. Great for interactive applications requiring quick responses. 200K context window.',
14252
14844
  pricing: {
14253
14845
  prompt: computeUsage(`$0.25 / 1M tokens`),
14254
14846
  output: computeUsage(`$1.25 / 1M tokens`),
@@ -14650,9 +15242,11 @@
14650
15242
  packageName: '@promptbook/azure-openai',
14651
15243
  className: 'AzureOpenAiExecutionTools',
14652
15244
  envVariables: ['AZUREOPENAI_RESOURCE_NAME', 'AZUREOPENAI_DEPLOYMENT_NAME', 'AZUREOPENAI_API_KEY'],
15245
+ trustLevel: 'CLOSED_BUSINESS',
15246
+ order: MODEL_ORDER.NORMAL,
14653
15247
  getBoilerplateConfiguration() {
14654
15248
  return {
14655
- title: 'Azure Open AI (boilerplate)',
15249
+ title: 'Azure Open AI',
14656
15250
  packageName: '@promptbook/azure-openai',
14657
15251
  className: 'AzureOpenAiExecutionTools',
14658
15252
  options: {
@@ -14733,9 +15327,10 @@
14733
15327
  modelVariant: 'COMPLETION',
14734
15328
  modelTitle: 'davinci-002',
14735
15329
  modelName: 'davinci-002',
15330
+ modelDescription: 'Legacy completion model with strong performance on text generation tasks. Optimized for complex instructions and longer outputs.',
14736
15331
  pricing: {
14737
15332
  prompt: computeUsage(`$2.00 / 1M tokens`),
14738
- output: computeUsage(`$2.00 / 1M tokens`), // <- not sure
15333
+ output: computeUsage(`$2.00 / 1M tokens`),
14739
15334
  },
14740
15335
  },
14741
15336
  /**/
@@ -14750,6 +15345,7 @@
14750
15345
  modelVariant: 'CHAT',
14751
15346
  modelTitle: 'gpt-3.5-turbo-16k',
14752
15347
  modelName: 'gpt-3.5-turbo-16k',
15348
+ modelDescription: 'GPT-3.5 Turbo with extended 16k token context length for handling longer conversations and documents.',
14753
15349
  pricing: {
14754
15350
  prompt: computeUsage(`$3.00 / 1M tokens`),
14755
15351
  output: computeUsage(`$4.00 / 1M tokens`),
@@ -14773,6 +15369,7 @@
14773
15369
  modelVariant: 'CHAT',
14774
15370
  modelTitle: 'gpt-4',
14775
15371
  modelName: 'gpt-4',
15372
+ modelDescription: 'GPT-4 is a powerful language model with enhanced reasoning, instruction-following capabilities, and 8K context window. Optimized for complex tasks requiring deep understanding.',
14776
15373
  pricing: {
14777
15374
  prompt: computeUsage(`$30.00 / 1M tokens`),
14778
15375
  output: computeUsage(`$60.00 / 1M tokens`),
@@ -14784,6 +15381,7 @@
14784
15381
  modelVariant: 'CHAT',
14785
15382
  modelTitle: 'gpt-4-32k',
14786
15383
  modelName: 'gpt-4-32k',
15384
+ modelDescription: 'Extended context version of GPT-4 with a 32K token window for processing very long inputs and generating comprehensive responses for complex tasks.',
14787
15385
  pricing: {
14788
15386
  prompt: computeUsage(`$60.00 / 1M tokens`),
14789
15387
  output: computeUsage(`$120.00 / 1M tokens`),
@@ -14806,6 +15404,7 @@
14806
15404
  modelVariant: 'CHAT',
14807
15405
  modelTitle: 'gpt-4-turbo-2024-04-09',
14808
15406
  modelName: 'gpt-4-turbo-2024-04-09',
15407
+ modelDescription: 'Latest stable GPT-4 Turbo model from April 2024 with enhanced reasoning and context handling capabilities. Offers 128K context window and improved performance.',
14809
15408
  pricing: {
14810
15409
  prompt: computeUsage(`$10.00 / 1M tokens`),
14811
15410
  output: computeUsage(`$30.00 / 1M tokens`),
@@ -14817,6 +15416,7 @@
14817
15416
  modelVariant: 'CHAT',
14818
15417
  modelTitle: 'gpt-3.5-turbo-1106',
14819
15418
  modelName: 'gpt-3.5-turbo-1106',
15419
+ modelDescription: 'November 2023 version of GPT-3.5 Turbo with improved instruction following and a 16K token context window.',
14820
15420
  pricing: {
14821
15421
  prompt: computeUsage(`$1.00 / 1M tokens`),
14822
15422
  output: computeUsage(`$2.00 / 1M tokens`),
@@ -14828,6 +15428,7 @@
14828
15428
  modelVariant: 'CHAT',
14829
15429
  modelTitle: 'gpt-4-turbo',
14830
15430
  modelName: 'gpt-4-turbo',
15431
+ modelDescription: 'More capable model than GPT-4 with improved instruction following, function calling and a 128K token context window for handling very large documents.',
14831
15432
  pricing: {
14832
15433
  prompt: computeUsage(`$10.00 / 1M tokens`),
14833
15434
  output: computeUsage(`$30.00 / 1M tokens`),
@@ -14839,6 +15440,7 @@
14839
15440
  modelVariant: 'COMPLETION',
14840
15441
  modelTitle: 'gpt-3.5-turbo-instruct-0914',
14841
15442
  modelName: 'gpt-3.5-turbo-instruct-0914',
15443
+ modelDescription: 'September 2023 version of GPT-3.5 Turbo optimized for completion-style instruction following with a 4K context window.',
14842
15444
  pricing: {
14843
15445
  prompt: computeUsage(`$1.50 / 1M tokens`),
14844
15446
  output: computeUsage(`$2.00 / 1M tokens`), // <- For gpt-3.5-turbo-instruct
@@ -14850,6 +15452,7 @@
14850
15452
  modelVariant: 'COMPLETION',
14851
15453
  modelTitle: 'gpt-3.5-turbo-instruct',
14852
15454
  modelName: 'gpt-3.5-turbo-instruct',
15455
+ modelDescription: 'Optimized version of GPT-3.5 for completion-style API with good instruction following and a 4K token context window.',
14853
15456
  pricing: {
14854
15457
  prompt: computeUsage(`$1.50 / 1M tokens`),
14855
15458
  output: computeUsage(`$2.00 / 1M tokens`),
@@ -14867,9 +15470,10 @@
14867
15470
  modelVariant: 'CHAT',
14868
15471
  modelTitle: 'gpt-3.5-turbo',
14869
15472
  modelName: 'gpt-3.5-turbo',
15473
+ modelDescription: 'Latest version of GPT-3.5 Turbo with improved performance and instruction following capabilities. Default 4K context window with options for 16K.',
14870
15474
  pricing: {
14871
- prompt: computeUsage(`$3.00 / 1M tokens`),
14872
- output: computeUsage(`$6.00 / 1M tokens`), // <- Not sure, refer to gpt-3.5-turbo in Fine-tuning models
15475
+ prompt: computeUsage(`$0.50 / 1M tokens`),
15476
+ output: computeUsage(`$1.50 / 1M tokens`),
14873
15477
  },
14874
15478
  },
14875
15479
  /**/
@@ -14878,6 +15482,7 @@
14878
15482
  modelVariant: 'CHAT',
14879
15483
  modelTitle: 'gpt-3.5-turbo-0301',
14880
15484
  modelName: 'gpt-3.5-turbo-0301',
15485
+ modelDescription: 'March 2023 version of GPT-3.5 Turbo with a 4K token context window. Legacy model maintained for backward compatibility.',
14881
15486
  pricing: {
14882
15487
  prompt: computeUsage(`$1.50 / 1M tokens`),
14883
15488
  output: computeUsage(`$2.00 / 1M tokens`),
@@ -14889,9 +15494,10 @@
14889
15494
  modelVariant: 'COMPLETION',
14890
15495
  modelTitle: 'babbage-002',
14891
15496
  modelName: 'babbage-002',
15497
+ modelDescription: 'Efficient legacy completion model with a good balance of performance and speed. Suitable for straightforward text generation tasks.',
14892
15498
  pricing: {
14893
15499
  prompt: computeUsage(`$0.40 / 1M tokens`),
14894
- output: computeUsage(`$0.40 / 1M tokens`), // <- Not sure
15500
+ output: computeUsage(`$0.40 / 1M tokens`),
14895
15501
  },
14896
15502
  },
14897
15503
  /**/
@@ -14900,6 +15506,7 @@
14900
15506
  modelVariant: 'CHAT',
14901
15507
  modelTitle: 'gpt-4-1106-preview',
14902
15508
  modelName: 'gpt-4-1106-preview',
15509
+ modelDescription: 'November 2023 preview version of GPT-4 Turbo with improved instruction following and a 128K token context window.',
14903
15510
  pricing: {
14904
15511
  prompt: computeUsage(`$10.00 / 1M tokens`),
14905
15512
  output: computeUsage(`$30.00 / 1M tokens`),
@@ -14911,6 +15518,7 @@
14911
15518
  modelVariant: 'CHAT',
14912
15519
  modelTitle: 'gpt-4-0125-preview',
14913
15520
  modelName: 'gpt-4-0125-preview',
15521
+ modelDescription: 'January 2024 preview version of GPT-4 Turbo with improved reasoning capabilities and a 128K token context window.',
14914
15522
  pricing: {
14915
15523
  prompt: computeUsage(`$10.00 / 1M tokens`),
14916
15524
  output: computeUsage(`$30.00 / 1M tokens`),
@@ -14928,6 +15536,7 @@
14928
15536
  modelVariant: 'CHAT',
14929
15537
  modelTitle: 'gpt-3.5-turbo-0125',
14930
15538
  modelName: 'gpt-3.5-turbo-0125',
15539
+ modelDescription: 'January 2024 version of GPT-3.5 Turbo with improved reasoning capabilities and a 16K token context window.',
14931
15540
  pricing: {
14932
15541
  prompt: computeUsage(`$0.50 / 1M tokens`),
14933
15542
  output: computeUsage(`$1.50 / 1M tokens`),
@@ -14939,9 +15548,10 @@
14939
15548
  modelVariant: 'CHAT',
14940
15549
  modelTitle: 'gpt-4-turbo-preview',
14941
15550
  modelName: 'gpt-4-turbo-preview',
15551
+ modelDescription: 'Preview version of GPT-4 Turbo that points to the latest model version. Features improved instruction following, 128K token context window and lower latency.',
14942
15552
  pricing: {
14943
15553
  prompt: computeUsage(`$10.00 / 1M tokens`),
14944
- output: computeUsage(`$30.00 / 1M tokens`), // <- Not sure, just for gpt-4-turbo
15554
+ output: computeUsage(`$30.00 / 1M tokens`),
14945
15555
  },
14946
15556
  },
14947
15557
  /**/
@@ -14950,6 +15560,7 @@
14950
15560
  modelVariant: 'EMBEDDING',
14951
15561
  modelTitle: 'text-embedding-3-large',
14952
15562
  modelName: 'text-embedding-3-large',
15563
+ modelDescription: "OpenAI's most capable text embedding model designed for high-quality embeddings for complex similarity tasks and information retrieval.",
14953
15564
  pricing: {
14954
15565
  prompt: computeUsage(`$0.13 / 1M tokens`),
14955
15566
  // TODO: [🏏] Leverage the batch API @see https://platform.openai.com/docs/guides/batch
@@ -14962,6 +15573,7 @@
14962
15573
  modelVariant: 'EMBEDDING',
14963
15574
  modelTitle: 'text-embedding-3-small',
14964
15575
  modelName: 'text-embedding-3-small',
15576
+ modelDescription: 'Cost-effective embedding model with good performance for simpler tasks like text similarity and retrieval. Good balance of quality and efficiency.',
14965
15577
  pricing: {
14966
15578
  prompt: computeUsage(`$0.02 / 1M tokens`),
14967
15579
  // TODO: [🏏] Leverage the batch API @see https://platform.openai.com/docs/guides/batch
@@ -14974,6 +15586,7 @@
14974
15586
  modelVariant: 'CHAT',
14975
15587
  modelTitle: 'gpt-3.5-turbo-0613',
14976
15588
  modelName: 'gpt-3.5-turbo-0613',
15589
+ modelDescription: 'June 2023 version of GPT-3.5 Turbo with function calling capabilities and a 4K token context window.',
14977
15590
  pricing: {
14978
15591
  prompt: computeUsage(`$1.50 / 1M tokens`),
14979
15592
  output: computeUsage(`$2.00 / 1M tokens`),
@@ -14985,6 +15598,7 @@
14985
15598
  modelVariant: 'EMBEDDING',
14986
15599
  modelTitle: 'text-embedding-ada-002',
14987
15600
  modelName: 'text-embedding-ada-002',
15601
+ modelDescription: 'Legacy text embedding model suitable for text similarity and retrieval augmented generation use cases. Replaced by newer embedding-3 models.',
14988
15602
  pricing: {
14989
15603
  prompt: computeUsage(`$0.1 / 1M tokens`),
14990
15604
  // TODO: [🏏] Leverage the batch API @see https://platform.openai.com/docs/guides/batch
@@ -15015,6 +15629,7 @@
15015
15629
  modelVariant: 'CHAT',
15016
15630
  modelTitle: 'gpt-4o-2024-05-13',
15017
15631
  modelName: 'gpt-4o-2024-05-13',
15632
+ modelDescription: 'May 2024 version of GPT-4o with enhanced multimodal capabilities, improved reasoning, and optimized for vision, audio and chat at lower latencies.',
15018
15633
  pricing: {
15019
15634
  prompt: computeUsage(`$5.00 / 1M tokens`),
15020
15635
  output: computeUsage(`$15.00 / 1M tokens`),
@@ -15026,6 +15641,7 @@
15026
15641
  modelVariant: 'CHAT',
15027
15642
  modelTitle: 'gpt-4o',
15028
15643
  modelName: 'gpt-4o',
15644
+ modelDescription: "OpenAI's most advanced multimodal model optimized for performance, speed, and cost. Capable of vision, reasoning, and high quality text generation.",
15029
15645
  pricing: {
15030
15646
  prompt: computeUsage(`$5.00 / 1M tokens`),
15031
15647
  output: computeUsage(`$15.00 / 1M tokens`),
@@ -15037,6 +15653,7 @@
15037
15653
  modelVariant: 'CHAT',
15038
15654
  modelTitle: 'gpt-4o-mini',
15039
15655
  modelName: 'gpt-4o-mini',
15656
+ modelDescription: 'Smaller, more cost-effective version of GPT-4o with good performance across text, vision, and audio tasks at reduced complexity.',
15040
15657
  pricing: {
15041
15658
  prompt: computeUsage(`$3.00 / 1M tokens`),
15042
15659
  output: computeUsage(`$9.00 / 1M tokens`),
@@ -15048,6 +15665,7 @@
15048
15665
  modelVariant: 'CHAT',
15049
15666
  modelTitle: 'o1-preview',
15050
15667
  modelName: 'o1-preview',
15668
+ modelDescription: 'Advanced reasoning model with exceptional performance on complex logical, mathematical, and analytical tasks. Built for deep reasoning and specialized professional tasks.',
15051
15669
  pricing: {
15052
15670
  prompt: computeUsage(`$15.00 / 1M tokens`),
15053
15671
  output: computeUsage(`$60.00 / 1M tokens`),
@@ -15059,6 +15677,7 @@
15059
15677
  modelVariant: 'CHAT',
15060
15678
  modelTitle: 'o1-preview-2024-09-12',
15061
15679
  modelName: 'o1-preview-2024-09-12',
15680
+ modelDescription: 'September 2024 version of O1 preview with specialized reasoning capabilities for complex tasks requiring precise analytical thinking.',
15062
15681
  // <- TODO: [💩] Some better system to organize theese date suffixes and versions
15063
15682
  pricing: {
15064
15683
  prompt: computeUsage(`$15.00 / 1M tokens`),
@@ -15071,6 +15690,7 @@
15071
15690
  modelVariant: 'CHAT',
15072
15691
  modelTitle: 'o1-mini',
15073
15692
  modelName: 'o1-mini',
15693
+ modelDescription: 'Smaller, cost-effective version of the O1 model with good performance on reasoning tasks while maintaining efficiency for everyday analytical use.',
15074
15694
  pricing: {
15075
15695
  prompt: computeUsage(`$3.00 / 1M tokens`),
15076
15696
  output: computeUsage(`$12.00 / 1M tokens`),
@@ -15082,10 +15702,10 @@
15082
15702
  modelVariant: 'CHAT',
15083
15703
  modelTitle: 'o1',
15084
15704
  modelName: 'o1',
15705
+ modelDescription: "OpenAI's advanced reasoning model focused on logic and problem-solving. Designed for complex analytical tasks with rigorous step-by-step reasoning. 128K context window.",
15085
15706
  pricing: {
15086
- prompt: computeUsage(`$3.00 / 1M tokens`),
15087
- output: computeUsage(`$12.00 / 1M tokens`),
15088
- // <- TODO: !! Unsure, check the pricing
15707
+ prompt: computeUsage(`$15.00 / 1M tokens`),
15708
+ output: computeUsage(`$60.00 / 1M tokens`),
15089
15709
  },
15090
15710
  },
15091
15711
  /**/
@@ -15094,6 +15714,7 @@
15094
15714
  modelVariant: 'CHAT',
15095
15715
  modelTitle: 'o3-mini',
15096
15716
  modelName: 'o3-mini',
15717
+ modelDescription: 'Cost-effective reasoning model optimized for academic and scientific problem-solving. Efficient performance on STEM tasks with deep mathematical and scientific knowledge. 128K context window.',
15097
15718
  pricing: {
15098
15719
  prompt: computeUsage(`$3.00 / 1M tokens`),
15099
15720
  output: computeUsage(`$12.00 / 1M tokens`),
@@ -15106,6 +15727,7 @@
15106
15727
  modelVariant: 'CHAT',
15107
15728
  modelTitle: 'o1-mini-2024-09-12',
15108
15729
  modelName: 'o1-mini-2024-09-12',
15730
+ modelDescription: "September 2024 version of O1-mini with balanced reasoning capabilities and cost-efficiency. Good for analytical tasks that don't require the full O1 model.",
15109
15731
  pricing: {
15110
15732
  prompt: computeUsage(`$3.00 / 1M tokens`),
15111
15733
  output: computeUsage(`$12.00 / 1M tokens`),
@@ -15117,6 +15739,7 @@
15117
15739
  modelVariant: 'CHAT',
15118
15740
  modelTitle: 'gpt-3.5-turbo-16k-0613',
15119
15741
  modelName: 'gpt-3.5-turbo-16k-0613',
15742
+ modelDescription: 'June 2023 version of GPT-3.5 Turbo with extended 16k token context window for processing longer conversations and documents.',
15120
15743
  pricing: {
15121
15744
  prompt: computeUsage(`$3.00 / 1M tokens`),
15122
15745
  output: computeUsage(`$4.00 / 1M tokens`),
@@ -15141,6 +15764,9 @@
15141
15764
  * Note: [💞] Ignore a discrepancy between file name and entity name
15142
15765
  */
15143
15766
 
15767
+ // Default rate limits (requests per minute) - adjust as needed based on Azure OpenAI tier
15768
+ const DEFAULT_RPM$1 = 60;
15769
+ // <- TODO: !!! Put in some better place
15144
15770
  /**
15145
15771
  * Execution Tools for calling Azure OpenAI API.
15146
15772
  *
@@ -15158,6 +15784,10 @@
15158
15784
  * OpenAI Azure API client.
15159
15785
  */
15160
15786
  this.client = null;
15787
+ // TODO: Allow configuring rate limits via options
15788
+ this.limiter = new Bottleneck__default["default"]({
15789
+ minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_RPM$1),
15790
+ });
15161
15791
  }
15162
15792
  get title() {
15163
15793
  return 'Azure OpenAI';
@@ -15235,7 +15865,9 @@
15235
15865
  console.info(colors__default["default"].bgWhite('messages'), JSON.stringify(messages, null, 4));
15236
15866
  }
15237
15867
  const rawRequest = [modelName, messages, modelSettings];
15238
- const rawResponse = await this.withTimeout(client.getChatCompletions(...rawRequest)).catch((error) => {
15868
+ const rawResponse = await this.limiter
15869
+ .schedule(() => this.withTimeout(client.getChatCompletions(...rawRequest)))
15870
+ .catch((error) => {
15239
15871
  if (this.options.isVerbose) {
15240
15872
  console.info(colors__default["default"].bgRed('error'), error);
15241
15873
  }
@@ -15331,7 +15963,9 @@
15331
15963
  [rawPromptContent],
15332
15964
  modelSettings,
15333
15965
  ];
15334
- const rawResponse = await this.withTimeout(client.getCompletions(...rawRequest)).catch((error) => {
15966
+ const rawResponse = await this.limiter
15967
+ .schedule(() => this.withTimeout(client.getCompletions(...rawRequest)))
15968
+ .catch((error) => {
15335
15969
  if (this.options.isVerbose) {
15336
15970
  console.info(colors__default["default"].bgRed('error'), error);
15337
15971
  }
@@ -15471,9 +16105,11 @@
15471
16105
  packageName: '@promptbook/deepseek',
15472
16106
  className: 'DeepseekExecutionTools',
15473
16107
  envVariables: ['DEEPSEEK_GENERATIVE_AI_API_KEY'],
16108
+ trustLevel: 'UNTRUSTED',
16109
+ order: MODEL_ORDER.NORMAL,
15474
16110
  getBoilerplateConfiguration() {
15475
16111
  return {
15476
- title: 'Deepseek (boilerplate)',
16112
+ title: 'Deepseek',
15477
16113
  packageName: '@promptbook/deepseek',
15478
16114
  className: 'DeepseekExecutionTools',
15479
16115
  options: {
@@ -15670,6 +16306,67 @@
15670
16306
  };
15671
16307
  }
15672
16308
 
16309
+ /**
16310
+ * List of available Deepseek models with descriptions
16311
+ *
16312
+ * Note: Done at 2025-04-22
16313
+ *
16314
+ * @see https://www.deepseek.com/models
16315
+ * @public exported from `@promptbook/deepseek`
16316
+ */
16317
+ const DEEPSEEK_MODELS = exportJson({
16318
+ name: 'DEEPSEEK_MODELS',
16319
+ value: [
16320
+ {
16321
+ modelVariant: 'CHAT',
16322
+ modelTitle: 'Deepseek Chat',
16323
+ modelName: 'deepseek-chat',
16324
+ modelDescription: 'General-purpose language model with strong performance across conversation, reasoning, and content generation. 128K context window with excellent instruction following capabilities.',
16325
+ pricing: {
16326
+ prompt: computeUsage(`$1.00 / 1M tokens`),
16327
+ output: computeUsage(`$2.00 / 1M tokens`),
16328
+ },
16329
+ },
16330
+ {
16331
+ modelVariant: 'CHAT',
16332
+ modelTitle: 'Deepseek Reasoner',
16333
+ modelName: 'deepseek-reasoner',
16334
+ modelDescription: 'Specialized model focused on complex reasoning tasks like mathematical problem-solving and logical analysis. Enhanced step-by-step reasoning with explicit chain-of-thought processes. 128K context window.',
16335
+ pricing: {
16336
+ prompt: computeUsage(`$4.00 / 1M tokens`),
16337
+ output: computeUsage(`$8.00 / 1M tokens`),
16338
+ },
16339
+ },
16340
+ {
16341
+ modelVariant: 'CHAT',
16342
+ modelTitle: 'DeepSeek V3',
16343
+ modelName: 'deepseek-v3-0324',
16344
+ modelDescription: 'Advanced general-purpose model with improved reasoning, coding abilities, and multimodal understanding. Built on the latest DeepSeek architecture with enhanced knowledge representation.',
16345
+ pricing: {
16346
+ prompt: computeUsage(`$1.50 / 1M tokens`),
16347
+ output: computeUsage(`$3.00 / 1M tokens`),
16348
+ },
16349
+ },
16350
+ {
16351
+ modelVariant: 'CHAT',
16352
+ modelTitle: 'DeepSeek R1',
16353
+ modelName: 'deepseek-r1',
16354
+ modelDescription: 'Research-focused model optimized for scientific problem-solving and analytical tasks. Excellent performance on tasks requiring domain-specific expertise and critical thinking.',
16355
+ pricing: {
16356
+ prompt: computeUsage(`$5.00 / 1M tokens`),
16357
+ output: computeUsage(`$10.00 / 1M tokens`),
16358
+ },
16359
+ },
16360
+ // <- [🕕]
16361
+ ],
16362
+ });
16363
+ /**
16364
+ * TODO: [🧠] Add information about context window sizes, capabilities, and relative performance characteristics
16365
+ * TODO: [🎰] Some mechanism to auto-update available models
16366
+ * TODO: [🧠] Verify pricing information is current with Deepseek's official documentation
16367
+ * Note: [💞] Ignore a discrepancy between file name and entity name
16368
+ */
16369
+
15673
16370
  /**
15674
16371
  * Execution Tools for calling Deepseek API.
15675
16372
  *
@@ -15691,18 +16388,7 @@
15691
16388
  title: 'Deepseek',
15692
16389
  description: 'Implementation of Deepseek models',
15693
16390
  vercelProvider: deepseekVercelProvider,
15694
- availableModels: [
15695
- {
15696
- modelName: 'deepseek-chat',
15697
- modelVariant: 'CHAT',
15698
- },
15699
- {
15700
- modelName: 'deepseek-reasoner',
15701
- modelVariant: 'CHAT',
15702
- },
15703
- // <- [🕕]
15704
- // <- TODO: How picking of the default model looks like in `createExecutionToolsFromVercelProvider`
15705
- ],
16391
+ availableModels: DEEPSEEK_MODELS,
15706
16392
  ...options,
15707
16393
  });
15708
16394
  }, {
@@ -15742,9 +16428,11 @@
15742
16428
  packageName: '@promptbook/google',
15743
16429
  className: 'GoogleExecutionTools',
15744
16430
  envVariables: ['GOOGLE_GENERATIVE_AI_API_KEY'],
16431
+ trustLevel: 'CLOSED',
16432
+ order: MODEL_ORDER.NORMAL,
15745
16433
  getBoilerplateConfiguration() {
15746
16434
  return {
15747
- title: 'Google Gemini (boilerplate)',
16435
+ title: 'Google Gemini',
15748
16436
  packageName: '@promptbook/google',
15749
16437
  className: 'GoogleExecutionTools',
15750
16438
  options: {
@@ -15777,6 +16465,173 @@
15777
16465
  * Note: [💞] Ignore a discrepancy between file name and entity name
15778
16466
  */
15779
16467
 
16468
+ /**
16469
+ * List of available Google models with descriptions
16470
+ *
16471
+ * Note: Done at 2025-04-22
16472
+ *
16473
+ * @see https://ai.google.dev/models/gemini
16474
+ * @public exported from `@promptbook/google`
16475
+ */
16476
+ const GOOGLE_MODELS = exportJson({
16477
+ name: 'GOOGLE_MODELS',
16478
+ value: [
16479
+ {
16480
+ modelVariant: 'CHAT',
16481
+ modelTitle: 'Gemini 2.5 Pro',
16482
+ modelName: 'gemini-2.5-pro-preview-03-25',
16483
+ modelDescription: 'Latest advanced multimodal model with exceptional reasoning, tool use, and instruction following. 1M token context window with improved vision capabilities for complex visual tasks.',
16484
+ pricing: {
16485
+ prompt: computeUsage(`$7.00 / 1M tokens`),
16486
+ output: computeUsage(`$21.00 / 1M tokens`),
16487
+ },
16488
+ },
16489
+ {
16490
+ modelVariant: 'CHAT',
16491
+ modelTitle: 'Gemini 2.0 Flash',
16492
+ modelName: 'gemini-2.0-flash',
16493
+ modelDescription: 'Fast, efficient model optimized for rapid response times. Good balance between performance and cost, with strong capabilities across text, code, and reasoning tasks. 128K context window.',
16494
+ pricing: {
16495
+ prompt: computeUsage(`$0.35 / 1M tokens`),
16496
+ output: computeUsage(`$1.05 / 1M tokens`),
16497
+ },
16498
+ },
16499
+ {
16500
+ modelVariant: 'CHAT',
16501
+ modelTitle: 'Gemini 2.0 Flash Lite',
16502
+ modelName: 'gemini-2.0-flash-lite',
16503
+ modelDescription: 'Streamlined version of Gemini 2.0 Flash, designed for extremely low-latency applications and edge deployments. Optimized for efficiency while maintaining core capabilities.',
16504
+ pricing: {
16505
+ prompt: computeUsage(`$0.20 / 1M tokens`),
16506
+ output: computeUsage(`$0.60 / 1M tokens`),
16507
+ },
16508
+ },
16509
+ {
16510
+ modelVariant: 'CHAT',
16511
+ modelTitle: 'Gemini 2.0 Flash Thinking',
16512
+ modelName: 'gemini-2.0-flash-thinking-exp-01-21',
16513
+ modelDescription: 'Experimental model focused on enhanced reasoning with explicit chain-of-thought processes. Designed for tasks requiring structured thinking and problem-solving approaches.',
16514
+ pricing: {
16515
+ prompt: computeUsage(`$0.35 / 1M tokens`),
16516
+ output: computeUsage(`$1.05 / 1M tokens`),
16517
+ },
16518
+ },
16519
+ {
16520
+ modelVariant: 'CHAT',
16521
+ modelTitle: 'Gemini 1.5 Flash',
16522
+ modelName: 'gemini-1.5-flash',
16523
+ modelDescription: 'Efficient model balancing speed and quality for general-purpose applications. 1M token context window with good multimodal capabilities and quick response times.',
16524
+ pricing: {
16525
+ prompt: computeUsage(`$0.35 / 1M tokens`),
16526
+ output: computeUsage(`$1.05 / 1M tokens`),
16527
+ },
16528
+ },
16529
+ {
16530
+ modelVariant: 'CHAT',
16531
+ modelTitle: 'Gemini 1.5 Flash Latest',
16532
+ modelName: 'gemini-1.5-flash-latest',
16533
+ modelDescription: 'Points to the latest version of Gemini 1.5 Flash, ensuring access to the most recent improvements and bug fixes while maintaining stable interfaces.',
16534
+ },
16535
+ {
16536
+ modelVariant: 'CHAT',
16537
+ modelTitle: 'Gemini 1.5 Flash 001',
16538
+ modelName: 'gemini-1.5-flash-001',
16539
+ modelDescription: 'First stable release of Gemini 1.5 Flash model with reliable performance characteristics for production applications. 1M token context window.',
16540
+ },
16541
+ {
16542
+ modelVariant: 'CHAT',
16543
+ modelTitle: 'Gemini 1.5 Flash 002',
16544
+ modelName: 'gemini-1.5-flash-002',
16545
+ modelDescription: 'Improved version of Gemini 1.5 Flash with enhanced instruction following and more consistent outputs. Refined for better application integration.',
16546
+ },
16547
+ {
16548
+ modelVariant: 'CHAT',
16549
+ modelTitle: 'Gemini 1.5 Flash Exp',
16550
+ modelName: 'gemini-1.5-flash-exp-0827',
16551
+ modelDescription: 'Experimental version of Gemini 1.5 Flash with new capabilities being tested. May offer improved performance but with potential behavior differences from stable releases.',
16552
+ },
16553
+ {
16554
+ modelVariant: 'CHAT',
16555
+ modelTitle: 'Gemini 1.5 Flash 8B',
16556
+ modelName: 'gemini-1.5-flash-8b',
16557
+ modelDescription: 'Compact 8B parameter model optimized for efficiency and deployment in resource-constrained environments. Good performance despite smaller size.',
16558
+ },
16559
+ {
16560
+ modelVariant: 'CHAT',
16561
+ modelTitle: 'Gemini 1.5 Flash 8B Latest',
16562
+ modelName: 'gemini-1.5-flash-8b-latest',
16563
+ modelDescription: 'Points to the most recent version of the compact 8B parameter model, providing latest improvements while maintaining a small footprint.',
16564
+ },
16565
+ {
16566
+ modelVariant: 'CHAT',
16567
+ modelTitle: 'Gemini 1.5 Flash 8B Exp',
16568
+ modelName: 'gemini-1.5-flash-8b-exp-0924',
16569
+ modelDescription: 'Experimental version of the 8B parameter model with new capabilities and optimizations being evaluated for future stable releases.',
16570
+ },
16571
+ {
16572
+ modelVariant: 'CHAT',
16573
+ modelTitle: 'Gemini 1.5 Flash 8B Exp',
16574
+ modelName: 'gemini-1.5-flash-8b-exp-0827',
16575
+ modelDescription: 'August experimental release of the efficient 8B parameter model with specific improvements to reasoning capabilities and response quality.',
16576
+ },
16577
+ {
16578
+ modelVariant: 'CHAT',
16579
+ modelTitle: 'Gemini 1.5 Pro Latest',
16580
+ modelName: 'gemini-1.5-pro-latest',
16581
+ modelDescription: 'Points to the most recent version of the flagship Gemini 1.5 Pro model, ensuring access to the latest capabilities and improvements.',
16582
+ pricing: {
16583
+ prompt: computeUsage(`$7.00 / 1M tokens`),
16584
+ output: computeUsage(`$21.00 / 1M tokens`),
16585
+ },
16586
+ },
16587
+ {
16588
+ modelVariant: 'CHAT',
16589
+ modelTitle: 'Gemini 1.5 Pro',
16590
+ modelName: 'gemini-1.5-pro',
16591
+ modelDescription: 'Flagship multimodal model with strong performance across text, code, vision, and audio tasks. 1M token context window with excellent reasoning capabilities.',
16592
+ pricing: {
16593
+ prompt: computeUsage(`$7.00 / 1M tokens`),
16594
+ output: computeUsage(`$21.00 / 1M tokens`),
16595
+ },
16596
+ },
16597
+ {
16598
+ modelVariant: 'CHAT',
16599
+ modelTitle: 'Gemini 1.5 Pro 001',
16600
+ modelName: 'gemini-1.5-pro-001',
16601
+ modelDescription: 'First stable release of Gemini 1.5 Pro with consistent performance characteristics and reliable behavior for production applications.',
16602
+ },
16603
+ {
16604
+ modelVariant: 'CHAT',
16605
+ modelTitle: 'Gemini 1.5 Pro 002',
16606
+ modelName: 'gemini-1.5-pro-002',
16607
+ modelDescription: 'Refined version of Gemini 1.5 Pro with improved instruction following, better multimodal understanding, and more consistent outputs.',
16608
+ },
16609
+ {
16610
+ modelVariant: 'CHAT',
16611
+ modelTitle: 'Gemini 1.5 Pro Exp',
16612
+ modelName: 'gemini-1.5-pro-exp-0827',
16613
+ modelDescription: 'Experimental version of Gemini 1.5 Pro with new capabilities and optimizations being tested before wider release. May offer improved performance.',
16614
+ },
16615
+ {
16616
+ modelVariant: 'CHAT',
16617
+ modelTitle: 'Gemini 1.0 Pro',
16618
+ modelName: 'gemini-1.0-pro',
16619
+ modelDescription: 'Original Gemini series foundation model with solid multimodal capabilities. 32K context window with good performance on text, code, and basic vision tasks.',
16620
+ pricing: {
16621
+ prompt: computeUsage(`$0.35 / 1M tokens`),
16622
+ output: computeUsage(`$1.05 / 1M tokens`),
16623
+ },
16624
+ },
16625
+ // <- [🕕]
16626
+ ],
16627
+ });
16628
+ /**
16629
+ * TODO: [🧠] Add information about context window sizes, capabilities, and relative performance characteristics
16630
+ * TODO: [🎰] Some mechanism to auto-update available models
16631
+ * TODO: [🧠] Verify pricing information is current with Google's official documentation
16632
+ * Note: [💞] Ignore a discrepancy between file name and entity name
16633
+ */
16634
+
15780
16635
  /**
15781
16636
  * Execution Tools for calling Google Gemini API.
15782
16637
  *
@@ -15798,29 +16653,7 @@
15798
16653
  title: 'Google',
15799
16654
  description: 'Implementation of Google models',
15800
16655
  vercelProvider: googleGeminiVercelProvider,
15801
- availableModels: [
15802
- // TODO: [🕘] Maybe list models in same way as in other providers - in separate file with metadata
15803
- 'gemini-2.5-pro-preview-03-25',
15804
- 'gemini-2.0-flash',
15805
- 'gemini-2.0-flash-lite',
15806
- 'gemini-2.0-flash-thinking-exp-01-21',
15807
- 'gemini-1.5-flash',
15808
- 'gemini-1.5-flash-latest',
15809
- 'gemini-1.5-flash-001',
15810
- 'gemini-1.5-flash-002',
15811
- 'gemini-1.5-flash-exp-0827',
15812
- 'gemini-1.5-flash-8b',
15813
- 'gemini-1.5-flash-8b-latest',
15814
- 'gemini-1.5-flash-8b-exp-0924',
15815
- 'gemini-1.5-flash-8b-exp-0827',
15816
- 'gemini-1.5-pro-latest',
15817
- 'gemini-1.5-pro',
15818
- 'gemini-1.5-pro-001',
15819
- 'gemini-1.5-pro-002',
15820
- 'gemini-1.5-pro-exp-0827',
15821
- 'gemini-1.0-pro',
15822
- // <- [🕕]
15823
- ].map((modelName) => ({ modelName, modelVariant: 'CHAT' })),
16656
+ availableModels: GOOGLE_MODELS,
15824
16657
  ...options,
15825
16658
  });
15826
16659
  }, {
@@ -15860,9 +16693,11 @@
15860
16693
  packageName: '@promptbook/openai',
15861
16694
  className: 'OpenAiExecutionTools',
15862
16695
  envVariables: ['OPENAI_API_KEY'],
16696
+ trustLevel: 'CLOSED',
16697
+ order: MODEL_ORDER.TOP_TIER,
15863
16698
  getBoilerplateConfiguration() {
15864
16699
  return {
15865
- title: 'Open AI (boilerplate)',
16700
+ title: 'Open AI',
15866
16701
  packageName: '@promptbook/openai',
15867
16702
  className: 'OpenAiExecutionTools',
15868
16703
  options: {
@@ -15900,9 +16735,11 @@
15900
16735
  className: 'OpenAiAssistantExecutionTools',
15901
16736
  envVariables: null,
15902
16737
  // <- TODO: ['OPENAI_API_KEY', 'OPENAI_ASSISTANT_ID']
16738
+ trustLevel: 'CLOSED',
16739
+ order: MODEL_ORDER.NORMAL,
15903
16740
  getBoilerplateConfiguration() {
15904
16741
  return {
15905
- title: 'Open AI Assistant (boilerplate)',
16742
+ title: 'Open AI Assistant',
15906
16743
  packageName: '@promptbook/openai',
15907
16744
  className: 'OpenAiAssistantExecutionTools',
15908
16745
  options: {
@@ -15978,6 +16815,9 @@
15978
16815
  * TODO: [🤝] DRY Maybe some common abstraction between `computeOpenAiUsage` and `computeAnthropicClaudeUsage`
15979
16816
  */
15980
16817
 
16818
+ // Default rate limits (requests per minute) - adjust as needed based on OpenAI tier
16819
+ const DEFAULT_RPM = 60;
16820
+ // <- TODO: !!! Put in some better place
15981
16821
  /**
15982
16822
  * Execution Tools for calling OpenAI API
15983
16823
  *
@@ -15995,6 +16835,10 @@
15995
16835
  * OpenAI API client.
15996
16836
  */
15997
16837
  this.client = null;
16838
+ // TODO: Allow configuring rate limits via options
16839
+ this.limiter = new Bottleneck__default["default"]({
16840
+ minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_RPM),
16841
+ });
15998
16842
  }
15999
16843
  get title() {
16000
16844
  return 'OpenAI';
@@ -16098,7 +16942,9 @@
16098
16942
  if (this.options.isVerbose) {
16099
16943
  console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
16100
16944
  }
16101
- const rawResponse = await client.chat.completions.create(rawRequest).catch((error) => {
16945
+ const rawResponse = await this.limiter
16946
+ .schedule(() => client.chat.completions.create(rawRequest))
16947
+ .catch((error) => {
16102
16948
  assertsError(error);
16103
16949
  if (this.options.isVerbose) {
16104
16950
  console.info(colors__default["default"].bgRed('error'), error);
@@ -16175,7 +17021,9 @@
16175
17021
  if (this.options.isVerbose) {
16176
17022
  console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
16177
17023
  }
16178
- const rawResponse = await client.completions.create(rawRequest).catch((error) => {
17024
+ const rawResponse = await this.limiter
17025
+ .schedule(() => client.completions.create(rawRequest))
17026
+ .catch((error) => {
16179
17027
  assertsError(error);
16180
17028
  if (this.options.isVerbose) {
16181
17029
  console.info(colors__default["default"].bgRed('error'), error);
@@ -16239,7 +17087,9 @@
16239
17087
  if (this.options.isVerbose) {
16240
17088
  console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
16241
17089
  }
16242
- const rawResponse = await client.embeddings.create(rawRequest).catch((error) => {
17090
+ const rawResponse = await this.limiter
17091
+ .schedule(() => client.embeddings.create(rawRequest))
17092
+ .catch((error) => {
16243
17093
  assertsError(error);
16244
17094
  if (this.options.isVerbose) {
16245
17095
  console.info(colors__default["default"].bgRed('error'), error);