@promptbook/node 0.81.0-9 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -8
- package/esm/index.es.js +1956 -1790
- package/esm/index.es.js.map +1 -1
- package/esm/typings/books/index.d.ts +38 -0
- package/esm/typings/src/_packages/core.index.d.ts +12 -4
- package/esm/typings/src/_packages/markdown-utils.index.d.ts +2 -2
- package/esm/typings/src/_packages/node.index.d.ts +0 -2
- package/esm/typings/src/_packages/templates.index.d.ts +2 -2
- package/esm/typings/src/_packages/types.index.d.ts +2 -0
- package/esm/typings/src/_packages/utils.index.d.ts +2 -0
- package/esm/typings/src/_packages/wizzard.index.d.ts +44 -0
- package/esm/typings/src/cli/cli-commands/make.d.ts +1 -1
- package/esm/typings/src/cli/cli-commands/run.d.ts +2 -2
- package/esm/typings/src/collection/constructors/createCollectionFromDirectory.d.ts +11 -0
- package/esm/typings/src/collection/constructors/createCollectionFromUrl.d.ts +1 -1
- package/esm/typings/src/commands/index.d.ts +1 -1
- package/esm/typings/src/config.d.ts +3 -3
- package/esm/typings/src/conversion/compilePipeline.d.ts +1 -4
- package/esm/typings/src/conversion/{precompilePipeline.d.ts → parsePipeline.d.ts} +3 -3
- package/esm/typings/src/conversion/prettify/renderPipelineMermaidOptions.d.ts +3 -3
- package/esm/typings/src/conversion/validation/validatePipeline.d.ts +7 -7
- package/esm/typings/src/errors/utils/getErrorReportUrl.d.ts +1 -1
- package/esm/typings/src/formfactors/generator/GeneratorFormfactorDefinition.d.ts +9 -4
- package/esm/typings/src/formfactors/image-generator/ImageGeneratorFormfactorDefinition.d.ts +24 -0
- package/esm/typings/src/formfactors/index.d.ts +31 -9
- package/esm/typings/src/high-level-abstractions/_common/HighLevelAbstraction.d.ts +1 -1
- package/esm/typings/src/high-level-abstractions/index.d.ts +3 -3
- package/esm/typings/src/high-level-abstractions/quick-chatbot/QuickChatbotHla.d.ts +3 -0
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +1 -1
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +1 -1
- package/esm/typings/src/llm-providers/_common/register/{$provideLlmToolsForCli.d.ts → $provideLlmToolsForWizzardOrCli.d.ts} +2 -2
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -1
- package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
- package/esm/typings/src/llm-providers/anthropic-claude/createAnthropicClaudeExecutionTools.d.ts +2 -2
- package/esm/typings/src/llm-providers/anthropic-claude/playground/playground.d.ts +2 -2
- package/esm/typings/src/llm-providers/anthropic-claude/register-configuration.d.ts +1 -0
- package/esm/typings/src/llm-providers/anthropic-claude/register-constructor.d.ts +2 -0
- package/esm/typings/src/llm-providers/azure-openai/register-configuration.d.ts +1 -0
- package/esm/typings/src/llm-providers/azure-openai/register-constructor.d.ts +1 -0
- package/esm/typings/src/llm-providers/google/register-configuration.d.ts +1 -0
- package/esm/typings/src/llm-providers/google/register-constructor.d.ts +1 -0
- package/esm/typings/src/llm-providers/openai/playground/playground.d.ts +1 -1
- package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +2 -0
- package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +2 -0
- package/esm/typings/src/llm-providers/vercel/playground/playground.d.ts +1 -1
- package/esm/typings/src/other/templates/getBookTemplates.d.ts +22 -0
- package/esm/typings/src/personas/preparePersona.d.ts +4 -4
- package/esm/typings/src/pipeline/PipelineString.d.ts +0 -3
- package/esm/typings/src/pipeline/book-notation.d.ts +14 -0
- package/esm/typings/src/pipeline/isValidPipelineString.d.ts +13 -0
- package/esm/typings/src/pipeline/isValidPipelineString.test.d.ts +4 -0
- package/esm/typings/src/pipeline/validatePipelineString.d.ts +14 -0
- package/esm/typings/src/prepare/isPipelinePrepared.d.ts +3 -1
- package/esm/typings/src/prepare/preparePipeline.d.ts +2 -0
- package/esm/typings/src/prepare/prepareTasks.d.ts +1 -1
- package/esm/typings/src/scrapers/_common/Converter.d.ts +1 -0
- package/esm/typings/src/scrapers/_common/Scraper.d.ts +1 -1
- package/esm/typings/src/scrapers/_common/ScraperIntermediateSource.d.ts +3 -0
- package/esm/typings/src/scrapers/_common/register/ScraperAndConverterMetadata.d.ts +2 -0
- package/esm/typings/src/scrapers/_common/utils/scraperFetch.d.ts +3 -0
- package/esm/typings/src/scrapers/document/register-constructor.d.ts +1 -0
- package/esm/typings/src/scrapers/document/register-metadata.d.ts +1 -0
- package/esm/typings/src/scrapers/document-legacy/register-constructor.d.ts +1 -0
- package/esm/typings/src/scrapers/document-legacy/register-metadata.d.ts +1 -0
- package/esm/typings/src/scrapers/markdown/register-constructor.d.ts +1 -0
- package/esm/typings/src/scrapers/markdown/register-metadata.d.ts +1 -0
- package/esm/typings/src/scrapers/pdf/PdfScraper.d.ts +1 -0
- package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/pdf/register-constructor.d.ts +1 -0
- package/esm/typings/src/scrapers/pdf/register-metadata.d.ts +2 -1
- package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +3 -1
- package/esm/typings/src/scrapers/website/register-constructor.d.ts +1 -0
- package/esm/typings/src/scrapers/website/register-metadata.d.ts +1 -0
- package/esm/typings/src/scripting/javascript/JavascriptEvalExecutionTools.test.d.ts +1 -1
- package/esm/typings/src/scripting/javascript/utils/preserve.d.ts +2 -1
- package/esm/typings/src/types/typeAliases.d.ts +8 -2
- package/esm/typings/src/utils/markdown/flattenMarkdown.d.ts +1 -1
- package/esm/typings/src/utils/markdown/{removeContentComments.d.ts → removeMarkdownComments.d.ts} +2 -2
- package/esm/typings/src/utils/organization/$sideEffect.d.ts +9 -0
- package/esm/typings/src/utils/serialization/checkSerializableAsJson.d.ts +1 -1
- package/esm/typings/src/utils/serialization/isSerializableAsJson.d.ts +2 -2
- package/esm/typings/src/utils/validators/filePath/isRootPath.d.ts +12 -0
- package/esm/typings/src/utils/validators/filePath/isRootPath.test.d.ts +4 -0
- package/esm/typings/src/utils/validators/filePath/isValidFilePath.d.ts +3 -0
- package/esm/typings/src/wizzard/$getCompiledBook.d.ts +16 -0
- package/esm/typings/src/wizzard/wizzard.d.ts +51 -7
- package/package.json +2 -2
- package/umd/index.umd.js +1955 -1790
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/other/templates/getBookTemplate.d.ts +0 -21
- package/esm/typings/src/scripting/javascript/utils/unknownToString.d.ts +0 -8
- /package/esm/typings/src/conversion/{precompilePipeline.test.d.ts → parsePipeline.test.d.ts} +0 -0
- /package/esm/typings/src/utils/markdown/{removeContentComments.test.d.ts → removeMarkdownComments.test.d.ts} +0 -0
package/umd/index.umd.js
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
* @generated
|
|
46
46
|
* @see https://github.com/webgptorg/promptbook
|
|
47
47
|
*/
|
|
48
|
-
var PROMPTBOOK_ENGINE_VERSION = '0.81.0-
|
|
48
|
+
var PROMPTBOOK_ENGINE_VERSION = '0.81.0-24';
|
|
49
49
|
/**
|
|
50
50
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
51
51
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
*
|
|
216
216
|
* @public exported from `@promptbook/core`
|
|
217
217
|
*/
|
|
218
|
-
var
|
|
218
|
+
var DEFAULT_BOOK_TITLE = "\u2728 Untitled Book";
|
|
219
219
|
// <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
|
|
220
220
|
/**
|
|
221
221
|
* The maximum number of iterations for a loops
|
|
@@ -326,1412 +326,834 @@
|
|
|
326
326
|
* TODO: [🧠][🧜♂️] Maybe join remoteUrl and path into single value
|
|
327
327
|
*/
|
|
328
328
|
|
|
329
|
-
/**
|
|
330
|
-
* Orders JSON object by keys
|
|
331
|
-
*
|
|
332
|
-
* @returns The same type of object as the input re-ordered
|
|
333
|
-
* @public exported from `@promptbook/utils`
|
|
334
|
-
*/
|
|
335
|
-
function orderJson(options) {
|
|
336
|
-
var value = options.value, order = options.order;
|
|
337
|
-
var orderedValue = __assign(__assign({}, (order === undefined ? {} : Object.fromEntries(order.map(function (key) { return [key, undefined]; })))), value);
|
|
338
|
-
return orderedValue;
|
|
339
|
-
}
|
|
329
|
+
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md",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.md`\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.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md",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.md`\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.md"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book.md",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.md`\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.md"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book.md",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.md`\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.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book.md",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.md`\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.md"}];
|
|
340
330
|
|
|
341
331
|
/**
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
* Note: `$` is used to indicate that this function is not a pure function - it mutates given object
|
|
345
|
-
* Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
|
|
332
|
+
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
346
333
|
*
|
|
347
|
-
* @returns The same object as the input, but deeply frozen
|
|
348
334
|
* @public exported from `@promptbook/utils`
|
|
349
335
|
*/
|
|
350
|
-
function
|
|
351
|
-
var e_1, _a;
|
|
352
|
-
if (Array.isArray(objectValue)) {
|
|
353
|
-
return Object.freeze(objectValue.map(function (item) { return $deepFreeze(item); }));
|
|
354
|
-
}
|
|
355
|
-
var propertyNames = Object.getOwnPropertyNames(objectValue);
|
|
336
|
+
function isValidJsonString(value /* <- [👨⚖️] */) {
|
|
356
337
|
try {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
var value = objectValue[propertyName];
|
|
360
|
-
if (value && typeof value === 'object') {
|
|
361
|
-
$deepFreeze(value);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
338
|
+
JSON.parse(value);
|
|
339
|
+
return true;
|
|
364
340
|
}
|
|
365
|
-
catch (
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
|
|
341
|
+
catch (error) {
|
|
342
|
+
if (!(error instanceof Error)) {
|
|
343
|
+
throw error;
|
|
369
344
|
}
|
|
370
|
-
|
|
345
|
+
if (error.message.includes('Unexpected token')) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
return false;
|
|
371
349
|
}
|
|
372
|
-
Object.freeze(objectValue);
|
|
373
|
-
return objectValue;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
377
|
-
*/
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Make error report URL for the given error
|
|
381
|
-
*
|
|
382
|
-
* @private !!!!!!
|
|
383
|
-
*/
|
|
384
|
-
function getErrorReportUrl(error) {
|
|
385
|
-
var report = {
|
|
386
|
-
title: "\uD83D\uDC1C Error report from ".concat(NAME),
|
|
387
|
-
body: spaceTrim__default["default"](function (block) { return "\n\n\n `".concat(error.name || 'Error', "` has occurred in the [").concat(NAME, "], please look into it @").concat(ADMIN_GITHUB_NAME, ".\n\n ```\n ").concat(block(error.message || '(no error message)'), "\n ```\n\n\n ## More info:\n\n - **Promptbook engine version:** ").concat(PROMPTBOOK_ENGINE_VERSION, "\n - **Book language version:** ").concat(BOOK_LANGUAGE_VERSION, "\n - **Time:** ").concat(new Date().toISOString(), "\n\n <details>\n <summary>Stack trace:</summary>\n\n ## Stack trace:\n\n ```stacktrace\n ").concat(block(error.stack || '(empty)'), "\n ```\n </details>\n\n "); }),
|
|
388
|
-
};
|
|
389
|
-
var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
|
|
390
|
-
reportUrl.searchParams.set('labels', 'bug');
|
|
391
|
-
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
392
|
-
reportUrl.searchParams.set('title', report.title);
|
|
393
|
-
reportUrl.searchParams.set('body', report.body);
|
|
394
|
-
return reportUrl;
|
|
395
350
|
}
|
|
396
351
|
|
|
397
352
|
/**
|
|
398
|
-
* This error
|
|
353
|
+
* This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
|
|
399
354
|
*
|
|
400
355
|
* @public exported from `@promptbook/core`
|
|
401
356
|
*/
|
|
402
|
-
var
|
|
403
|
-
__extends(
|
|
404
|
-
function
|
|
405
|
-
var _this = _super.call(this,
|
|
406
|
-
_this.name = '
|
|
407
|
-
Object.setPrototypeOf(_this,
|
|
357
|
+
var ParseError = /** @class */ (function (_super) {
|
|
358
|
+
__extends(ParseError, _super);
|
|
359
|
+
function ParseError(message) {
|
|
360
|
+
var _this = _super.call(this, message) || this;
|
|
361
|
+
_this.name = 'ParseError';
|
|
362
|
+
Object.setPrototypeOf(_this, ParseError.prototype);
|
|
408
363
|
return _this;
|
|
409
364
|
}
|
|
410
|
-
return
|
|
365
|
+
return ParseError;
|
|
411
366
|
}(Error));
|
|
367
|
+
/**
|
|
368
|
+
* TODO: Maybe split `ParseError` and `ApplyError`
|
|
369
|
+
*/
|
|
412
370
|
|
|
413
371
|
/**
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
417
|
-
* - Almost all primitives are serializable BUT:
|
|
418
|
-
* - `undefined` is not serializable
|
|
419
|
-
* - `NaN` is not serializable
|
|
420
|
-
* - Objects and arrays are serializable if all their properties are serializable
|
|
421
|
-
* - Functions are not serializable
|
|
422
|
-
* - Circular references are not serializable
|
|
423
|
-
* - `Date` objects are not serializable
|
|
424
|
-
* - `Map` and `Set` objects are not serializable
|
|
425
|
-
* - `RegExp` objects are not serializable
|
|
426
|
-
* - `Error` objects are not serializable
|
|
427
|
-
* - `Symbol` objects are not serializable
|
|
428
|
-
* - And much more...
|
|
372
|
+
* Function `validatePipelineString` will validate the if the string is a valid pipeline string
|
|
373
|
+
* It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
|
|
429
374
|
*
|
|
430
|
-
* @
|
|
431
|
-
* @
|
|
375
|
+
* @param {string} pipelineString the candidate for a pipeline string
|
|
376
|
+
* @returns {PipelineString} the same string as input, but validated as valid
|
|
377
|
+
* @throws {ParseError} if the string is not a valid pipeline string
|
|
378
|
+
* @public exported from `@promptbook/core`
|
|
432
379
|
*/
|
|
433
|
-
function
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (value === undefined) {
|
|
437
|
-
throw new UnexpectedError("".concat(name, " is undefined"));
|
|
438
|
-
}
|
|
439
|
-
else if (value === null) {
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
else if (typeof value === 'boolean') {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
else if (typeof value === 'number' && !isNaN(value)) {
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
else if (typeof value === 'string') {
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
else if (typeof value === 'symbol') {
|
|
452
|
-
throw new UnexpectedError("".concat(name, " is symbol"));
|
|
453
|
-
}
|
|
454
|
-
else if (typeof value === 'function') {
|
|
455
|
-
throw new UnexpectedError("".concat(name, " is function"));
|
|
456
|
-
}
|
|
457
|
-
else if (typeof value === 'object' && Array.isArray(value)) {
|
|
458
|
-
for (var i = 0; i < value.length; i++) {
|
|
459
|
-
checkSerializableAsJson({ name: "".concat(name, "[").concat(i, "]"), value: value[i], message: message });
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
else if (typeof value === 'object') {
|
|
463
|
-
if (value instanceof Date) {
|
|
464
|
-
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is Date\n\n Use `string_date_iso8601` instead\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
465
|
-
}
|
|
466
|
-
else if (value instanceof Map) {
|
|
467
|
-
throw new UnexpectedError("".concat(name, " is Map"));
|
|
468
|
-
}
|
|
469
|
-
else if (value instanceof Set) {
|
|
470
|
-
throw new UnexpectedError("".concat(name, " is Set"));
|
|
471
|
-
}
|
|
472
|
-
else if (value instanceof RegExp) {
|
|
473
|
-
throw new UnexpectedError("".concat(name, " is RegExp"));
|
|
474
|
-
}
|
|
475
|
-
else if (value instanceof Error) {
|
|
476
|
-
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unserialized Error\n\n Use function `serializeError`\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n\n "); }));
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
try {
|
|
480
|
-
for (var _b = __values(Object.entries(value)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
481
|
-
var _d = __read(_c.value, 2), subName = _d[0], subValue = _d[1];
|
|
482
|
-
if (subValue === undefined) {
|
|
483
|
-
// Note: undefined in object is serializable - it is just omited
|
|
484
|
-
continue;
|
|
485
|
-
}
|
|
486
|
-
checkSerializableAsJson({ name: "".concat(name, ".").concat(subName), value: subValue, message: message });
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
490
|
-
finally {
|
|
491
|
-
try {
|
|
492
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
493
|
-
}
|
|
494
|
-
finally { if (e_1) throw e_1.error; }
|
|
495
|
-
}
|
|
496
|
-
try {
|
|
497
|
-
JSON.stringify(value); // <- TODO: [0]
|
|
498
|
-
}
|
|
499
|
-
catch (error) {
|
|
500
|
-
if (!(error instanceof Error)) {
|
|
501
|
-
throw error;
|
|
502
|
-
}
|
|
503
|
-
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.toString()), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
504
|
-
}
|
|
505
|
-
/*
|
|
506
|
-
TODO: [0] Is there some more elegant way to check circular references?
|
|
507
|
-
const seen = new Set();
|
|
508
|
-
const stack = [{ value }];
|
|
509
|
-
while (stack.length > 0) {
|
|
510
|
-
const { value } = stack.pop()!;
|
|
511
|
-
if (typeof value === 'object' && value !== null) {
|
|
512
|
-
if (seen.has(value)) {
|
|
513
|
-
throw new UnexpectedError(`${name} has circular reference`);
|
|
514
|
-
}
|
|
515
|
-
seen.add(value);
|
|
516
|
-
if (Array.isArray(value)) {
|
|
517
|
-
stack.push(...value.map((value) => ({ value })));
|
|
518
|
-
} else {
|
|
519
|
-
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
*/
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
else {
|
|
528
|
-
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unknown type\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
380
|
+
function validatePipelineString(pipelineString) {
|
|
381
|
+
if (isValidJsonString(pipelineString)) {
|
|
382
|
+
throw new ParseError('Expected a book, but got a JSON string');
|
|
529
383
|
}
|
|
384
|
+
// <- TODO: Implement the validation + add tests when the pipeline logic considered as invalid
|
|
385
|
+
return pipelineString;
|
|
530
386
|
}
|
|
531
387
|
/**
|
|
532
|
-
* TODO:
|
|
533
|
-
* TODO: [🧠][main] !!! In-memory cache of same values to prevent multiple checks
|
|
534
|
-
* Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
388
|
+
* TODO: [🧠][🈴] Where is the best location for this file
|
|
535
389
|
*/
|
|
536
390
|
|
|
537
391
|
/**
|
|
538
|
-
*
|
|
392
|
+
* Prettify the html code
|
|
539
393
|
*
|
|
540
|
-
* @
|
|
394
|
+
* @param content raw html code
|
|
395
|
+
* @returns formatted html code
|
|
396
|
+
* @private withing the package because of HUGE size of prettier dependency
|
|
541
397
|
*/
|
|
542
|
-
function
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
398
|
+
function prettifyMarkdown(content) {
|
|
399
|
+
try {
|
|
400
|
+
return prettier.format(content, {
|
|
401
|
+
parser: 'markdown',
|
|
402
|
+
plugins: [parserHtml__default["default"]],
|
|
403
|
+
// TODO: DRY - make some import or auto-copy of .prettierrc
|
|
404
|
+
endOfLine: 'lf',
|
|
405
|
+
tabWidth: 4,
|
|
406
|
+
singleQuote: true,
|
|
407
|
+
trailingComma: 'all',
|
|
408
|
+
arrowParens: 'always',
|
|
409
|
+
printWidth: 120,
|
|
410
|
+
htmlWhitespaceSensitivity: 'ignore',
|
|
411
|
+
jsxBracketSameLine: false,
|
|
412
|
+
bracketSpacing: true,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
// TODO: [🟥] Detect browser / node and make it colorfull
|
|
417
|
+
console.error('There was an error with prettifying the markdown, using the original as the fallback', {
|
|
418
|
+
error: error,
|
|
419
|
+
html: content,
|
|
420
|
+
});
|
|
421
|
+
return content;
|
|
422
|
+
}
|
|
556
423
|
}
|
|
424
|
+
|
|
557
425
|
/**
|
|
558
|
-
*
|
|
426
|
+
* Makes first letter of a string uppercase
|
|
427
|
+
*
|
|
428
|
+
* @public exported from `@promptbook/utils`
|
|
559
429
|
*/
|
|
430
|
+
function capitalize(word) {
|
|
431
|
+
return word.substring(0, 1).toUpperCase() + word.substring(1);
|
|
432
|
+
}
|
|
560
433
|
|
|
561
434
|
/**
|
|
562
|
-
*
|
|
435
|
+
* Converts promptbook in JSON format to string format
|
|
563
436
|
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
* Note: This function does not mutates the given object
|
|
570
|
-
*
|
|
571
|
-
* @returns The same type of object as the input but read-only and re-ordered
|
|
572
|
-
* @public exported from `@promptbook/utils`
|
|
437
|
+
* @deprecated TODO: [🥍][🧠] Backup original files in `PipelineJson` same as in Promptbook.studio
|
|
438
|
+
* @param pipelineJson Promptbook in JSON format (.book.json)
|
|
439
|
+
* @returns Promptbook in string format (.book.md)
|
|
440
|
+
* @public exported from `@promptbook/core`
|
|
573
441
|
*/
|
|
574
|
-
function
|
|
575
|
-
var
|
|
576
|
-
|
|
577
|
-
var
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
442
|
+
function pipelineJsonToString(pipelineJson) {
|
|
443
|
+
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
|
|
444
|
+
var title = pipelineJson.title, pipelineUrl = pipelineJson.pipelineUrl, bookVersion = pipelineJson.bookVersion, description = pipelineJson.description, parameters = pipelineJson.parameters, tasks = pipelineJson.tasks;
|
|
445
|
+
var pipelineString = "# ".concat(title);
|
|
446
|
+
if (description) {
|
|
447
|
+
pipelineString += '\n\n';
|
|
448
|
+
pipelineString += description;
|
|
449
|
+
}
|
|
450
|
+
var commands = [];
|
|
451
|
+
if (pipelineUrl) {
|
|
452
|
+
commands.push("PIPELINE URL ".concat(pipelineUrl));
|
|
453
|
+
}
|
|
454
|
+
if (bookVersion !== "undefined") {
|
|
455
|
+
commands.push("BOOK VERSION ".concat(bookVersion));
|
|
456
|
+
}
|
|
457
|
+
// TODO: [main] !!5 This increases size of the bundle and is probbably not necessary
|
|
458
|
+
pipelineString = prettifyMarkdown(pipelineString);
|
|
459
|
+
try {
|
|
460
|
+
for (var _g = __values(parameters.filter(function (_a) {
|
|
461
|
+
var isInput = _a.isInput;
|
|
462
|
+
return isInput;
|
|
463
|
+
})), _h = _g.next(); !_h.done; _h = _g.next()) {
|
|
464
|
+
var parameter = _h.value;
|
|
465
|
+
commands.push("INPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
469
|
+
finally {
|
|
470
|
+
try {
|
|
471
|
+
if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
|
|
472
|
+
}
|
|
473
|
+
finally { if (e_1) throw e_1.error; }
|
|
474
|
+
}
|
|
475
|
+
try {
|
|
476
|
+
for (var _j = __values(parameters.filter(function (_a) {
|
|
477
|
+
var isOutput = _a.isOutput;
|
|
478
|
+
return isOutput;
|
|
479
|
+
})), _k = _j.next(); !_k.done; _k = _j.next()) {
|
|
480
|
+
var parameter = _k.value;
|
|
481
|
+
commands.push("OUTPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
485
|
+
finally {
|
|
486
|
+
try {
|
|
487
|
+
if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
|
|
488
|
+
}
|
|
489
|
+
finally { if (e_2) throw e_2.error; }
|
|
490
|
+
}
|
|
491
|
+
pipelineString += '\n\n';
|
|
492
|
+
pipelineString += commands.map(function (command) { return "- ".concat(command); }).join('\n');
|
|
493
|
+
try {
|
|
494
|
+
for (var tasks_1 = __values(tasks), tasks_1_1 = tasks_1.next(); !tasks_1_1.done; tasks_1_1 = tasks_1.next()) {
|
|
495
|
+
var task = tasks_1_1.value;
|
|
496
|
+
var
|
|
497
|
+
/* Note: Not using:> name, */
|
|
498
|
+
title_1 = task.title, description_1 = task.description,
|
|
499
|
+
/* Note: dependentParameterNames, */
|
|
500
|
+
jokers = task.jokerParameterNames, taskType = task.taskType, content = task.content, postprocessing = task.postprocessingFunctionNames, expectations = task.expectations, format = task.format, resultingParameterName = task.resultingParameterName;
|
|
501
|
+
pipelineString += '\n\n';
|
|
502
|
+
pipelineString += "## ".concat(title_1);
|
|
503
|
+
if (description_1) {
|
|
504
|
+
pipelineString += '\n\n';
|
|
505
|
+
pipelineString += description_1;
|
|
506
|
+
}
|
|
507
|
+
var commands_1 = [];
|
|
508
|
+
var contentLanguage = 'text';
|
|
509
|
+
if (taskType === 'PROMPT_TASK') {
|
|
510
|
+
var modelRequirements = task.modelRequirements;
|
|
511
|
+
var _l = modelRequirements || {}, modelName = _l.modelName, modelVariant = _l.modelVariant;
|
|
512
|
+
// Note: Do nothing, it is default
|
|
513
|
+
// commands.push(`PROMPT`);
|
|
514
|
+
if (modelVariant) {
|
|
515
|
+
commands_1.push("MODEL VARIANT ".concat(capitalize(modelVariant)));
|
|
516
|
+
}
|
|
517
|
+
if (modelName) {
|
|
518
|
+
commands_1.push("MODEL NAME `".concat(modelName, "`"));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
else if (taskType === 'SIMPLE_TASK') {
|
|
522
|
+
commands_1.push("SIMPLE TEMPLATE");
|
|
523
|
+
// Note: Nothing special here
|
|
524
|
+
}
|
|
525
|
+
else if (taskType === 'SCRIPT_TASK') {
|
|
526
|
+
commands_1.push("SCRIPT");
|
|
527
|
+
if (task.contentLanguage) {
|
|
528
|
+
contentLanguage = task.contentLanguage;
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
contentLanguage = '';
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
else if (taskType === 'DIALOG_TASK') {
|
|
535
|
+
commands_1.push("DIALOG");
|
|
536
|
+
// Note: Nothing special here
|
|
537
|
+
} // <- }else if([🅱]
|
|
538
|
+
if (jokers) {
|
|
539
|
+
try {
|
|
540
|
+
for (var jokers_1 = (e_4 = void 0, __values(jokers)), jokers_1_1 = jokers_1.next(); !jokers_1_1.done; jokers_1_1 = jokers_1.next()) {
|
|
541
|
+
var joker = jokers_1_1.value;
|
|
542
|
+
commands_1.push("JOKER {".concat(joker, "}"));
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
546
|
+
finally {
|
|
547
|
+
try {
|
|
548
|
+
if (jokers_1_1 && !jokers_1_1.done && (_d = jokers_1.return)) _d.call(jokers_1);
|
|
549
|
+
}
|
|
550
|
+
finally { if (e_4) throw e_4.error; }
|
|
551
|
+
}
|
|
552
|
+
} /* not else */
|
|
553
|
+
if (postprocessing) {
|
|
554
|
+
try {
|
|
555
|
+
for (var postprocessing_1 = (e_5 = void 0, __values(postprocessing)), postprocessing_1_1 = postprocessing_1.next(); !postprocessing_1_1.done; postprocessing_1_1 = postprocessing_1.next()) {
|
|
556
|
+
var postprocessingFunctionName = postprocessing_1_1.value;
|
|
557
|
+
commands_1.push("POSTPROCESSING `".concat(postprocessingFunctionName, "`"));
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
561
|
+
finally {
|
|
562
|
+
try {
|
|
563
|
+
if (postprocessing_1_1 && !postprocessing_1_1.done && (_e = postprocessing_1.return)) _e.call(postprocessing_1);
|
|
564
|
+
}
|
|
565
|
+
finally { if (e_5) throw e_5.error; }
|
|
566
|
+
}
|
|
567
|
+
} /* not else */
|
|
568
|
+
if (expectations) {
|
|
569
|
+
try {
|
|
570
|
+
for (var _m = (e_6 = void 0, __values(Object.entries(expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
|
|
571
|
+
var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
|
|
572
|
+
if (min === max) {
|
|
573
|
+
commands_1.push("EXPECT EXACTLY ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
if (min !== undefined) {
|
|
577
|
+
commands_1.push("EXPECT MIN ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
578
|
+
} /* not else */
|
|
579
|
+
if (max !== undefined) {
|
|
580
|
+
commands_1.push("EXPECT MAX ".concat(max, " ").concat(capitalize(unit + (max > 1 ? 's' : ''))));
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
586
|
+
finally {
|
|
587
|
+
try {
|
|
588
|
+
if (_o && !_o.done && (_f = _m.return)) _f.call(_m);
|
|
589
|
+
}
|
|
590
|
+
finally { if (e_6) throw e_6.error; }
|
|
591
|
+
}
|
|
592
|
+
} /* not else */
|
|
593
|
+
if (format) {
|
|
594
|
+
if (format === 'JSON') {
|
|
595
|
+
// TODO: @deprecated remove
|
|
596
|
+
commands_1.push("FORMAT JSON");
|
|
597
|
+
}
|
|
598
|
+
} /* not else */
|
|
599
|
+
pipelineString += '\n\n';
|
|
600
|
+
pipelineString += commands_1.map(function (command) { return "- ".concat(command); }).join('\n');
|
|
601
|
+
pipelineString += '\n\n';
|
|
602
|
+
pipelineString += '```' + contentLanguage;
|
|
603
|
+
pipelineString += '\n';
|
|
604
|
+
pipelineString += spaceTrim__default["default"](content);
|
|
605
|
+
// <- TODO: [main] !!3 Escape
|
|
606
|
+
// <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
|
|
607
|
+
pipelineString += '\n';
|
|
608
|
+
pipelineString += '```';
|
|
609
|
+
pipelineString += '\n\n';
|
|
610
|
+
pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: [main] !!3 If the parameter here has description, add it and use taskParameterJsonToString
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
614
|
+
finally {
|
|
615
|
+
try {
|
|
616
|
+
if (tasks_1_1 && !tasks_1_1.done && (_c = tasks_1.return)) _c.call(tasks_1);
|
|
617
|
+
}
|
|
618
|
+
finally { if (e_3) throw e_3.error; }
|
|
619
|
+
}
|
|
620
|
+
return validatePipelineString(pipelineString);
|
|
590
621
|
}
|
|
591
622
|
/**
|
|
592
|
-
*
|
|
623
|
+
* @private internal utility of `pipelineJsonToString`
|
|
593
624
|
*/
|
|
594
|
-
|
|
625
|
+
function taskParameterJsonToString(taskParameterJson) {
|
|
626
|
+
var name = taskParameterJson.name, description = taskParameterJson.description;
|
|
627
|
+
var parameterString = "{".concat(name, "}");
|
|
628
|
+
if (description) {
|
|
629
|
+
parameterString = "".concat(parameterString, " ").concat(description);
|
|
630
|
+
}
|
|
631
|
+
return parameterString;
|
|
632
|
+
}
|
|
595
633
|
/**
|
|
596
|
-
*
|
|
597
|
-
*
|
|
598
|
-
*
|
|
634
|
+
* TODO: [🛋] Implement new features and commands into `pipelineJsonToString` + `taskParameterJsonToString` , use `stringifyCommand`
|
|
635
|
+
* TODO: [🧠] Is there a way to auto-detect missing features in pipelineJsonToString
|
|
636
|
+
* TODO: [🏛] Maybe make some markdown builder
|
|
637
|
+
* TODO: [🏛] Escape all
|
|
638
|
+
* TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
|
|
599
639
|
*/
|
|
600
|
-
|
|
601
|
-
// Note: [🍙] In this order will be pipeline serialized
|
|
602
|
-
'title',
|
|
603
|
-
'pipelineUrl',
|
|
604
|
-
'bookVersion',
|
|
605
|
-
'description',
|
|
606
|
-
'formfactorName',
|
|
607
|
-
'parameters',
|
|
608
|
-
'tasks',
|
|
609
|
-
'personas',
|
|
610
|
-
'preparations',
|
|
611
|
-
'knowledgeSources',
|
|
612
|
-
'knowledgePieces',
|
|
613
|
-
'sources', // <- TODO: [🧠] Where should the `sources` be
|
|
614
|
-
];
|
|
640
|
+
|
|
615
641
|
/**
|
|
616
|
-
*
|
|
642
|
+
* Orders JSON object by keys
|
|
617
643
|
*
|
|
618
|
-
* @
|
|
644
|
+
* @returns The same type of object as the input re-ordered
|
|
645
|
+
* @public exported from `@promptbook/utils`
|
|
619
646
|
*/
|
|
620
|
-
|
|
647
|
+
function orderJson(options) {
|
|
648
|
+
var value = options.value, order = options.order;
|
|
649
|
+
var orderedValue = __assign(__assign({}, (order === undefined ? {} : Object.fromEntries(order.map(function (key) { return [key, undefined]; })))), value);
|
|
650
|
+
return orderedValue;
|
|
651
|
+
}
|
|
652
|
+
|
|
621
653
|
/**
|
|
622
|
-
*
|
|
654
|
+
* Freezes the given object and all its nested objects recursively
|
|
623
655
|
*
|
|
624
|
-
*
|
|
625
|
-
|
|
626
|
-
var RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
|
|
627
|
-
/**
|
|
628
|
-
* @@@
|
|
656
|
+
* Note: `$` is used to indicate that this function is not a pure function - it mutates given object
|
|
657
|
+
* Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
|
|
629
658
|
*
|
|
630
|
-
* @
|
|
659
|
+
* @returns The same object as the input, but deeply frozen
|
|
660
|
+
* @public exported from `@promptbook/utils`
|
|
631
661
|
*/
|
|
632
|
-
|
|
662
|
+
function $deepFreeze(objectValue) {
|
|
663
|
+
var e_1, _a;
|
|
664
|
+
if (Array.isArray(objectValue)) {
|
|
665
|
+
return Object.freeze(objectValue.map(function (item) { return $deepFreeze(item); }));
|
|
666
|
+
}
|
|
667
|
+
var propertyNames = Object.getOwnPropertyNames(objectValue);
|
|
668
|
+
try {
|
|
669
|
+
for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
|
|
670
|
+
var propertyName = propertyNames_1_1.value;
|
|
671
|
+
var value = objectValue[propertyName];
|
|
672
|
+
if (value && typeof value === 'object') {
|
|
673
|
+
$deepFreeze(value);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
678
|
+
finally {
|
|
679
|
+
try {
|
|
680
|
+
if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
|
|
681
|
+
}
|
|
682
|
+
finally { if (e_1) throw e_1.error; }
|
|
683
|
+
}
|
|
684
|
+
Object.freeze(objectValue);
|
|
685
|
+
return objectValue;
|
|
686
|
+
}
|
|
633
687
|
/**
|
|
634
|
-
*
|
|
635
|
-
*
|
|
636
|
-
* @public exported from `@promptbook/core`
|
|
688
|
+
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
637
689
|
*/
|
|
638
|
-
|
|
639
|
-
name: 'RESERVED_PARAMETER_NAMES',
|
|
640
|
-
message: "The names of the parameters that are reserved for special purposes",
|
|
641
|
-
value: [
|
|
642
|
-
'content',
|
|
643
|
-
'context',
|
|
644
|
-
'knowledge',
|
|
645
|
-
'examples',
|
|
646
|
-
'modelName',
|
|
647
|
-
'currentDate',
|
|
648
|
-
// <- TODO: list here all command names
|
|
649
|
-
// <- TODO: Add more like 'date', 'modelName',...
|
|
650
|
-
// <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
|
|
651
|
-
],
|
|
652
|
-
});
|
|
690
|
+
|
|
653
691
|
/**
|
|
654
|
-
*
|
|
692
|
+
* Make error report URL for the given error
|
|
693
|
+
*
|
|
694
|
+
* @private private within the repository
|
|
655
695
|
*/
|
|
696
|
+
function getErrorReportUrl(error) {
|
|
697
|
+
var report = {
|
|
698
|
+
title: "\uD83D\uDC1C Error report from ".concat(NAME),
|
|
699
|
+
body: spaceTrim__default["default"](function (block) { return "\n\n\n `".concat(error.name || 'Error', "` has occurred in the [").concat(NAME, "], please look into it @").concat(ADMIN_GITHUB_NAME, ".\n\n ```\n ").concat(block(error.message || '(no error message)'), "\n ```\n\n\n ## More info:\n\n - **Promptbook engine version:** ").concat(PROMPTBOOK_ENGINE_VERSION, "\n - **Book language version:** ").concat(BOOK_LANGUAGE_VERSION, "\n - **Time:** ").concat(new Date().toISOString(), "\n\n <details>\n <summary>Stack trace:</summary>\n\n ## Stack trace:\n\n ```stacktrace\n ").concat(block(error.stack || '(empty)'), "\n ```\n </details>\n\n "); }),
|
|
700
|
+
};
|
|
701
|
+
var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
|
|
702
|
+
reportUrl.searchParams.set('labels', 'bug');
|
|
703
|
+
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
704
|
+
reportUrl.searchParams.set('title', report.title);
|
|
705
|
+
reportUrl.searchParams.set('body', report.body);
|
|
706
|
+
return reportUrl;
|
|
707
|
+
}
|
|
656
708
|
|
|
657
709
|
/**
|
|
658
|
-
* This error type indicates that
|
|
710
|
+
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
659
711
|
*
|
|
660
712
|
* @public exported from `@promptbook/core`
|
|
661
713
|
*/
|
|
662
|
-
var
|
|
663
|
-
__extends(
|
|
664
|
-
function
|
|
665
|
-
var _this = _super.call(this, spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note:
|
|
666
|
-
_this.name = '
|
|
667
|
-
Object.setPrototypeOf(_this,
|
|
714
|
+
var UnexpectedError = /** @class */ (function (_super) {
|
|
715
|
+
__extends(UnexpectedError, _super);
|
|
716
|
+
function UnexpectedError(message) {
|
|
717
|
+
var _this = _super.call(this, spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note: This error should not happen.\n It's probbably a bug in the pipeline collection\n\n Please report issue:\n ").concat(block(getErrorReportUrl(new Error(message)).href), "\n\n Or contact us on ").concat(ADMIN_EMAIL, "\n\n "); })) || this;
|
|
718
|
+
_this.name = 'UnexpectedError';
|
|
719
|
+
Object.setPrototypeOf(_this, UnexpectedError.prototype);
|
|
668
720
|
return _this;
|
|
669
721
|
}
|
|
670
|
-
return
|
|
722
|
+
return UnexpectedError;
|
|
671
723
|
}(Error));
|
|
672
724
|
|
|
673
725
|
/**
|
|
674
|
-
*
|
|
726
|
+
* Checks if the value is [🚉] serializable as JSON
|
|
727
|
+
* If not, throws an UnexpectedError with a rich error message and tracking
|
|
675
728
|
*
|
|
676
|
-
*
|
|
677
|
-
*
|
|
678
|
-
*
|
|
729
|
+
* - Almost all primitives are serializable BUT:
|
|
730
|
+
* - `undefined` is not serializable
|
|
731
|
+
* - `NaN` is not serializable
|
|
732
|
+
* - Objects and arrays are serializable if all their properties are serializable
|
|
733
|
+
* - Functions are not serializable
|
|
734
|
+
* - Circular references are not serializable
|
|
735
|
+
* - `Date` objects are not serializable
|
|
736
|
+
* - `Map` and `Set` objects are not serializable
|
|
737
|
+
* - `RegExp` objects are not serializable
|
|
738
|
+
* - `Error` objects are not serializable
|
|
739
|
+
* - `Symbol` objects are not serializable
|
|
740
|
+
* - And much more...
|
|
741
|
+
*
|
|
742
|
+
* @throws UnexpectedError if the value is not serializable as JSON
|
|
679
743
|
* @public exported from `@promptbook/utils`
|
|
680
|
-
* @deprecated [🪂] Use queues instead
|
|
681
744
|
*/
|
|
682
|
-
function
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
};
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
case 7:
|
|
735
|
-
try {
|
|
736
|
-
if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
|
|
745
|
+
function checkSerializableAsJson(options) {
|
|
746
|
+
var e_1, _a;
|
|
747
|
+
var value = options.value, name = options.name, message = options.message;
|
|
748
|
+
if (value === undefined) {
|
|
749
|
+
throw new UnexpectedError("".concat(name, " is undefined"));
|
|
750
|
+
}
|
|
751
|
+
else if (value === null) {
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
else if (typeof value === 'boolean') {
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
else if (typeof value === 'number' && !isNaN(value)) {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
else if (typeof value === 'string') {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
else if (typeof value === 'symbol') {
|
|
764
|
+
throw new UnexpectedError("".concat(name, " is symbol"));
|
|
765
|
+
}
|
|
766
|
+
else if (typeof value === 'function') {
|
|
767
|
+
throw new UnexpectedError("".concat(name, " is function"));
|
|
768
|
+
}
|
|
769
|
+
else if (typeof value === 'object' && Array.isArray(value)) {
|
|
770
|
+
for (var i = 0; i < value.length; i++) {
|
|
771
|
+
checkSerializableAsJson({ name: "".concat(name, "[").concat(i, "]"), value: value[i], message: message });
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
else if (typeof value === 'object') {
|
|
775
|
+
if (value instanceof Date) {
|
|
776
|
+
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is Date\n\n Use `string_date_iso8601` instead\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
777
|
+
}
|
|
778
|
+
else if (value instanceof Map) {
|
|
779
|
+
throw new UnexpectedError("".concat(name, " is Map"));
|
|
780
|
+
}
|
|
781
|
+
else if (value instanceof Set) {
|
|
782
|
+
throw new UnexpectedError("".concat(name, " is Set"));
|
|
783
|
+
}
|
|
784
|
+
else if (value instanceof RegExp) {
|
|
785
|
+
throw new UnexpectedError("".concat(name, " is RegExp"));
|
|
786
|
+
}
|
|
787
|
+
else if (value instanceof Error) {
|
|
788
|
+
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unserialized Error\n\n Use function `serializeError`\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n\n "); }));
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
try {
|
|
792
|
+
for (var _b = __values(Object.entries(value)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
793
|
+
var _d = __read(_c.value, 2), subName = _d[0], subValue = _d[1];
|
|
794
|
+
if (subValue === undefined) {
|
|
795
|
+
// Note: undefined in object is serializable - it is just omited
|
|
796
|
+
continue;
|
|
737
797
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
case 8: return [4 /*yield*/, Promise.all(tasks)];
|
|
741
|
-
case 9:
|
|
742
|
-
_e.sent();
|
|
743
|
-
return [2 /*return*/];
|
|
798
|
+
checkSerializableAsJson({ name: "".concat(name, ".").concat(subName), value: subValue, message: message });
|
|
799
|
+
}
|
|
744
800
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
/**
|
|
750
|
-
* Represents the usage with no resources consumed
|
|
751
|
-
*
|
|
752
|
-
* @public exported from `@promptbook/core`
|
|
753
|
-
*/
|
|
754
|
-
var ZERO_USAGE = $deepFreeze({
|
|
755
|
-
price: { value: 0 },
|
|
756
|
-
input: {
|
|
757
|
-
tokensCount: { value: 0 },
|
|
758
|
-
charactersCount: { value: 0 },
|
|
759
|
-
wordsCount: { value: 0 },
|
|
760
|
-
sentencesCount: { value: 0 },
|
|
761
|
-
linesCount: { value: 0 },
|
|
762
|
-
paragraphsCount: { value: 0 },
|
|
763
|
-
pagesCount: { value: 0 },
|
|
764
|
-
},
|
|
765
|
-
output: {
|
|
766
|
-
tokensCount: { value: 0 },
|
|
767
|
-
charactersCount: { value: 0 },
|
|
768
|
-
wordsCount: { value: 0 },
|
|
769
|
-
sentencesCount: { value: 0 },
|
|
770
|
-
linesCount: { value: 0 },
|
|
771
|
-
paragraphsCount: { value: 0 },
|
|
772
|
-
pagesCount: { value: 0 },
|
|
773
|
-
},
|
|
774
|
-
});
|
|
775
|
-
/**
|
|
776
|
-
* Represents the usage with unknown resources consumed
|
|
777
|
-
*
|
|
778
|
-
* @public exported from `@promptbook/core`
|
|
779
|
-
*/
|
|
780
|
-
$deepFreeze({
|
|
781
|
-
price: { value: 0, isUncertain: true },
|
|
782
|
-
input: {
|
|
783
|
-
tokensCount: { value: 0, isUncertain: true },
|
|
784
|
-
charactersCount: { value: 0, isUncertain: true },
|
|
785
|
-
wordsCount: { value: 0, isUncertain: true },
|
|
786
|
-
sentencesCount: { value: 0, isUncertain: true },
|
|
787
|
-
linesCount: { value: 0, isUncertain: true },
|
|
788
|
-
paragraphsCount: { value: 0, isUncertain: true },
|
|
789
|
-
pagesCount: { value: 0, isUncertain: true },
|
|
790
|
-
},
|
|
791
|
-
output: {
|
|
792
|
-
tokensCount: { value: 0, isUncertain: true },
|
|
793
|
-
charactersCount: { value: 0, isUncertain: true },
|
|
794
|
-
wordsCount: { value: 0, isUncertain: true },
|
|
795
|
-
sentencesCount: { value: 0, isUncertain: true },
|
|
796
|
-
linesCount: { value: 0, isUncertain: true },
|
|
797
|
-
paragraphsCount: { value: 0, isUncertain: true },
|
|
798
|
-
pagesCount: { value: 0, isUncertain: true },
|
|
799
|
-
},
|
|
800
|
-
});
|
|
801
|
-
/**
|
|
802
|
-
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
803
|
-
*/
|
|
804
|
-
|
|
805
|
-
/**
|
|
806
|
-
* Function `addUsage` will add multiple usages into one
|
|
807
|
-
*
|
|
808
|
-
* Note: If you provide 0 values, it returns ZERO_USAGE
|
|
809
|
-
*
|
|
810
|
-
* @public exported from `@promptbook/core`
|
|
811
|
-
*/
|
|
812
|
-
function addUsage() {
|
|
813
|
-
var usageItems = [];
|
|
814
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
815
|
-
usageItems[_i] = arguments[_i];
|
|
816
|
-
}
|
|
817
|
-
return usageItems.reduce(function (acc, item) {
|
|
818
|
-
var e_1, _a, e_2, _b;
|
|
819
|
-
var _c;
|
|
820
|
-
acc.price.value += ((_c = item.price) === null || _c === void 0 ? void 0 : _c.value) || 0;
|
|
821
|
-
try {
|
|
822
|
-
for (var _d = __values(Object.keys(acc.input)), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
823
|
-
var key = _e.value;
|
|
824
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
825
|
-
//@ts-ignore
|
|
826
|
-
if (item.input[key]) {
|
|
827
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
828
|
-
//@ts-ignore
|
|
829
|
-
acc.input[key].value += item.input[key].value || 0;
|
|
830
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
831
|
-
//@ts-ignore
|
|
832
|
-
if (item.input[key].isUncertain) {
|
|
833
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
834
|
-
//@ts-ignore
|
|
835
|
-
acc.input[key].isUncertain = true;
|
|
836
|
-
}
|
|
801
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
802
|
+
finally {
|
|
803
|
+
try {
|
|
804
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
837
805
|
}
|
|
806
|
+
finally { if (e_1) throw e_1.error; }
|
|
838
807
|
}
|
|
839
|
-
}
|
|
840
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
841
|
-
finally {
|
|
842
808
|
try {
|
|
843
|
-
|
|
809
|
+
JSON.stringify(value); // <- TODO: [0]
|
|
844
810
|
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
for (var _f = __values(Object.keys(acc.output)), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
849
|
-
var key = _g.value;
|
|
850
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
851
|
-
//@ts-ignore
|
|
852
|
-
if (item.output[key]) {
|
|
853
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
854
|
-
//@ts-ignore
|
|
855
|
-
acc.output[key].value += item.output[key].value || 0;
|
|
856
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
857
|
-
//@ts-ignore
|
|
858
|
-
if (item.output[key].isUncertain) {
|
|
859
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
860
|
-
//@ts-ignore
|
|
861
|
-
acc.output[key].isUncertain = true;
|
|
862
|
-
}
|
|
811
|
+
catch (error) {
|
|
812
|
+
if (!(error instanceof Error)) {
|
|
813
|
+
throw error;
|
|
863
814
|
}
|
|
815
|
+
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.stack || error.message), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
864
816
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
817
|
+
/*
|
|
818
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
819
|
+
const seen = new Set();
|
|
820
|
+
const stack = [{ value }];
|
|
821
|
+
while (stack.length > 0) {
|
|
822
|
+
const { value } = stack.pop()!;
|
|
823
|
+
if (typeof value === 'object' && value !== null) {
|
|
824
|
+
if (seen.has(value)) {
|
|
825
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
826
|
+
}
|
|
827
|
+
seen.add(value);
|
|
828
|
+
if (Array.isArray(value)) {
|
|
829
|
+
stack.push(...value.map((value) => ({ value })));
|
|
830
|
+
} else {
|
|
831
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
832
|
+
}
|
|
833
|
+
}
|
|
870
834
|
}
|
|
871
|
-
|
|
835
|
+
*/
|
|
836
|
+
return;
|
|
872
837
|
}
|
|
873
|
-
return acc;
|
|
874
|
-
}, deepClone(ZERO_USAGE));
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
/**
|
|
878
|
-
* Intercepts LLM tools and counts total usage of the tools
|
|
879
|
-
*
|
|
880
|
-
* @param llmTools LLM tools to be intercepted with usage counting
|
|
881
|
-
* @returns LLM tools with same functionality with added total cost counting
|
|
882
|
-
* @public exported from `@promptbook/core`
|
|
883
|
-
*/
|
|
884
|
-
function countTotalUsage(llmTools) {
|
|
885
|
-
var _this = this;
|
|
886
|
-
var totalUsage = ZERO_USAGE;
|
|
887
|
-
var proxyTools = {
|
|
888
|
-
get title() {
|
|
889
|
-
// TODO: [🧠] Maybe put here some suffix
|
|
890
|
-
return llmTools.title;
|
|
891
|
-
},
|
|
892
|
-
get description() {
|
|
893
|
-
// TODO: [🧠] Maybe put here some suffix
|
|
894
|
-
return llmTools.description;
|
|
895
|
-
},
|
|
896
|
-
checkConfiguration: function () {
|
|
897
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
898
|
-
return __generator(this, function (_a) {
|
|
899
|
-
return [2 /*return*/, /* not await */ llmTools.checkConfiguration()];
|
|
900
|
-
});
|
|
901
|
-
});
|
|
902
|
-
},
|
|
903
|
-
listModels: function () {
|
|
904
|
-
return /* not await */ llmTools.listModels();
|
|
905
|
-
},
|
|
906
|
-
getTotalUsage: function () {
|
|
907
|
-
// <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
|
|
908
|
-
return totalUsage;
|
|
909
|
-
},
|
|
910
|
-
};
|
|
911
|
-
if (llmTools.callChatModel !== undefined) {
|
|
912
|
-
proxyTools.callChatModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
|
|
913
|
-
var promptResult;
|
|
914
|
-
return __generator(this, function (_a) {
|
|
915
|
-
switch (_a.label) {
|
|
916
|
-
case 0: return [4 /*yield*/, llmTools.callChatModel(prompt)];
|
|
917
|
-
case 1:
|
|
918
|
-
promptResult = _a.sent();
|
|
919
|
-
totalUsage = addUsage(totalUsage, promptResult.usage);
|
|
920
|
-
return [2 /*return*/, promptResult];
|
|
921
|
-
}
|
|
922
|
-
});
|
|
923
|
-
}); };
|
|
924
|
-
}
|
|
925
|
-
if (llmTools.callCompletionModel !== undefined) {
|
|
926
|
-
proxyTools.callCompletionModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
|
|
927
|
-
var promptResult;
|
|
928
|
-
return __generator(this, function (_a) {
|
|
929
|
-
switch (_a.label) {
|
|
930
|
-
case 0: return [4 /*yield*/, llmTools.callCompletionModel(prompt)];
|
|
931
|
-
case 1:
|
|
932
|
-
promptResult = _a.sent();
|
|
933
|
-
totalUsage = addUsage(totalUsage, promptResult.usage);
|
|
934
|
-
return [2 /*return*/, promptResult];
|
|
935
|
-
}
|
|
936
|
-
});
|
|
937
|
-
}); };
|
|
938
838
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
var promptResult;
|
|
942
|
-
return __generator(this, function (_a) {
|
|
943
|
-
switch (_a.label) {
|
|
944
|
-
case 0: return [4 /*yield*/, llmTools.callEmbeddingModel(prompt)];
|
|
945
|
-
case 1:
|
|
946
|
-
promptResult = _a.sent();
|
|
947
|
-
totalUsage = addUsage(totalUsage, promptResult.usage);
|
|
948
|
-
return [2 /*return*/, promptResult];
|
|
949
|
-
}
|
|
950
|
-
});
|
|
951
|
-
}); };
|
|
839
|
+
else {
|
|
840
|
+
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unknown type\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
952
841
|
}
|
|
953
|
-
// <- Note: [🤖]
|
|
954
|
-
return proxyTools;
|
|
955
842
|
}
|
|
956
843
|
/**
|
|
957
|
-
* TODO:
|
|
958
|
-
* TODO: [🧠]
|
|
959
|
-
*
|
|
960
|
-
* > const [llmToolsWithUsage,getUsage] = countTotalUsage(llmTools);
|
|
961
|
-
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
844
|
+
* TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
845
|
+
* TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
846
|
+
* Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
962
847
|
*/
|
|
963
848
|
|
|
964
849
|
/**
|
|
965
|
-
*
|
|
850
|
+
* @@@
|
|
966
851
|
*
|
|
967
|
-
* @public exported from `@promptbook/
|
|
852
|
+
* @public exported from `@promptbook/utils`
|
|
853
|
+
*/
|
|
854
|
+
function deepClone(objectValue) {
|
|
855
|
+
return JSON.parse(JSON.stringify(objectValue));
|
|
856
|
+
/*
|
|
857
|
+
TODO: [🧠] Is there a better implementation?
|
|
858
|
+
> const propertyNames = Object.getOwnPropertyNames(objectValue);
|
|
859
|
+
> for (const propertyName of propertyNames) {
|
|
860
|
+
> const value = (objectValue as really_any)[propertyName];
|
|
861
|
+
> if (value && typeof value === 'object') {
|
|
862
|
+
> deepClone(value);
|
|
863
|
+
> }
|
|
864
|
+
> }
|
|
865
|
+
> return Object.assign({}, objectValue);
|
|
866
|
+
*/
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
968
870
|
*/
|
|
969
|
-
var PipelineExecutionError = /** @class */ (function (_super) {
|
|
970
|
-
__extends(PipelineExecutionError, _super);
|
|
971
|
-
function PipelineExecutionError(message) {
|
|
972
|
-
var _this = _super.call(this, message) || this;
|
|
973
|
-
_this.name = 'PipelineExecutionError';
|
|
974
|
-
Object.setPrototypeOf(_this, PipelineExecutionError.prototype);
|
|
975
|
-
return _this;
|
|
976
|
-
}
|
|
977
|
-
return PipelineExecutionError;
|
|
978
|
-
}(Error));
|
|
979
871
|
|
|
980
872
|
/**
|
|
981
|
-
*
|
|
873
|
+
* Utility to export a JSON object from a function
|
|
982
874
|
*
|
|
983
|
-
*
|
|
984
|
-
*
|
|
875
|
+
* 1) Checks if the value is serializable as JSON
|
|
876
|
+
* 2) Makes a deep clone of the object
|
|
877
|
+
* 2) Orders the object properties
|
|
878
|
+
* 2) Deeply freezes the cloned object
|
|
879
|
+
*
|
|
880
|
+
* Note: This function does not mutates the given object
|
|
881
|
+
*
|
|
882
|
+
* @returns The same type of object as the input but read-only and re-ordered
|
|
883
|
+
* @public exported from `@promptbook/utils`
|
|
985
884
|
*/
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
return 'Multiple LLM Providers';
|
|
1000
|
-
},
|
|
1001
|
-
enumerable: false,
|
|
1002
|
-
configurable: true
|
|
1003
|
-
});
|
|
1004
|
-
Object.defineProperty(MultipleLlmExecutionTools.prototype, "description", {
|
|
1005
|
-
get: function () {
|
|
1006
|
-
return this.llmExecutionTools.map(function (_a, index) {
|
|
1007
|
-
var title = _a.title;
|
|
1008
|
-
return "".concat(index + 1, ") `").concat(title, "`");
|
|
1009
|
-
}).join('\n');
|
|
1010
|
-
},
|
|
1011
|
-
enumerable: false,
|
|
1012
|
-
configurable: true
|
|
1013
|
-
});
|
|
1014
|
-
/**
|
|
1015
|
-
* Check the configuration of all execution tools
|
|
1016
|
-
*/
|
|
1017
|
-
MultipleLlmExecutionTools.prototype.checkConfiguration = function () {
|
|
1018
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
1019
|
-
var _a, _b, llmExecutionTools, e_1_1;
|
|
1020
|
-
var e_1, _c;
|
|
1021
|
-
return __generator(this, function (_d) {
|
|
1022
|
-
switch (_d.label) {
|
|
1023
|
-
case 0:
|
|
1024
|
-
_d.trys.push([0, 5, 6, 7]);
|
|
1025
|
-
_a = __values(this.llmExecutionTools), _b = _a.next();
|
|
1026
|
-
_d.label = 1;
|
|
1027
|
-
case 1:
|
|
1028
|
-
if (!!_b.done) return [3 /*break*/, 4];
|
|
1029
|
-
llmExecutionTools = _b.value;
|
|
1030
|
-
return [4 /*yield*/, llmExecutionTools.checkConfiguration()];
|
|
1031
|
-
case 2:
|
|
1032
|
-
_d.sent();
|
|
1033
|
-
_d.label = 3;
|
|
1034
|
-
case 3:
|
|
1035
|
-
_b = _a.next();
|
|
1036
|
-
return [3 /*break*/, 1];
|
|
1037
|
-
case 4: return [3 /*break*/, 7];
|
|
1038
|
-
case 5:
|
|
1039
|
-
e_1_1 = _d.sent();
|
|
1040
|
-
e_1 = { error: e_1_1 };
|
|
1041
|
-
return [3 /*break*/, 7];
|
|
1042
|
-
case 6:
|
|
1043
|
-
try {
|
|
1044
|
-
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
1045
|
-
}
|
|
1046
|
-
finally { if (e_1) throw e_1.error; }
|
|
1047
|
-
return [7 /*endfinally*/];
|
|
1048
|
-
case 7: return [2 /*return*/];
|
|
1049
|
-
}
|
|
1050
|
-
});
|
|
1051
|
-
});
|
|
1052
|
-
};
|
|
1053
|
-
/**
|
|
1054
|
-
* List all available models that can be used
|
|
1055
|
-
* This lists is a combination of all available models from all execution tools
|
|
1056
|
-
*/
|
|
1057
|
-
MultipleLlmExecutionTools.prototype.listModels = function () {
|
|
1058
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
1059
|
-
var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
|
|
1060
|
-
var e_2, _c;
|
|
1061
|
-
return __generator(this, function (_d) {
|
|
1062
|
-
switch (_d.label) {
|
|
1063
|
-
case 0:
|
|
1064
|
-
availableModels = [];
|
|
1065
|
-
_d.label = 1;
|
|
1066
|
-
case 1:
|
|
1067
|
-
_d.trys.push([1, 6, 7, 8]);
|
|
1068
|
-
_a = __values(this.llmExecutionTools), _b = _a.next();
|
|
1069
|
-
_d.label = 2;
|
|
1070
|
-
case 2:
|
|
1071
|
-
if (!!_b.done) return [3 /*break*/, 5];
|
|
1072
|
-
llmExecutionTools = _b.value;
|
|
1073
|
-
return [4 /*yield*/, llmExecutionTools.listModels()];
|
|
1074
|
-
case 3:
|
|
1075
|
-
models = _d.sent();
|
|
1076
|
-
availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
|
|
1077
|
-
_d.label = 4;
|
|
1078
|
-
case 4:
|
|
1079
|
-
_b = _a.next();
|
|
1080
|
-
return [3 /*break*/, 2];
|
|
1081
|
-
case 5: return [3 /*break*/, 8];
|
|
1082
|
-
case 6:
|
|
1083
|
-
e_2_1 = _d.sent();
|
|
1084
|
-
e_2 = { error: e_2_1 };
|
|
1085
|
-
return [3 /*break*/, 8];
|
|
1086
|
-
case 7:
|
|
1087
|
-
try {
|
|
1088
|
-
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
1089
|
-
}
|
|
1090
|
-
finally { if (e_2) throw e_2.error; }
|
|
1091
|
-
return [7 /*endfinally*/];
|
|
1092
|
-
case 8: return [2 /*return*/, availableModels];
|
|
1093
|
-
}
|
|
1094
|
-
});
|
|
1095
|
-
});
|
|
1096
|
-
};
|
|
1097
|
-
/**
|
|
1098
|
-
* Calls the best available chat model
|
|
1099
|
-
*/
|
|
1100
|
-
MultipleLlmExecutionTools.prototype.callChatModel = function (prompt) {
|
|
1101
|
-
return this.callCommonModel(prompt);
|
|
1102
|
-
};
|
|
1103
|
-
/**
|
|
1104
|
-
* Calls the best available completion model
|
|
1105
|
-
*/
|
|
1106
|
-
MultipleLlmExecutionTools.prototype.callCompletionModel = function (prompt) {
|
|
1107
|
-
return this.callCommonModel(prompt);
|
|
1108
|
-
};
|
|
1109
|
-
/**
|
|
1110
|
-
* Calls the best available embedding model
|
|
1111
|
-
*/
|
|
1112
|
-
MultipleLlmExecutionTools.prototype.callEmbeddingModel = function (prompt) {
|
|
1113
|
-
return this.callCommonModel(prompt);
|
|
1114
|
-
};
|
|
1115
|
-
// <- Note: [🤖]
|
|
1116
|
-
/**
|
|
1117
|
-
* Calls the best available model
|
|
1118
|
-
*
|
|
1119
|
-
* Note: This should be private or protected but is public to be usable with duck typing
|
|
1120
|
-
*/
|
|
1121
|
-
MultipleLlmExecutionTools.prototype.callCommonModel = function (prompt) {
|
|
1122
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
1123
|
-
var errors, _a, _b, llmExecutionTools, _c, error_1, e_3_1;
|
|
1124
|
-
var e_3, _d;
|
|
1125
|
-
var _this = this;
|
|
1126
|
-
return __generator(this, function (_e) {
|
|
1127
|
-
switch (_e.label) {
|
|
1128
|
-
case 0:
|
|
1129
|
-
errors = [];
|
|
1130
|
-
_e.label = 1;
|
|
1131
|
-
case 1:
|
|
1132
|
-
_e.trys.push([1, 15, 16, 17]);
|
|
1133
|
-
_a = __values(this.llmExecutionTools), _b = _a.next();
|
|
1134
|
-
_e.label = 2;
|
|
1135
|
-
case 2:
|
|
1136
|
-
if (!!_b.done) return [3 /*break*/, 14];
|
|
1137
|
-
llmExecutionTools = _b.value;
|
|
1138
|
-
_e.label = 3;
|
|
1139
|
-
case 3:
|
|
1140
|
-
_e.trys.push([3, 12, , 13]);
|
|
1141
|
-
_c = prompt.modelRequirements.modelVariant;
|
|
1142
|
-
switch (_c) {
|
|
1143
|
-
case 'CHAT': return [3 /*break*/, 4];
|
|
1144
|
-
case 'COMPLETION': return [3 /*break*/, 6];
|
|
1145
|
-
case 'EMBEDDING': return [3 /*break*/, 8];
|
|
1146
|
-
}
|
|
1147
|
-
return [3 /*break*/, 10];
|
|
1148
|
-
case 4:
|
|
1149
|
-
if (llmExecutionTools.callChatModel === undefined) {
|
|
1150
|
-
return [3 /*break*/, 13];
|
|
1151
|
-
}
|
|
1152
|
-
return [4 /*yield*/, llmExecutionTools.callChatModel(prompt)];
|
|
1153
|
-
case 5: return [2 /*return*/, _e.sent()];
|
|
1154
|
-
case 6:
|
|
1155
|
-
if (llmExecutionTools.callCompletionModel === undefined) {
|
|
1156
|
-
return [3 /*break*/, 13];
|
|
1157
|
-
}
|
|
1158
|
-
return [4 /*yield*/, llmExecutionTools.callCompletionModel(prompt)];
|
|
1159
|
-
case 7: return [2 /*return*/, _e.sent()];
|
|
1160
|
-
case 8:
|
|
1161
|
-
if (llmExecutionTools.callEmbeddingModel === undefined) {
|
|
1162
|
-
return [3 /*break*/, 13];
|
|
1163
|
-
}
|
|
1164
|
-
return [4 /*yield*/, llmExecutionTools.callEmbeddingModel(prompt)];
|
|
1165
|
-
case 9: return [2 /*return*/, _e.sent()];
|
|
1166
|
-
case 10: throw new UnexpectedError("Unknown model variant \"".concat(prompt.modelRequirements.modelVariant, "\""));
|
|
1167
|
-
case 11: return [3 /*break*/, 13];
|
|
1168
|
-
case 12:
|
|
1169
|
-
error_1 = _e.sent();
|
|
1170
|
-
if (!(error_1 instanceof Error) || error_1 instanceof UnexpectedError) {
|
|
1171
|
-
throw error_1;
|
|
1172
|
-
}
|
|
1173
|
-
errors.push(error_1);
|
|
1174
|
-
return [3 /*break*/, 13];
|
|
1175
|
-
case 13:
|
|
1176
|
-
_b = _a.next();
|
|
1177
|
-
return [3 /*break*/, 2];
|
|
1178
|
-
case 14: return [3 /*break*/, 17];
|
|
1179
|
-
case 15:
|
|
1180
|
-
e_3_1 = _e.sent();
|
|
1181
|
-
e_3 = { error: e_3_1 };
|
|
1182
|
-
return [3 /*break*/, 17];
|
|
1183
|
-
case 16:
|
|
1184
|
-
try {
|
|
1185
|
-
if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
|
|
1186
|
-
}
|
|
1187
|
-
finally { if (e_3) throw e_3.error; }
|
|
1188
|
-
return [7 /*endfinally*/];
|
|
1189
|
-
case 17:
|
|
1190
|
-
if (errors.length === 1) {
|
|
1191
|
-
throw errors[0];
|
|
1192
|
-
}
|
|
1193
|
-
else if (errors.length > 1) {
|
|
1194
|
-
throw new PipelineExecutionError(
|
|
1195
|
-
// TODO: Tell which execution tools failed like
|
|
1196
|
-
// 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
1197
|
-
// 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
1198
|
-
// 3) ...
|
|
1199
|
-
spaceTrim__default["default"](function (block) { return "\n All execution tools failed:\n\n ".concat(block(errors
|
|
1200
|
-
.map(function (error, i) { return "".concat(i + 1, ") **").concat(error.name || 'Error', ":** ").concat(error.message); })
|
|
1201
|
-
.join('\n')), "\n\n "); }));
|
|
1202
|
-
}
|
|
1203
|
-
else if (this.llmExecutionTools.length === 0) {
|
|
1204
|
-
throw new PipelineExecutionError("You have not provided any `LlmExecutionTools`");
|
|
1205
|
-
}
|
|
1206
|
-
else {
|
|
1207
|
-
throw new PipelineExecutionError(spaceTrim__default["default"](function (block) { return "\n You have not provided any `LlmExecutionTools` that support model variant \"".concat(prompt.modelRequirements.modelVariant, "\"\n\n Available `LlmExecutionTools`:\n ").concat(block(_this.description), "\n\n "); }));
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
});
|
|
885
|
+
function exportJson(options) {
|
|
886
|
+
var name = options.name, value = options.value, order = options.order, message = options.message;
|
|
887
|
+
checkSerializableAsJson({ name: name, value: value, message: message });
|
|
888
|
+
var orderedValue =
|
|
889
|
+
// TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
|
|
890
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
891
|
+
// @ts-ignore
|
|
892
|
+
order === undefined
|
|
893
|
+
? deepClone(value)
|
|
894
|
+
: orderJson({
|
|
895
|
+
value: value,
|
|
896
|
+
// <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
|
|
897
|
+
order: order,
|
|
1211
898
|
});
|
|
1212
|
-
|
|
1213
|
-
return
|
|
1214
|
-
}
|
|
899
|
+
$deepFreeze(orderedValue);
|
|
900
|
+
return orderedValue;
|
|
901
|
+
}
|
|
1215
902
|
/**
|
|
1216
|
-
* TODO: [🧠]
|
|
1217
|
-
* TODO: [🏖] If no llmTools have for example not defined `callCompletionModel` this will still return object with defined `callCompletionModel` which just throws `PipelineExecutionError`, make it undefined instead
|
|
1218
|
-
* Look how `countTotalUsage` (and `cacheLlmTools`) implements it
|
|
903
|
+
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
1219
904
|
*/
|
|
1220
905
|
|
|
1221
906
|
/**
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1224
|
-
* @returns {LlmExecutionTools} Single wrapper for multiple LlmExecutionTools
|
|
1225
|
-
*
|
|
1226
|
-
* 0) If there is no LlmExecutionTools, it warns and returns valid but empty LlmExecutionTools
|
|
1227
|
-
* 1) If there is only one LlmExecutionTools, it returns it wrapped in a proxy object
|
|
1228
|
-
* 2) If there are multiple LlmExecutionTools, first will be used first, second will be used if the first hasn`t defined model variant or fails, etc.
|
|
1229
|
-
* 3) When all LlmExecutionTools fail, it throws an error with a list of all errors merged into one
|
|
1230
|
-
*
|
|
1231
|
-
*
|
|
1232
|
-
* Tip: You don't have to use this function directly, just pass an array of LlmExecutionTools to the `ExecutionTools`
|
|
907
|
+
* Order of keys in the pipeline JSON
|
|
1233
908
|
*
|
|
1234
909
|
* @public exported from `@promptbook/core`
|
|
1235
910
|
*/
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
911
|
+
var ORDER_OF_PIPELINE_JSON = [
|
|
912
|
+
// Note: [🍙] In this order will be pipeline serialized
|
|
913
|
+
'title',
|
|
914
|
+
'pipelineUrl',
|
|
915
|
+
'bookVersion',
|
|
916
|
+
'description',
|
|
917
|
+
'formfactorName',
|
|
918
|
+
'parameters',
|
|
919
|
+
'tasks',
|
|
920
|
+
'personas',
|
|
921
|
+
'preparations',
|
|
922
|
+
'knowledgeSources',
|
|
923
|
+
'knowledgePieces',
|
|
924
|
+
'sources', // <- TODO: [🧠] Where should the `sources` be
|
|
925
|
+
];
|
|
926
|
+
/**
|
|
927
|
+
* Nonce which is used for replacing things in strings
|
|
928
|
+
*
|
|
929
|
+
* @private within the repository
|
|
930
|
+
*/
|
|
931
|
+
var REPLACING_NONCE = 'u$k42k%!V2zo34w7Fu#@QUHYPW';
|
|
932
|
+
/**
|
|
933
|
+
* @@@
|
|
934
|
+
*
|
|
935
|
+
* @private within the repository
|
|
936
|
+
*/
|
|
937
|
+
var RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
|
|
938
|
+
/**
|
|
939
|
+
* @@@
|
|
940
|
+
*
|
|
941
|
+
* @private within the repository
|
|
942
|
+
*/
|
|
943
|
+
var RESERVED_PARAMETER_RESTRICTED = 'RESTRICTED-' + REPLACING_NONCE;
|
|
944
|
+
/**
|
|
945
|
+
* The names of the parameters that are reserved for special purposes
|
|
946
|
+
*
|
|
947
|
+
* @public exported from `@promptbook/core`
|
|
948
|
+
*/
|
|
949
|
+
var RESERVED_PARAMETER_NAMES = exportJson({
|
|
950
|
+
name: 'RESERVED_PARAMETER_NAMES',
|
|
951
|
+
message: "The names of the parameters that are reserved for special purposes",
|
|
952
|
+
value: [
|
|
953
|
+
'content',
|
|
954
|
+
'context',
|
|
955
|
+
'knowledge',
|
|
956
|
+
'examples',
|
|
957
|
+
'modelName',
|
|
958
|
+
'currentDate',
|
|
959
|
+
// <- TODO: list here all command names
|
|
960
|
+
// <- TODO: Add more like 'date', 'modelName',...
|
|
961
|
+
// <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
|
|
962
|
+
],
|
|
963
|
+
});
|
|
964
|
+
/**
|
|
965
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
966
|
+
*/
|
|
1254
967
|
|
|
1255
|
-
|
|
968
|
+
/**
|
|
969
|
+
* This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
|
|
970
|
+
*
|
|
971
|
+
* @public exported from `@promptbook/core`
|
|
972
|
+
*/
|
|
973
|
+
var PipelineLogicError = /** @class */ (function (_super) {
|
|
974
|
+
__extends(PipelineLogicError, _super);
|
|
975
|
+
function PipelineLogicError(message) {
|
|
976
|
+
var _this = _super.call(this, message) || this;
|
|
977
|
+
_this.name = 'PipelineLogicError';
|
|
978
|
+
Object.setPrototypeOf(_this, PipelineLogicError.prototype);
|
|
979
|
+
return _this;
|
|
980
|
+
}
|
|
981
|
+
return PipelineLogicError;
|
|
982
|
+
}(Error));
|
|
1256
983
|
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
984
|
+
/**
|
|
985
|
+
* Tests if given string is valid semantic version
|
|
986
|
+
*
|
|
987
|
+
* Note: There are two simmilar functions:
|
|
988
|
+
* - `isValidSemanticVersion` which tests any semantic version
|
|
989
|
+
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
990
|
+
*
|
|
991
|
+
* @public exported from `@promptbook/utils`
|
|
992
|
+
*/
|
|
993
|
+
function isValidSemanticVersion(version) {
|
|
994
|
+
if (typeof version !== 'string') {
|
|
995
|
+
return false;
|
|
1265
996
|
}
|
|
1266
|
-
|
|
997
|
+
if (version.startsWith('0.0.0')) {
|
|
998
|
+
return false;
|
|
999
|
+
}
|
|
1000
|
+
return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
|
|
1267
1001
|
}
|
|
1002
|
+
|
|
1268
1003
|
/**
|
|
1269
|
-
*
|
|
1004
|
+
* Tests if given string is valid promptbook version
|
|
1005
|
+
* It looks into list of known promptbook versions.
|
|
1006
|
+
*
|
|
1007
|
+
* @see https://www.npmjs.com/package/promptbook?activeTab=versions
|
|
1008
|
+
* Note: When you are using for example promptbook 2.0.0 and there already is promptbook 3.0.0 it don`t know about it.
|
|
1009
|
+
* Note: There are two simmilar functions:
|
|
1010
|
+
* - `isValidSemanticVersion` which tests any semantic version
|
|
1011
|
+
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
1012
|
+
*
|
|
1013
|
+
* @public exported from `@promptbook/utils`
|
|
1270
1014
|
*/
|
|
1271
|
-
|
|
1272
|
-
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md",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.md`\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.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md",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.md`\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.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book.md",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- Title should be concise and clear\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 Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book.md`\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- Title should be concise and clear\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.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book.md",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 Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book.md`\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.md"}];
|
|
1015
|
+
function isValidPromptbookVersion(version) {
|
|
1016
|
+
if (!isValidSemanticVersion(version)) {
|
|
1017
|
+
return false;
|
|
1018
|
+
}
|
|
1019
|
+
if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
// <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
|
|
1023
|
+
return true;
|
|
1024
|
+
}
|
|
1273
1025
|
|
|
1274
1026
|
/**
|
|
1275
|
-
*
|
|
1027
|
+
* Checks if an URL is reserved for private networks or localhost.
|
|
1276
1028
|
*
|
|
1277
|
-
*
|
|
1278
|
-
*
|
|
1279
|
-
*
|
|
1029
|
+
* Note: There are two simmilar functions:
|
|
1030
|
+
* - `isUrlOnPrivateNetwork` which tests full URL
|
|
1031
|
+
* - `isHostnameOnPrivateNetwork` *(this one)* which tests just hostname
|
|
1032
|
+
*
|
|
1033
|
+
* @public exported from `@promptbook/utils`
|
|
1280
1034
|
*/
|
|
1281
|
-
function
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
trailingComma: 'all',
|
|
1291
|
-
arrowParens: 'always',
|
|
1292
|
-
printWidth: 120,
|
|
1293
|
-
htmlWhitespaceSensitivity: 'ignore',
|
|
1294
|
-
jsxBracketSameLine: false,
|
|
1295
|
-
bracketSpacing: true,
|
|
1296
|
-
});
|
|
1035
|
+
function isHostnameOnPrivateNetwork(hostname) {
|
|
1036
|
+
if (hostname === 'example.com' ||
|
|
1037
|
+
hostname === 'localhost' ||
|
|
1038
|
+
hostname.endsWith('.localhost') ||
|
|
1039
|
+
hostname.endsWith('.local') ||
|
|
1040
|
+
hostname.endsWith('.test') ||
|
|
1041
|
+
hostname === '127.0.0.1' ||
|
|
1042
|
+
hostname === '::1') {
|
|
1043
|
+
return true;
|
|
1297
1044
|
}
|
|
1298
|
-
|
|
1299
|
-
//
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1045
|
+
if (hostname.includes(':')) {
|
|
1046
|
+
// IPv6
|
|
1047
|
+
var ipParts = hostname.split(':');
|
|
1048
|
+
return ipParts[0] === 'fc00' || ipParts[0] === 'fd00' || ipParts[0] === 'fe80';
|
|
1049
|
+
}
|
|
1050
|
+
else {
|
|
1051
|
+
// IPv4
|
|
1052
|
+
var ipParts = hostname.split('.').map(function (part) { return Number.parseInt(part, 10); });
|
|
1053
|
+
return (ipParts[0] === 10 ||
|
|
1054
|
+
(ipParts[0] === 172 && ipParts[1] >= 16 && ipParts[1] <= 31) ||
|
|
1055
|
+
(ipParts[0] === 192 && ipParts[1] === 168));
|
|
1305
1056
|
}
|
|
1306
1057
|
}
|
|
1307
1058
|
|
|
1308
1059
|
/**
|
|
1309
|
-
*
|
|
1060
|
+
* Checks if an IP address or hostname is reserved for private networks or localhost.
|
|
1061
|
+
*
|
|
1062
|
+
* Note: There are two simmilar functions:
|
|
1063
|
+
* - `isUrlOnPrivateNetwork` *(this one)* which tests full URL
|
|
1064
|
+
* - `isHostnameOnPrivateNetwork` which tests just hostname
|
|
1310
1065
|
*
|
|
1066
|
+
* @param {string} ipAddress - The IP address to check.
|
|
1067
|
+
* @returns {boolean} Returns true if the IP address is reserved for private networks or localhost, otherwise false.
|
|
1311
1068
|
* @public exported from `@promptbook/utils`
|
|
1312
1069
|
*/
|
|
1313
|
-
function
|
|
1314
|
-
|
|
1070
|
+
function isUrlOnPrivateNetwork(url) {
|
|
1071
|
+
if (typeof url === 'string') {
|
|
1072
|
+
url = new URL(url);
|
|
1073
|
+
}
|
|
1074
|
+
return isHostnameOnPrivateNetwork(url.hostname);
|
|
1315
1075
|
}
|
|
1316
1076
|
|
|
1317
1077
|
/**
|
|
1318
|
-
*
|
|
1078
|
+
* Tests if given string is valid URL.
|
|
1319
1079
|
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1080
|
+
* Note: Dataurl are considered perfectly valid.
|
|
1081
|
+
* Note: There are two simmilar functions:
|
|
1082
|
+
* - `isValidUrl` which tests any URL
|
|
1083
|
+
* - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
|
|
1084
|
+
*
|
|
1085
|
+
* @public exported from `@promptbook/utils`
|
|
1324
1086
|
*/
|
|
1325
|
-
function
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
var pipelineString = "# ".concat(title);
|
|
1329
|
-
if (description) {
|
|
1330
|
-
pipelineString += '\n\n';
|
|
1331
|
-
pipelineString += description;
|
|
1332
|
-
}
|
|
1333
|
-
var commands = [];
|
|
1334
|
-
if (pipelineUrl) {
|
|
1335
|
-
commands.push("PIPELINE URL ".concat(pipelineUrl));
|
|
1336
|
-
}
|
|
1337
|
-
if (bookVersion !== "undefined") {
|
|
1338
|
-
commands.push("BOOK VERSION ".concat(bookVersion));
|
|
1087
|
+
function isValidUrl(url) {
|
|
1088
|
+
if (typeof url !== 'string') {
|
|
1089
|
+
return false;
|
|
1339
1090
|
}
|
|
1340
|
-
// TODO: [main] !!!!! This increases size of the bundle and is probbably not necessary
|
|
1341
|
-
pipelineString = prettifyMarkdown(pipelineString);
|
|
1342
1091
|
try {
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
return isInput;
|
|
1346
|
-
})), _h = _g.next(); !_h.done; _h = _g.next()) {
|
|
1347
|
-
var parameter = _h.value;
|
|
1348
|
-
commands.push("INPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
1092
|
+
if (url.startsWith('blob:')) {
|
|
1093
|
+
url = url.replace(/^blob:/, '');
|
|
1349
1094
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
try {
|
|
1354
|
-
if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
|
|
1095
|
+
var urlObject = new URL(url /* because fail is handled */);
|
|
1096
|
+
if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
|
|
1097
|
+
return false;
|
|
1355
1098
|
}
|
|
1356
|
-
|
|
1099
|
+
return true;
|
|
1357
1100
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
var isOutput = _a.isOutput;
|
|
1361
|
-
return isOutput;
|
|
1362
|
-
})), _k = _j.next(); !_k.done; _k = _j.next()) {
|
|
1363
|
-
var parameter = _k.value;
|
|
1364
|
-
commands.push("OUTPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
1365
|
-
}
|
|
1101
|
+
catch (error) {
|
|
1102
|
+
return false;
|
|
1366
1103
|
}
|
|
1367
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
1368
|
-
finally {
|
|
1369
|
-
try {
|
|
1370
|
-
if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
|
|
1371
|
-
}
|
|
1372
|
-
finally { if (e_2) throw e_2.error; }
|
|
1373
|
-
}
|
|
1374
|
-
pipelineString += '\n\n';
|
|
1375
|
-
pipelineString += commands.map(function (command) { return "- ".concat(command); }).join('\n');
|
|
1376
|
-
try {
|
|
1377
|
-
for (var tasks_1 = __values(tasks), tasks_1_1 = tasks_1.next(); !tasks_1_1.done; tasks_1_1 = tasks_1.next()) {
|
|
1378
|
-
var task = tasks_1_1.value;
|
|
1379
|
-
var
|
|
1380
|
-
/* Note: Not using:> name, */
|
|
1381
|
-
title_1 = task.title, description_1 = task.description,
|
|
1382
|
-
/* Note: dependentParameterNames, */
|
|
1383
|
-
jokers = task.jokerParameterNames, taskType = task.taskType, content = task.content, postprocessing = task.postprocessingFunctionNames, expectations = task.expectations, format = task.format, resultingParameterName = task.resultingParameterName;
|
|
1384
|
-
pipelineString += '\n\n';
|
|
1385
|
-
pipelineString += "## ".concat(title_1);
|
|
1386
|
-
if (description_1) {
|
|
1387
|
-
pipelineString += '\n\n';
|
|
1388
|
-
pipelineString += description_1;
|
|
1389
|
-
}
|
|
1390
|
-
var commands_1 = [];
|
|
1391
|
-
var contentLanguage = 'text';
|
|
1392
|
-
if (taskType === 'PROMPT_TASK') {
|
|
1393
|
-
var modelRequirements = task.modelRequirements;
|
|
1394
|
-
var _l = modelRequirements || {}, modelName = _l.modelName, modelVariant = _l.modelVariant;
|
|
1395
|
-
// Note: Do nothing, it is default
|
|
1396
|
-
// commands.push(`PROMPT`);
|
|
1397
|
-
if (modelVariant) {
|
|
1398
|
-
commands_1.push("MODEL VARIANT ".concat(capitalize(modelVariant)));
|
|
1399
|
-
}
|
|
1400
|
-
if (modelName) {
|
|
1401
|
-
commands_1.push("MODEL NAME `".concat(modelName, "`"));
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
else if (taskType === 'SIMPLE_TASK') {
|
|
1405
|
-
commands_1.push("SIMPLE TEMPLATE");
|
|
1406
|
-
// Note: Nothing special here
|
|
1407
|
-
}
|
|
1408
|
-
else if (taskType === 'SCRIPT_TASK') {
|
|
1409
|
-
commands_1.push("SCRIPT");
|
|
1410
|
-
if (task.contentLanguage) {
|
|
1411
|
-
contentLanguage = task.contentLanguage;
|
|
1412
|
-
}
|
|
1413
|
-
else {
|
|
1414
|
-
contentLanguage = '';
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
else if (taskType === 'DIALOG_TASK') {
|
|
1418
|
-
commands_1.push("DIALOG");
|
|
1419
|
-
// Note: Nothing special here
|
|
1420
|
-
} // <- }else if([🅱]
|
|
1421
|
-
if (jokers) {
|
|
1422
|
-
try {
|
|
1423
|
-
for (var jokers_1 = (e_4 = void 0, __values(jokers)), jokers_1_1 = jokers_1.next(); !jokers_1_1.done; jokers_1_1 = jokers_1.next()) {
|
|
1424
|
-
var joker = jokers_1_1.value;
|
|
1425
|
-
commands_1.push("JOKER {".concat(joker, "}"));
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
1429
|
-
finally {
|
|
1430
|
-
try {
|
|
1431
|
-
if (jokers_1_1 && !jokers_1_1.done && (_d = jokers_1.return)) _d.call(jokers_1);
|
|
1432
|
-
}
|
|
1433
|
-
finally { if (e_4) throw e_4.error; }
|
|
1434
|
-
}
|
|
1435
|
-
} /* not else */
|
|
1436
|
-
if (postprocessing) {
|
|
1437
|
-
try {
|
|
1438
|
-
for (var postprocessing_1 = (e_5 = void 0, __values(postprocessing)), postprocessing_1_1 = postprocessing_1.next(); !postprocessing_1_1.done; postprocessing_1_1 = postprocessing_1.next()) {
|
|
1439
|
-
var postprocessingFunctionName = postprocessing_1_1.value;
|
|
1440
|
-
commands_1.push("POSTPROCESSING `".concat(postprocessingFunctionName, "`"));
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
1444
|
-
finally {
|
|
1445
|
-
try {
|
|
1446
|
-
if (postprocessing_1_1 && !postprocessing_1_1.done && (_e = postprocessing_1.return)) _e.call(postprocessing_1);
|
|
1447
|
-
}
|
|
1448
|
-
finally { if (e_5) throw e_5.error; }
|
|
1449
|
-
}
|
|
1450
|
-
} /* not else */
|
|
1451
|
-
if (expectations) {
|
|
1452
|
-
try {
|
|
1453
|
-
for (var _m = (e_6 = void 0, __values(Object.entries(expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
|
|
1454
|
-
var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
|
|
1455
|
-
if (min === max) {
|
|
1456
|
-
commands_1.push("EXPECT EXACTLY ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
1457
|
-
}
|
|
1458
|
-
else {
|
|
1459
|
-
if (min !== undefined) {
|
|
1460
|
-
commands_1.push("EXPECT MIN ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
1461
|
-
} /* not else */
|
|
1462
|
-
if (max !== undefined) {
|
|
1463
|
-
commands_1.push("EXPECT MAX ".concat(max, " ").concat(capitalize(unit + (max > 1 ? 's' : ''))));
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
1469
|
-
finally {
|
|
1470
|
-
try {
|
|
1471
|
-
if (_o && !_o.done && (_f = _m.return)) _f.call(_m);
|
|
1472
|
-
}
|
|
1473
|
-
finally { if (e_6) throw e_6.error; }
|
|
1474
|
-
}
|
|
1475
|
-
} /* not else */
|
|
1476
|
-
if (format) {
|
|
1477
|
-
if (format === 'JSON') {
|
|
1478
|
-
// TODO: @deprecated remove
|
|
1479
|
-
commands_1.push("FORMAT JSON");
|
|
1480
|
-
}
|
|
1481
|
-
} /* not else */
|
|
1482
|
-
pipelineString += '\n\n';
|
|
1483
|
-
pipelineString += commands_1.map(function (command) { return "- ".concat(command); }).join('\n');
|
|
1484
|
-
pipelineString += '\n\n';
|
|
1485
|
-
pipelineString += '```' + contentLanguage;
|
|
1486
|
-
pipelineString += '\n';
|
|
1487
|
-
pipelineString += spaceTrim__default["default"](content);
|
|
1488
|
-
// <- TODO: [main] !!! Escape
|
|
1489
|
-
// <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
|
|
1490
|
-
pipelineString += '\n';
|
|
1491
|
-
pipelineString += '```';
|
|
1492
|
-
pipelineString += '\n\n';
|
|
1493
|
-
pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: [main] !!! If the parameter here has description, add it and use taskParameterJsonToString
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
1497
|
-
finally {
|
|
1498
|
-
try {
|
|
1499
|
-
if (tasks_1_1 && !tasks_1_1.done && (_c = tasks_1.return)) _c.call(tasks_1);
|
|
1500
|
-
}
|
|
1501
|
-
finally { if (e_3) throw e_3.error; }
|
|
1502
|
-
}
|
|
1503
|
-
return pipelineString;
|
|
1504
|
-
}
|
|
1505
|
-
/**
|
|
1506
|
-
* @private internal utility of `pipelineJsonToString`
|
|
1507
|
-
*/
|
|
1508
|
-
function taskParameterJsonToString(taskParameterJson) {
|
|
1509
|
-
var name = taskParameterJson.name, description = taskParameterJson.description;
|
|
1510
|
-
var parameterString = "{".concat(name, "}");
|
|
1511
|
-
if (description) {
|
|
1512
|
-
parameterString = "".concat(parameterString, " ").concat(description);
|
|
1513
|
-
}
|
|
1514
|
-
return parameterString;
|
|
1515
1104
|
}
|
|
1516
|
-
/**
|
|
1517
|
-
* TODO: [🛋] Implement new features and commands into `pipelineJsonToString` + `taskParameterJsonToString` , use `stringifyCommand`
|
|
1518
|
-
* TODO: [🧠] Is there a way to auto-detect missing features in pipelineJsonToString
|
|
1519
|
-
* TODO: [🏛] Maybe make some markdown builder
|
|
1520
|
-
* TODO: [🏛] Escape all
|
|
1521
|
-
* TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
|
|
1522
|
-
*/
|
|
1523
|
-
|
|
1524
|
-
/**
|
|
1525
|
-
* This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
|
|
1526
|
-
*
|
|
1527
|
-
* @public exported from `@promptbook/core`
|
|
1528
|
-
*/
|
|
1529
|
-
var ParseError = /** @class */ (function (_super) {
|
|
1530
|
-
__extends(ParseError, _super);
|
|
1531
|
-
function ParseError(message) {
|
|
1532
|
-
var _this = _super.call(this, message) || this;
|
|
1533
|
-
_this.name = 'ParseError';
|
|
1534
|
-
Object.setPrototypeOf(_this, ParseError.prototype);
|
|
1535
|
-
return _this;
|
|
1536
|
-
}
|
|
1537
|
-
return ParseError;
|
|
1538
|
-
}(Error));
|
|
1539
|
-
/**
|
|
1540
|
-
* TODO: Maybe split `ParseError` and `ApplyError`
|
|
1541
|
-
*/
|
|
1542
|
-
|
|
1543
|
-
/**
|
|
1544
|
-
* This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
|
|
1545
|
-
*
|
|
1546
|
-
* @public exported from `@promptbook/core`
|
|
1547
|
-
*/
|
|
1548
|
-
var PipelineLogicError = /** @class */ (function (_super) {
|
|
1549
|
-
__extends(PipelineLogicError, _super);
|
|
1550
|
-
function PipelineLogicError(message) {
|
|
1551
|
-
var _this = _super.call(this, message) || this;
|
|
1552
|
-
_this.name = 'PipelineLogicError';
|
|
1553
|
-
Object.setPrototypeOf(_this, PipelineLogicError.prototype);
|
|
1554
|
-
return _this;
|
|
1555
|
-
}
|
|
1556
|
-
return PipelineLogicError;
|
|
1557
|
-
}(Error));
|
|
1558
1105
|
|
|
1559
1106
|
/**
|
|
1560
|
-
* Tests if given string is valid
|
|
1107
|
+
* Tests if given string is valid pipeline URL URL.
|
|
1561
1108
|
*
|
|
1562
1109
|
* Note: There are two simmilar functions:
|
|
1563
|
-
* - `
|
|
1564
|
-
* - `
|
|
1110
|
+
* - `isValidUrl` which tests any URL
|
|
1111
|
+
* - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
|
|
1565
1112
|
*
|
|
1566
1113
|
* @public exported from `@promptbook/utils`
|
|
1567
1114
|
*/
|
|
1568
|
-
function
|
|
1569
|
-
if (
|
|
1115
|
+
function isValidPipelineUrl(url) {
|
|
1116
|
+
if (!isValidUrl(url)) {
|
|
1570
1117
|
return false;
|
|
1571
1118
|
}
|
|
1572
|
-
if (
|
|
1119
|
+
if (!url.startsWith('https://')) {
|
|
1573
1120
|
return false;
|
|
1574
1121
|
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
/**
|
|
1579
|
-
* Tests if given string is valid promptbook version
|
|
1580
|
-
* It looks into list of known promptbook versions.
|
|
1581
|
-
*
|
|
1582
|
-
* @see https://www.npmjs.com/package/promptbook?activeTab=versions
|
|
1583
|
-
* Note: When you are using for example promptbook 2.0.0 and there already is promptbook 3.0.0 it don`t know about it.
|
|
1584
|
-
* Note: There are two simmilar functions:
|
|
1585
|
-
* - `isValidSemanticVersion` which tests any semantic version
|
|
1586
|
-
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
1587
|
-
*
|
|
1588
|
-
* @public exported from `@promptbook/utils`
|
|
1589
|
-
*/
|
|
1590
|
-
function isValidPromptbookVersion(version) {
|
|
1591
|
-
if (!isValidSemanticVersion(version)) {
|
|
1122
|
+
if (url.includes('#')) {
|
|
1123
|
+
// TODO: [🐠]
|
|
1592
1124
|
return false;
|
|
1593
1125
|
}
|
|
1594
|
-
if (
|
|
1126
|
+
if (isUrlOnPrivateNetwork(url)) {
|
|
1595
1127
|
return false;
|
|
1596
1128
|
}
|
|
1597
|
-
// <- TODO: [main] !!! Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
|
|
1598
1129
|
return true;
|
|
1599
1130
|
}
|
|
1131
|
+
/**
|
|
1132
|
+
* TODO: [🐠] Maybe more info why the URL is invalid
|
|
1133
|
+
*/
|
|
1600
1134
|
|
|
1601
1135
|
/**
|
|
1602
|
-
*
|
|
1136
|
+
* Validates PipelineJson if it is logically valid
|
|
1603
1137
|
*
|
|
1604
|
-
*
|
|
1605
|
-
* -
|
|
1606
|
-
* - `isHostnameOnPrivateNetwork` *(this one)* which tests just hostname
|
|
1138
|
+
* It checks:
|
|
1139
|
+
* - if it has correct parameters dependency
|
|
1607
1140
|
*
|
|
1608
|
-
*
|
|
1141
|
+
* It does NOT check:
|
|
1142
|
+
* - if it is valid json
|
|
1143
|
+
* - if it is meaningful
|
|
1144
|
+
*
|
|
1145
|
+
* @param pipeline valid or invalid PipelineJson
|
|
1146
|
+
* @returns the same pipeline if it is logically valid
|
|
1147
|
+
* @throws {PipelineLogicError} on logical error in the pipeline
|
|
1148
|
+
* @public exported from `@promptbook/core`
|
|
1609
1149
|
*/
|
|
1610
|
-
function
|
|
1611
|
-
if (
|
|
1612
|
-
|
|
1613
|
-
hostname.endsWith('.localhost') ||
|
|
1614
|
-
hostname.endsWith('.local') ||
|
|
1615
|
-
hostname.endsWith('.test') ||
|
|
1616
|
-
hostname === '127.0.0.1' ||
|
|
1617
|
-
hostname === '::1') {
|
|
1618
|
-
return true;
|
|
1619
|
-
}
|
|
1620
|
-
if (hostname.includes(':')) {
|
|
1621
|
-
// IPv6
|
|
1622
|
-
var ipParts = hostname.split(':');
|
|
1623
|
-
return ipParts[0] === 'fc00' || ipParts[0] === 'fd00' || ipParts[0] === 'fe80';
|
|
1624
|
-
}
|
|
1625
|
-
else {
|
|
1626
|
-
// IPv4
|
|
1627
|
-
var ipParts = hostname.split('.').map(function (part) { return Number.parseInt(part, 10); });
|
|
1628
|
-
return (ipParts[0] === 10 ||
|
|
1629
|
-
(ipParts[0] === 172 && ipParts[1] >= 16 && ipParts[1] <= 31) ||
|
|
1630
|
-
(ipParts[0] === 192 && ipParts[1] === 168));
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
/**
|
|
1635
|
-
* Checks if an IP address or hostname is reserved for private networks or localhost.
|
|
1636
|
-
*
|
|
1637
|
-
* Note: There are two simmilar functions:
|
|
1638
|
-
* - `isUrlOnPrivateNetwork` *(this one)* which tests full URL
|
|
1639
|
-
* - `isHostnameOnPrivateNetwork` which tests just hostname
|
|
1640
|
-
*
|
|
1641
|
-
* @param {string} ipAddress - The IP address to check.
|
|
1642
|
-
* @returns {boolean} Returns true if the IP address is reserved for private networks or localhost, otherwise false.
|
|
1643
|
-
* @public exported from `@promptbook/utils`
|
|
1644
|
-
*/
|
|
1645
|
-
function isUrlOnPrivateNetwork(url) {
|
|
1646
|
-
if (typeof url === 'string') {
|
|
1647
|
-
url = new URL(url);
|
|
1648
|
-
}
|
|
1649
|
-
return isHostnameOnPrivateNetwork(url.hostname);
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
/**
|
|
1653
|
-
* Tests if given string is valid URL.
|
|
1654
|
-
*
|
|
1655
|
-
* Note: Dataurl are considered perfectly valid.
|
|
1656
|
-
* Note: There are two simmilar functions:
|
|
1657
|
-
* - `isValidUrl` which tests any URL
|
|
1658
|
-
* - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
|
|
1659
|
-
*
|
|
1660
|
-
* @public exported from `@promptbook/utils`
|
|
1661
|
-
*/
|
|
1662
|
-
function isValidUrl(url) {
|
|
1663
|
-
if (typeof url !== 'string') {
|
|
1664
|
-
return false;
|
|
1665
|
-
}
|
|
1666
|
-
try {
|
|
1667
|
-
if (url.startsWith('blob:')) {
|
|
1668
|
-
url = url.replace(/^blob:/, '');
|
|
1669
|
-
}
|
|
1670
|
-
var urlObject = new URL(url /* because fail is handled */);
|
|
1671
|
-
if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
|
|
1672
|
-
return false;
|
|
1673
|
-
}
|
|
1674
|
-
return true;
|
|
1675
|
-
}
|
|
1676
|
-
catch (error) {
|
|
1677
|
-
return false;
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
|
|
1681
|
-
/**
|
|
1682
|
-
* Tests if given string is valid pipeline URL URL.
|
|
1683
|
-
*
|
|
1684
|
-
* Note: There are two simmilar functions:
|
|
1685
|
-
* - `isValidUrl` which tests any URL
|
|
1686
|
-
* - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
|
|
1687
|
-
*
|
|
1688
|
-
* @public exported from `@promptbook/utils`
|
|
1689
|
-
*/
|
|
1690
|
-
function isValidPipelineUrl(url) {
|
|
1691
|
-
if (!isValidUrl(url)) {
|
|
1692
|
-
return false;
|
|
1693
|
-
}
|
|
1694
|
-
if (!url.startsWith('https://')) {
|
|
1695
|
-
return false;
|
|
1696
|
-
}
|
|
1697
|
-
if (!(url.endsWith('.book.md') || url.endsWith('.book') || url.endsWith('.book.md') || url.endsWith('.ptbk'))) {
|
|
1698
|
-
return false;
|
|
1699
|
-
}
|
|
1700
|
-
if (url.includes('#')) {
|
|
1701
|
-
// TODO: [🐠]
|
|
1702
|
-
return false;
|
|
1703
|
-
}
|
|
1704
|
-
if (isUrlOnPrivateNetwork(url)) {
|
|
1705
|
-
return false;
|
|
1706
|
-
}
|
|
1707
|
-
return true;
|
|
1708
|
-
}
|
|
1709
|
-
/**
|
|
1710
|
-
* TODO: [🐠] Maybe more info why the URL is invalid
|
|
1711
|
-
*/
|
|
1712
|
-
|
|
1713
|
-
/**
|
|
1714
|
-
* Validates PipelineJson if it is logically valid
|
|
1715
|
-
*
|
|
1716
|
-
* It checks:
|
|
1717
|
-
* - if it has correct parameters dependency
|
|
1718
|
-
*
|
|
1719
|
-
* It does NOT check:
|
|
1720
|
-
* - if it is valid json
|
|
1721
|
-
* - if it is meaningful
|
|
1722
|
-
*
|
|
1723
|
-
* @param pipeline valid or invalid PipelineJson
|
|
1724
|
-
* @returns the same pipeline if it is logically valid
|
|
1725
|
-
* @throws {PipelineLogicError} on logical error in the pipeline
|
|
1726
|
-
* @public exported from `@promptbook/core`
|
|
1727
|
-
*/
|
|
1728
|
-
function validatePipeline(pipeline) {
|
|
1729
|
-
if (IS_PIPELINE_LOGIC_VALIDATED) {
|
|
1730
|
-
validatePipelineCore(pipeline);
|
|
1150
|
+
function validatePipeline(pipeline) {
|
|
1151
|
+
if (IS_PIPELINE_LOGIC_VALIDATED) {
|
|
1152
|
+
validatePipeline_InnerFunction(pipeline);
|
|
1731
1153
|
}
|
|
1732
1154
|
else {
|
|
1733
1155
|
try {
|
|
1734
|
-
|
|
1156
|
+
validatePipeline_InnerFunction(pipeline);
|
|
1735
1157
|
}
|
|
1736
1158
|
catch (error) {
|
|
1737
1159
|
if (!(error instanceof PipelineLogicError)) {
|
|
@@ -1745,7 +1167,7 @@
|
|
|
1745
1167
|
/**
|
|
1746
1168
|
* @private internal function for `validatePipeline`
|
|
1747
1169
|
*/
|
|
1748
|
-
function
|
|
1170
|
+
function validatePipeline_InnerFunction(pipeline) {
|
|
1749
1171
|
// TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
|
|
1750
1172
|
var e_1, _a, e_2, _b, e_3, _c;
|
|
1751
1173
|
var pipelineIdentification = (function () {
|
|
@@ -1969,11 +1391,11 @@
|
|
|
1969
1391
|
_loop_3();
|
|
1970
1392
|
}
|
|
1971
1393
|
// Note: Check that formfactor is corresponding to the pipeline interface
|
|
1972
|
-
// TODO:
|
|
1394
|
+
// TODO: !!6 Implement this
|
|
1973
1395
|
// pipeline.formfactorName
|
|
1974
1396
|
}
|
|
1975
1397
|
/**
|
|
1976
|
-
* TODO:
|
|
1398
|
+
* TODO: [🧞♀️] Do not allow joker + foreach
|
|
1977
1399
|
* TODO: [🧠] Work with promptbookVersion
|
|
1978
1400
|
* TODO: Use here some json-schema, Zod or something similar and change it to:
|
|
1979
1401
|
* > /**
|
|
@@ -1985,11 +1407,11 @@
|
|
|
1985
1407
|
* > ex port function validatePipeline(promptbook: really_unknown): asserts promptbook is PipelineJson {
|
|
1986
1408
|
*/
|
|
1987
1409
|
/**
|
|
1988
|
-
* TODO: [🧳][main]
|
|
1989
|
-
* TODO: [🧳][🐝][main]
|
|
1990
|
-
* TODO: [🧳][main]
|
|
1991
|
-
* TODO: [🧳][main]
|
|
1992
|
-
* TODO: [🧳][main]
|
|
1410
|
+
* TODO: [🧳][main] !!4 Validate that all examples match expectations
|
|
1411
|
+
* TODO: [🧳][🐝][main] !!4 Validate that knowledge is valid (non-void)
|
|
1412
|
+
* TODO: [🧳][main] !!4 Validate that persona can be used only with CHAT variant
|
|
1413
|
+
* TODO: [🧳][main] !!4 Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
|
|
1414
|
+
* TODO: [🧳][main] !!4 Validate that reserved parameter is not used as joker
|
|
1993
1415
|
* TODO: [🧠] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
|
|
1994
1416
|
* TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
|
|
1995
1417
|
*/
|
|
@@ -2125,7 +1547,7 @@
|
|
|
2125
1547
|
pipelineJsonToString(unpreparePipeline(pipeline)) !==
|
|
2126
1548
|
pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
|
|
2127
1549
|
var existing = this.collection.get(pipeline.pipelineUrl);
|
|
2128
|
-
throw new PipelineUrlError(spaceTrim.spaceTrim("\n Pipeline with URL
|
|
1550
|
+
throw new PipelineUrlError(spaceTrim.spaceTrim("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is already in the collection \uD83C\uDF4E\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: You have probably forgotten to run \"ptbk make\" to update the collection\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
|
|
2129
1551
|
}
|
|
2130
1552
|
// Note: [🧠] Overwrite existing pipeline with the same URL
|
|
2131
1553
|
this.collection.set(pipeline.pipelineUrl, pipeline);
|
|
@@ -2190,6 +1612,38 @@
|
|
|
2190
1612
|
return new (SimplePipelineCollection.bind.apply(SimplePipelineCollection, __spreadArray([void 0], __read(promptbooks), false)))();
|
|
2191
1613
|
}
|
|
2192
1614
|
|
|
1615
|
+
/**
|
|
1616
|
+
* This error type indicates that some tools are missing for pipeline execution or preparation
|
|
1617
|
+
*
|
|
1618
|
+
* @public exported from `@promptbook/core`
|
|
1619
|
+
*/
|
|
1620
|
+
var MissingToolsError = /** @class */ (function (_super) {
|
|
1621
|
+
__extends(MissingToolsError, _super);
|
|
1622
|
+
function MissingToolsError(message) {
|
|
1623
|
+
var _this = _super.call(this, spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note: You have probbably forgot to provide some tools for pipeline execution or preparation\n\n "); })) || this;
|
|
1624
|
+
_this.name = 'MissingToolsError';
|
|
1625
|
+
Object.setPrototypeOf(_this, MissingToolsError.prototype);
|
|
1626
|
+
return _this;
|
|
1627
|
+
}
|
|
1628
|
+
return MissingToolsError;
|
|
1629
|
+
}(Error));
|
|
1630
|
+
|
|
1631
|
+
/**
|
|
1632
|
+
* This error indicates errors during the execution of the pipeline
|
|
1633
|
+
*
|
|
1634
|
+
* @public exported from `@promptbook/core`
|
|
1635
|
+
*/
|
|
1636
|
+
var PipelineExecutionError = /** @class */ (function (_super) {
|
|
1637
|
+
__extends(PipelineExecutionError, _super);
|
|
1638
|
+
function PipelineExecutionError(message) {
|
|
1639
|
+
var _this = _super.call(this, message) || this;
|
|
1640
|
+
_this.name = 'PipelineExecutionError';
|
|
1641
|
+
Object.setPrototypeOf(_this, PipelineExecutionError.prototype);
|
|
1642
|
+
return _this;
|
|
1643
|
+
}
|
|
1644
|
+
return PipelineExecutionError;
|
|
1645
|
+
}(Error));
|
|
1646
|
+
|
|
2193
1647
|
/**
|
|
2194
1648
|
* This error indicates problems parsing the format value
|
|
2195
1649
|
*
|
|
@@ -2429,11 +1883,16 @@
|
|
|
2429
1883
|
/**
|
|
2430
1884
|
* Determine if the pipeline is fully prepared
|
|
2431
1885
|
*
|
|
1886
|
+
* @see https://github.com/webgptorg/promptbook/discussions/196
|
|
1887
|
+
*
|
|
2432
1888
|
* @public exported from `@promptbook/core`
|
|
2433
1889
|
*/
|
|
2434
1890
|
function isPipelinePrepared(pipeline) {
|
|
2435
1891
|
// Note: Ignoring `pipeline.preparations` @@@
|
|
2436
1892
|
// Note: Ignoring `pipeline.knowledgePieces` @@@
|
|
1893
|
+
if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
|
|
1894
|
+
return false;
|
|
1895
|
+
}
|
|
2437
1896
|
if (!pipeline.personas.every(function (persona) { return persona.modelRequirements !== undefined; })) {
|
|
2438
1897
|
return false;
|
|
2439
1898
|
}
|
|
@@ -2449,7 +1908,7 @@
|
|
|
2449
1908
|
return true;
|
|
2450
1909
|
}
|
|
2451
1910
|
/**
|
|
2452
|
-
* TODO: [🔃][main]
|
|
1911
|
+
* TODO: [🔃][main] If the pipeline was prepared with different version or different set of models, prepare it once again
|
|
2453
1912
|
* TODO: [🐠] Maybe base this on `makeValidator`
|
|
2454
1913
|
* TODO: [🧊] Pipeline can be partially prepared, this should return true ONLY if fully prepared
|
|
2455
1914
|
* TODO: [🧿] Maybe do same process with same granularity and subfinctions as `preparePipeline`
|
|
@@ -2551,76 +2010,204 @@
|
|
|
2551
2010
|
}
|
|
2552
2011
|
|
|
2553
2012
|
/**
|
|
2554
|
-
*
|
|
2013
|
+
* Represents the usage with no resources consumed
|
|
2555
2014
|
*
|
|
2556
|
-
* @
|
|
2557
|
-
* @returns the list of variable names
|
|
2558
|
-
* @throws {ParseError} if the script is invalid
|
|
2559
|
-
* @public exported from `@promptbook/utils` <- Note: [👖] This is usable elsewhere than in Promptbook, so keeping in utils
|
|
2015
|
+
* @public exported from `@promptbook/core`
|
|
2560
2016
|
*/
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
var variableName = undefined;
|
|
2583
|
-
if (error.message.startsWith("Can't")) {
|
|
2584
|
-
// 🍏 Case
|
|
2585
|
-
variableName = error.message.split(' ').pop();
|
|
2586
|
-
}
|
|
2587
|
-
else {
|
|
2588
|
-
// 🌟 Case
|
|
2589
|
-
variableName = error.message.split(' ').shift();
|
|
2590
|
-
}
|
|
2591
|
-
if (variableName === undefined) {
|
|
2592
|
-
throw error;
|
|
2593
|
-
}
|
|
2594
|
-
if (script.includes(variableName + '(')) {
|
|
2595
|
-
script = "const ".concat(variableName, " = ()=>'';") + script;
|
|
2596
|
-
}
|
|
2597
|
-
else {
|
|
2598
|
-
variables.add(variableName);
|
|
2599
|
-
script = "const ".concat(variableName, " = '';") + script;
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
}
|
|
2603
|
-
catch (error) {
|
|
2604
|
-
if (!(error instanceof Error)) {
|
|
2605
|
-
throw error;
|
|
2606
|
-
}
|
|
2607
|
-
throw new ParseError(spaceTrim.spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.toString()), "}\n\n\n Found variables:\n\n ").concat(Array.from(variables)
|
|
2608
|
-
.map(function (variableName, i) { return "".concat(i + 1, ") ").concat(variableName); })
|
|
2609
|
-
.join('\n'), "\n\n\n The script:\n\n ```javascript\n ").concat(block(originalScript), "\n ```\n "); }));
|
|
2610
|
-
}
|
|
2611
|
-
return variables;
|
|
2612
|
-
}
|
|
2017
|
+
var ZERO_USAGE = $deepFreeze({
|
|
2018
|
+
price: { value: 0 },
|
|
2019
|
+
input: {
|
|
2020
|
+
tokensCount: { value: 0 },
|
|
2021
|
+
charactersCount: { value: 0 },
|
|
2022
|
+
wordsCount: { value: 0 },
|
|
2023
|
+
sentencesCount: { value: 0 },
|
|
2024
|
+
linesCount: { value: 0 },
|
|
2025
|
+
paragraphsCount: { value: 0 },
|
|
2026
|
+
pagesCount: { value: 0 },
|
|
2027
|
+
},
|
|
2028
|
+
output: {
|
|
2029
|
+
tokensCount: { value: 0 },
|
|
2030
|
+
charactersCount: { value: 0 },
|
|
2031
|
+
wordsCount: { value: 0 },
|
|
2032
|
+
sentencesCount: { value: 0 },
|
|
2033
|
+
linesCount: { value: 0 },
|
|
2034
|
+
paragraphsCount: { value: 0 },
|
|
2035
|
+
pagesCount: { value: 0 },
|
|
2036
|
+
},
|
|
2037
|
+
});
|
|
2613
2038
|
/**
|
|
2614
|
-
*
|
|
2039
|
+
* Represents the usage with unknown resources consumed
|
|
2040
|
+
*
|
|
2041
|
+
* @public exported from `@promptbook/core`
|
|
2042
|
+
*/
|
|
2043
|
+
$deepFreeze({
|
|
2044
|
+
price: { value: 0, isUncertain: true },
|
|
2045
|
+
input: {
|
|
2046
|
+
tokensCount: { value: 0, isUncertain: true },
|
|
2047
|
+
charactersCount: { value: 0, isUncertain: true },
|
|
2048
|
+
wordsCount: { value: 0, isUncertain: true },
|
|
2049
|
+
sentencesCount: { value: 0, isUncertain: true },
|
|
2050
|
+
linesCount: { value: 0, isUncertain: true },
|
|
2051
|
+
paragraphsCount: { value: 0, isUncertain: true },
|
|
2052
|
+
pagesCount: { value: 0, isUncertain: true },
|
|
2053
|
+
},
|
|
2054
|
+
output: {
|
|
2055
|
+
tokensCount: { value: 0, isUncertain: true },
|
|
2056
|
+
charactersCount: { value: 0, isUncertain: true },
|
|
2057
|
+
wordsCount: { value: 0, isUncertain: true },
|
|
2058
|
+
sentencesCount: { value: 0, isUncertain: true },
|
|
2059
|
+
linesCount: { value: 0, isUncertain: true },
|
|
2060
|
+
paragraphsCount: { value: 0, isUncertain: true },
|
|
2061
|
+
pagesCount: { value: 0, isUncertain: true },
|
|
2062
|
+
},
|
|
2063
|
+
});
|
|
2064
|
+
/**
|
|
2065
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2615
2066
|
*/
|
|
2616
2067
|
|
|
2617
2068
|
/**
|
|
2618
|
-
*
|
|
2069
|
+
* Function `addUsage` will add multiple usages into one
|
|
2619
2070
|
*
|
|
2620
|
-
*
|
|
2621
|
-
*
|
|
2622
|
-
* @
|
|
2623
|
-
|
|
2071
|
+
* Note: If you provide 0 values, it returns ZERO_USAGE
|
|
2072
|
+
*
|
|
2073
|
+
* @public exported from `@promptbook/core`
|
|
2074
|
+
*/
|
|
2075
|
+
function addUsage() {
|
|
2076
|
+
var usageItems = [];
|
|
2077
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
2078
|
+
usageItems[_i] = arguments[_i];
|
|
2079
|
+
}
|
|
2080
|
+
return usageItems.reduce(function (acc, item) {
|
|
2081
|
+
var e_1, _a, e_2, _b;
|
|
2082
|
+
var _c;
|
|
2083
|
+
acc.price.value += ((_c = item.price) === null || _c === void 0 ? void 0 : _c.value) || 0;
|
|
2084
|
+
try {
|
|
2085
|
+
for (var _d = __values(Object.keys(acc.input)), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
2086
|
+
var key = _e.value;
|
|
2087
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2088
|
+
//@ts-ignore
|
|
2089
|
+
if (item.input[key]) {
|
|
2090
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2091
|
+
//@ts-ignore
|
|
2092
|
+
acc.input[key].value += item.input[key].value || 0;
|
|
2093
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2094
|
+
//@ts-ignore
|
|
2095
|
+
if (item.input[key].isUncertain) {
|
|
2096
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2097
|
+
//@ts-ignore
|
|
2098
|
+
acc.input[key].isUncertain = true;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
2104
|
+
finally {
|
|
2105
|
+
try {
|
|
2106
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
2107
|
+
}
|
|
2108
|
+
finally { if (e_1) throw e_1.error; }
|
|
2109
|
+
}
|
|
2110
|
+
try {
|
|
2111
|
+
for (var _f = __values(Object.keys(acc.output)), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
2112
|
+
var key = _g.value;
|
|
2113
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2114
|
+
//@ts-ignore
|
|
2115
|
+
if (item.output[key]) {
|
|
2116
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2117
|
+
//@ts-ignore
|
|
2118
|
+
acc.output[key].value += item.output[key].value || 0;
|
|
2119
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2120
|
+
//@ts-ignore
|
|
2121
|
+
if (item.output[key].isUncertain) {
|
|
2122
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2123
|
+
//@ts-ignore
|
|
2124
|
+
acc.output[key].isUncertain = true;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
2130
|
+
finally {
|
|
2131
|
+
try {
|
|
2132
|
+
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
2133
|
+
}
|
|
2134
|
+
finally { if (e_2) throw e_2.error; }
|
|
2135
|
+
}
|
|
2136
|
+
return acc;
|
|
2137
|
+
}, deepClone(ZERO_USAGE));
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
/**
|
|
2141
|
+
* Parses the given script and returns the list of all used variables that are not defined in the script
|
|
2142
|
+
*
|
|
2143
|
+
* @param script from which to extract the variables
|
|
2144
|
+
* @returns the list of variable names
|
|
2145
|
+
* @throws {ParseError} if the script is invalid
|
|
2146
|
+
* @public exported from `@promptbook/utils` <- Note: [👖] This is usable elsewhere than in Promptbook, so keeping in utils
|
|
2147
|
+
*/
|
|
2148
|
+
function extractVariablesFromScript(script) {
|
|
2149
|
+
var variables = new Set();
|
|
2150
|
+
var originalScript = script;
|
|
2151
|
+
script = "(()=>{".concat(script, "})()");
|
|
2152
|
+
try {
|
|
2153
|
+
for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
|
|
2154
|
+
try {
|
|
2155
|
+
eval(script);
|
|
2156
|
+
}
|
|
2157
|
+
catch (error) {
|
|
2158
|
+
if (!(error instanceof ReferenceError)) {
|
|
2159
|
+
throw error;
|
|
2160
|
+
}
|
|
2161
|
+
/*
|
|
2162
|
+
Note: Parsing the error
|
|
2163
|
+
🌟 Most devices:
|
|
2164
|
+
[PipelineUrlError: thing is not defined]
|
|
2165
|
+
|
|
2166
|
+
🍏 iPhone`s Safari:
|
|
2167
|
+
[PipelineUrlError: Can't find variable: thing]
|
|
2168
|
+
*/
|
|
2169
|
+
var variableName = undefined;
|
|
2170
|
+
if (error.message.startsWith("Can't")) {
|
|
2171
|
+
// 🍏 Case
|
|
2172
|
+
variableName = error.message.split(' ').pop();
|
|
2173
|
+
}
|
|
2174
|
+
else {
|
|
2175
|
+
// 🌟 Case
|
|
2176
|
+
variableName = error.message.split(' ').shift();
|
|
2177
|
+
}
|
|
2178
|
+
if (variableName === undefined) {
|
|
2179
|
+
throw error;
|
|
2180
|
+
}
|
|
2181
|
+
if (script.includes(variableName + '(')) {
|
|
2182
|
+
script = "const ".concat(variableName, " = ()=>'';") + script;
|
|
2183
|
+
}
|
|
2184
|
+
else {
|
|
2185
|
+
variables.add(variableName);
|
|
2186
|
+
script = "const ".concat(variableName, " = '';") + script;
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
catch (error) {
|
|
2191
|
+
if (!(error instanceof Error)) {
|
|
2192
|
+
throw error;
|
|
2193
|
+
}
|
|
2194
|
+
throw new ParseError(spaceTrim.spaceTrim(function (block) { return "\n Can not extract variables from the script\n ".concat(block(error.stack || error.message), "\n\n Found variables:\n ").concat(Array.from(variables)
|
|
2195
|
+
.map(function (variableName, i) { return "".concat(i + 1, ") ").concat(variableName); })
|
|
2196
|
+
.join('\n'), "\n\n\n The script:\n\n ```javascript\n ").concat(block(originalScript), "\n ```\n "); }));
|
|
2197
|
+
}
|
|
2198
|
+
return variables;
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* TODO: [🔣] Support for multiple languages - python, java,...
|
|
2202
|
+
*/
|
|
2203
|
+
|
|
2204
|
+
/**
|
|
2205
|
+
* Parses the task and returns the set of all used parameters
|
|
2206
|
+
*
|
|
2207
|
+
* @param task the task with used parameters
|
|
2208
|
+
* @returns the set of parameter names
|
|
2209
|
+
* @throws {ParseError} if the script is invalid
|
|
2210
|
+
* @public exported from `@promptbook/core` <- Note: [👖] This utility is so tightly interconnected with the Promptbook that it is not exported as util but in core
|
|
2624
2211
|
*/
|
|
2625
2212
|
function extractParameterNamesFromTask(task) {
|
|
2626
2213
|
var e_1, _a, e_2, _b, e_3, _c, e_4, _d;
|
|
@@ -2870,242 +2457,513 @@
|
|
|
2870
2457
|
mappedData = _a.sent();
|
|
2871
2458
|
return [2 /*return*/, papaparse.unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
|
|
2872
2459
|
}
|
|
2873
|
-
});
|
|
2874
|
-
});
|
|
2875
|
-
},
|
|
2876
|
-
},
|
|
2877
|
-
],
|
|
2878
|
-
};
|
|
2879
|
-
/**
|
|
2880
|
-
* TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
|
|
2881
|
-
* TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
|
|
2882
|
-
* TODO: [🍓] In `CsvFormatDefinition` implement `heal
|
|
2883
|
-
* TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
|
|
2884
|
-
* TODO: [🏢] Allow to expect something inside CSV objects and other formats
|
|
2885
|
-
*/
|
|
2886
|
-
|
|
2887
|
-
/**
|
|
2888
|
-
*
|
|
2889
|
-
*
|
|
2890
|
-
* @
|
|
2891
|
-
*/
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
*
|
|
2910
|
-
*
|
|
2911
|
-
*
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2460
|
+
});
|
|
2461
|
+
});
|
|
2462
|
+
},
|
|
2463
|
+
},
|
|
2464
|
+
],
|
|
2465
|
+
};
|
|
2466
|
+
/**
|
|
2467
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
|
|
2468
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
|
|
2469
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement `heal
|
|
2470
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
|
|
2471
|
+
* TODO: [🏢] Allow to expect something inside CSV objects and other formats
|
|
2472
|
+
*/
|
|
2473
|
+
|
|
2474
|
+
/**
|
|
2475
|
+
* Definition for JSON format
|
|
2476
|
+
*
|
|
2477
|
+
* @private still in development [🏢]
|
|
2478
|
+
*/
|
|
2479
|
+
var JsonFormatDefinition = {
|
|
2480
|
+
formatName: 'JSON',
|
|
2481
|
+
mimeType: 'application/json',
|
|
2482
|
+
isValid: function (value, settings, schema) {
|
|
2483
|
+
return isValidJsonString(value);
|
|
2484
|
+
},
|
|
2485
|
+
canBeValid: function (partialValue, settings, schema) {
|
|
2486
|
+
return true;
|
|
2487
|
+
},
|
|
2488
|
+
heal: function (value, settings, schema) {
|
|
2489
|
+
throw new Error('Not implemented');
|
|
2490
|
+
},
|
|
2491
|
+
subvalueDefinitions: [],
|
|
2492
|
+
};
|
|
2493
|
+
/**
|
|
2494
|
+
* TODO: [🧠] Maybe propper instance of object
|
|
2495
|
+
* TODO: [0] Make string_serialized_json
|
|
2496
|
+
* TODO: [1] Make type for JSON Settings and Schema
|
|
2497
|
+
* TODO: [🧠] What to use for validating JSONs - JSON Schema, ZoD, typescript types/interfaces,...?
|
|
2498
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement simple `isValid`
|
|
2499
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement partial `canBeValid`
|
|
2500
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement `heal
|
|
2501
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement `subvalueDefinitions`
|
|
2502
|
+
* TODO: [🏢] Allow to expect something inside JSON objects and other formats
|
|
2503
|
+
*/
|
|
2504
|
+
|
|
2505
|
+
/**
|
|
2506
|
+
* Definition for any text - this will be always valid
|
|
2507
|
+
*
|
|
2508
|
+
* Note: This is not useful for validation, but for splitting and mapping with `subvalueDefinitions`
|
|
2509
|
+
*
|
|
2510
|
+
* @public exported from `@promptbook/core`
|
|
2511
|
+
*/
|
|
2512
|
+
var TextFormatDefinition = {
|
|
2513
|
+
formatName: 'TEXT',
|
|
2514
|
+
isValid: function (value) {
|
|
2515
|
+
return typeof value === 'string';
|
|
2516
|
+
},
|
|
2517
|
+
canBeValid: function (partialValue) {
|
|
2518
|
+
return typeof partialValue === 'string';
|
|
2519
|
+
},
|
|
2520
|
+
heal: function () {
|
|
2521
|
+
throw new UnexpectedError('It does not make sense to call `TextFormatDefinition.heal`');
|
|
2522
|
+
},
|
|
2523
|
+
subvalueDefinitions: [
|
|
2524
|
+
{
|
|
2525
|
+
subvalueName: 'LINE',
|
|
2526
|
+
mapValues: function (value, outputParameterName, settings, mapCallback) {
|
|
2527
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2528
|
+
var lines, mappedLines;
|
|
2529
|
+
return __generator(this, function (_a) {
|
|
2530
|
+
switch (_a.label) {
|
|
2531
|
+
case 0:
|
|
2532
|
+
lines = value.split('\n');
|
|
2533
|
+
return [4 /*yield*/, Promise.all(lines.map(function (lineContent, lineNumber) {
|
|
2534
|
+
// TODO: [🧠] Maybe option to skip empty line
|
|
2535
|
+
/* not await */ return mapCallback({
|
|
2536
|
+
lineContent: lineContent,
|
|
2537
|
+
// TODO: [🧠] Maybe also put here `lineNumber`
|
|
2538
|
+
}, lineNumber);
|
|
2539
|
+
}))];
|
|
2540
|
+
case 1:
|
|
2541
|
+
mappedLines = _a.sent();
|
|
2542
|
+
return [2 /*return*/, mappedLines.join('\n')];
|
|
2543
|
+
}
|
|
2544
|
+
});
|
|
2545
|
+
});
|
|
2546
|
+
},
|
|
2547
|
+
},
|
|
2548
|
+
// <- TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
|
|
2549
|
+
],
|
|
2550
|
+
};
|
|
2551
|
+
/**
|
|
2552
|
+
* TODO: [1] Make type for XML Text and Schema
|
|
2553
|
+
* TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
|
|
2554
|
+
* TODO: [🍓] In `TextFormatDefinition` implement simple `isValid`
|
|
2555
|
+
* TODO: [🍓] In `TextFormatDefinition` implement partial `canBeValid`
|
|
2556
|
+
* TODO: [🍓] In `TextFormatDefinition` implement `heal
|
|
2557
|
+
* TODO: [🍓] In `TextFormatDefinition` implement `subvalueDefinitions`
|
|
2558
|
+
* TODO: [🏢] Allow to expect something inside each item of list and other formats
|
|
2559
|
+
*/
|
|
2560
|
+
|
|
2561
|
+
/**
|
|
2562
|
+
* Definition for XML format
|
|
2563
|
+
*
|
|
2564
|
+
* @private still in development [🏢]
|
|
2565
|
+
*/
|
|
2566
|
+
var XmlFormatDefinition = {
|
|
2567
|
+
formatName: 'XML',
|
|
2568
|
+
mimeType: 'application/xml',
|
|
2569
|
+
isValid: function (value, settings, schema) {
|
|
2570
|
+
return true;
|
|
2571
|
+
},
|
|
2572
|
+
canBeValid: function (partialValue, settings, schema) {
|
|
2573
|
+
return true;
|
|
2574
|
+
},
|
|
2575
|
+
heal: function (value, settings, schema) {
|
|
2576
|
+
throw new Error('Not implemented');
|
|
2577
|
+
},
|
|
2578
|
+
subvalueDefinitions: [],
|
|
2579
|
+
};
|
|
2580
|
+
/**
|
|
2581
|
+
* TODO: [🧠] Maybe propper instance of object
|
|
2582
|
+
* TODO: [0] Make string_serialized_xml
|
|
2583
|
+
* TODO: [1] Make type for XML Settings and Schema
|
|
2584
|
+
* TODO: [🧠] What to use for validating XMLs - XSD,...
|
|
2585
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement simple `isValid`
|
|
2586
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement partial `canBeValid`
|
|
2587
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement `heal
|
|
2588
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement `subvalueDefinitions`
|
|
2589
|
+
* TODO: [🏢] Allow to expect something inside XML and other formats
|
|
2590
|
+
*/
|
|
2591
|
+
|
|
2592
|
+
/**
|
|
2593
|
+
* Definitions for all formats supported by Promptbook
|
|
2594
|
+
*
|
|
2595
|
+
* @private internal index of `...` <- TODO [🏢]
|
|
2596
|
+
*/
|
|
2597
|
+
var FORMAT_DEFINITIONS = [
|
|
2598
|
+
JsonFormatDefinition,
|
|
2599
|
+
XmlFormatDefinition,
|
|
2600
|
+
TextFormatDefinition,
|
|
2601
|
+
CsvFormatDefinition,
|
|
2602
|
+
];
|
|
2603
|
+
/**
|
|
2604
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2605
|
+
*/
|
|
2606
|
+
|
|
2607
|
+
/**
|
|
2608
|
+
* Maps available parameters to expected parameters
|
|
2609
|
+
*
|
|
2610
|
+
* The strategy is:
|
|
2611
|
+
* 1) @@@
|
|
2612
|
+
* 2) @@@
|
|
2613
|
+
*
|
|
2614
|
+
* @throws {PipelineExecutionError} @@@
|
|
2615
|
+
* @private within the repository used in `createPipelineExecutor`
|
|
2616
|
+
*/
|
|
2617
|
+
function mapAvailableToExpectedParameters(options) {
|
|
2618
|
+
var e_1, _a;
|
|
2619
|
+
var expectedParameters = options.expectedParameters, availableParameters = options.availableParameters;
|
|
2620
|
+
var availableParametersNames = new Set(Object.keys(availableParameters));
|
|
2621
|
+
var expectedParameterNames = new Set(Object.keys(expectedParameters));
|
|
2622
|
+
var mappedParameters = {};
|
|
2623
|
+
try {
|
|
2624
|
+
// Phase 1️⃣: Matching mapping
|
|
2625
|
+
for (var _b = __values(Array.from(union(availableParametersNames, expectedParameterNames))), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
2626
|
+
var parameterName = _c.value;
|
|
2627
|
+
// Situation: Parameter is available and expected
|
|
2628
|
+
if (availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) {
|
|
2629
|
+
mappedParameters[parameterName] = availableParameters[parameterName];
|
|
2630
|
+
// <- Note: [👩👩👧] Maybe detect parameter collision here?
|
|
2631
|
+
availableParametersNames.delete(parameterName);
|
|
2632
|
+
expectedParameterNames.delete(parameterName);
|
|
2633
|
+
}
|
|
2634
|
+
// Situation: Parameter is available but NOT expected
|
|
2635
|
+
else if (availableParametersNames.has(parameterName) && !expectedParameterNames.has(parameterName)) {
|
|
2636
|
+
// [🐱👤] Do not pass this parameter to prompt - Maybe use it non-matching mapping
|
|
2637
|
+
}
|
|
2638
|
+
// Situation: Parameter is NOT available BUT expected
|
|
2639
|
+
else if (!availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) {
|
|
2640
|
+
// Do nothing here - this will be maybe fixed in the non-matching mapping
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
2645
|
+
finally {
|
|
2646
|
+
try {
|
|
2647
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
2648
|
+
}
|
|
2649
|
+
finally { if (e_1) throw e_1.error; }
|
|
2650
|
+
}
|
|
2651
|
+
if (expectedParameterNames.size === 0) {
|
|
2652
|
+
// Note: [👨👨👧] Now we can freeze `mappedParameters` to prevent @@@
|
|
2653
|
+
Object.freeze(mappedParameters);
|
|
2654
|
+
return mappedParameters;
|
|
2655
|
+
}
|
|
2656
|
+
// Phase 2️⃣: Non-matching mapping
|
|
2657
|
+
if (expectedParameterNames.size !== availableParametersNames.size) {
|
|
2658
|
+
throw new PipelineExecutionError(spaceTrim__default["default"](function (block) { return "\n Can not map available parameters to expected parameters\n\n Mapped parameters:\n ".concat(block(Object.keys(mappedParameters)
|
|
2659
|
+
.map(function (parameterName) { return "- {".concat(parameterName, "}"); })
|
|
2660
|
+
.join('\n')), "\n\n Expected parameters which can not be mapped:\n ").concat(block(Array.from(expectedParameterNames)
|
|
2661
|
+
.map(function (parameterName) { return "- {".concat(parameterName, "}"); })
|
|
2662
|
+
.join('\n')), "\n\n Remaining available parameters:\n ").concat(block(Array.from(availableParametersNames)
|
|
2663
|
+
.map(function (parameterName) { return "- {".concat(parameterName, "}"); })
|
|
2664
|
+
.join('\n')), "\n\n "); }));
|
|
2665
|
+
}
|
|
2666
|
+
var expectedParameterNamesArray = Array.from(expectedParameterNames);
|
|
2667
|
+
var availableParametersNamesArray = Array.from(availableParametersNames);
|
|
2668
|
+
for (var i = 0; i < expectedParameterNames.size; i++) {
|
|
2669
|
+
mappedParameters[expectedParameterNamesArray[i]] = availableParameters[availableParametersNamesArray[i]];
|
|
2670
|
+
}
|
|
2671
|
+
// Note: [👨👨👧] Now we can freeze `mappedParameters` to prevent @@@
|
|
2672
|
+
Object.freeze(mappedParameters);
|
|
2673
|
+
return mappedParameters;
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
/**
|
|
2677
|
+
* Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
|
|
2678
|
+
*
|
|
2679
|
+
* Note: Internal utility of `joinLlmExecutionTools` but exposed type
|
|
2680
|
+
* @public exported from `@promptbook/core`
|
|
2681
|
+
*/
|
|
2682
|
+
var MultipleLlmExecutionTools = /** @class */ (function () {
|
|
2683
|
+
/**
|
|
2684
|
+
* Gets array of execution tools in order of priority
|
|
2685
|
+
*/
|
|
2686
|
+
function MultipleLlmExecutionTools() {
|
|
2687
|
+
var llmExecutionTools = [];
|
|
2688
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
2689
|
+
llmExecutionTools[_i] = arguments[_i];
|
|
2690
|
+
}
|
|
2691
|
+
this.llmExecutionTools = llmExecutionTools;
|
|
2692
|
+
}
|
|
2693
|
+
Object.defineProperty(MultipleLlmExecutionTools.prototype, "title", {
|
|
2694
|
+
get: function () {
|
|
2695
|
+
return 'Multiple LLM Providers';
|
|
2696
|
+
},
|
|
2697
|
+
enumerable: false,
|
|
2698
|
+
configurable: true
|
|
2699
|
+
});
|
|
2700
|
+
Object.defineProperty(MultipleLlmExecutionTools.prototype, "description", {
|
|
2701
|
+
get: function () {
|
|
2702
|
+
return this.llmExecutionTools.map(function (_a, index) {
|
|
2703
|
+
var title = _a.title;
|
|
2704
|
+
return "".concat(index + 1, ") `").concat(title, "`");
|
|
2705
|
+
}).join('\n');
|
|
2706
|
+
},
|
|
2707
|
+
enumerable: false,
|
|
2708
|
+
configurable: true
|
|
2709
|
+
});
|
|
2710
|
+
/**
|
|
2711
|
+
* Check the configuration of all execution tools
|
|
2712
|
+
*/
|
|
2713
|
+
MultipleLlmExecutionTools.prototype.checkConfiguration = function () {
|
|
2714
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2715
|
+
var _a, _b, llmExecutionTools, e_1_1;
|
|
2716
|
+
var e_1, _c;
|
|
2717
|
+
return __generator(this, function (_d) {
|
|
2718
|
+
switch (_d.label) {
|
|
2719
|
+
case 0:
|
|
2720
|
+
_d.trys.push([0, 5, 6, 7]);
|
|
2721
|
+
_a = __values(this.llmExecutionTools), _b = _a.next();
|
|
2722
|
+
_d.label = 1;
|
|
2723
|
+
case 1:
|
|
2724
|
+
if (!!_b.done) return [3 /*break*/, 4];
|
|
2725
|
+
llmExecutionTools = _b.value;
|
|
2726
|
+
return [4 /*yield*/, llmExecutionTools.checkConfiguration()];
|
|
2727
|
+
case 2:
|
|
2728
|
+
_d.sent();
|
|
2729
|
+
_d.label = 3;
|
|
2730
|
+
case 3:
|
|
2731
|
+
_b = _a.next();
|
|
2732
|
+
return [3 /*break*/, 1];
|
|
2733
|
+
case 4: return [3 /*break*/, 7];
|
|
2734
|
+
case 5:
|
|
2735
|
+
e_1_1 = _d.sent();
|
|
2736
|
+
e_1 = { error: e_1_1 };
|
|
2737
|
+
return [3 /*break*/, 7];
|
|
2738
|
+
case 6:
|
|
2739
|
+
try {
|
|
2740
|
+
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
2741
|
+
}
|
|
2742
|
+
finally { if (e_1) throw e_1.error; }
|
|
2743
|
+
return [7 /*endfinally*/];
|
|
2744
|
+
case 7: return [2 /*return*/];
|
|
2745
|
+
}
|
|
2746
|
+
});
|
|
2747
|
+
});
|
|
2748
|
+
};
|
|
2749
|
+
/**
|
|
2750
|
+
* List all available models that can be used
|
|
2751
|
+
* This lists is a combination of all available models from all execution tools
|
|
2752
|
+
*/
|
|
2753
|
+
MultipleLlmExecutionTools.prototype.listModels = function () {
|
|
2754
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2755
|
+
var availableModels, _a, _b, llmExecutionTools, models, e_2_1;
|
|
2756
|
+
var e_2, _c;
|
|
2757
|
+
return __generator(this, function (_d) {
|
|
2758
|
+
switch (_d.label) {
|
|
2759
|
+
case 0:
|
|
2760
|
+
availableModels = [];
|
|
2761
|
+
_d.label = 1;
|
|
2762
|
+
case 1:
|
|
2763
|
+
_d.trys.push([1, 6, 7, 8]);
|
|
2764
|
+
_a = __values(this.llmExecutionTools), _b = _a.next();
|
|
2765
|
+
_d.label = 2;
|
|
2766
|
+
case 2:
|
|
2767
|
+
if (!!_b.done) return [3 /*break*/, 5];
|
|
2768
|
+
llmExecutionTools = _b.value;
|
|
2769
|
+
return [4 /*yield*/, llmExecutionTools.listModels()];
|
|
2770
|
+
case 3:
|
|
2771
|
+
models = _d.sent();
|
|
2772
|
+
availableModels.push.apply(availableModels, __spreadArray([], __read(models), false));
|
|
2773
|
+
_d.label = 4;
|
|
2774
|
+
case 4:
|
|
2775
|
+
_b = _a.next();
|
|
2776
|
+
return [3 /*break*/, 2];
|
|
2777
|
+
case 5: return [3 /*break*/, 8];
|
|
2778
|
+
case 6:
|
|
2779
|
+
e_2_1 = _d.sent();
|
|
2780
|
+
e_2 = { error: e_2_1 };
|
|
2781
|
+
return [3 /*break*/, 8];
|
|
2782
|
+
case 7:
|
|
2783
|
+
try {
|
|
2784
|
+
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
2785
|
+
}
|
|
2786
|
+
finally { if (e_2) throw e_2.error; }
|
|
2787
|
+
return [7 /*endfinally*/];
|
|
2788
|
+
case 8: return [2 /*return*/, availableModels];
|
|
2789
|
+
}
|
|
2790
|
+
});
|
|
2791
|
+
});
|
|
2792
|
+
};
|
|
2793
|
+
/**
|
|
2794
|
+
* Calls the best available chat model
|
|
2795
|
+
*/
|
|
2796
|
+
MultipleLlmExecutionTools.prototype.callChatModel = function (prompt) {
|
|
2797
|
+
return this.callCommonModel(prompt);
|
|
2798
|
+
};
|
|
2799
|
+
/**
|
|
2800
|
+
* Calls the best available completion model
|
|
2801
|
+
*/
|
|
2802
|
+
MultipleLlmExecutionTools.prototype.callCompletionModel = function (prompt) {
|
|
2803
|
+
return this.callCommonModel(prompt);
|
|
2804
|
+
};
|
|
2805
|
+
/**
|
|
2806
|
+
* Calls the best available embedding model
|
|
2807
|
+
*/
|
|
2808
|
+
MultipleLlmExecutionTools.prototype.callEmbeddingModel = function (prompt) {
|
|
2809
|
+
return this.callCommonModel(prompt);
|
|
2810
|
+
};
|
|
2811
|
+
// <- Note: [🤖]
|
|
2812
|
+
/**
|
|
2813
|
+
* Calls the best available model
|
|
2814
|
+
*
|
|
2815
|
+
* Note: This should be private or protected but is public to be usable with duck typing
|
|
2816
|
+
*/
|
|
2817
|
+
MultipleLlmExecutionTools.prototype.callCommonModel = function (prompt) {
|
|
2818
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2819
|
+
var errors, _a, _b, llmExecutionTools, _c, error_1, e_3_1;
|
|
2820
|
+
var e_3, _d;
|
|
2821
|
+
var _this = this;
|
|
2822
|
+
return __generator(this, function (_e) {
|
|
2823
|
+
switch (_e.label) {
|
|
2824
|
+
case 0:
|
|
2825
|
+
errors = [];
|
|
2826
|
+
_e.label = 1;
|
|
2827
|
+
case 1:
|
|
2828
|
+
_e.trys.push([1, 15, 16, 17]);
|
|
2829
|
+
_a = __values(this.llmExecutionTools), _b = _a.next();
|
|
2830
|
+
_e.label = 2;
|
|
2831
|
+
case 2:
|
|
2832
|
+
if (!!_b.done) return [3 /*break*/, 14];
|
|
2833
|
+
llmExecutionTools = _b.value;
|
|
2834
|
+
_e.label = 3;
|
|
2835
|
+
case 3:
|
|
2836
|
+
_e.trys.push([3, 12, , 13]);
|
|
2837
|
+
_c = prompt.modelRequirements.modelVariant;
|
|
2838
|
+
switch (_c) {
|
|
2839
|
+
case 'CHAT': return [3 /*break*/, 4];
|
|
2840
|
+
case 'COMPLETION': return [3 /*break*/, 6];
|
|
2841
|
+
case 'EMBEDDING': return [3 /*break*/, 8];
|
|
2842
|
+
}
|
|
2843
|
+
return [3 /*break*/, 10];
|
|
2844
|
+
case 4:
|
|
2845
|
+
if (llmExecutionTools.callChatModel === undefined) {
|
|
2846
|
+
return [3 /*break*/, 13];
|
|
2847
|
+
}
|
|
2848
|
+
return [4 /*yield*/, llmExecutionTools.callChatModel(prompt)];
|
|
2849
|
+
case 5: return [2 /*return*/, _e.sent()];
|
|
2850
|
+
case 6:
|
|
2851
|
+
if (llmExecutionTools.callCompletionModel === undefined) {
|
|
2852
|
+
return [3 /*break*/, 13];
|
|
2853
|
+
}
|
|
2854
|
+
return [4 /*yield*/, llmExecutionTools.callCompletionModel(prompt)];
|
|
2855
|
+
case 7: return [2 /*return*/, _e.sent()];
|
|
2856
|
+
case 8:
|
|
2857
|
+
if (llmExecutionTools.callEmbeddingModel === undefined) {
|
|
2858
|
+
return [3 /*break*/, 13];
|
|
2859
|
+
}
|
|
2860
|
+
return [4 /*yield*/, llmExecutionTools.callEmbeddingModel(prompt)];
|
|
2861
|
+
case 9: return [2 /*return*/, _e.sent()];
|
|
2862
|
+
case 10: throw new UnexpectedError("Unknown model variant \"".concat(prompt.modelRequirements.modelVariant, "\""));
|
|
2863
|
+
case 11: return [3 /*break*/, 13];
|
|
2864
|
+
case 12:
|
|
2865
|
+
error_1 = _e.sent();
|
|
2866
|
+
if (!(error_1 instanceof Error) || error_1 instanceof UnexpectedError) {
|
|
2867
|
+
throw error_1;
|
|
2868
|
+
}
|
|
2869
|
+
errors.push(error_1);
|
|
2870
|
+
return [3 /*break*/, 13];
|
|
2871
|
+
case 13:
|
|
2872
|
+
_b = _a.next();
|
|
2873
|
+
return [3 /*break*/, 2];
|
|
2874
|
+
case 14: return [3 /*break*/, 17];
|
|
2875
|
+
case 15:
|
|
2876
|
+
e_3_1 = _e.sent();
|
|
2877
|
+
e_3 = { error: e_3_1 };
|
|
2878
|
+
return [3 /*break*/, 17];
|
|
2879
|
+
case 16:
|
|
2880
|
+
try {
|
|
2881
|
+
if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
|
|
2882
|
+
}
|
|
2883
|
+
finally { if (e_3) throw e_3.error; }
|
|
2884
|
+
return [7 /*endfinally*/];
|
|
2885
|
+
case 17:
|
|
2886
|
+
if (errors.length === 1) {
|
|
2887
|
+
throw errors[0];
|
|
2977
2888
|
}
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
var XmlFormatDefinition = {
|
|
3001
|
-
formatName: 'XML',
|
|
3002
|
-
mimeType: 'application/xml',
|
|
3003
|
-
isValid: function (value, settings, schema) {
|
|
3004
|
-
return true;
|
|
3005
|
-
},
|
|
3006
|
-
canBeValid: function (partialValue, settings, schema) {
|
|
3007
|
-
return true;
|
|
3008
|
-
},
|
|
3009
|
-
heal: function (value, settings, schema) {
|
|
3010
|
-
throw new Error('Not implemented');
|
|
3011
|
-
},
|
|
3012
|
-
subvalueDefinitions: [],
|
|
3013
|
-
};
|
|
3014
|
-
/**
|
|
3015
|
-
* TODO: [🧠] Maybe propper instance of object
|
|
3016
|
-
* TODO: [0] Make string_serialized_xml
|
|
3017
|
-
* TODO: [1] Make type for XML Settings and Schema
|
|
3018
|
-
* TODO: [🧠] What to use for validating XMLs - XSD,...
|
|
3019
|
-
* TODO: [🍓] In `XmlFormatDefinition` implement simple `isValid`
|
|
3020
|
-
* TODO: [🍓] In `XmlFormatDefinition` implement partial `canBeValid`
|
|
3021
|
-
* TODO: [🍓] In `XmlFormatDefinition` implement `heal
|
|
3022
|
-
* TODO: [🍓] In `XmlFormatDefinition` implement `subvalueDefinitions`
|
|
3023
|
-
* TODO: [🏢] Allow to expect something inside XML and other formats
|
|
3024
|
-
*/
|
|
3025
|
-
|
|
3026
|
-
/**
|
|
3027
|
-
* Definitions for all formats supported by Promptbook
|
|
3028
|
-
*
|
|
3029
|
-
* @private internal index of `...` <- TODO [🏢]
|
|
3030
|
-
*/
|
|
3031
|
-
var FORMAT_DEFINITIONS = [
|
|
3032
|
-
JsonFormatDefinition,
|
|
3033
|
-
XmlFormatDefinition,
|
|
3034
|
-
TextFormatDefinition,
|
|
3035
|
-
CsvFormatDefinition,
|
|
3036
|
-
];
|
|
2889
|
+
else if (errors.length > 1) {
|
|
2890
|
+
throw new PipelineExecutionError(
|
|
2891
|
+
// TODO: Tell which execution tools failed like
|
|
2892
|
+
// 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
2893
|
+
// 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
2894
|
+
// 3) ...
|
|
2895
|
+
spaceTrim__default["default"](function (block) { return "\n All execution tools failed:\n\n ".concat(block(errors
|
|
2896
|
+
.map(function (error, i) { return "".concat(i + 1, ") **").concat(error.name || 'Error', ":** ").concat(error.message); })
|
|
2897
|
+
.join('\n')), "\n\n "); }));
|
|
2898
|
+
}
|
|
2899
|
+
else if (this.llmExecutionTools.length === 0) {
|
|
2900
|
+
throw new PipelineExecutionError("You have not provided any `LlmExecutionTools`");
|
|
2901
|
+
}
|
|
2902
|
+
else {
|
|
2903
|
+
throw new PipelineExecutionError(spaceTrim__default["default"](function (block) { return "\n You have not provided any `LlmExecutionTools` that support model variant \"".concat(prompt.modelRequirements.modelVariant, "\"\n\n Available `LlmExecutionTools`:\n ").concat(block(_this.description), "\n\n "); }));
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
});
|
|
2907
|
+
});
|
|
2908
|
+
};
|
|
2909
|
+
return MultipleLlmExecutionTools;
|
|
2910
|
+
}());
|
|
3037
2911
|
/**
|
|
3038
|
-
*
|
|
2912
|
+
* TODO: [🧠][🎛] Aggregating multiple models - have result not only from one first aviable model BUT all of them
|
|
2913
|
+
* TODO: [🏖] If no llmTools have for example not defined `callCompletionModel` this will still return object with defined `callCompletionModel` which just throws `PipelineExecutionError`, make it undefined instead
|
|
2914
|
+
* Look how `countTotalUsage` (and `cacheLlmTools`) implements it
|
|
3039
2915
|
*/
|
|
3040
2916
|
|
|
3041
2917
|
/**
|
|
3042
|
-
*
|
|
2918
|
+
* Joins multiple LLM Execution Tools into one
|
|
3043
2919
|
*
|
|
3044
|
-
*
|
|
3045
|
-
* 1) @@@
|
|
3046
|
-
* 2) @@@
|
|
2920
|
+
* @returns {LlmExecutionTools} Single wrapper for multiple LlmExecutionTools
|
|
3047
2921
|
*
|
|
3048
|
-
*
|
|
3049
|
-
*
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
if (availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) {
|
|
3063
|
-
mappedParameters[parameterName] = availableParameters[parameterName];
|
|
3064
|
-
// <- Note: [👩👩👧] Maybe detect parameter collision here?
|
|
3065
|
-
availableParametersNames.delete(parameterName);
|
|
3066
|
-
expectedParameterNames.delete(parameterName);
|
|
3067
|
-
}
|
|
3068
|
-
// Situation: Parameter is available but NOT expected
|
|
3069
|
-
else if (availableParametersNames.has(parameterName) && !expectedParameterNames.has(parameterName)) {
|
|
3070
|
-
// [🐱👤] Do not pass this parameter to prompt - Maybe use it non-matching mapping
|
|
3071
|
-
}
|
|
3072
|
-
// Situation: Parameter is NOT available BUT expected
|
|
3073
|
-
else if (!availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) {
|
|
3074
|
-
// Do nothing here - this will be maybe fixed in the non-matching mapping
|
|
3075
|
-
}
|
|
3076
|
-
}
|
|
3077
|
-
}
|
|
3078
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
3079
|
-
finally {
|
|
3080
|
-
try {
|
|
3081
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
3082
|
-
}
|
|
3083
|
-
finally { if (e_1) throw e_1.error; }
|
|
3084
|
-
}
|
|
3085
|
-
if (expectedParameterNames.size === 0) {
|
|
3086
|
-
// Note: [👨👨👧] Now we can freeze `mappedParameters` to prevent @@@
|
|
3087
|
-
Object.freeze(mappedParameters);
|
|
3088
|
-
return mappedParameters;
|
|
3089
|
-
}
|
|
3090
|
-
// Phase 2️⃣: Non-matching mapping
|
|
3091
|
-
if (expectedParameterNames.size !== availableParametersNames.size) {
|
|
3092
|
-
throw new PipelineExecutionError(spaceTrim__default["default"](function (block) { return "\n Can not map available parameters to expected parameters\n\n Mapped parameters:\n ".concat(block(Object.keys(mappedParameters)
|
|
3093
|
-
.map(function (parameterName) { return "- {".concat(parameterName, "}"); })
|
|
3094
|
-
.join('\n')), "\n\n Expected parameters which can not be mapped:\n ").concat(block(Array.from(expectedParameterNames)
|
|
3095
|
-
.map(function (parameterName) { return "- {".concat(parameterName, "}"); })
|
|
3096
|
-
.join('\n')), "\n\n Remaining available parameters:\n ").concat(block(Array.from(availableParametersNames)
|
|
3097
|
-
.map(function (parameterName) { return "- {".concat(parameterName, "}"); })
|
|
3098
|
-
.join('\n')), "\n\n "); }));
|
|
2922
|
+
* 0) If there is no LlmExecutionTools, it warns and returns valid but empty LlmExecutionTools
|
|
2923
|
+
* 1) If there is only one LlmExecutionTools, it returns it wrapped in a proxy object
|
|
2924
|
+
* 2) If there are multiple LlmExecutionTools, first will be used first, second will be used if the first hasn`t defined model variant or fails, etc.
|
|
2925
|
+
* 3) When all LlmExecutionTools fail, it throws an error with a list of all errors merged into one
|
|
2926
|
+
*
|
|
2927
|
+
*
|
|
2928
|
+
* Tip: You don't have to use this function directly, just pass an array of LlmExecutionTools to the `ExecutionTools`
|
|
2929
|
+
*
|
|
2930
|
+
* @public exported from `@promptbook/core`
|
|
2931
|
+
*/
|
|
2932
|
+
function joinLlmExecutionTools() {
|
|
2933
|
+
var llmExecutionTools = [];
|
|
2934
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
2935
|
+
llmExecutionTools[_i] = arguments[_i];
|
|
3099
2936
|
}
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
2937
|
+
if (llmExecutionTools.length === 0) {
|
|
2938
|
+
var warningMessage = spaceTrim__default["default"]("\n You have not provided any `LlmExecutionTools`\n This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.\n\n Technically, it's not an error, but it's probably not what you want because it does not make sense to use Promptbook without language models.\n ");
|
|
2939
|
+
// TODO: [🟥] Detect browser / node and make it colorfull
|
|
2940
|
+
console.warn(warningMessage);
|
|
2941
|
+
/*
|
|
2942
|
+
return {
|
|
2943
|
+
async listModels() {
|
|
2944
|
+
// TODO: [🟥] Detect browser / node and make it colorfull
|
|
2945
|
+
console.warn(
|
|
2946
|
+
spaceTrim(
|
|
2947
|
+
(block) => `
|
|
2948
|
+
|
|
2949
|
+
You can't list models because you have no LLM Execution Tools defined:
|
|
2950
|
+
|
|
2951
|
+
tl;dr
|
|
2952
|
+
|
|
2953
|
+
${block(warningMessage)}
|
|
2954
|
+
`,
|
|
2955
|
+
),
|
|
2956
|
+
);
|
|
2957
|
+
return [];
|
|
2958
|
+
},
|
|
2959
|
+
};
|
|
2960
|
+
*/
|
|
3104
2961
|
}
|
|
3105
|
-
|
|
3106
|
-
Object.freeze(mappedParameters);
|
|
3107
|
-
return mappedParameters;
|
|
2962
|
+
return new (MultipleLlmExecutionTools.bind.apply(MultipleLlmExecutionTools, __spreadArray([void 0], __read(llmExecutionTools), false)))();
|
|
3108
2963
|
}
|
|
2964
|
+
/**
|
|
2965
|
+
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
2966
|
+
*/
|
|
3109
2967
|
|
|
3110
2968
|
/**
|
|
3111
2969
|
* Extracts all code blocks from markdown.
|
|
@@ -3298,6 +3156,8 @@
|
|
|
3298
3156
|
throw new PipelineExecutionError("Parameter `{".concat(parameterName, "}` is not defined"));
|
|
3299
3157
|
}
|
|
3300
3158
|
parameterValue = valueToString(parameterValue);
|
|
3159
|
+
// Escape curly braces in parameter values to prevent prompt-injection
|
|
3160
|
+
parameterValue = parameterValue.replace(/[{}]/g, '\\$&');
|
|
3301
3161
|
if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
|
|
3302
3162
|
parameterValue = parameterValue
|
|
3303
3163
|
.split('\n')
|
|
@@ -3918,7 +3778,7 @@
|
|
|
3918
3778
|
promptTitle: task.title,
|
|
3919
3779
|
promptMessage: templateParameters(task.description || '', parameters),
|
|
3920
3780
|
defaultValue: templateParameters(preparedContent, parameters),
|
|
3921
|
-
// TODO: [🧠]
|
|
3781
|
+
// TODO: [🧠] Figure out how to define placeholder in .book.md file
|
|
3922
3782
|
placeholder: undefined,
|
|
3923
3783
|
priority: priority,
|
|
3924
3784
|
}))];
|
|
@@ -4856,6 +4716,169 @@
|
|
|
4856
4716
|
* TODO: [🐚] Change onProgress to object that represents the running execution, can be subscribed via RxJS to and also awaited
|
|
4857
4717
|
*/
|
|
4858
4718
|
|
|
4719
|
+
/**
|
|
4720
|
+
* Async version of Array.forEach
|
|
4721
|
+
*
|
|
4722
|
+
* @param array - Array to iterate over
|
|
4723
|
+
* @param options - Options for the function
|
|
4724
|
+
* @param callbackfunction - Function to call for each item
|
|
4725
|
+
* @public exported from `@promptbook/utils`
|
|
4726
|
+
* @deprecated [🪂] Use queues instead
|
|
4727
|
+
*/
|
|
4728
|
+
function forEachAsync(array, options, callbackfunction) {
|
|
4729
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
4730
|
+
var _a, maxParallelCount, index, runningTasks, tasks, _loop_1, _b, _c, item, e_1_1;
|
|
4731
|
+
var e_1, _d;
|
|
4732
|
+
return __generator(this, function (_e) {
|
|
4733
|
+
switch (_e.label) {
|
|
4734
|
+
case 0:
|
|
4735
|
+
_a = options.maxParallelCount, maxParallelCount = _a === void 0 ? Infinity : _a;
|
|
4736
|
+
index = 0;
|
|
4737
|
+
runningTasks = [];
|
|
4738
|
+
tasks = [];
|
|
4739
|
+
_loop_1 = function (item) {
|
|
4740
|
+
var currentIndex, task;
|
|
4741
|
+
return __generator(this, function (_f) {
|
|
4742
|
+
switch (_f.label) {
|
|
4743
|
+
case 0:
|
|
4744
|
+
currentIndex = index++;
|
|
4745
|
+
task = callbackfunction(item, currentIndex, array);
|
|
4746
|
+
tasks.push(task);
|
|
4747
|
+
runningTasks.push(task);
|
|
4748
|
+
/* not await */ Promise.resolve(task).then(function () {
|
|
4749
|
+
runningTasks = runningTasks.filter(function (t) { return t !== task; });
|
|
4750
|
+
});
|
|
4751
|
+
if (!(maxParallelCount < runningTasks.length)) return [3 /*break*/, 2];
|
|
4752
|
+
return [4 /*yield*/, Promise.race(runningTasks)];
|
|
4753
|
+
case 1:
|
|
4754
|
+
_f.sent();
|
|
4755
|
+
_f.label = 2;
|
|
4756
|
+
case 2: return [2 /*return*/];
|
|
4757
|
+
}
|
|
4758
|
+
});
|
|
4759
|
+
};
|
|
4760
|
+
_e.label = 1;
|
|
4761
|
+
case 1:
|
|
4762
|
+
_e.trys.push([1, 6, 7, 8]);
|
|
4763
|
+
_b = __values(array), _c = _b.next();
|
|
4764
|
+
_e.label = 2;
|
|
4765
|
+
case 2:
|
|
4766
|
+
if (!!_c.done) return [3 /*break*/, 5];
|
|
4767
|
+
item = _c.value;
|
|
4768
|
+
return [5 /*yield**/, _loop_1(item)];
|
|
4769
|
+
case 3:
|
|
4770
|
+
_e.sent();
|
|
4771
|
+
_e.label = 4;
|
|
4772
|
+
case 4:
|
|
4773
|
+
_c = _b.next();
|
|
4774
|
+
return [3 /*break*/, 2];
|
|
4775
|
+
case 5: return [3 /*break*/, 8];
|
|
4776
|
+
case 6:
|
|
4777
|
+
e_1_1 = _e.sent();
|
|
4778
|
+
e_1 = { error: e_1_1 };
|
|
4779
|
+
return [3 /*break*/, 8];
|
|
4780
|
+
case 7:
|
|
4781
|
+
try {
|
|
4782
|
+
if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
|
|
4783
|
+
}
|
|
4784
|
+
finally { if (e_1) throw e_1.error; }
|
|
4785
|
+
return [7 /*endfinally*/];
|
|
4786
|
+
case 8: return [4 /*yield*/, Promise.all(tasks)];
|
|
4787
|
+
case 9:
|
|
4788
|
+
_e.sent();
|
|
4789
|
+
return [2 /*return*/];
|
|
4790
|
+
}
|
|
4791
|
+
});
|
|
4792
|
+
});
|
|
4793
|
+
}
|
|
4794
|
+
|
|
4795
|
+
/**
|
|
4796
|
+
* Intercepts LLM tools and counts total usage of the tools
|
|
4797
|
+
*
|
|
4798
|
+
* @param llmTools LLM tools to be intercepted with usage counting
|
|
4799
|
+
* @returns LLM tools with same functionality with added total cost counting
|
|
4800
|
+
* @public exported from `@promptbook/core`
|
|
4801
|
+
*/
|
|
4802
|
+
function countTotalUsage(llmTools) {
|
|
4803
|
+
var _this = this;
|
|
4804
|
+
var totalUsage = ZERO_USAGE;
|
|
4805
|
+
var proxyTools = {
|
|
4806
|
+
get title() {
|
|
4807
|
+
// TODO: [🧠] Maybe put here some suffix
|
|
4808
|
+
return llmTools.title;
|
|
4809
|
+
},
|
|
4810
|
+
get description() {
|
|
4811
|
+
// TODO: [🧠] Maybe put here some suffix
|
|
4812
|
+
return llmTools.description;
|
|
4813
|
+
},
|
|
4814
|
+
checkConfiguration: function () {
|
|
4815
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
4816
|
+
return __generator(this, function (_a) {
|
|
4817
|
+
return [2 /*return*/, /* not await */ llmTools.checkConfiguration()];
|
|
4818
|
+
});
|
|
4819
|
+
});
|
|
4820
|
+
},
|
|
4821
|
+
listModels: function () {
|
|
4822
|
+
return /* not await */ llmTools.listModels();
|
|
4823
|
+
},
|
|
4824
|
+
getTotalUsage: function () {
|
|
4825
|
+
// <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
|
|
4826
|
+
return totalUsage;
|
|
4827
|
+
},
|
|
4828
|
+
};
|
|
4829
|
+
if (llmTools.callChatModel !== undefined) {
|
|
4830
|
+
proxyTools.callChatModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
|
|
4831
|
+
var promptResult;
|
|
4832
|
+
return __generator(this, function (_a) {
|
|
4833
|
+
switch (_a.label) {
|
|
4834
|
+
case 0: return [4 /*yield*/, llmTools.callChatModel(prompt)];
|
|
4835
|
+
case 1:
|
|
4836
|
+
promptResult = _a.sent();
|
|
4837
|
+
totalUsage = addUsage(totalUsage, promptResult.usage);
|
|
4838
|
+
return [2 /*return*/, promptResult];
|
|
4839
|
+
}
|
|
4840
|
+
});
|
|
4841
|
+
}); };
|
|
4842
|
+
}
|
|
4843
|
+
if (llmTools.callCompletionModel !== undefined) {
|
|
4844
|
+
proxyTools.callCompletionModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
|
|
4845
|
+
var promptResult;
|
|
4846
|
+
return __generator(this, function (_a) {
|
|
4847
|
+
switch (_a.label) {
|
|
4848
|
+
case 0: return [4 /*yield*/, llmTools.callCompletionModel(prompt)];
|
|
4849
|
+
case 1:
|
|
4850
|
+
promptResult = _a.sent();
|
|
4851
|
+
totalUsage = addUsage(totalUsage, promptResult.usage);
|
|
4852
|
+
return [2 /*return*/, promptResult];
|
|
4853
|
+
}
|
|
4854
|
+
});
|
|
4855
|
+
}); };
|
|
4856
|
+
}
|
|
4857
|
+
if (llmTools.callEmbeddingModel !== undefined) {
|
|
4858
|
+
proxyTools.callEmbeddingModel = function (prompt) { return __awaiter(_this, void 0, void 0, function () {
|
|
4859
|
+
var promptResult;
|
|
4860
|
+
return __generator(this, function (_a) {
|
|
4861
|
+
switch (_a.label) {
|
|
4862
|
+
case 0: return [4 /*yield*/, llmTools.callEmbeddingModel(prompt)];
|
|
4863
|
+
case 1:
|
|
4864
|
+
promptResult = _a.sent();
|
|
4865
|
+
totalUsage = addUsage(totalUsage, promptResult.usage);
|
|
4866
|
+
return [2 /*return*/, promptResult];
|
|
4867
|
+
}
|
|
4868
|
+
});
|
|
4869
|
+
}); };
|
|
4870
|
+
}
|
|
4871
|
+
// <- Note: [🤖]
|
|
4872
|
+
return proxyTools;
|
|
4873
|
+
}
|
|
4874
|
+
/**
|
|
4875
|
+
* TODO: [🧠][💸] Maybe make some common abstraction `interceptLlmTools` and use here (or use javascript Proxy?)
|
|
4876
|
+
* TODO: [🧠] Is there some meaningfull way how to test this util
|
|
4877
|
+
* TODO: [🧠][🌯] Maybe a way how to hide ability to `get totalUsage`
|
|
4878
|
+
* > const [llmToolsWithUsage,getUsage] = countTotalUsage(llmTools);
|
|
4879
|
+
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
4880
|
+
*/
|
|
4881
|
+
|
|
4859
4882
|
/**
|
|
4860
4883
|
* Prepares the persona for the pipeline
|
|
4861
4884
|
*
|
|
@@ -4918,10 +4941,10 @@
|
|
|
4918
4941
|
});
|
|
4919
4942
|
}
|
|
4920
4943
|
/**
|
|
4921
|
-
* TODO: [🔃][main]
|
|
4922
|
-
* TODO: [🏢]
|
|
4923
|
-
* TODO: [🏢]
|
|
4924
|
-
* TODO: [🏢]
|
|
4944
|
+
* TODO: [🔃][main] If the persona was prepared with different version or different set of models, prepare it once again
|
|
4945
|
+
* TODO: [🏢] Check validity of `modelName` in pipeline
|
|
4946
|
+
* TODO: [🏢] Check validity of `systemMessage` in pipeline
|
|
4947
|
+
* TODO: [🏢] Check validity of `temperature` in pipeline
|
|
4925
4948
|
*/
|
|
4926
4949
|
|
|
4927
4950
|
/**
|
|
@@ -5355,21 +5378,44 @@
|
|
|
5355
5378
|
if (typeof filename !== 'string') {
|
|
5356
5379
|
return false;
|
|
5357
5380
|
}
|
|
5381
|
+
if (filename.split('\n').length > 1) {
|
|
5382
|
+
return false;
|
|
5383
|
+
}
|
|
5384
|
+
if (filename.split(' ').length >
|
|
5385
|
+
5 /* <- TODO: [🧠][🈷] Make some better non-arbitrary way how to distinct filenames from informational texts */) {
|
|
5386
|
+
return false;
|
|
5387
|
+
}
|
|
5358
5388
|
var filenameSlashes = filename.split('\\').join('/');
|
|
5359
5389
|
// Absolute Unix path: /hello.txt
|
|
5360
5390
|
if (/^(\/)/i.test(filenameSlashes)) {
|
|
5391
|
+
// console.log(filename, 'Absolute Unix path: /hello.txt');
|
|
5361
5392
|
return true;
|
|
5362
5393
|
}
|
|
5363
5394
|
// Absolute Windows path: /hello.txt
|
|
5364
5395
|
if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
|
|
5396
|
+
// console.log(filename, 'Absolute Windows path: /hello.txt');
|
|
5365
5397
|
return true;
|
|
5366
5398
|
}
|
|
5367
5399
|
// Relative path: ./hello.txt
|
|
5368
5400
|
if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
|
|
5401
|
+
// console.log(filename, 'Relative path: ./hello.txt');
|
|
5402
|
+
return true;
|
|
5403
|
+
}
|
|
5404
|
+
// Allow paths like foo/hello
|
|
5405
|
+
if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
|
|
5406
|
+
// console.log(filename, 'Allow paths like foo/hello');
|
|
5407
|
+
return true;
|
|
5408
|
+
}
|
|
5409
|
+
// Allow paths like hello.book
|
|
5410
|
+
if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
|
|
5411
|
+
// console.log(filename, 'Allow paths like hello.book');
|
|
5369
5412
|
return true;
|
|
5370
5413
|
}
|
|
5371
5414
|
return false;
|
|
5372
5415
|
}
|
|
5416
|
+
/**
|
|
5417
|
+
* TODO: [🍏] Implement for MacOs
|
|
5418
|
+
*/
|
|
5373
5419
|
|
|
5374
5420
|
/**
|
|
5375
5421
|
* The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
|
|
@@ -5394,6 +5440,9 @@
|
|
|
5394
5440
|
}
|
|
5395
5441
|
});
|
|
5396
5442
|
}); };
|
|
5443
|
+
/**
|
|
5444
|
+
* TODO: [🧠] Maybe rename because it is not used only for scrapers but also in `$getCompiledBook`
|
|
5445
|
+
*/
|
|
5397
5446
|
|
|
5398
5447
|
/**
|
|
5399
5448
|
* @@@
|
|
@@ -5461,7 +5510,7 @@
|
|
|
5461
5510
|
},
|
|
5462
5511
|
}];
|
|
5463
5512
|
case 2:
|
|
5464
|
-
if (!
|
|
5513
|
+
if (!isValidFilePath(sourceContent)) return [3 /*break*/, 4];
|
|
5465
5514
|
if (tools.fs === undefined) {
|
|
5466
5515
|
throw new EnvironmentMismatchError('Can not import file knowledge without filesystem tools');
|
|
5467
5516
|
// <- TODO: [🧠] What is the best error type here`
|
|
@@ -5476,7 +5525,7 @@
|
|
|
5476
5525
|
return [4 /*yield*/, isFileExisting(filename_1, tools.fs)];
|
|
5477
5526
|
case 3:
|
|
5478
5527
|
if (!(_f.sent())) {
|
|
5479
|
-
throw new NotFoundError(spaceTrim__default["default"](function (block) { return "\n Can not make source handler for file which does not exist:\n\n File:\n ".concat(block(filename_1), "\n "); }));
|
|
5528
|
+
throw new NotFoundError(spaceTrim__default["default"](function (block) { return "\n Can not make source handler for file which does not exist:\n\n File:\n ".concat(block(sourceContent), "\n\n Full file path:\n ").concat(block(filename_1), "\n "); }));
|
|
5480
5529
|
}
|
|
5481
5530
|
// TODO: [🧠][😿] Test security file - file is scoped to the project (BUT maybe do this in `filesystemTools`)
|
|
5482
5531
|
return [2 /*return*/, {
|
|
@@ -5589,7 +5638,7 @@
|
|
|
5589
5638
|
partialPieces = __spreadArray([], __read(partialPiecesUnchecked), false);
|
|
5590
5639
|
return [2 /*return*/, "break"];
|
|
5591
5640
|
}
|
|
5592
|
-
console.warn(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge from source despite the scraper `".concat(scraper.metadata.className, "` supports the mime type \"").concat(sourceHandler.mimeType, "\".\n
|
|
5641
|
+
console.warn(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge from source despite the scraper `".concat(scraper.metadata.className, "` supports the mime type \"").concat(sourceHandler.mimeType, "\".\n\n The source:\n ").concat(block(knowledgeSource.sourceContent
|
|
5593
5642
|
.split('\n')
|
|
5594
5643
|
.map(function (line) { return "> ".concat(line); })
|
|
5595
5644
|
.join('\n')), "\n\n ").concat(block($registeredScrapersMessage(scrapers)), "\n\n\n "); }));
|
|
@@ -5627,7 +5676,7 @@
|
|
|
5627
5676
|
return [7 /*endfinally*/];
|
|
5628
5677
|
case 9:
|
|
5629
5678
|
if (partialPieces === null) {
|
|
5630
|
-
throw new KnowledgeScrapeError(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge\n
|
|
5679
|
+
throw new KnowledgeScrapeError(spaceTrim__default["default"](function (block) { return "\n Cannot scrape knowledge\n\n The source:\n > ".concat(block(knowledgeSource.sourceContent
|
|
5631
5680
|
.split('\n')
|
|
5632
5681
|
.map(function (line) { return "> ".concat(line); })
|
|
5633
5682
|
.join('\n')), "\n\n No scraper found for the mime type \"").concat(sourceHandler.mimeType, "\"\n\n ").concat(block($registeredScrapersMessage(scrapers)), "\n\n\n "); }));
|
|
@@ -5718,7 +5767,7 @@
|
|
|
5718
5767
|
* TODO: [😂] Adding knowledge should be convert to async high-level abstractions, simmilar thing with expectations to sync high-level abstractions
|
|
5719
5768
|
* TODO: [🧠] Add context to each task (if missing)
|
|
5720
5769
|
* TODO: [🧠] What is better name `prepareTask` or `prepareTaskAndParameters`
|
|
5721
|
-
* TODO: [♨][main]
|
|
5770
|
+
* TODO: [♨][main] !!3 Prepare index the examples and maybe tasks
|
|
5722
5771
|
* TODO: Write tests for `preparePipeline`
|
|
5723
5772
|
* TODO: [🏏] Leverage the batch API and build queues @see https://platform.openai.com/docs/guides/batch
|
|
5724
5773
|
* TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
|
|
@@ -5728,6 +5777,8 @@
|
|
|
5728
5777
|
/**
|
|
5729
5778
|
* Prepare pipeline from string (markdown) format to JSON format
|
|
5730
5779
|
*
|
|
5780
|
+
* @see https://github.com/webgptorg/promptbook/discussions/196
|
|
5781
|
+
*
|
|
5731
5782
|
* Note: This function does not validate logic of the pipeline
|
|
5732
5783
|
* Note: This function acts as part of compilation process
|
|
5733
5784
|
* Note: When the pipeline is already prepared, it returns the same pipeline
|
|
@@ -5740,16 +5791,17 @@
|
|
|
5740
5791
|
<- TODO: [🧠][🪑] `promptbookVersion` */
|
|
5741
5792
|
knowledgeSources /*
|
|
5742
5793
|
<- TODO: [🧊] `knowledgePieces` */, personas /*
|
|
5743
|
-
<- TODO: [🧊] `preparations` */, _llms, llmTools, llmToolsWithUsage, currentPreparation, preparations, preparedPersonas, knowledgeSourcesPrepared, partialknowledgePiecesPrepared, knowledgePiecesPrepared, tasksPrepared /* TODO: parameters: parametersPrepared*/;
|
|
5794
|
+
<- TODO: [🧊] `preparations` */, sources, _llms, llmTools, llmToolsWithUsage, currentPreparation, preparations, title, collection, prepareTitleExecutor, _c, result, outputParameters, titleRaw, preparedPersonas, knowledgeSourcesPrepared, partialknowledgePiecesPrepared, knowledgePiecesPrepared, tasksPrepared /* TODO: parameters: parametersPrepared*/;
|
|
5795
|
+
var _d;
|
|
5744
5796
|
var _this = this;
|
|
5745
|
-
return __generator(this, function (
|
|
5746
|
-
switch (
|
|
5797
|
+
return __generator(this, function (_e) {
|
|
5798
|
+
switch (_e.label) {
|
|
5747
5799
|
case 0:
|
|
5748
5800
|
if (isPipelinePrepared(pipeline)) {
|
|
5749
5801
|
return [2 /*return*/, pipeline];
|
|
5750
5802
|
}
|
|
5751
5803
|
rootDirname = options.rootDirname, _a = options.maxParallelCount, maxParallelCount = _a === void 0 ? DEFAULT_MAX_PARALLEL_COUNT : _a, _b = options.isVerbose, isVerbose = _b === void 0 ? DEFAULT_IS_VERBOSE : _b;
|
|
5752
|
-
parameters = pipeline.parameters, tasks = pipeline.tasks, knowledgeSources = pipeline.knowledgeSources, personas = pipeline.personas;
|
|
5804
|
+
parameters = pipeline.parameters, tasks = pipeline.tasks, knowledgeSources = pipeline.knowledgeSources, personas = pipeline.personas, sources = pipeline.sources;
|
|
5753
5805
|
if (tools === undefined || tools.llm === undefined) {
|
|
5754
5806
|
throw new MissingToolsError('LLM tools are required for preparing the pipeline');
|
|
5755
5807
|
}
|
|
@@ -5767,6 +5819,33 @@
|
|
|
5767
5819
|
// <- TODO: [🧊]
|
|
5768
5820
|
currentPreparation,
|
|
5769
5821
|
];
|
|
5822
|
+
title = pipeline.title;
|
|
5823
|
+
if (!(title === undefined || title === '' || title === DEFAULT_BOOK_TITLE)) return [3 /*break*/, 3];
|
|
5824
|
+
collection = createCollectionFromJson.apply(void 0, __spreadArray([], __read(PipelineCollection), false));
|
|
5825
|
+
_c = createPipelineExecutor;
|
|
5826
|
+
_d = {};
|
|
5827
|
+
return [4 /*yield*/, collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-title.book.md')];
|
|
5828
|
+
case 1:
|
|
5829
|
+
prepareTitleExecutor = _c.apply(void 0, [(_d.pipeline = _e.sent(),
|
|
5830
|
+
_d.tools = tools,
|
|
5831
|
+
_d)]);
|
|
5832
|
+
return [4 /*yield*/, prepareTitleExecutor({
|
|
5833
|
+
book: sources.map(function (_a) {
|
|
5834
|
+
var content = _a.content;
|
|
5835
|
+
return content;
|
|
5836
|
+
}).join('\n\n'),
|
|
5837
|
+
})];
|
|
5838
|
+
case 2:
|
|
5839
|
+
result = _e.sent();
|
|
5840
|
+
assertsExecutionSuccessful(result);
|
|
5841
|
+
outputParameters = result.outputParameters;
|
|
5842
|
+
titleRaw = outputParameters.title;
|
|
5843
|
+
if (isVerbose) {
|
|
5844
|
+
console.info("The title is \"".concat(titleRaw, "\""));
|
|
5845
|
+
}
|
|
5846
|
+
title = titleRaw || DEFAULT_BOOK_TITLE;
|
|
5847
|
+
_e.label = 3;
|
|
5848
|
+
case 3:
|
|
5770
5849
|
preparedPersonas = new Array(personas.length);
|
|
5771
5850
|
return [4 /*yield*/, forEachAsync(personas, { maxParallelCount: maxParallelCount /* <- TODO: [🪂] When there are subtasks, this maximul limit can be broken */ }, function (persona, index) { return __awaiter(_this, void 0, void 0, function () {
|
|
5772
5851
|
var modelRequirements, preparedPersona;
|
|
@@ -5785,12 +5864,12 @@
|
|
|
5785
5864
|
}
|
|
5786
5865
|
});
|
|
5787
5866
|
}); })];
|
|
5788
|
-
case
|
|
5789
|
-
|
|
5867
|
+
case 4:
|
|
5868
|
+
_e.sent();
|
|
5790
5869
|
knowledgeSourcesPrepared = knowledgeSources.map(function (source) { return (__assign(__assign({}, source), { preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id] })); });
|
|
5791
5870
|
return [4 /*yield*/, prepareKnowledgePieces(knowledgeSources /* <- TODO: [🧊] {knowledgeSources, knowledgePieces} */, __assign(__assign({}, tools), { llm: llmToolsWithUsage }), __assign(__assign({}, options), { rootDirname: rootDirname, maxParallelCount: maxParallelCount /* <- TODO: [🪂] */, isVerbose: isVerbose }))];
|
|
5792
|
-
case
|
|
5793
|
-
partialknowledgePiecesPrepared =
|
|
5871
|
+
case 5:
|
|
5872
|
+
partialknowledgePiecesPrepared = _e.sent();
|
|
5794
5873
|
knowledgePiecesPrepared = partialknowledgePiecesPrepared.map(function (piece) { return (__assign(__assign({}, piece), { preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id] })); });
|
|
5795
5874
|
return [4 /*yield*/, prepareTasks({
|
|
5796
5875
|
parameters: parameters,
|
|
@@ -5801,8 +5880,8 @@
|
|
|
5801
5880
|
maxParallelCount: maxParallelCount /* <- TODO: [🪂] */,
|
|
5802
5881
|
isVerbose: isVerbose,
|
|
5803
5882
|
})];
|
|
5804
|
-
case
|
|
5805
|
-
tasksPrepared = (
|
|
5883
|
+
case 6:
|
|
5884
|
+
tasksPrepared = (_e.sent()).tasksPrepared;
|
|
5806
5885
|
// ----- /Tasks preparation -----
|
|
5807
5886
|
// TODO: [😂] Use here all `AsyncHighLevelAbstraction`
|
|
5808
5887
|
// Note: Count total usage
|
|
@@ -5813,7 +5892,7 @@
|
|
|
5813
5892
|
order: ORDER_OF_PIPELINE_JSON,
|
|
5814
5893
|
value: __assign(__assign({}, pipeline), {
|
|
5815
5894
|
// <- TODO: Probbably deeply clone the pipeline because `$exportJson` freezes the subobjects
|
|
5816
|
-
knowledgeSources: knowledgeSourcesPrepared, knowledgePieces: knowledgePiecesPrepared, tasks: __spreadArray([], __read(tasksPrepared), false),
|
|
5895
|
+
title: title, knowledgeSources: knowledgeSourcesPrepared, knowledgePieces: knowledgePiecesPrepared, tasks: __spreadArray([], __read(tasksPrepared), false),
|
|
5817
5896
|
// <- TODO: [🪓] Here should be no need for spreading new array, just ` tasks: tasksPrepared`
|
|
5818
5897
|
personas: preparedPersonas, preparations: __spreadArray([], __read(preparations), false) }),
|
|
5819
5898
|
})];
|
|
@@ -5908,7 +5987,7 @@
|
|
|
5908
5987
|
if (sourceContent === '') {
|
|
5909
5988
|
throw new ParseError("Source is not defined");
|
|
5910
5989
|
}
|
|
5911
|
-
// TODO: [main]
|
|
5990
|
+
// TODO: [main] !!4 Following checks should be applied every link in the `sourceContent`
|
|
5912
5991
|
if (sourceContent.startsWith('http://')) {
|
|
5913
5992
|
throw new ParseError("Source is not secure");
|
|
5914
5993
|
}
|
|
@@ -6080,7 +6159,7 @@
|
|
|
6080
6159
|
expectResultingParameterName();
|
|
6081
6160
|
var parameter = $pipelineJson.parameters.find(function (param) { return param.name === $taskJson.resultingParameterName; });
|
|
6082
6161
|
if (parameter === undefined) {
|
|
6083
|
-
// TODO:
|
|
6162
|
+
// TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
|
|
6084
6163
|
throw new ParseError("Parameter `{".concat($taskJson.resultingParameterName, "}` is not defined so can not define example value of it"));
|
|
6085
6164
|
}
|
|
6086
6165
|
parameter.exampleValues = parameter.exampleValues || [];
|
|
@@ -6091,7 +6170,7 @@
|
|
|
6091
6170
|
if (command.taskType === 'KNOWLEDGE') {
|
|
6092
6171
|
knowledgeCommandParser.$applyToPipelineJson({
|
|
6093
6172
|
type: 'KNOWLEDGE',
|
|
6094
|
-
sourceContent: $taskJson.content, // <- TODO: [🐝][main]
|
|
6173
|
+
sourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
|
|
6095
6174
|
}, $pipelineJson);
|
|
6096
6175
|
$taskJson.isTask = false;
|
|
6097
6176
|
return;
|
|
@@ -6986,20 +7065,24 @@
|
|
|
6986
7065
|
*/
|
|
6987
7066
|
var GeneratorFormfactorDefinition = {
|
|
6988
7067
|
name: 'GENERATOR',
|
|
6989
|
-
description: "
|
|
7068
|
+
description: "Generates any kind (in HTML with possible scripts and css format) of content from input message",
|
|
6990
7069
|
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
|
|
6991
7070
|
pipelineInterface: {
|
|
6992
7071
|
inputParameters: [
|
|
6993
|
-
/* @@@ */
|
|
6994
7072
|
{
|
|
6995
|
-
name: '
|
|
6996
|
-
description:
|
|
7073
|
+
name: 'inputMessage',
|
|
7074
|
+
description: "Input message to be image made from",
|
|
6997
7075
|
isInput: true,
|
|
6998
7076
|
isOutput: false,
|
|
6999
7077
|
},
|
|
7000
7078
|
],
|
|
7001
7079
|
outputParameters: [
|
|
7002
|
-
|
|
7080
|
+
{
|
|
7081
|
+
name: 'result',
|
|
7082
|
+
description: "Result in HTML to be shown to user",
|
|
7083
|
+
isInput: false,
|
|
7084
|
+
isOutput: true,
|
|
7085
|
+
},
|
|
7003
7086
|
],
|
|
7004
7087
|
},
|
|
7005
7088
|
};
|
|
@@ -7031,6 +7114,35 @@
|
|
|
7031
7114
|
pipelineInterface: GENERIC_PIPELINE_INTERFACE,
|
|
7032
7115
|
};
|
|
7033
7116
|
|
|
7117
|
+
/**
|
|
7118
|
+
* Image generator is form of app that generates image from input message
|
|
7119
|
+
*
|
|
7120
|
+
* @public exported from `@promptbook/core`
|
|
7121
|
+
*/
|
|
7122
|
+
var ImageGeneratorFormfactorDefinition = {
|
|
7123
|
+
name: 'IMAGE_GENERATOR',
|
|
7124
|
+
description: "Generates prompt for image generation from input message",
|
|
7125
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
|
|
7126
|
+
pipelineInterface: {
|
|
7127
|
+
inputParameters: [
|
|
7128
|
+
{
|
|
7129
|
+
name: 'inputMessage',
|
|
7130
|
+
description: "Input message to be image made from",
|
|
7131
|
+
isInput: true,
|
|
7132
|
+
isOutput: false,
|
|
7133
|
+
},
|
|
7134
|
+
],
|
|
7135
|
+
outputParameters: [
|
|
7136
|
+
{
|
|
7137
|
+
name: 'prompt',
|
|
7138
|
+
description: "Prompt to be used for image generation",
|
|
7139
|
+
isInput: false,
|
|
7140
|
+
isOutput: true,
|
|
7141
|
+
},
|
|
7142
|
+
],
|
|
7143
|
+
},
|
|
7144
|
+
};
|
|
7145
|
+
|
|
7034
7146
|
/**
|
|
7035
7147
|
* Matcher is form of app that @@@
|
|
7036
7148
|
*
|
|
@@ -7129,6 +7241,7 @@
|
|
|
7129
7241
|
SheetsFormfactorDefinition,
|
|
7130
7242
|
MatcherFormfactorDefinition,
|
|
7131
7243
|
GeneratorFormfactorDefinition,
|
|
7244
|
+
ImageGeneratorFormfactorDefinition,
|
|
7132
7245
|
];
|
|
7133
7246
|
/**
|
|
7134
7247
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -7515,7 +7628,7 @@
|
|
|
7515
7628
|
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
7516
7629
|
*/
|
|
7517
7630
|
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
7518
|
-
// Note: [🍣] Do nothing, its application is implemented separately in `
|
|
7631
|
+
// Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
|
|
7519
7632
|
},
|
|
7520
7633
|
/**
|
|
7521
7634
|
* Apply the PARAMETER command to the `pipelineJson`
|
|
@@ -7523,7 +7636,7 @@
|
|
|
7523
7636
|
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
7524
7637
|
*/
|
|
7525
7638
|
$applyToTaskJson: function (command, $taskJson, $pipelineJson) {
|
|
7526
|
-
// Note: [🍣] Do nothing, its application is implemented separately in `
|
|
7639
|
+
// Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
|
|
7527
7640
|
},
|
|
7528
7641
|
/**
|
|
7529
7642
|
* Converts the PARAMETER command back to string
|
|
@@ -8018,7 +8131,7 @@
|
|
|
8018
8131
|
instrumentCommandParser,
|
|
8019
8132
|
personaCommandParser,
|
|
8020
8133
|
foreachCommandParser,
|
|
8021
|
-
boilerplateCommandParser, // <- TODO:
|
|
8134
|
+
boilerplateCommandParser, // <- TODO: Only in development, remove in production
|
|
8022
8135
|
// <- Note: [♓️][💩] This is the order of the commands in the pipeline, BUT its not used in parsing and before usage maybe it should be done better
|
|
8023
8136
|
];
|
|
8024
8137
|
/**
|
|
@@ -8442,7 +8555,7 @@
|
|
|
8442
8555
|
isOutput: true,
|
|
8443
8556
|
exampleValues: ['Hello, I am a Pavol`s virtual avatar. How can I help you?'],
|
|
8444
8557
|
});
|
|
8445
|
-
// TODO:
|
|
8558
|
+
// TODO: Use spaceTrim in multiline strings
|
|
8446
8559
|
$pipelineJson.tasks.push({
|
|
8447
8560
|
taskType: 'PROMPT_TASK',
|
|
8448
8561
|
name: 'create-an-answer',
|
|
@@ -8450,8 +8563,11 @@
|
|
|
8450
8563
|
content: 'Write a response to the user message:\n\n**Question from user**\n\n> {userMessage}\n\n**Previous conversation**\n\n> {previousConversationSummary}',
|
|
8451
8564
|
resultingParameterName: 'chatbotResponse',
|
|
8452
8565
|
personaName: personaName,
|
|
8453
|
-
dependentParameterNames: [
|
|
8454
|
-
|
|
8566
|
+
dependentParameterNames: [
|
|
8567
|
+
'userMessage',
|
|
8568
|
+
'previousConversationSummary' /* TODO: [🧠][📛], 'knowledge'*/,
|
|
8569
|
+
],
|
|
8570
|
+
// TODO: [🧠][📛] preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
|
|
8455
8571
|
}, {
|
|
8456
8572
|
taskType: 'PROMPT_TASK',
|
|
8457
8573
|
name: 'summarize-the-conversation',
|
|
@@ -8465,24 +8581,27 @@
|
|
|
8465
8581
|
max: 10,
|
|
8466
8582
|
},
|
|
8467
8583
|
},
|
|
8468
|
-
dependentParameterNames: ['userMessage', 'chatbotResponse' /*
|
|
8469
|
-
//
|
|
8584
|
+
dependentParameterNames: ['userMessage', 'chatbotResponse' /* TODO: [🧠][📛], 'knowledge'*/],
|
|
8585
|
+
// TODO: [🧠][📛] preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
|
|
8470
8586
|
}, {
|
|
8471
8587
|
taskType: 'SIMPLE_TASK',
|
|
8472
8588
|
name: 'title',
|
|
8473
8589
|
title: 'Title',
|
|
8474
8590
|
content: '{conversationSummary}',
|
|
8475
8591
|
resultingParameterName: 'title',
|
|
8476
|
-
dependentParameterNames: ['conversationSummary' /*
|
|
8477
|
-
//
|
|
8592
|
+
dependentParameterNames: ['conversationSummary' /* TODO: [🧠][📛], 'knowledge'*/],
|
|
8593
|
+
// TODO: [🧠][📛] preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
|
|
8478
8594
|
});
|
|
8479
8595
|
},
|
|
8480
8596
|
};
|
|
8597
|
+
/**
|
|
8598
|
+
* TODO: [🧠][📛] Should this be here?
|
|
8599
|
+
*/
|
|
8481
8600
|
|
|
8482
8601
|
/**
|
|
8483
8602
|
* All high-level abstractions
|
|
8484
8603
|
*
|
|
8485
|
-
* @private internal index of `
|
|
8604
|
+
* @private internal index of `parsePipeline` (= used for sync) and `preparePipeline` (= used for async)
|
|
8486
8605
|
*/
|
|
8487
8606
|
var HIGH_LEVEL_ABSTRACTIONS = [
|
|
8488
8607
|
ImplicitFormfactorHla,
|
|
@@ -8616,7 +8735,7 @@
|
|
|
8616
8735
|
return;
|
|
8617
8736
|
}
|
|
8618
8737
|
if (!section.startsWith('#')) {
|
|
8619
|
-
section = "# ".concat(
|
|
8738
|
+
section = "# ".concat(DEFAULT_BOOK_TITLE, "\n\n").concat(section);
|
|
8620
8739
|
}
|
|
8621
8740
|
sections.push(section);
|
|
8622
8741
|
buffer = [];
|
|
@@ -8671,7 +8790,7 @@
|
|
|
8671
8790
|
/**
|
|
8672
8791
|
* Normalizes the markdown by flattening the structure
|
|
8673
8792
|
*
|
|
8674
|
-
* - It always have h1 - if there is no h1 in the markdown, it will be added
|
|
8793
|
+
* - It always have h1 - if there is no h1 in the markdown, it will be added `DEFAULT_BOOK_TITLE`
|
|
8675
8794
|
* - All other headings are normalized to h2
|
|
8676
8795
|
*
|
|
8677
8796
|
* @public exported from `@promptbook/markdown-utils`
|
|
@@ -8680,7 +8799,7 @@
|
|
|
8680
8799
|
var e_1, _a;
|
|
8681
8800
|
var sections = splitMarkdownIntoSections(markdown);
|
|
8682
8801
|
if (sections.length === 0) {
|
|
8683
|
-
return "# ".concat(
|
|
8802
|
+
return "# ".concat(DEFAULT_BOOK_TITLE);
|
|
8684
8803
|
}
|
|
8685
8804
|
var flattenedMarkdown = '';
|
|
8686
8805
|
var parsedSections = sections.map(parseMarkdownSection);
|
|
@@ -8691,7 +8810,7 @@
|
|
|
8691
8810
|
}
|
|
8692
8811
|
else {
|
|
8693
8812
|
parsedSections.unshift(firstSection);
|
|
8694
|
-
flattenedMarkdown += "# ".concat(
|
|
8813
|
+
flattenedMarkdown += "# ".concat(DEFAULT_BOOK_TITLE) + "\n\n"; // <- [🧠] Maybe 3 new lines?
|
|
8695
8814
|
}
|
|
8696
8815
|
try {
|
|
8697
8816
|
for (var parsedSections_1 = __values(parsedSections), parsedSections_1_1 = parsedSections_1.next(); !parsedSections_1_1.done; parsedSections_1_1 = parsedSections_1.next()) {
|
|
@@ -8718,13 +8837,13 @@
|
|
|
8718
8837
|
*/
|
|
8719
8838
|
|
|
8720
8839
|
/**
|
|
8721
|
-
* Removes
|
|
8840
|
+
* Removes Markdown (or HTML) comments
|
|
8722
8841
|
*
|
|
8723
8842
|
* @param {string} content - The string to remove comments from.
|
|
8724
8843
|
* @returns {string} The input string with all comments removed.
|
|
8725
8844
|
* @public exported from `@promptbook/markdown-utils`
|
|
8726
8845
|
*/
|
|
8727
|
-
function
|
|
8846
|
+
function removeMarkdownComments(content) {
|
|
8728
8847
|
return spaceTrim.spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
|
|
8729
8848
|
}
|
|
8730
8849
|
|
|
@@ -8757,7 +8876,7 @@
|
|
|
8757
8876
|
*
|
|
8758
8877
|
* Note: There are 3 similar functions:
|
|
8759
8878
|
* - `compilePipeline` **(preferred)** - which propperly compiles the promptbook and use embedding for external knowledge
|
|
8760
|
-
* - `
|
|
8879
|
+
* - `parsePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
|
|
8761
8880
|
* - `preparePipeline` - just one step in the compilation process
|
|
8762
8881
|
*
|
|
8763
8882
|
* Note: This function does not validate logic of the pipeline only the parsing
|
|
@@ -8768,10 +8887,10 @@
|
|
|
8768
8887
|
* @throws {ParseError} if the promptbook string is not valid
|
|
8769
8888
|
* @public exported from `@promptbook/core`
|
|
8770
8889
|
*/
|
|
8771
|
-
function
|
|
8890
|
+
function parsePipeline(pipelineString) {
|
|
8772
8891
|
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
|
|
8773
8892
|
var $pipelineJson = {
|
|
8774
|
-
title:
|
|
8893
|
+
title: DEFAULT_BOOK_TITLE,
|
|
8775
8894
|
parameters: [],
|
|
8776
8895
|
tasks: [],
|
|
8777
8896
|
knowledgeSources: [],
|
|
@@ -8782,7 +8901,7 @@
|
|
|
8782
8901
|
{
|
|
8783
8902
|
type: 'BOOK',
|
|
8784
8903
|
path: null,
|
|
8785
|
-
// <- TODO:
|
|
8904
|
+
// <- TODO: !!6 Pass here path of the file
|
|
8786
8905
|
content: pipelineString,
|
|
8787
8906
|
},
|
|
8788
8907
|
],
|
|
@@ -8807,16 +8926,29 @@
|
|
|
8807
8926
|
if (!(shebangLine_1 || '').includes('ptbk')) {
|
|
8808
8927
|
throw new ParseError(spaceTrim.spaceTrim(function (block) { return "\n It seems that you try to parse a book file which has non-standard shebang line for book files:\n Shebang line must contain 'ptbk'\n\n You have:\n ".concat(block(shebangLine_1 || '(empty line)'), "\n\n It should look like this:\n #!/usr/bin/env ptbk\n\n ").concat(block(getPipelineIdentification()), "\n "); }));
|
|
8809
8928
|
}
|
|
8810
|
-
pipelineString = restLines.join('\n');
|
|
8929
|
+
pipelineString = validatePipelineString(restLines.join('\n'));
|
|
8811
8930
|
}
|
|
8812
|
-
pipelineString =
|
|
8931
|
+
pipelineString = removeMarkdownComments(pipelineString);
|
|
8932
|
+
pipelineString = spaceTrim.spaceTrim(pipelineString);
|
|
8933
|
+
// <- TODO: [😧] `spaceTrim` should preserve discriminated type *(or at lease `PipelineString`)*
|
|
8813
8934
|
// ==============
|
|
8814
8935
|
// Note: 1️⃣◽2️⃣ Process flat pipeline
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
//
|
|
8818
|
-
// const
|
|
8819
|
-
// const
|
|
8936
|
+
var isMarkdownBeginningWithHeadline = pipelineString.startsWith('# ');
|
|
8937
|
+
var isLastLineReturnStatement = pipelineString.split('\n').pop().split('`').join('').startsWith('->');
|
|
8938
|
+
// TODO: Also (double)check
|
|
8939
|
+
// > const usedCommands
|
|
8940
|
+
// > const isBlocksUsed
|
|
8941
|
+
// > const returnStatementCount
|
|
8942
|
+
var isFlatPipeline = !isMarkdownBeginningWithHeadline && isLastLineReturnStatement;
|
|
8943
|
+
// console.log({ isMarkdownBeginningWithHeadline, isLastLineReturnStatement, isFlatPipeline });
|
|
8944
|
+
if (isFlatPipeline) {
|
|
8945
|
+
var pipelineStringLines = pipelineString.split('\n');
|
|
8946
|
+
var returnStatement_1 = pipelineStringLines.pop();
|
|
8947
|
+
var prompt_1 = spaceTrim.spaceTrim(pipelineStringLines.join('\n'));
|
|
8948
|
+
pipelineString = validatePipelineString(spaceTrim.spaceTrim(function (block) { return "\n # ".concat(DEFAULT_BOOK_TITLE, "\n\n ## Prompt\n\n ```\n ").concat(block(prompt_1), "\n ```\n\n ").concat(returnStatement_1, "\n "); }));
|
|
8949
|
+
// <- TODO: Maybe use book` notation
|
|
8950
|
+
// console.log(pipelineString);
|
|
8951
|
+
}
|
|
8820
8952
|
// ==============
|
|
8821
8953
|
// Note: 1️⃣◽3️⃣ Parse the markdown
|
|
8822
8954
|
pipelineString = flattenMarkdown(pipelineString) /* <- Note: [🥞] */;
|
|
@@ -9208,14 +9340,14 @@
|
|
|
9208
9340
|
// =============================================================
|
|
9209
9341
|
return exportJson({
|
|
9210
9342
|
name: 'pipelineJson',
|
|
9211
|
-
message: "Result of `
|
|
9343
|
+
message: "Result of `parsePipeline`",
|
|
9212
9344
|
order: ORDER_OF_PIPELINE_JSON,
|
|
9213
9345
|
value: __assign({ formfactorName: 'GENERIC' }, $pipelineJson),
|
|
9214
9346
|
});
|
|
9215
9347
|
}
|
|
9216
9348
|
/**
|
|
9217
9349
|
* TODO: [🧠] Maybe more things here can be refactored as high-level abstractions
|
|
9218
|
-
* TODO: [main]
|
|
9350
|
+
* TODO: [main] !!4 Warn if used only sync version
|
|
9219
9351
|
* TODO: [🚞] Report here line/column of error
|
|
9220
9352
|
* TODO: Use spaceTrim more effectively
|
|
9221
9353
|
* TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
|
|
@@ -9228,10 +9360,7 @@
|
|
|
9228
9360
|
/**
|
|
9229
9361
|
* Compile pipeline from string (markdown) format to JSON format
|
|
9230
9362
|
*
|
|
9231
|
-
*
|
|
9232
|
-
* - `compilePipeline` **(preferred)** - which propperly compiles the promptbook and use embedding for external knowledge
|
|
9233
|
-
* - `precompilePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
|
|
9234
|
-
* - `preparePipeline` - just one step in the compilation process
|
|
9363
|
+
* @see https://github.com/webgptorg/promptbook/discussions/196
|
|
9235
9364
|
*
|
|
9236
9365
|
* Note: This function does not validate logic of the pipeline only the parsing
|
|
9237
9366
|
* Note: This function acts as compilation process
|
|
@@ -9249,7 +9378,7 @@
|
|
|
9249
9378
|
return __generator(this, function (_a) {
|
|
9250
9379
|
switch (_a.label) {
|
|
9251
9380
|
case 0:
|
|
9252
|
-
pipelineJson =
|
|
9381
|
+
pipelineJson = parsePipeline(pipelineString);
|
|
9253
9382
|
if (!(tools !== undefined && tools.llm !== undefined)) return [3 /*break*/, 2];
|
|
9254
9383
|
return [4 /*yield*/, preparePipeline(pipelineJson, tools, options || {
|
|
9255
9384
|
rootDirname: null,
|
|
@@ -9258,7 +9387,7 @@
|
|
|
9258
9387
|
pipelineJson = _a.sent();
|
|
9259
9388
|
_a.label = 2;
|
|
9260
9389
|
case 2:
|
|
9261
|
-
// Note: No need to use `$exportJson` because `
|
|
9390
|
+
// Note: No need to use `$exportJson` because `parsePipeline` and `preparePipeline` already do that
|
|
9262
9391
|
return [2 /*return*/, pipelineJson];
|
|
9263
9392
|
}
|
|
9264
9393
|
});
|
|
@@ -9609,6 +9738,25 @@
|
|
|
9609
9738
|
* TODO: [®] DRY Register logic
|
|
9610
9739
|
*/
|
|
9611
9740
|
|
|
9741
|
+
/**
|
|
9742
|
+
* Determines if the given path is a root path.
|
|
9743
|
+
*
|
|
9744
|
+
* Note: This does not check if the file exists only if the path is valid
|
|
9745
|
+
* @public exported from `@promptbook/utils`
|
|
9746
|
+
*/
|
|
9747
|
+
function isRootPath(value) {
|
|
9748
|
+
if (value === '/') {
|
|
9749
|
+
return true;
|
|
9750
|
+
}
|
|
9751
|
+
if (/^[A-Z]:\\$/i.test(value)) {
|
|
9752
|
+
return true;
|
|
9753
|
+
}
|
|
9754
|
+
return false;
|
|
9755
|
+
}
|
|
9756
|
+
/**
|
|
9757
|
+
* TODO: [🍏] Make for MacOS paths
|
|
9758
|
+
*/
|
|
9759
|
+
|
|
9612
9760
|
/**
|
|
9613
9761
|
* @@@
|
|
9614
9762
|
*
|
|
@@ -9623,17 +9771,45 @@
|
|
|
9623
9771
|
* @public exported from `@promptbook/node`
|
|
9624
9772
|
*/
|
|
9625
9773
|
function $provideLlmToolsConfigurationFromEnv() {
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9774
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
9775
|
+
var rootDirname, i, envFilename, llmToolsConfiguration;
|
|
9776
|
+
return __generator(this, function (_a) {
|
|
9777
|
+
switch (_a.label) {
|
|
9778
|
+
case 0:
|
|
9779
|
+
if (!$isRunningInNode()) {
|
|
9780
|
+
throw new EnvironmentMismatchError('Function `$provideLlmToolsFromEnv` works only in Node.js environment');
|
|
9781
|
+
}
|
|
9782
|
+
rootDirname = process.cwd();
|
|
9783
|
+
i = 0;
|
|
9784
|
+
_a.label = 1;
|
|
9785
|
+
case 1:
|
|
9786
|
+
if (!(i < LOOP_LIMIT)) return [3 /*break*/, 4];
|
|
9787
|
+
envFilename = path.join(rootDirname, '.env' /* <- TODO: [🕝] Make here more candidates */);
|
|
9788
|
+
return [4 /*yield*/, isFileExisting(envFilename, $provideFilesystemForNode())];
|
|
9789
|
+
case 2:
|
|
9790
|
+
// console.log({ rootDirname, envFilename });
|
|
9791
|
+
if (_a.sent()) {
|
|
9792
|
+
dotenv__namespace.config({ path: envFilename });
|
|
9793
|
+
return [3 /*break*/, 4];
|
|
9794
|
+
}
|
|
9795
|
+
if (isRootPath(rootDirname)) {
|
|
9796
|
+
return [3 /*break*/, 4];
|
|
9797
|
+
}
|
|
9798
|
+
// Note: If the directory does not exist, try the parent directory
|
|
9799
|
+
rootDirname = path.join(rootDirname, '..');
|
|
9800
|
+
_a.label = 3;
|
|
9801
|
+
case 3:
|
|
9802
|
+
i++;
|
|
9803
|
+
return [3 /*break*/, 1];
|
|
9804
|
+
case 4:
|
|
9805
|
+
llmToolsConfiguration = $llmToolsMetadataRegister
|
|
9806
|
+
.list()
|
|
9807
|
+
.map(function (metadata) { return metadata.createConfigurationFromEnv(process.env); })
|
|
9808
|
+
.filter(function (configuration) { return configuration !== null; });
|
|
9809
|
+
return [2 /*return*/, llmToolsConfiguration];
|
|
9810
|
+
}
|
|
9811
|
+
});
|
|
9812
|
+
});
|
|
9637
9813
|
}
|
|
9638
9814
|
/**
|
|
9639
9815
|
* TODO: [🧠][🪁] Maybe do allow to do auto-install if package not registered and not found
|
|
@@ -9856,15 +10032,28 @@
|
|
|
9856
10032
|
*/
|
|
9857
10033
|
function $provideLlmToolsFromEnv(options) {
|
|
9858
10034
|
if (options === void 0) { options = {}; }
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
10035
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
10036
|
+
var configuration;
|
|
10037
|
+
return __generator(this, function (_a) {
|
|
10038
|
+
switch (_a.label) {
|
|
10039
|
+
case 0:
|
|
10040
|
+
if (!$isRunningInNode()) {
|
|
10041
|
+
throw new EnvironmentMismatchError('Function `$provideLlmToolsFromEnv` works only in Node.js environment');
|
|
10042
|
+
}
|
|
10043
|
+
return [4 /*yield*/, $provideLlmToolsConfigurationFromEnv()];
|
|
10044
|
+
case 1:
|
|
10045
|
+
configuration = _a.sent();
|
|
10046
|
+
if (configuration.length === 0) {
|
|
10047
|
+
if ($llmToolsMetadataRegister.list().length === 0) {
|
|
10048
|
+
throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n No LLM tools registered, this is probably a bug in the Promptbook library\n\n ".concat(block($registeredLlmToolsMessage()), "}\n "); }));
|
|
10049
|
+
}
|
|
10050
|
+
// TODO: [🥃]
|
|
10051
|
+
throw new Error(spaceTrim__default["default"](function (block) { return "\n No LLM tools found in the environment\n\n ".concat(block($registeredLlmToolsMessage()), "}\n "); }));
|
|
10052
|
+
}
|
|
10053
|
+
return [2 /*return*/, createLlmToolsFromConfiguration(configuration, options)];
|
|
10054
|
+
}
|
|
10055
|
+
});
|
|
10056
|
+
});
|
|
9868
10057
|
}
|
|
9869
10058
|
/**
|
|
9870
10059
|
* TODO: @@@ write `$provideLlmToolsFromEnv` vs `$provideLlmToolsConfigurationFromEnv` vs `createLlmToolsFromConfiguration`
|
|
@@ -9933,23 +10122,31 @@
|
|
|
9933
10122
|
*/
|
|
9934
10123
|
|
|
9935
10124
|
/**
|
|
9936
|
-
*
|
|
10125
|
+
* Detects if the code is running in a browser environment in main thread (Not in a web worker)
|
|
9937
10126
|
*
|
|
9938
|
-
*
|
|
10127
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
9939
10128
|
*
|
|
9940
|
-
*
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
10129
|
+
* @public exported from `@promptbook/utils`
|
|
10130
|
+
*/
|
|
10131
|
+
new Function("\n try {\n return this === window;\n } catch (e) {\n return false;\n }\n");
|
|
10132
|
+
|
|
10133
|
+
/**
|
|
10134
|
+
* Detects if the code is running in jest environment
|
|
9945
10135
|
*
|
|
9946
|
-
*
|
|
9947
|
-
*
|
|
10136
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10137
|
+
*
|
|
10138
|
+
* @public exported from `@promptbook/utils`
|
|
9948
10139
|
*/
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
10140
|
+
new Function("\n try {\n return process.env.JEST_WORKER_ID !== undefined;\n } catch (e) {\n return false;\n }\n");
|
|
10141
|
+
|
|
10142
|
+
/**
|
|
10143
|
+
* Detects if the code is running in a web worker
|
|
10144
|
+
*
|
|
10145
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10146
|
+
*
|
|
10147
|
+
* @public exported from `@promptbook/utils`
|
|
10148
|
+
*/
|
|
10149
|
+
new Function("\n try {\n if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {\n return true;\n } else {\n return false;\n }\n } catch (e) {\n return false;\n }\n");
|
|
9953
10150
|
|
|
9954
10151
|
/**
|
|
9955
10152
|
* Makes first letter of a string uppercase
|
|
@@ -9960,6 +10157,21 @@
|
|
|
9960
10157
|
return word.substring(0, 1).toLowerCase() + word.substring(1);
|
|
9961
10158
|
}
|
|
9962
10159
|
|
|
10160
|
+
/**
|
|
10161
|
+
* Parses keywords from a string
|
|
10162
|
+
*
|
|
10163
|
+
* @param {string} input
|
|
10164
|
+
* @returns {Set} of keywords without diacritics in lowercase
|
|
10165
|
+
* @public exported from `@promptbook/utils`
|
|
10166
|
+
*/
|
|
10167
|
+
function parseKeywordsFromString(input) {
|
|
10168
|
+
var keywords = normalizeTo_SCREAMING_CASE(removeDiacritics(input))
|
|
10169
|
+
.toLowerCase()
|
|
10170
|
+
.split(/[^a-z0-9]+/gs)
|
|
10171
|
+
.filter(function (value) { return value; });
|
|
10172
|
+
return new Set(keywords);
|
|
10173
|
+
}
|
|
10174
|
+
|
|
9963
10175
|
/**
|
|
9964
10176
|
* @@@
|
|
9965
10177
|
*
|
|
@@ -10013,20 +10225,39 @@
|
|
|
10013
10225
|
return sentence.replace(/\s+/gs, ' ').trim();
|
|
10014
10226
|
}
|
|
10015
10227
|
|
|
10228
|
+
// <- TODO: Auto convert to type `import { ... } from 'type-fest';`
|
|
10016
10229
|
/**
|
|
10017
|
-
*
|
|
10230
|
+
* Tests if the value is [🚉] serializable as JSON
|
|
10231
|
+
*
|
|
10232
|
+
* - Almost all primitives are serializable BUT:
|
|
10233
|
+
* - `undefined` is not serializable
|
|
10234
|
+
* - `NaN` is not serializable
|
|
10235
|
+
* - Objects and arrays are serializable if all their properties are serializable
|
|
10236
|
+
* - Functions are not serializable
|
|
10237
|
+
* - Circular references are not serializable
|
|
10238
|
+
* - `Date` objects are not serializable
|
|
10239
|
+
* - `Map` and `Set` objects are not serializable
|
|
10240
|
+
* - `RegExp` objects are not serializable
|
|
10241
|
+
* - `Error` objects are not serializable
|
|
10242
|
+
* - `Symbol` objects are not serializable
|
|
10243
|
+
* - And much more...
|
|
10244
|
+
*
|
|
10018
10245
|
*
|
|
10019
|
-
* @param {string} input
|
|
10020
|
-
* @returns {Set} of keywords without diacritics in lowercase
|
|
10021
10246
|
* @public exported from `@promptbook/utils`
|
|
10022
10247
|
*/
|
|
10023
|
-
function
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10248
|
+
function isSerializableAsJson(value) {
|
|
10249
|
+
try {
|
|
10250
|
+
checkSerializableAsJson({ value: value });
|
|
10251
|
+
return true;
|
|
10252
|
+
}
|
|
10253
|
+
catch (error) {
|
|
10254
|
+
return false;
|
|
10255
|
+
}
|
|
10029
10256
|
}
|
|
10257
|
+
/**
|
|
10258
|
+
* TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
10259
|
+
* TODO: [🧠][💺] Can be done this on type-level?
|
|
10260
|
+
*/
|
|
10030
10261
|
|
|
10031
10262
|
/**
|
|
10032
10263
|
* Function trimCodeBlock will trim starting and ending code block from the string if it is present.
|
|
@@ -10134,6 +10365,25 @@
|
|
|
10134
10365
|
* TODO: [🧠] Should this also unwrap the (parenthesis)
|
|
10135
10366
|
*/
|
|
10136
10367
|
|
|
10368
|
+
/**
|
|
10369
|
+
* Extracts code block from markdown.
|
|
10370
|
+
*
|
|
10371
|
+
* - When there are multiple or no code blocks the function throws a `ParseError`
|
|
10372
|
+
*
|
|
10373
|
+
* Note: There are multiple simmilar function:
|
|
10374
|
+
* - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
|
|
10375
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
10376
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
10377
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
10378
|
+
*
|
|
10379
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
10380
|
+
* @throws {ParseError} if there is not exactly one code block in the markdown
|
|
10381
|
+
*/
|
|
10382
|
+
function extractBlock(markdown) {
|
|
10383
|
+
var content = extractOneBlockFromMarkdown(markdown).content;
|
|
10384
|
+
return content;
|
|
10385
|
+
}
|
|
10386
|
+
|
|
10137
10387
|
/**
|
|
10138
10388
|
* Does nothing, but preserves the function in the bundle
|
|
10139
10389
|
* Compiler is tricked into thinking the function is used
|
|
@@ -10168,36 +10418,9 @@
|
|
|
10168
10418
|
}); })();
|
|
10169
10419
|
}
|
|
10170
10420
|
/**
|
|
10171
|
-
* TODO:
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
/**
|
|
10175
|
-
* Converts anything to string that can be used for debugging and logging
|
|
10176
|
-
*
|
|
10177
|
-
* @param value String value for logging
|
|
10178
|
-
* @private internal util
|
|
10421
|
+
* TODO: Probbably remove in favour of `keepImported`
|
|
10422
|
+
* TODO: [1] This maybe does memory leak
|
|
10179
10423
|
*/
|
|
10180
|
-
function unknownToString(value) {
|
|
10181
|
-
if (value === undefined) {
|
|
10182
|
-
return 'undefined';
|
|
10183
|
-
}
|
|
10184
|
-
else if (value === null) {
|
|
10185
|
-
return 'null';
|
|
10186
|
-
}
|
|
10187
|
-
else if (['number', 'string', 'boolean'].includes(typeof value)) {
|
|
10188
|
-
return typeof value + ' ' + value.toString();
|
|
10189
|
-
}
|
|
10190
|
-
else if (typeof value === 'object' && Array.isArray(value)) {
|
|
10191
|
-
return 'array containing [' + value.map(function (item) { return unknownToString(item); }).join(', ') + ']';
|
|
10192
|
-
}
|
|
10193
|
-
else if (typeof value === 'object') {
|
|
10194
|
-
// TODO: Maybe serialize the object
|
|
10195
|
-
return 'object';
|
|
10196
|
-
}
|
|
10197
|
-
else {
|
|
10198
|
-
return 'unknown (Search in promptbook code for [🔹])';
|
|
10199
|
-
}
|
|
10200
|
-
}
|
|
10201
10424
|
|
|
10202
10425
|
/**
|
|
10203
10426
|
* ScriptExecutionTools for JavaScript implemented via eval
|
|
@@ -10328,7 +10551,7 @@
|
|
|
10328
10551
|
case 2:
|
|
10329
10552
|
result = _a.sent();
|
|
10330
10553
|
if (typeof result !== 'string') {
|
|
10331
|
-
throw new PipelineExecutionError("Script must return a string, but returned ".concat(
|
|
10554
|
+
throw new PipelineExecutionError("Script must return a string, but returned ".concat(valueToString(result)));
|
|
10332
10555
|
}
|
|
10333
10556
|
return [3 /*break*/, 4];
|
|
10334
10557
|
case 3:
|
|
@@ -10355,7 +10578,7 @@
|
|
|
10355
10578
|
throw error_1;
|
|
10356
10579
|
case 4:
|
|
10357
10580
|
if (typeof result !== 'string') {
|
|
10358
|
-
throw new PipelineExecutionError("Script must return a string, but ".concat(
|
|
10581
|
+
throw new PipelineExecutionError("Script must return a string, but ".concat(valueToString(result)));
|
|
10359
10582
|
}
|
|
10360
10583
|
return [2 /*return*/, result];
|
|
10361
10584
|
}
|
|
@@ -10395,9 +10618,11 @@
|
|
|
10395
10618
|
throw new EnvironmentMismatchError('Function `$getExecutionToolsForNode` works only in Node.js environment');
|
|
10396
10619
|
}
|
|
10397
10620
|
fs = $provideFilesystemForNode();
|
|
10398
|
-
|
|
10399
|
-
return [4 /*yield*/, $provideExecutablesForNode(options)];
|
|
10621
|
+
return [4 /*yield*/, $provideLlmToolsFromEnv(options)];
|
|
10400
10622
|
case 1:
|
|
10623
|
+
llm = _b.sent();
|
|
10624
|
+
return [4 /*yield*/, $provideExecutablesForNode(options)];
|
|
10625
|
+
case 2:
|
|
10401
10626
|
executables = _b.sent();
|
|
10402
10627
|
_a = {
|
|
10403
10628
|
llm: llm,
|
|
@@ -10405,7 +10630,7 @@
|
|
|
10405
10630
|
executables: executables
|
|
10406
10631
|
};
|
|
10407
10632
|
return [4 /*yield*/, $provideScrapersForNode({ fs: fs, llm: llm, executables: executables }, options)];
|
|
10408
|
-
case
|
|
10633
|
+
case 3:
|
|
10409
10634
|
tools = (_a.scrapers = _b.sent(),
|
|
10410
10635
|
_a.script = [new JavascriptExecutionTools(options)],
|
|
10411
10636
|
_a);
|
|
@@ -10628,7 +10853,7 @@
|
|
|
10628
10853
|
*/
|
|
10629
10854
|
function createCollectionFromDirectory(path$1, tools, options) {
|
|
10630
10855
|
return __awaiter(this, void 0, void 0, function () {
|
|
10631
|
-
var
|
|
10856
|
+
var madeLibraryFilePath, _a, _b, isRecursive, _c, isVerbose, _d, isLazyLoaded, _e, isCrashedOnError, rootUrl, collection;
|
|
10632
10857
|
var _this = this;
|
|
10633
10858
|
return __generator(this, function (_f) {
|
|
10634
10859
|
switch (_f.label) {
|
|
@@ -10643,18 +10868,18 @@
|
|
|
10643
10868
|
throw new EnvironmentMismatchError('Can not create collection without filesystem tools');
|
|
10644
10869
|
// <- TODO: [🧠] What is the best error type here`
|
|
10645
10870
|
}
|
|
10646
|
-
|
|
10871
|
+
madeLibraryFilePath = path.join(path$1, "".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
|
|
10647
10872
|
// <- TODO: [🦒] Allow to override (pass different value into the function)
|
|
10648
10873
|
, ".json"));
|
|
10649
|
-
return [4 /*yield*/, isFileExisting(
|
|
10874
|
+
return [4 /*yield*/, isFileExisting(madeLibraryFilePath, tools.fs)];
|
|
10650
10875
|
case 3:
|
|
10651
10876
|
if (!(_f.sent())) ;
|
|
10652
10877
|
else {
|
|
10653
|
-
colors__default["default"].green("(In future, not implemented yet) Using your compiled pipeline collection ".concat(
|
|
10654
|
-
// TODO:
|
|
10878
|
+
colors__default["default"].green("(In future, not implemented yet) Using your compiled pipeline collection ".concat(madeLibraryFilePath));
|
|
10879
|
+
// TODO: Implement;
|
|
10655
10880
|
// TODO: [🌗]
|
|
10656
10881
|
}
|
|
10657
|
-
_a = options || {}, _b = _a.isRecursive, isRecursive = _b === void 0 ? true : _b, _c = _a.isVerbose, isVerbose = _c === void 0 ? DEFAULT_IS_VERBOSE : _c, _d = _a.isLazyLoaded, isLazyLoaded = _d === void 0 ? false : _d, _e = _a.isCrashedOnError, isCrashedOnError = _e === void 0 ? true : _e;
|
|
10882
|
+
_a = options || {}, _b = _a.isRecursive, isRecursive = _b === void 0 ? true : _b, _c = _a.isVerbose, isVerbose = _c === void 0 ? DEFAULT_IS_VERBOSE : _c, _d = _a.isLazyLoaded, isLazyLoaded = _d === void 0 ? false : _d, _e = _a.isCrashedOnError, isCrashedOnError = _e === void 0 ? true : _e, rootUrl = _a.rootUrl;
|
|
10658
10883
|
collection = createCollectionFromPromise(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
10659
10884
|
var fileNames, collection, _loop_1, fileNames_1, fileNames_1_1, fileName, e_1_1;
|
|
10660
10885
|
var e_1, _a;
|
|
@@ -10680,34 +10905,35 @@
|
|
|
10680
10905
|
});
|
|
10681
10906
|
collection = new Map();
|
|
10682
10907
|
_loop_1 = function (fileName) {
|
|
10683
|
-
var sourceFile, rootDirname, pipeline, pipelineString, _c, _d, existing, error_1, wrappedErrorMessage;
|
|
10684
|
-
return __generator(this, function (
|
|
10685
|
-
switch (
|
|
10908
|
+
var sourceFile, rootDirname, pipeline, pipelineString, _c, _d, _e, pipelineUrl, existing, error_1, wrappedErrorMessage;
|
|
10909
|
+
return __generator(this, function (_f) {
|
|
10910
|
+
switch (_f.label) {
|
|
10686
10911
|
case 0:
|
|
10687
10912
|
sourceFile = './' + fileName.split('\\').join('/');
|
|
10688
10913
|
rootDirname = path.dirname(sourceFile).split('\\').join('/');
|
|
10689
|
-
|
|
10914
|
+
_f.label = 1;
|
|
10690
10915
|
case 1:
|
|
10691
|
-
|
|
10916
|
+
_f.trys.push([1, 8, , 9]);
|
|
10692
10917
|
pipeline = null;
|
|
10693
10918
|
if (!fileName.endsWith('.book.md')) return [3 /*break*/, 4];
|
|
10919
|
+
_c = validatePipelineString;
|
|
10694
10920
|
return [4 /*yield*/, promises.readFile(fileName, 'utf-8')];
|
|
10695
10921
|
case 2:
|
|
10696
|
-
pipelineString = (
|
|
10922
|
+
pipelineString = _c.apply(void 0, [_f.sent()]);
|
|
10697
10923
|
return [4 /*yield*/, compilePipeline(pipelineString, tools, {
|
|
10698
10924
|
rootDirname: rootDirname,
|
|
10699
10925
|
})];
|
|
10700
10926
|
case 3:
|
|
10701
|
-
pipeline =
|
|
10927
|
+
pipeline = _f.sent();
|
|
10702
10928
|
pipeline = __assign(__assign({}, pipeline), { sourceFile: sourceFile });
|
|
10703
10929
|
return [3 /*break*/, 7];
|
|
10704
10930
|
case 4:
|
|
10705
10931
|
if (!fileName.endsWith('.book.json')) return [3 /*break*/, 6];
|
|
10706
|
-
|
|
10932
|
+
_e = (_d = JSON).parse;
|
|
10707
10933
|
return [4 /*yield*/, promises.readFile(fileName, 'utf-8')];
|
|
10708
10934
|
case 5:
|
|
10709
10935
|
// TODO: Handle non-valid JSON files
|
|
10710
|
-
pipeline =
|
|
10936
|
+
pipeline = _e.apply(_d, [_f.sent()]);
|
|
10711
10937
|
// TODO: [🌗]
|
|
10712
10938
|
pipeline = __assign(__assign({}, pipeline), { sourceFile: sourceFile });
|
|
10713
10939
|
return [3 /*break*/, 7];
|
|
@@ -10715,10 +10941,24 @@
|
|
|
10715
10941
|
if (isVerbose) {
|
|
10716
10942
|
console.info(colors__default["default"].gray("Skipped file ".concat(fileName.split('\\').join('/'), " \u2013\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060 Not a book")));
|
|
10717
10943
|
}
|
|
10718
|
-
|
|
10944
|
+
_f.label = 7;
|
|
10719
10945
|
case 7:
|
|
10720
10946
|
// ---
|
|
10721
10947
|
if (pipeline !== null) {
|
|
10948
|
+
if (rootUrl !== undefined) {
|
|
10949
|
+
if (pipeline.pipelineUrl === undefined) {
|
|
10950
|
+
pipelineUrl = rootUrl + '/' + fileName.split('\\').join('/');
|
|
10951
|
+
if (isVerbose) {
|
|
10952
|
+
console.info(colors__default["default"].yellow("Implicitly set pipeline URL to ".concat(pipelineUrl, " from ").concat(fileName
|
|
10953
|
+
.split('\\')
|
|
10954
|
+
.join('/'))));
|
|
10955
|
+
}
|
|
10956
|
+
pipeline = __assign(__assign({}, pipeline), { pipelineUrl: pipelineUrl });
|
|
10957
|
+
}
|
|
10958
|
+
else if (!pipeline.pipelineUrl.startsWith(rootUrl)) {
|
|
10959
|
+
throw new PipelineUrlError(spaceTrim__default["default"]("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is not a child of the root URL ").concat(rootUrl, " \uD83C\uDF4F\n\n File:\n ").concat(sourceFile || 'Unknown', "\n\n ")));
|
|
10960
|
+
}
|
|
10961
|
+
}
|
|
10722
10962
|
// TODO: [👠] DRY
|
|
10723
10963
|
if (pipeline.pipelineUrl === undefined) {
|
|
10724
10964
|
if (isVerbose) {
|
|
@@ -10750,17 +10990,17 @@
|
|
|
10750
10990
|
}
|
|
10751
10991
|
else {
|
|
10752
10992
|
existing = collection.get(pipeline.pipelineUrl);
|
|
10753
|
-
throw new PipelineUrlError(spaceTrim__default["default"]("\n Pipeline with URL
|
|
10993
|
+
throw new PipelineUrlError(spaceTrim__default["default"]("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is already in the collection \uD83C\uDF4F\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: You have probably forgotten to run \"ptbk make\" to update the collection\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
|
|
10754
10994
|
}
|
|
10755
10995
|
}
|
|
10756
10996
|
}
|
|
10757
10997
|
return [3 /*break*/, 9];
|
|
10758
10998
|
case 8:
|
|
10759
|
-
error_1 =
|
|
10999
|
+
error_1 = _f.sent();
|
|
10760
11000
|
if (!(error_1 instanceof Error)) {
|
|
10761
11001
|
throw error_1;
|
|
10762
11002
|
}
|
|
10763
|
-
wrappedErrorMessage = spaceTrim__default["default"](function (block) { return "\n
|
|
11003
|
+
wrappedErrorMessage = spaceTrim__default["default"](function (block) { return "\n ".concat(error_1.name, " in pipeline ").concat(fileName.split('\\').join('/'), "\u2060:\n\n Original error message:\n ").concat(block(error_1.message), "\n\n Original stack trace:\n ").concat(block(error_1.stack || ''), "\n\n ---\n\n "); }) + '\n';
|
|
10764
11004
|
if (isCrashedOnError) {
|
|
10765
11005
|
throw new CollectionError(wrappedErrorMessage);
|
|
10766
11006
|
}
|
|
@@ -10816,40 +11056,6 @@
|
|
|
10816
11056
|
* TODO: Maybe move from `@promptbook/node` to `@promptbook/core` as we removes direct dependency on `fs`
|
|
10817
11057
|
*/
|
|
10818
11058
|
|
|
10819
|
-
// <- TODO: !!!!!!! Auto convert to type `import { ... } from 'type-fest';`
|
|
10820
|
-
/**
|
|
10821
|
-
* Tests if the value is [🚉] serializable as JSON
|
|
10822
|
-
*
|
|
10823
|
-
* - Almost all primitives are serializable BUT:
|
|
10824
|
-
* - `undefined` is not serializable
|
|
10825
|
-
* - `NaN` is not serializable
|
|
10826
|
-
* - Objects and arrays are serializable if all their properties are serializable
|
|
10827
|
-
* - Functions are not serializable
|
|
10828
|
-
* - Circular references are not serializable
|
|
10829
|
-
* - `Date` objects are not serializable
|
|
10830
|
-
* - `Map` and `Set` objects are not serializable
|
|
10831
|
-
* - `RegExp` objects are not serializable
|
|
10832
|
-
* - `Error` objects are not serializable
|
|
10833
|
-
* - `Symbol` objects are not serializable
|
|
10834
|
-
* - And much more...
|
|
10835
|
-
*
|
|
10836
|
-
*
|
|
10837
|
-
* @public exported from `@promptbook/utils`
|
|
10838
|
-
*/
|
|
10839
|
-
function isSerializableAsJson(value) {
|
|
10840
|
-
try {
|
|
10841
|
-
checkSerializableAsJson({ value: value });
|
|
10842
|
-
return true;
|
|
10843
|
-
}
|
|
10844
|
-
catch (error) {
|
|
10845
|
-
return false;
|
|
10846
|
-
}
|
|
10847
|
-
}
|
|
10848
|
-
/**
|
|
10849
|
-
* TODO: [🧠][main] !!! In-memory cache of same values to prevent multiple checks
|
|
10850
|
-
* TODO: [🧠][💺] Can be done this on type-level?
|
|
10851
|
-
*/
|
|
10852
|
-
|
|
10853
11059
|
/**
|
|
10854
11060
|
* Stringify the PipelineJson with proper formatting
|
|
10855
11061
|
*
|
|
@@ -11199,46 +11405,6 @@
|
|
|
11199
11405
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
11200
11406
|
*/
|
|
11201
11407
|
|
|
11202
|
-
/**
|
|
11203
|
-
* @@@
|
|
11204
|
-
*
|
|
11205
|
-
* @public exported from `@promptbook/node`
|
|
11206
|
-
*/
|
|
11207
|
-
var wizzard = {
|
|
11208
|
-
/**
|
|
11209
|
-
* @@@!!!!!!
|
|
11210
|
-
*/
|
|
11211
|
-
execute: function (book, inputParameters, onProgress) {
|
|
11212
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
11213
|
-
var tools, collection, pipeline, pipelineExecutor, result;
|
|
11214
|
-
return __generator(this, function (_a) {
|
|
11215
|
-
switch (_a.label) {
|
|
11216
|
-
case 0: return [4 /*yield*/, $provideExecutionToolsForNode()];
|
|
11217
|
-
case 1:
|
|
11218
|
-
tools = _a.sent();
|
|
11219
|
-
return [4 /*yield*/, createCollectionFromDirectory('./books', tools)];
|
|
11220
|
-
case 2:
|
|
11221
|
-
collection = _a.sent();
|
|
11222
|
-
return [4 /*yield*/, collection.getPipelineByUrl(book)];
|
|
11223
|
-
case 3:
|
|
11224
|
-
pipeline = _a.sent();
|
|
11225
|
-
pipelineExecutor = createPipelineExecutor({ pipeline: pipeline, tools: tools });
|
|
11226
|
-
return [4 /*yield*/, pipelineExecutor(inputParameters, onProgress)];
|
|
11227
|
-
case 4:
|
|
11228
|
-
result = _a.sent();
|
|
11229
|
-
// ▶ Fail if the execution was not successful
|
|
11230
|
-
assertsExecutionSuccessful(result);
|
|
11231
|
-
// ▶ Return the result
|
|
11232
|
-
return [2 /*return*/, result];
|
|
11233
|
-
}
|
|
11234
|
-
});
|
|
11235
|
-
});
|
|
11236
|
-
},
|
|
11237
|
-
};
|
|
11238
|
-
/**
|
|
11239
|
-
* TODO: !!!!!! Add to readmes - one markdown here imported in all packages
|
|
11240
|
-
*/
|
|
11241
|
-
|
|
11242
11408
|
exports.$execCommand = $execCommand;
|
|
11243
11409
|
exports.$execCommands = $execCommands;
|
|
11244
11410
|
exports.$provideExecutablesForNode = $provideExecutablesForNode;
|
|
@@ -11251,7 +11417,6 @@
|
|
|
11251
11417
|
exports.FileCacheStorage = FileCacheStorage;
|
|
11252
11418
|
exports.PROMPTBOOK_ENGINE_VERSION = PROMPTBOOK_ENGINE_VERSION;
|
|
11253
11419
|
exports.createCollectionFromDirectory = createCollectionFromDirectory;
|
|
11254
|
-
exports.wizzard = wizzard;
|
|
11255
11420
|
|
|
11256
11421
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
11257
11422
|
|