@promptbook/node 0.89.0-9 โ 0.92.0-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/esm/index.es.js +320 -97
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +40 -0
- package/esm/typings/src/_packages/core.index.d.ts +14 -4
- package/esm/typings/src/_packages/deepseek.index.d.ts +2 -0
- package/esm/typings/src/_packages/google.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +18 -0
- package/esm/typings/src/_packages/utils.index.d.ts +6 -0
- package/esm/typings/src/cli/cli-commands/login.d.ts +0 -1
- package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +16 -3
- package/esm/typings/src/cli/test/ptbk.d.ts +1 -1
- package/esm/typings/src/commands/EXPECT/expectCommandParser.d.ts +2 -0
- package/esm/typings/src/config.d.ts +10 -19
- package/esm/typings/src/conversion/archive/loadArchive.d.ts +2 -2
- package/esm/typings/src/errors/0-index.d.ts +7 -4
- package/esm/typings/src/errors/PipelineExecutionError.d.ts +1 -1
- package/esm/typings/src/errors/WrappedError.d.ts +10 -0
- package/esm/typings/src/errors/assertsError.d.ts +11 -0
- package/esm/typings/src/execution/CommonToolsOptions.d.ts +4 -0
- package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
- package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTask.d.ts +12 -0
- package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTask.d.ts +5 -0
- package/esm/typings/src/formats/csv/utils/csvParse.d.ts +12 -0
- package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +9 -0
- package/esm/typings/src/formats/csv/utils/isValidCsvString.test.d.ts +1 -0
- package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +3 -0
- package/esm/typings/src/formats/json/utils/jsonParse.d.ts +11 -0
- package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +9 -0
- package/esm/typings/src/formats/xml/utils/isValidXmlString.test.d.ts +1 -0
- package/esm/typings/src/llm-providers/_common/filterModels.d.ts +15 -0
- package/esm/typings/src/llm-providers/_common/register/{$provideEnvFilepath.d.ts โ $provideEnvFilename.d.ts} +2 -2
- 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/$provideLlmToolsForWizzardOrCli.d.ts +11 -2
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -1
- package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +43 -0
- package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +4 -0
- package/esm/typings/src/llm-providers/deepseek/deepseek-models.d.ts +23 -0
- package/esm/typings/src/llm-providers/google/google-models.d.ts +23 -0
- package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
- package/esm/typings/src/personas/preparePersona.d.ts +1 -1
- package/esm/typings/src/pipeline/PipelineJson/PersonaJson.d.ts +4 -2
- package/esm/typings/src/remote-server/openapi-types.d.ts +626 -0
- package/esm/typings/src/remote-server/openapi.d.ts +581 -0
- package/esm/typings/src/remote-server/socket-types/_subtypes/Identification.d.ts +7 -1
- package/esm/typings/src/remote-server/socket-types/_subtypes/identificationToPromptbookToken.d.ts +11 -0
- package/esm/typings/src/remote-server/socket-types/_subtypes/promptbookTokenToIdentification.d.ts +10 -0
- package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -2
- package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +15 -9
- package/esm/typings/src/storage/env-storage/$EnvStorage.d.ts +40 -0
- package/esm/typings/src/types/typeAliases.d.ts +26 -0
- package/package.json +9 -5
- package/umd/index.umd.js +320 -97
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/cli/test/ptbk2.d.ts +0 -5
package/esm/index.es.js
CHANGED
|
@@ -30,7 +30,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
30
30
|
* @generated
|
|
31
31
|
* @see https://github.com/webgptorg/promptbook
|
|
32
32
|
*/
|
|
33
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
33
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.92.0-10';
|
|
34
34
|
/**
|
|
35
35
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
36
36
|
* Note: [๐] Ignore a discrepancy between file name and entity name
|
|
@@ -76,6 +76,7 @@ const ADMIN_EMAIL = 'pavol@ptbk.io';
|
|
|
76
76
|
* @public exported from `@promptbook/core`
|
|
77
77
|
*/
|
|
78
78
|
const ADMIN_GITHUB_NAME = 'hejny';
|
|
79
|
+
// <- TODO: [๐] Pick the best claim
|
|
79
80
|
/**
|
|
80
81
|
* When the title is not provided, the default title is used
|
|
81
82
|
*
|
|
@@ -120,6 +121,7 @@ const VALUE_STRINGS = {
|
|
|
120
121
|
infinity: '(infinity; โ)',
|
|
121
122
|
negativeInfinity: '(negative infinity; -โ)',
|
|
122
123
|
unserializable: '(unserializable value)',
|
|
124
|
+
circular: '(circular JSON)',
|
|
123
125
|
};
|
|
124
126
|
/**
|
|
125
127
|
* Small number limit
|
|
@@ -159,7 +161,7 @@ const DEFAULT_MAX_PARALLEL_COUNT = 5; // <- TODO: [๐คนโโ๏ธ]
|
|
|
159
161
|
*/
|
|
160
162
|
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 10; // <- TODO: [๐คนโโ๏ธ]
|
|
161
163
|
// <- TODO: [๐] Make also `BOOKS_DIRNAME_ALTERNATIVES`
|
|
162
|
-
// TODO:
|
|
164
|
+
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
163
165
|
/**
|
|
164
166
|
* Where to store the temporary downloads
|
|
165
167
|
*
|
|
@@ -297,6 +299,45 @@ class UnexpectedError extends Error {
|
|
|
297
299
|
}
|
|
298
300
|
}
|
|
299
301
|
|
|
302
|
+
/**
|
|
303
|
+
* Converts a JavaScript Object Notation (JSON) string into an object.
|
|
304
|
+
*
|
|
305
|
+
* Note: This is wrapper around `JSON.parse()` with better error and type handling
|
|
306
|
+
*
|
|
307
|
+
* @public exported from `@promptbook/utils`
|
|
308
|
+
*/
|
|
309
|
+
function jsonParse(value) {
|
|
310
|
+
if (value === undefined) {
|
|
311
|
+
throw new Error(`Can not parse JSON from undefined value.`);
|
|
312
|
+
}
|
|
313
|
+
else if (typeof value !== 'string') {
|
|
314
|
+
console.error('Can not parse JSON from non-string value.', { text: value });
|
|
315
|
+
throw new Error(spaceTrim(`
|
|
316
|
+
Can not parse JSON from non-string value.
|
|
317
|
+
|
|
318
|
+
The value type: ${typeof value}
|
|
319
|
+
See more in console.
|
|
320
|
+
`));
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
return JSON.parse(value);
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
if (!(error instanceof Error)) {
|
|
327
|
+
throw error;
|
|
328
|
+
}
|
|
329
|
+
throw new Error(spaceTrim((block) => `
|
|
330
|
+
${block(error.message)}
|
|
331
|
+
|
|
332
|
+
The JSON text:
|
|
333
|
+
${block(value)}
|
|
334
|
+
`));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* TODO: !!!! Use in Promptbook.studio
|
|
339
|
+
*/
|
|
340
|
+
|
|
300
341
|
/**
|
|
301
342
|
* Orders JSON object by keys
|
|
302
343
|
*
|
|
@@ -339,6 +380,54 @@ function $deepFreeze(objectValue) {
|
|
|
339
380
|
* TODO: [๐ง ] Is there a way how to meaningfully test this utility
|
|
340
381
|
*/
|
|
341
382
|
|
|
383
|
+
/**
|
|
384
|
+
* This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
|
|
385
|
+
*
|
|
386
|
+
* @public exported from `@promptbook/core`
|
|
387
|
+
*/
|
|
388
|
+
class WrappedError extends Error {
|
|
389
|
+
constructor(whatWasThrown) {
|
|
390
|
+
const tag = `[๐คฎ]`;
|
|
391
|
+
console.error(tag, whatWasThrown);
|
|
392
|
+
super(spaceTrim$1(`
|
|
393
|
+
Non-Error object was thrown
|
|
394
|
+
|
|
395
|
+
Note: Look for ${tag} in the console for more details
|
|
396
|
+
Please report issue on ${ADMIN_EMAIL}
|
|
397
|
+
`));
|
|
398
|
+
this.name = 'WrappedError';
|
|
399
|
+
Object.setPrototypeOf(this, WrappedError.prototype);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Helper used in catch blocks to assert that the error is an instance of `Error`
|
|
405
|
+
*
|
|
406
|
+
* @param whatWasThrown Any object that was thrown
|
|
407
|
+
* @returns Nothing if the error is an instance of `Error`
|
|
408
|
+
* @throws `WrappedError` or `UnexpectedError` if the error is not standard
|
|
409
|
+
*
|
|
410
|
+
* @private within the repository
|
|
411
|
+
*/
|
|
412
|
+
function assertsError(whatWasThrown) {
|
|
413
|
+
// Case 1: Handle error which was rethrown as `WrappedError`
|
|
414
|
+
if (whatWasThrown instanceof WrappedError) {
|
|
415
|
+
const wrappedError = whatWasThrown;
|
|
416
|
+
throw wrappedError;
|
|
417
|
+
}
|
|
418
|
+
// Case 2: Handle unexpected errors
|
|
419
|
+
if (whatWasThrown instanceof UnexpectedError) {
|
|
420
|
+
const unexpectedError = whatWasThrown;
|
|
421
|
+
throw unexpectedError;
|
|
422
|
+
}
|
|
423
|
+
// Case 3: Handle standard errors - keep them up to consumer
|
|
424
|
+
if (whatWasThrown instanceof Error) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
// Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
|
|
428
|
+
throw new WrappedError(whatWasThrown);
|
|
429
|
+
}
|
|
430
|
+
|
|
342
431
|
/**
|
|
343
432
|
* Checks if the value is [๐] serializable as JSON
|
|
344
433
|
* If not, throws an UnexpectedError with a rich error message and tracking
|
|
@@ -430,9 +519,7 @@ function checkSerializableAsJson(options) {
|
|
|
430
519
|
JSON.stringify(value); // <- TODO: [0]
|
|
431
520
|
}
|
|
432
521
|
catch (error) {
|
|
433
|
-
|
|
434
|
-
throw error;
|
|
435
|
-
}
|
|
522
|
+
assertsError(error);
|
|
436
523
|
throw new UnexpectedError(spaceTrim((block) => `
|
|
437
524
|
\`${name}\` is not serializable
|
|
438
525
|
|
|
@@ -1040,7 +1127,7 @@ async function loadArchive(filePath, fs) {
|
|
|
1040
1127
|
if (!indexFile) {
|
|
1041
1128
|
throw new UnexpectedError(`Archive does not contain 'index.book.json' file`);
|
|
1042
1129
|
}
|
|
1043
|
-
const collectionJson =
|
|
1130
|
+
const collectionJson = jsonParse(await indexFile.async('text'));
|
|
1044
1131
|
for (const pipeline of collectionJson) {
|
|
1045
1132
|
validatePipeline(pipeline);
|
|
1046
1133
|
}
|
|
@@ -1050,7 +1137,7 @@ async function loadArchive(filePath, fs) {
|
|
|
1050
1137
|
* Note: [๐ข] Code in this file should never be never released in packages that could be imported into browser environment
|
|
1051
1138
|
*/
|
|
1052
1139
|
|
|
1053
|
-
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
|
|
1140
|
+
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModels",description:"List of available model names together with their descriptions as JSON",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelsRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n```json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n```\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nHere are the available models:\n\n```json\n{availableModels}\n```\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelsRequirements",format:"JSON",dependentParameterNames:["availableModels","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModels}` List of available model names together with their descriptions as JSON\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelsRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n\\`\\`\\`json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nHere are the available models:\n\n\\`\\`\\`json\n{availableModels}\n\\`\\`\\`\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelsRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
|
|
1054
1141
|
|
|
1055
1142
|
/**
|
|
1056
1143
|
* Checks if value is valid email
|
|
@@ -1119,6 +1206,9 @@ function isValidFilePath(filename) {
|
|
|
1119
1206
|
/**
|
|
1120
1207
|
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
1121
1208
|
*
|
|
1209
|
+
* @param value The string to check
|
|
1210
|
+
* @returns True if the string is a valid JSON string, false otherwise
|
|
1211
|
+
*
|
|
1122
1212
|
* @public exported from `@promptbook/utils`
|
|
1123
1213
|
*/
|
|
1124
1214
|
function isValidJsonString(value /* <- [๐จโโ๏ธ] */) {
|
|
@@ -1127,9 +1217,7 @@ function isValidJsonString(value /* <- [๐จโโ๏ธ] */) {
|
|
|
1127
1217
|
return true;
|
|
1128
1218
|
}
|
|
1129
1219
|
catch (error) {
|
|
1130
|
-
|
|
1131
|
-
throw error;
|
|
1132
|
-
}
|
|
1220
|
+
assertsError(error);
|
|
1133
1221
|
if (error.message.includes('Unexpected token')) {
|
|
1134
1222
|
return false;
|
|
1135
1223
|
}
|
|
@@ -1400,7 +1488,7 @@ function extractParameterNames(template) {
|
|
|
1400
1488
|
*/
|
|
1401
1489
|
function unpreparePipeline(pipeline) {
|
|
1402
1490
|
let { personas, knowledgeSources, tasks } = pipeline;
|
|
1403
|
-
personas = personas.map((persona) => ({ ...persona,
|
|
1491
|
+
personas = personas.map((persona) => ({ ...persona, modelsRequirements: undefined, preparationIds: undefined }));
|
|
1404
1492
|
knowledgeSources = knowledgeSources.map((knowledgeSource) => ({ ...knowledgeSource, preparationIds: undefined }));
|
|
1405
1493
|
tasks = tasks.map((task) => {
|
|
1406
1494
|
let { dependentParameterNames } = task;
|
|
@@ -1576,7 +1664,7 @@ function isPipelinePrepared(pipeline) {
|
|
|
1576
1664
|
if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
|
|
1577
1665
|
return false;
|
|
1578
1666
|
}
|
|
1579
|
-
if (!pipeline.personas.every((persona) => persona.
|
|
1667
|
+
if (!pipeline.personas.every((persona) => persona.modelsRequirements !== undefined)) {
|
|
1580
1668
|
return false;
|
|
1581
1669
|
}
|
|
1582
1670
|
if (!pipeline.knowledgeSources.every((knowledgeSource) => knowledgeSource.preparationIds !== undefined)) {
|
|
@@ -1633,7 +1721,7 @@ function jsonStringsToJsons(object) {
|
|
|
1633
1721
|
const newObject = { ...object };
|
|
1634
1722
|
for (const [key, value] of Object.entries(object)) {
|
|
1635
1723
|
if (typeof value === 'string' && isValidJsonString(value)) {
|
|
1636
|
-
newObject[key] =
|
|
1724
|
+
newObject[key] = jsonParse(value);
|
|
1637
1725
|
}
|
|
1638
1726
|
else {
|
|
1639
1727
|
newObject[key] = jsonStringsToJsons(value);
|
|
@@ -1661,7 +1749,7 @@ class PipelineExecutionError extends Error {
|
|
|
1661
1749
|
}
|
|
1662
1750
|
}
|
|
1663
1751
|
/**
|
|
1664
|
-
* TODO:
|
|
1752
|
+
* TODO: [๐ง ][๐] Add id to all errors
|
|
1665
1753
|
*/
|
|
1666
1754
|
|
|
1667
1755
|
/**
|
|
@@ -1831,7 +1919,10 @@ const PROMPTBOOK_ERRORS = {
|
|
|
1831
1919
|
PipelineExecutionError,
|
|
1832
1920
|
PipelineLogicError,
|
|
1833
1921
|
PipelineUrlError,
|
|
1922
|
+
AuthenticationError,
|
|
1923
|
+
PromptbookFetchError,
|
|
1834
1924
|
UnexpectedError,
|
|
1925
|
+
WrappedError,
|
|
1835
1926
|
// TODO: [๐ช]> VersionMismatchError,
|
|
1836
1927
|
};
|
|
1837
1928
|
/**
|
|
@@ -1848,8 +1939,6 @@ const COMMON_JAVASCRIPT_ERRORS = {
|
|
|
1848
1939
|
TypeError,
|
|
1849
1940
|
URIError,
|
|
1850
1941
|
AggregateError,
|
|
1851
|
-
AuthenticationError,
|
|
1852
|
-
PromptbookFetchError,
|
|
1853
1942
|
/*
|
|
1854
1943
|
Note: Not widely supported
|
|
1855
1944
|
> InternalError,
|
|
@@ -1972,8 +2061,8 @@ function createTask(options) {
|
|
|
1972
2061
|
updatedAt = new Date();
|
|
1973
2062
|
errors.push(...executionResult.errors);
|
|
1974
2063
|
warnings.push(...executionResult.warnings);
|
|
1975
|
-
// <- TODO:
|
|
1976
|
-
// TODO: [๐ง ]
|
|
2064
|
+
// <- TODO: [๐] Only unique errors and warnings should be added (or filtered)
|
|
2065
|
+
// TODO: [๐ง ] !! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
|
|
1977
2066
|
// Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
|
|
1978
2067
|
// And delete `ExecutionTask.currentValue.preparedPipeline`
|
|
1979
2068
|
assertsTaskSuccessful(executionResult);
|
|
@@ -1983,6 +2072,7 @@ function createTask(options) {
|
|
|
1983
2072
|
partialResultSubject.next(executionResult);
|
|
1984
2073
|
}
|
|
1985
2074
|
catch (error) {
|
|
2075
|
+
assertsError(error);
|
|
1986
2076
|
status = 'ERROR';
|
|
1987
2077
|
errors.push(error);
|
|
1988
2078
|
partialResultSubject.error(error);
|
|
@@ -2128,13 +2218,19 @@ function valueToString(value) {
|
|
|
2128
2218
|
return value.toISOString();
|
|
2129
2219
|
}
|
|
2130
2220
|
else {
|
|
2131
|
-
|
|
2221
|
+
try {
|
|
2222
|
+
return JSON.stringify(value);
|
|
2223
|
+
}
|
|
2224
|
+
catch (error) {
|
|
2225
|
+
if (error instanceof TypeError && error.message.includes('circular structure')) {
|
|
2226
|
+
return VALUE_STRINGS.circular;
|
|
2227
|
+
}
|
|
2228
|
+
throw error;
|
|
2229
|
+
}
|
|
2132
2230
|
}
|
|
2133
2231
|
}
|
|
2134
2232
|
catch (error) {
|
|
2135
|
-
|
|
2136
|
-
throw error;
|
|
2137
|
-
}
|
|
2233
|
+
assertsError(error);
|
|
2138
2234
|
console.error(error);
|
|
2139
2235
|
return VALUE_STRINGS.unserializable;
|
|
2140
2236
|
}
|
|
@@ -2306,9 +2402,7 @@ function extractVariablesFromJavascript(script) {
|
|
|
2306
2402
|
}
|
|
2307
2403
|
}
|
|
2308
2404
|
catch (error) {
|
|
2309
|
-
|
|
2310
|
-
throw error;
|
|
2311
|
-
}
|
|
2405
|
+
assertsError(error);
|
|
2312
2406
|
throw new ParseError(spaceTrim$1((block) => `
|
|
2313
2407
|
Can not extract variables from the script
|
|
2314
2408
|
${block(error.stack || error.message)}
|
|
@@ -2427,6 +2521,46 @@ const MANDATORY_CSV_SETTINGS = Object.freeze({
|
|
|
2427
2521
|
// encoding: 'utf-8',
|
|
2428
2522
|
});
|
|
2429
2523
|
|
|
2524
|
+
/**
|
|
2525
|
+
* Function to check if a string is valid CSV
|
|
2526
|
+
*
|
|
2527
|
+
* @param value The string to check
|
|
2528
|
+
* @returns True if the string is a valid CSV string, false otherwise
|
|
2529
|
+
*
|
|
2530
|
+
* @public exported from `@promptbook/utils`
|
|
2531
|
+
*/
|
|
2532
|
+
function isValidCsvString(value) {
|
|
2533
|
+
try {
|
|
2534
|
+
// A simple check for CSV format: at least one comma and no invalid characters
|
|
2535
|
+
if (value.includes(',') && /^[\w\s,"']+$/.test(value)) {
|
|
2536
|
+
return true;
|
|
2537
|
+
}
|
|
2538
|
+
return false;
|
|
2539
|
+
}
|
|
2540
|
+
catch (error) {
|
|
2541
|
+
assertsError(error);
|
|
2542
|
+
return false;
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
/**
|
|
2547
|
+
* Converts a CSV string into an object
|
|
2548
|
+
*
|
|
2549
|
+
* Note: This is wrapper around `papaparse.parse()` with better autohealing
|
|
2550
|
+
*
|
|
2551
|
+
* @private - for now until `@promptbook/csv` is released
|
|
2552
|
+
*/
|
|
2553
|
+
function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO: Make CSV Schemas */) {
|
|
2554
|
+
settings = { ...settings, ...MANDATORY_CSV_SETTINGS };
|
|
2555
|
+
// Note: Autoheal invalid '\n' characters
|
|
2556
|
+
if (settings.newline && !settings.newline.includes('\r') && value.includes('\r')) {
|
|
2557
|
+
console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
|
|
2558
|
+
value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
2559
|
+
}
|
|
2560
|
+
const csv = parse(value, settings);
|
|
2561
|
+
return csv;
|
|
2562
|
+
}
|
|
2563
|
+
|
|
2430
2564
|
/**
|
|
2431
2565
|
* Definition for CSV spreadsheet
|
|
2432
2566
|
*
|
|
@@ -2437,7 +2571,7 @@ const CsvFormatDefinition = {
|
|
|
2437
2571
|
formatName: 'CSV',
|
|
2438
2572
|
aliases: ['SPREADSHEET', 'TABLE'],
|
|
2439
2573
|
isValid(value, settings, schema) {
|
|
2440
|
-
return
|
|
2574
|
+
return isValidCsvString(value);
|
|
2441
2575
|
},
|
|
2442
2576
|
canBeValid(partialValue, settings, schema) {
|
|
2443
2577
|
return true;
|
|
@@ -2449,8 +2583,7 @@ const CsvFormatDefinition = {
|
|
|
2449
2583
|
{
|
|
2450
2584
|
subvalueName: 'ROW',
|
|
2451
2585
|
async mapValues(value, outputParameterName, settings, mapCallback) {
|
|
2452
|
-
|
|
2453
|
-
const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
2586
|
+
const csv = csvParse(value, settings);
|
|
2454
2587
|
if (csv.errors.length !== 0) {
|
|
2455
2588
|
throw new CsvFormatError(spaceTrim((block) => `
|
|
2456
2589
|
CSV parsing error
|
|
@@ -2480,8 +2613,7 @@ const CsvFormatDefinition = {
|
|
|
2480
2613
|
{
|
|
2481
2614
|
subvalueName: 'CELL',
|
|
2482
2615
|
async mapValues(value, outputParameterName, settings, mapCallback) {
|
|
2483
|
-
|
|
2484
|
-
const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
2616
|
+
const csv = csvParse(value, settings);
|
|
2485
2617
|
if (csv.errors.length !== 0) {
|
|
2486
2618
|
throw new CsvFormatError(spaceTrim((block) => `
|
|
2487
2619
|
CSV parsing error
|
|
@@ -2591,6 +2723,30 @@ const TextFormatDefinition = {
|
|
|
2591
2723
|
* TODO: [๐ข] Allow to expect something inside each item of list and other formats
|
|
2592
2724
|
*/
|
|
2593
2725
|
|
|
2726
|
+
/**
|
|
2727
|
+
* Function to check if a string is valid XML
|
|
2728
|
+
*
|
|
2729
|
+
* @param value
|
|
2730
|
+
* @returns True if the string is a valid XML string, false otherwise
|
|
2731
|
+
*
|
|
2732
|
+
* @public exported from `@promptbook/utils`
|
|
2733
|
+
*/
|
|
2734
|
+
function isValidXmlString(value) {
|
|
2735
|
+
try {
|
|
2736
|
+
const parser = new DOMParser();
|
|
2737
|
+
const parsedDocument = parser.parseFromString(value, 'application/xml');
|
|
2738
|
+
const parserError = parsedDocument.getElementsByTagName('parsererror');
|
|
2739
|
+
if (parserError.length > 0) {
|
|
2740
|
+
return false;
|
|
2741
|
+
}
|
|
2742
|
+
return true;
|
|
2743
|
+
}
|
|
2744
|
+
catch (error) {
|
|
2745
|
+
assertsError(error);
|
|
2746
|
+
return false;
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2594
2750
|
/**
|
|
2595
2751
|
* Definition for XML format
|
|
2596
2752
|
*
|
|
@@ -2600,7 +2756,7 @@ const XmlFormatDefinition = {
|
|
|
2600
2756
|
formatName: 'XML',
|
|
2601
2757
|
mimeType: 'application/xml',
|
|
2602
2758
|
isValid(value, settings, schema) {
|
|
2603
|
-
return
|
|
2759
|
+
return isValidXmlString(value);
|
|
2604
2760
|
},
|
|
2605
2761
|
canBeValid(partialValue, settings, schema) {
|
|
2606
2762
|
return true;
|
|
@@ -2797,14 +2953,15 @@ class MultipleLlmExecutionTools {
|
|
|
2797
2953
|
}
|
|
2798
2954
|
}
|
|
2799
2955
|
catch (error) {
|
|
2800
|
-
|
|
2956
|
+
assertsError(error);
|
|
2957
|
+
if (error instanceof UnexpectedError) {
|
|
2801
2958
|
throw error;
|
|
2802
2959
|
}
|
|
2803
2960
|
errors.push({ llmExecutionTools, error });
|
|
2804
2961
|
}
|
|
2805
2962
|
}
|
|
2806
2963
|
if (errors.length === 1) {
|
|
2807
|
-
throw errors[0];
|
|
2964
|
+
throw errors[0].error;
|
|
2808
2965
|
}
|
|
2809
2966
|
else if (errors.length > 1) {
|
|
2810
2967
|
throw new PipelineExecutionError(
|
|
@@ -3661,9 +3818,7 @@ async function executeAttempts(options) {
|
|
|
3661
3818
|
break scripts;
|
|
3662
3819
|
}
|
|
3663
3820
|
catch (error) {
|
|
3664
|
-
|
|
3665
|
-
throw error;
|
|
3666
|
-
}
|
|
3821
|
+
assertsError(error);
|
|
3667
3822
|
if (error instanceof UnexpectedError) {
|
|
3668
3823
|
throw error;
|
|
3669
3824
|
}
|
|
@@ -3733,9 +3888,7 @@ async function executeAttempts(options) {
|
|
|
3733
3888
|
break scripts;
|
|
3734
3889
|
}
|
|
3735
3890
|
catch (error) {
|
|
3736
|
-
|
|
3737
|
-
throw error;
|
|
3738
|
-
}
|
|
3891
|
+
assertsError(error);
|
|
3739
3892
|
if (error instanceof UnexpectedError) {
|
|
3740
3893
|
throw error;
|
|
3741
3894
|
}
|
|
@@ -3978,13 +4131,79 @@ async function getExamplesForTask(task) {
|
|
|
3978
4131
|
/**
|
|
3979
4132
|
* @@@
|
|
3980
4133
|
*
|
|
4134
|
+
* Here is the place where RAG (retrieval-augmented generation) happens
|
|
4135
|
+
*
|
|
3981
4136
|
* @private internal utility of `createPipelineExecutor`
|
|
3982
4137
|
*/
|
|
3983
4138
|
async function getKnowledgeForTask(options) {
|
|
3984
|
-
const { preparedPipeline, task } = options;
|
|
3985
|
-
|
|
4139
|
+
const { tools, preparedPipeline, task } = options;
|
|
4140
|
+
const firstKnowlegePiece = preparedPipeline.knowledgePieces[0];
|
|
4141
|
+
const firstKnowlegeIndex = firstKnowlegePiece === null || firstKnowlegePiece === void 0 ? void 0 : firstKnowlegePiece.index[0];
|
|
4142
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
|
|
4143
|
+
if (firstKnowlegePiece === undefined || firstKnowlegeIndex === undefined) {
|
|
4144
|
+
return 'No knowledge pieces found';
|
|
4145
|
+
}
|
|
4146
|
+
// TODO: [๐] Make arrayable LLMs -> single LLM DRY
|
|
4147
|
+
const _llms = arrayableToArray(tools.llm);
|
|
4148
|
+
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
4149
|
+
const taskEmbeddingPrompt = {
|
|
4150
|
+
title: 'Knowledge Search',
|
|
4151
|
+
modelRequirements: {
|
|
4152
|
+
modelVariant: 'EMBEDDING',
|
|
4153
|
+
modelName: firstKnowlegeIndex.modelName,
|
|
4154
|
+
},
|
|
4155
|
+
content: task.content,
|
|
4156
|
+
parameters: {
|
|
4157
|
+
/* !!!!!!!! */
|
|
4158
|
+
},
|
|
4159
|
+
};
|
|
4160
|
+
const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
|
|
4161
|
+
const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
|
|
4162
|
+
const { index } = knowledgePiece;
|
|
4163
|
+
const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
|
|
4164
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model
|
|
4165
|
+
if (knowledgePieceIndex === undefined) {
|
|
4166
|
+
return {
|
|
4167
|
+
content: knowledgePiece.content,
|
|
4168
|
+
relevance: 0,
|
|
4169
|
+
};
|
|
4170
|
+
}
|
|
4171
|
+
const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
|
|
4172
|
+
return {
|
|
4173
|
+
content: knowledgePiece.content,
|
|
4174
|
+
relevance,
|
|
4175
|
+
};
|
|
4176
|
+
});
|
|
4177
|
+
const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
|
|
4178
|
+
const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
|
|
4179
|
+
console.log('!!! Embedding', {
|
|
4180
|
+
task,
|
|
4181
|
+
taskEmbeddingPrompt,
|
|
4182
|
+
taskEmbeddingResult,
|
|
4183
|
+
firstKnowlegePiece,
|
|
4184
|
+
firstKnowlegeIndex,
|
|
4185
|
+
knowledgePiecesWithRelevance,
|
|
4186
|
+
knowledgePiecesSorted,
|
|
4187
|
+
knowledgePiecesLimited,
|
|
4188
|
+
});
|
|
4189
|
+
return knowledgePiecesLimited.map(({ content }) => `- ${content}`).join('\n');
|
|
3986
4190
|
// <- TODO: [๐ง ] Some smart aggregation of knowledge pieces, single-line vs multi-line vs mixed
|
|
3987
4191
|
}
|
|
4192
|
+
// TODO: !!!!!! Annotate + to new file
|
|
4193
|
+
function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
|
|
4194
|
+
if (embeddingVector1.length !== embeddingVector2.length) {
|
|
4195
|
+
throw new TypeError('Embedding vectors must have the same length');
|
|
4196
|
+
}
|
|
4197
|
+
const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
|
|
4198
|
+
const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
|
|
4199
|
+
const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
|
|
4200
|
+
return 1 - dotProduct / (magnitude1 * magnitude2);
|
|
4201
|
+
}
|
|
4202
|
+
/**
|
|
4203
|
+
* TODO: !!!! Verify if this is working
|
|
4204
|
+
* TODO: [โจ] Implement Better - use keyword search
|
|
4205
|
+
* TODO: [โจ] Examples of values
|
|
4206
|
+
*/
|
|
3988
4207
|
|
|
3989
4208
|
/**
|
|
3990
4209
|
* @@@
|
|
@@ -3992,9 +4211,9 @@ async function getKnowledgeForTask(options) {
|
|
|
3992
4211
|
* @private internal utility of `createPipelineExecutor`
|
|
3993
4212
|
*/
|
|
3994
4213
|
async function getReservedParametersForTask(options) {
|
|
3995
|
-
const { preparedPipeline, task, pipelineIdentification } = options;
|
|
4214
|
+
const { tools, preparedPipeline, task, pipelineIdentification } = options;
|
|
3996
4215
|
const context = await getContextForTask(); // <- [๐]
|
|
3997
|
-
const knowledge = await getKnowledgeForTask({ preparedPipeline, task });
|
|
4216
|
+
const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task });
|
|
3998
4217
|
const examples = await getExamplesForTask();
|
|
3999
4218
|
const currentDate = new Date().toISOString(); // <- TODO: [๐ง ][๐ฉ] Better
|
|
4000
4219
|
const modelName = RESERVED_PARAMETER_MISSING_VALUE;
|
|
@@ -4056,6 +4275,7 @@ async function executeTask(options) {
|
|
|
4056
4275
|
}
|
|
4057
4276
|
const definedParameters = Object.freeze({
|
|
4058
4277
|
...(await getReservedParametersForTask({
|
|
4278
|
+
tools,
|
|
4059
4279
|
preparedPipeline,
|
|
4060
4280
|
task: currentTask,
|
|
4061
4281
|
pipelineIdentification,
|
|
@@ -4356,9 +4576,7 @@ async function executePipeline(options) {
|
|
|
4356
4576
|
await Promise.all(resolving);
|
|
4357
4577
|
}
|
|
4358
4578
|
catch (error /* <- Note: [3] */) {
|
|
4359
|
-
|
|
4360
|
-
throw error;
|
|
4361
|
-
}
|
|
4579
|
+
assertsError(error);
|
|
4362
4580
|
// Note: No need to rethrow UnexpectedError
|
|
4363
4581
|
// if (error instanceof UnexpectedError) {
|
|
4364
4582
|
// Note: Count usage, [๐ง ] Maybe put to separate function executionReportJsonToUsage + DRY [๐คนโโ๏ธ]
|
|
@@ -4614,27 +4832,48 @@ async function preparePersona(personaDescription, tools, options) {
|
|
|
4614
4832
|
pipeline: await collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.book'),
|
|
4615
4833
|
tools,
|
|
4616
4834
|
});
|
|
4617
|
-
// TODO: [๐] Make arrayable LLMs -> single LLM DRY
|
|
4618
4835
|
const _llms = arrayableToArray(tools.llm);
|
|
4619
4836
|
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
4620
|
-
const availableModels = await llmTools.listModels()
|
|
4621
|
-
const availableModelNames = availableModels
|
|
4837
|
+
const availableModels = (await llmTools.listModels())
|
|
4622
4838
|
.filter(({ modelVariant }) => modelVariant === 'CHAT')
|
|
4623
|
-
.map(({ modelName }) =>
|
|
4624
|
-
|
|
4625
|
-
|
|
4839
|
+
.map(({ modelName, modelDescription }) => ({
|
|
4840
|
+
modelName,
|
|
4841
|
+
modelDescription,
|
|
4842
|
+
// <- Note: `modelTitle` and `modelVariant` is not relevant for this task
|
|
4843
|
+
}));
|
|
4844
|
+
const result = await preparePersonaExecutor({
|
|
4845
|
+
availableModels /* <- Note: Passing as JSON */,
|
|
4846
|
+
personaDescription,
|
|
4847
|
+
}).asPromise();
|
|
4626
4848
|
const { outputParameters } = result;
|
|
4627
|
-
const {
|
|
4628
|
-
|
|
4849
|
+
const { modelsRequirements: modelsRequirementsJson } = outputParameters;
|
|
4850
|
+
let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
|
|
4629
4851
|
if (isVerbose) {
|
|
4630
|
-
console.info(`PERSONA ${personaDescription}`,
|
|
4852
|
+
console.info(`PERSONA ${personaDescription}`, modelsRequirementsUnchecked);
|
|
4631
4853
|
}
|
|
4632
|
-
|
|
4633
|
-
|
|
4854
|
+
if (!Array.isArray(modelsRequirementsUnchecked)) {
|
|
4855
|
+
// <- TODO: Book should have syntax and system to enforce shape of JSON
|
|
4856
|
+
modelsRequirementsUnchecked = [modelsRequirementsUnchecked];
|
|
4857
|
+
/*
|
|
4858
|
+
throw new UnexpectedError(
|
|
4859
|
+
spaceTrim(
|
|
4860
|
+
(block) => `
|
|
4861
|
+
Invalid \`modelsRequirements\`:
|
|
4862
|
+
|
|
4863
|
+
\`\`\`json
|
|
4864
|
+
${block(JSON.stringify(modelsRequirementsUnchecked, null, 4))}
|
|
4865
|
+
\`\`\`
|
|
4866
|
+
`,
|
|
4867
|
+
),
|
|
4868
|
+
);
|
|
4869
|
+
*/
|
|
4870
|
+
}
|
|
4871
|
+
const modelsRequirements = modelsRequirementsUnchecked.map((modelRequirements) => ({
|
|
4634
4872
|
modelVariant: 'CHAT',
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4873
|
+
...modelRequirements,
|
|
4874
|
+
}));
|
|
4875
|
+
return {
|
|
4876
|
+
modelsRequirements,
|
|
4638
4877
|
};
|
|
4639
4878
|
}
|
|
4640
4879
|
/**
|
|
@@ -5068,9 +5307,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
|
|
|
5068
5307
|
return await fetch(urlOrRequest, init);
|
|
5069
5308
|
}
|
|
5070
5309
|
catch (error) {
|
|
5071
|
-
|
|
5072
|
-
throw error;
|
|
5073
|
-
}
|
|
5310
|
+
assertsError(error);
|
|
5074
5311
|
let url;
|
|
5075
5312
|
if (typeof urlOrRequest === 'string') {
|
|
5076
5313
|
url = urlOrRequest;
|
|
@@ -5199,7 +5436,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
|
5199
5436
|
> },
|
|
5200
5437
|
*/
|
|
5201
5438
|
async asJson() {
|
|
5202
|
-
return
|
|
5439
|
+
return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
|
|
5203
5440
|
},
|
|
5204
5441
|
async asText() {
|
|
5205
5442
|
return await tools.fs.readFile(filename, 'utf-8');
|
|
@@ -5301,9 +5538,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
5301
5538
|
knowledgePreparedUnflatten[index] = pieces;
|
|
5302
5539
|
}
|
|
5303
5540
|
catch (error) {
|
|
5304
|
-
|
|
5305
|
-
throw error;
|
|
5306
|
-
}
|
|
5541
|
+
assertsError(error);
|
|
5307
5542
|
console.warn(error);
|
|
5308
5543
|
// <- TODO: [๐ฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
5309
5544
|
}
|
|
@@ -5459,14 +5694,14 @@ async function preparePipeline(pipeline, tools, options) {
|
|
|
5459
5694
|
// TODO: [๐][๐ง ] Implement some `mapAsync` function
|
|
5460
5695
|
const preparedPersonas = new Array(personas.length);
|
|
5461
5696
|
await forEachAsync(personas, { maxParallelCount /* <- TODO: [๐ช] When there are subtasks, this maximul limit can be broken */ }, async (persona, index) => {
|
|
5462
|
-
const
|
|
5697
|
+
const { modelsRequirements } = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
|
|
5463
5698
|
rootDirname,
|
|
5464
5699
|
maxParallelCount /* <- TODO: [๐ช] */,
|
|
5465
5700
|
isVerbose,
|
|
5466
5701
|
});
|
|
5467
5702
|
const preparedPersona = {
|
|
5468
5703
|
...persona,
|
|
5469
|
-
|
|
5704
|
+
modelsRequirements,
|
|
5470
5705
|
preparationIds: [/* TODO: [๐ง] -> */ currentPreparation.id],
|
|
5471
5706
|
// <- TODO: [๐] Make some standard order of json properties
|
|
5472
5707
|
};
|
|
@@ -6101,6 +6336,8 @@ function parseNumber(value) {
|
|
|
6101
6336
|
*/
|
|
6102
6337
|
|
|
6103
6338
|
/**
|
|
6339
|
+
import { WrappedError } from '../../errors/WrappedError';
|
|
6340
|
+
import { assertsError } from '../../errors/assertsError';
|
|
6104
6341
|
* Parses the expect command
|
|
6105
6342
|
*
|
|
6106
6343
|
* @see `documentationUrl` for more details
|
|
@@ -6192,9 +6429,7 @@ const expectCommandParser = {
|
|
|
6192
6429
|
};
|
|
6193
6430
|
}
|
|
6194
6431
|
catch (error) {
|
|
6195
|
-
|
|
6196
|
-
throw error;
|
|
6197
|
-
}
|
|
6432
|
+
assertsError(error);
|
|
6198
6433
|
throw new ParseError(spaceTrim((block) => `
|
|
6199
6434
|
Invalid FORMAT command
|
|
6200
6435
|
${block(error.message)}:
|
|
@@ -9175,9 +9410,7 @@ async function locateAppOnLinux({ linuxWhich, }) {
|
|
|
9175
9410
|
return result.trim();
|
|
9176
9411
|
}
|
|
9177
9412
|
catch (error) {
|
|
9178
|
-
|
|
9179
|
-
throw error;
|
|
9180
|
-
}
|
|
9413
|
+
assertsError(error);
|
|
9181
9414
|
return null;
|
|
9182
9415
|
}
|
|
9183
9416
|
}
|
|
@@ -9255,9 +9488,7 @@ async function locateAppOnMacOs({ macOsName, }) {
|
|
|
9255
9488
|
return result.trim() + toExec;
|
|
9256
9489
|
}
|
|
9257
9490
|
catch (error) {
|
|
9258
|
-
|
|
9259
|
-
throw error;
|
|
9260
|
-
}
|
|
9491
|
+
assertsError(error);
|
|
9261
9492
|
return null;
|
|
9262
9493
|
}
|
|
9263
9494
|
}
|
|
@@ -9288,9 +9519,7 @@ async function locateAppOnWindows({ appName, windowsSuffix, }) {
|
|
|
9288
9519
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|
|
9289
9520
|
}
|
|
9290
9521
|
catch (error) {
|
|
9291
|
-
|
|
9292
|
-
throw error;
|
|
9293
|
-
}
|
|
9522
|
+
assertsError(error);
|
|
9294
9523
|
return null;
|
|
9295
9524
|
}
|
|
9296
9525
|
}
|
|
@@ -9581,13 +9810,13 @@ function $registeredLlmToolsMessage() {
|
|
|
9581
9810
|
/**
|
|
9582
9811
|
* Provides the path to the `.env` file
|
|
9583
9812
|
*
|
|
9584
|
-
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access
|
|
9813
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
9585
9814
|
*
|
|
9586
9815
|
* @private within the repository - for CLI utils
|
|
9587
9816
|
*/
|
|
9588
|
-
async function $
|
|
9817
|
+
async function $provideEnvFilename() {
|
|
9589
9818
|
if (!$isRunningInNode()) {
|
|
9590
|
-
throw new EnvironmentMismatchError('Function `$
|
|
9819
|
+
throw new EnvironmentMismatchError('Function `$provideEnvFilename` works only in Node.js environment');
|
|
9591
9820
|
}
|
|
9592
9821
|
const envFilePatterns = [
|
|
9593
9822
|
'.env',
|
|
@@ -9626,7 +9855,7 @@ async function $provideEnvFilepath() {
|
|
|
9626
9855
|
* @@@
|
|
9627
9856
|
*
|
|
9628
9857
|
* @@@ .env
|
|
9629
|
-
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access
|
|
9858
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
9630
9859
|
*
|
|
9631
9860
|
* It looks for environment variables:
|
|
9632
9861
|
* - `process.env.OPENAI_API_KEY`
|
|
@@ -9640,7 +9869,7 @@ async function $provideLlmToolsConfigurationFromEnv() {
|
|
|
9640
9869
|
if (!$isRunningInNode()) {
|
|
9641
9870
|
throw new EnvironmentMismatchError('Function `$provideLlmToolsFromEnv` works only in Node.js environment');
|
|
9642
9871
|
}
|
|
9643
|
-
const envFilepath = await $
|
|
9872
|
+
const envFilepath = await $provideEnvFilename();
|
|
9644
9873
|
if (envFilepath !== null) {
|
|
9645
9874
|
dotenv.config({ path: envFilepath });
|
|
9646
9875
|
}
|
|
@@ -9711,7 +9940,7 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
9711
9940
|
* Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
|
|
9712
9941
|
*
|
|
9713
9942
|
* @@@ .env
|
|
9714
|
-
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access
|
|
9943
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
9715
9944
|
*
|
|
9716
9945
|
* It looks for environment variables:
|
|
9717
9946
|
* - `process.env.OPENAI_API_KEY`
|
|
@@ -10245,9 +10474,7 @@ class JavascriptEvalExecutionTools {
|
|
|
10245
10474
|
}
|
|
10246
10475
|
}
|
|
10247
10476
|
catch (error) {
|
|
10248
|
-
|
|
10249
|
-
throw error;
|
|
10250
|
-
}
|
|
10477
|
+
assertsError(error);
|
|
10251
10478
|
if (error instanceof ReferenceError) {
|
|
10252
10479
|
const undefinedName = error.message.split(' ')[0];
|
|
10253
10480
|
/*
|
|
@@ -10522,9 +10749,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
10522
10749
|
// ---
|
|
10523
10750
|
}
|
|
10524
10751
|
catch (error) {
|
|
10525
|
-
|
|
10526
|
-
throw error;
|
|
10527
|
-
}
|
|
10752
|
+
assertsError(error);
|
|
10528
10753
|
// TODO: [7] DRY
|
|
10529
10754
|
const wrappedErrorMessage = spaceTrim((block) => `
|
|
10530
10755
|
${error.name} in pipeline ${fileName.split('\\').join('/')}โ :
|
|
@@ -10615,9 +10840,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
10615
10840
|
}
|
|
10616
10841
|
}
|
|
10617
10842
|
catch (error) {
|
|
10618
|
-
|
|
10619
|
-
throw error;
|
|
10620
|
-
}
|
|
10843
|
+
assertsError(error);
|
|
10621
10844
|
// TODO: [7] DRY
|
|
10622
10845
|
const wrappedErrorMessage = spaceTrim((block) => `
|
|
10623
10846
|
${error.name} in pipeline ${fileName.split('\\').join('/')}โ :
|
|
@@ -10733,7 +10956,7 @@ class FileCacheStorage {
|
|
|
10733
10956
|
return null;
|
|
10734
10957
|
}
|
|
10735
10958
|
const fileContent = await readFile(filename, 'utf-8');
|
|
10736
|
-
const value =
|
|
10959
|
+
const value = jsonParse(fileContent);
|
|
10737
10960
|
// TODO: [๐]
|
|
10738
10961
|
return value;
|
|
10739
10962
|
}
|