@promptbook/cli 0.92.0-3 → 0.92.0-31
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/esm/index.es.js +1661 -526
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/browser.index.d.ts +2 -0
- package/esm/typings/src/_packages/core.index.d.ts +22 -6
- 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 +4 -2
- package/esm/typings/src/_packages/utils.index.d.ts +2 -0
- package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +1 -1
- package/esm/typings/src/collection/PipelineCollection.d.ts +0 -2
- package/esm/typings/src/collection/SimplePipelineCollection.d.ts +1 -1
- package/esm/typings/src/commands/FOREACH/ForeachJson.d.ts +6 -6
- package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +0 -2
- package/esm/typings/src/commands/FORMFACTOR/formfactorCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/_BOILERPLATE/boilerplateCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/_common/types/CommandParser.d.ts +36 -28
- package/esm/typings/src/config.d.ts +41 -11
- package/esm/typings/src/constants.d.ts +43 -2
- package/esm/typings/src/conversion/archive/loadArchive.d.ts +2 -2
- package/esm/typings/src/errors/0-BoilerplateError.d.ts +2 -2
- package/esm/typings/src/executables/$provideExecutablesForNode.d.ts +1 -1
- package/esm/typings/src/executables/apps/locateLibreoffice.d.ts +2 -1
- package/esm/typings/src/executables/apps/locatePandoc.d.ts +2 -1
- package/esm/typings/src/executables/locateApp.d.ts +2 -2
- package/esm/typings/src/executables/platforms/locateAppOnLinux.d.ts +2 -1
- package/esm/typings/src/executables/platforms/locateAppOnMacOs.d.ts +2 -1
- package/esm/typings/src/executables/platforms/locateAppOnWindows.d.ts +2 -1
- package/esm/typings/src/execution/AbstractTaskResult.d.ts +1 -1
- package/esm/typings/src/execution/CommonToolsOptions.d.ts +5 -1
- package/esm/typings/src/execution/LlmExecutionToolsConstructor.d.ts +2 -1
- package/esm/typings/src/execution/PipelineExecutorResult.d.ts +4 -2
- package/esm/typings/src/execution/createPipelineExecutor/$OngoingTaskResult.d.ts +12 -9
- package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +13 -10
- package/esm/typings/src/execution/createPipelineExecutor/20-executeTask.d.ts +12 -9
- package/esm/typings/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +15 -3
- package/esm/typings/src/execution/createPipelineExecutor/40-executeAttempts.d.ts +20 -14
- package/esm/typings/src/execution/createPipelineExecutor/computeCosineSimilarity.d.ts +13 -0
- package/esm/typings/src/execution/createPipelineExecutor/filterJustOutputParameters.d.ts +7 -6
- package/esm/typings/src/execution/createPipelineExecutor/getContextForTask.d.ts +5 -1
- package/esm/typings/src/execution/createPipelineExecutor/getExamplesForTask.d.ts +1 -1
- package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTask.d.ts +21 -5
- package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTask.d.ts +19 -5
- package/esm/typings/src/execution/createPipelineExecutor/knowledgePiecesToString.d.ts +9 -0
- package/esm/typings/src/execution/translation/automatic-translate/automatic-translators/LindatAutomaticTranslator.d.ts +4 -4
- package/esm/typings/src/execution/utils/checkExpectations.d.ts +1 -1
- package/esm/typings/src/execution/utils/uncertainNumber.d.ts +3 -2
- package/esm/typings/src/formats/_common/{FormatDefinition.d.ts → FormatParser.d.ts} +8 -6
- package/esm/typings/src/formats/_common/FormatSubvalueParser.d.ts +66 -0
- package/esm/typings/src/formats/csv/CsvFormatParser.d.ts +17 -0
- package/esm/typings/src/formats/csv/CsvSettings.d.ts +2 -2
- package/esm/typings/src/formats/csv/utils/csvParse.d.ts +12 -0
- package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +1 -1
- package/esm/typings/src/formats/index.d.ts +2 -2
- package/esm/typings/src/formats/json/{JsonFormatDefinition.d.ts → JsonFormatParser.d.ts} +6 -6
- package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +1 -1
- package/esm/typings/src/formats/json/utils/jsonParse.d.ts +8 -0
- package/esm/typings/src/formats/text/{TextFormatDefinition.d.ts → TextFormatParser.d.ts} +7 -7
- package/esm/typings/src/formats/xml/XmlFormatParser.d.ts +19 -0
- package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +1 -1
- package/esm/typings/src/formfactors/_boilerplate/BoilerplateFormfactorDefinition.d.ts +3 -2
- package/esm/typings/src/formfactors/_common/AbstractFormfactorDefinition.d.ts +16 -7
- package/esm/typings/src/formfactors/_common/FormfactorDefinition.d.ts +3 -1
- package/esm/typings/src/formfactors/_common/string_formfactor_name.d.ts +2 -1
- package/esm/typings/src/formfactors/chatbot/ChatbotFormfactorDefinition.d.ts +2 -2
- package/esm/typings/src/formfactors/completion/CompletionFormfactorDefinition.d.ts +29 -0
- package/esm/typings/src/formfactors/generator/GeneratorFormfactorDefinition.d.ts +2 -1
- package/esm/typings/src/formfactors/generic/GenericFormfactorDefinition.d.ts +2 -2
- package/esm/typings/src/formfactors/index.d.ts +33 -8
- package/esm/typings/src/formfactors/matcher/MatcherFormfactorDefinition.d.ts +4 -2
- package/esm/typings/src/formfactors/sheets/SheetsFormfactorDefinition.d.ts +3 -2
- package/esm/typings/src/formfactors/translator/TranslatorFormfactorDefinition.d.ts +3 -2
- package/esm/typings/src/high-level-abstractions/index.d.ts +2 -2
- package/esm/typings/src/llm-providers/_common/register/$llmToolsMetadataRegister.d.ts +3 -3
- package/esm/typings/src/llm-providers/_common/register/$llmToolsRegister.d.ts +3 -3
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +4 -4
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +4 -3
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +17 -4
- package/esm/typings/src/llm-providers/_common/register/LlmToolsConfiguration.d.ts +11 -4
- package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +27 -5
- package/esm/typings/src/llm-providers/_common/register/LlmToolsOptions.d.ts +9 -2
- package/esm/typings/src/llm-providers/_common/register/createLlmToolsFromConfiguration.d.ts +12 -3
- package/esm/typings/src/llm-providers/_common/utils/cache/CacheItem.d.ts +10 -5
- package/esm/typings/src/llm-providers/_common/utils/cache/CacheLlmToolsOptions.d.ts +5 -3
- package/esm/typings/src/llm-providers/_common/utils/cache/cacheLlmTools.d.ts +3 -3
- package/esm/typings/src/llm-providers/_common/utils/count-total-usage/limitTotalUsage.d.ts +5 -5
- package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
- 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/llm-providers/openai/openai-models.d.ts +1 -1
- package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +2 -2
- package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +2 -2
- package/esm/typings/src/migrations/migratePipeline.d.ts +9 -0
- package/esm/typings/src/other/templates/getBookTemplates.d.ts +2 -2
- package/esm/typings/src/personas/preparePersona.d.ts +1 -1
- package/esm/typings/src/pipeline/PipelineInterface/PipelineInterface.d.ts +3 -3
- package/esm/typings/src/pipeline/PipelineInterface/constants.d.ts +1 -1
- package/esm/typings/src/pipeline/PipelineInterface/getPipelineInterface.d.ts +1 -1
- package/esm/typings/src/pipeline/PipelineInterface/isPipelineImplementingInterface.d.ts +5 -4
- package/esm/typings/src/pipeline/PipelineInterface/isPipelineInterfacesEqual.d.ts +1 -1
- package/esm/typings/src/pipeline/PipelineJson/CommonTaskJson.d.ts +9 -6
- package/esm/typings/src/pipeline/PipelineJson/PersonaJson.d.ts +4 -2
- package/esm/typings/src/pipeline/PipelineJson/PipelineJson.d.ts +3 -2
- package/esm/typings/src/pipeline/PipelineString.d.ts +3 -1
- package/esm/typings/src/pipeline/book-notation.d.ts +2 -2
- package/esm/typings/src/postprocessing/utils/extractJsonBlock.d.ts +1 -1
- package/esm/typings/src/prepare/prepareTasks.d.ts +7 -4
- package/esm/typings/src/remote-server/openapi-types.d.ts +348 -6
- package/esm/typings/src/remote-server/openapi.d.ts +398 -4
- package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +2 -1
- package/esm/typings/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +3 -3
- package/esm/typings/src/scrapers/_boilerplate/createBoilerplateScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/_boilerplate/register-metadata.d.ts +1 -1
- package/esm/typings/src/scrapers/_common/Converter.d.ts +3 -1
- package/esm/typings/src/scrapers/_common/Scraper.d.ts +4 -3
- package/esm/typings/src/scrapers/_common/ScraperIntermediateSource.d.ts +4 -2
- package/esm/typings/src/scrapers/_common/register/$provideFilesystemForNode.d.ts +2 -1
- package/esm/typings/src/scrapers/_common/register/$provideScrapersForBrowser.d.ts +6 -3
- package/esm/typings/src/scrapers/_common/register/$provideScrapersForNode.d.ts +3 -5
- package/esm/typings/src/scrapers/_common/register/$scrapersMetadataRegister.d.ts +3 -3
- package/esm/typings/src/scrapers/_common/register/$scrapersRegister.d.ts +3 -2
- package/esm/typings/src/scrapers/_common/register/ScraperAndConverterMetadata.d.ts +8 -5
- package/esm/typings/src/scrapers/_common/register/ScraperConstructor.d.ts +2 -1
- package/esm/typings/src/scrapers/_common/utils/getScraperIntermediateSource.d.ts +6 -5
- package/esm/typings/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +3 -1
- package/esm/typings/src/scrapers/document/createDocumentScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/document-legacy/createLegacyDocumentScraper.d.ts +2 -1
- package/esm/typings/src/scrapers/markdown/createMarkdownScraper.d.ts +4 -1
- package/esm/typings/src/scrapers/markitdown/MarkitdownScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +2 -1
- package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +3 -4
- package/esm/typings/src/scripting/javascript/postprocessing-functions.d.ts +5 -1
- package/esm/typings/src/storage/file-cache-storage/FileCacheStorage.d.ts +12 -5
- package/esm/typings/src/storage/file-cache-storage/FileCacheStorageOptions.d.ts +4 -2
- package/esm/typings/src/storage/file-cache-storage/utils/nameToSubfolderPath.d.ts +2 -1
- package/esm/typings/src/storage/local-storage/getIndexedDbStorage.d.ts +10 -0
- package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromIndexedDb.d.ts +7 -0
- package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromWebStorage.d.ts +2 -1
- package/esm/typings/src/types/IntermediateFilesStrategy.d.ts +2 -1
- package/esm/typings/src/types/ModelVariant.d.ts +5 -5
- package/esm/typings/src/types/typeAliases.d.ts +17 -13
- package/esm/typings/src/utils/$Register.d.ts +8 -7
- package/esm/typings/src/utils/editable/edit-pipeline-string/addPipelineCommand.d.ts +2 -2
- package/esm/typings/src/utils/editable/edit-pipeline-string/deflatePipeline.d.ts +4 -1
- package/esm/typings/src/utils/editable/utils/isFlatPipeline.d.ts +2 -1
- package/esm/typings/src/utils/environment/$getGlobalScope.d.ts +2 -1
- package/esm/typings/src/utils/expectation-counters/index.d.ts +1 -1
- package/esm/typings/src/utils/markdown/extractAllListItemsFromMarkdown.d.ts +1 -1
- package/esm/typings/src/utils/normalization/nameToUriPart.d.ts +4 -4
- package/esm/typings/src/utils/normalization/nameToUriParts.d.ts +4 -4
- package/esm/typings/src/utils/normalization/normalize-to-kebab-case.d.ts +3 -3
- package/esm/typings/src/utils/normalization/normalizeTo_SCREAMING_CASE.d.ts +3 -3
- package/esm/typings/src/utils/normalization/normalizeTo_camelCase.d.ts +4 -4
- package/esm/typings/src/utils/normalization/normalizeTo_snake_case.d.ts +3 -3
- package/esm/typings/src/utils/normalization/removeDiacritics.d.ts +3 -3
- package/esm/typings/src/utils/normalization/searchKeywords.d.ts +4 -1
- package/esm/typings/src/utils/normalization/titleToName.d.ts +4 -4
- package/esm/typings/src/utils/organization/empty_object.d.ts +2 -2
- package/esm/typings/src/utils/organization/just_empty_object.d.ts +4 -4
- package/esm/typings/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +7 -7
- package/esm/typings/src/utils/serialization/clonePipeline.d.ts +4 -3
- package/esm/typings/src/utils/serialization/deepClone.d.ts +5 -1
- package/esm/typings/src/utils/validators/javascriptName/isValidJavascriptName.d.ts +3 -3
- package/esm/typings/src/utils/validators/parameterName/validateParameterName.d.ts +5 -4
- package/esm/typings/src/version.d.ts +2 -1
- package/package.json +2 -1
- package/umd/index.umd.js +1669 -534
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/formats/_common/FormatSubvalueDefinition.d.ts +0 -31
- package/esm/typings/src/formats/csv/CsvFormatDefinition.d.ts +0 -17
- package/esm/typings/src/formats/xml/XmlFormatDefinition.d.ts +0 -19
package/esm/index.es.js
CHANGED
|
@@ -21,12 +21,13 @@ import { lookup, extension } from 'mime-types';
|
|
|
21
21
|
import glob from 'glob-promise';
|
|
22
22
|
import moment from 'moment';
|
|
23
23
|
import express from 'express';
|
|
24
|
+
import * as OpenApiValidator from 'express-openapi-validator';
|
|
24
25
|
import http from 'http';
|
|
25
26
|
import { Server } from 'socket.io';
|
|
26
|
-
import * as OpenApiValidator from 'express-openapi-validator';
|
|
27
27
|
import swaggerUi from 'swagger-ui-express';
|
|
28
28
|
import Anthropic from '@anthropic-ai/sdk';
|
|
29
29
|
import { OpenAIClient, AzureKeyCredential } from '@azure/openai';
|
|
30
|
+
import Bottleneck from 'bottleneck';
|
|
30
31
|
import OpenAI from 'openai';
|
|
31
32
|
import { Readability } from '@mozilla/readability';
|
|
32
33
|
import { JSDOM } from 'jsdom';
|
|
@@ -46,7 +47,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
46
47
|
* @generated
|
|
47
48
|
* @see https://github.com/webgptorg/promptbook
|
|
48
49
|
*/
|
|
49
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.92.0-
|
|
50
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.92.0-31';
|
|
50
51
|
/**
|
|
51
52
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
52
53
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -162,6 +163,21 @@ const DEFAULT_BOOK_OUTPUT_PARAMETER_NAME = 'result';
|
|
|
162
163
|
* @public exported from `@promptbook/core`
|
|
163
164
|
*/
|
|
164
165
|
const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
|
|
166
|
+
/**
|
|
167
|
+
* Threshold value that determines when a dataset is considered "big"
|
|
168
|
+
* and may require special handling or optimizations
|
|
169
|
+
*
|
|
170
|
+
* For example, when error occurs in one item of the big dataset, it will not fail the whole pipeline
|
|
171
|
+
*
|
|
172
|
+
* @public exported from `@promptbook/core`
|
|
173
|
+
*/
|
|
174
|
+
const BIG_DATASET_TRESHOLD = 50;
|
|
175
|
+
/**
|
|
176
|
+
* Placeholder text used to represent a placeholder value of failed operation
|
|
177
|
+
*
|
|
178
|
+
* @public exported from `@promptbook/core`
|
|
179
|
+
*/
|
|
180
|
+
const FAILED_VALUE_PLACEHOLDER = '!?';
|
|
165
181
|
/**
|
|
166
182
|
* Warning message for the generated sections and files files
|
|
167
183
|
*
|
|
@@ -246,6 +262,7 @@ const DEFAULT_MAX_PARALLEL_COUNT = 5; // <- TODO: [🤹♂️]
|
|
|
246
262
|
* @public exported from `@promptbook/core`
|
|
247
263
|
*/
|
|
248
264
|
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 10; // <- TODO: [🤹♂️]
|
|
265
|
+
// <- TODO: [🐝]
|
|
249
266
|
/**
|
|
250
267
|
* Where to store your books
|
|
251
268
|
* This is kind of a "src" for your books
|
|
@@ -317,7 +334,7 @@ const MOMENT_ARG_THRESHOLDS = {
|
|
|
317
334
|
const DEFAULT_REMOTE_SERVER_URL = REMOTE_SERVER_URLS[0].urls[0];
|
|
318
335
|
// <- TODO: [🧜♂️]
|
|
319
336
|
/**
|
|
320
|
-
*
|
|
337
|
+
* Default settings for parsing and generating CSV files in Promptbook.
|
|
321
338
|
*
|
|
322
339
|
* @public exported from `@promptbook/core`
|
|
323
340
|
*/
|
|
@@ -328,13 +345,13 @@ const DEFAULT_CSV_SETTINGS = Object.freeze({
|
|
|
328
345
|
skipEmptyLines: true,
|
|
329
346
|
});
|
|
330
347
|
/**
|
|
331
|
-
*
|
|
348
|
+
* Controls whether verbose logging is enabled by default throughout the application.
|
|
332
349
|
*
|
|
333
350
|
* @public exported from `@promptbook/core`
|
|
334
351
|
*/
|
|
335
352
|
let DEFAULT_IS_VERBOSE = false;
|
|
336
353
|
/**
|
|
337
|
-
*
|
|
354
|
+
* Controls whether auto-installation of dependencies is enabled by default.
|
|
338
355
|
*
|
|
339
356
|
* @public exported from `@promptbook/core`
|
|
340
357
|
*/
|
|
@@ -346,7 +363,15 @@ const DEFAULT_IS_AUTO_INSTALLED = false;
|
|
|
346
363
|
*/
|
|
347
364
|
const DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME = `getPipelineCollection`;
|
|
348
365
|
/**
|
|
349
|
-
*
|
|
366
|
+
* Default rate limits (requests per minute)
|
|
367
|
+
*
|
|
368
|
+
* Note: Adjust based on the provider tier you are have
|
|
369
|
+
*
|
|
370
|
+
* @public exported from `@promptbook/core`
|
|
371
|
+
*/
|
|
372
|
+
const DEFAULT_MAX_REQUESTS_PER_MINUTE = 60;
|
|
373
|
+
/**
|
|
374
|
+
* Indicates whether pipeline logic validation is enabled. When true, the pipeline logic is checked for consistency.
|
|
350
375
|
*
|
|
351
376
|
* @private within the repository
|
|
352
377
|
*/
|
|
@@ -686,7 +711,8 @@ class NotYetImplementedError extends Error {
|
|
|
686
711
|
}
|
|
687
712
|
|
|
688
713
|
/**
|
|
689
|
-
*
|
|
714
|
+
* Safely retrieves the global scope object (window in browser, global in Node.js)
|
|
715
|
+
* regardless of the JavaScript environment in which the code is running
|
|
690
716
|
*
|
|
691
717
|
* Note: `$` is used to indicate that this function is not a pure function - it access global scope
|
|
692
718
|
*
|
|
@@ -697,10 +723,10 @@ function $getGlobalScope() {
|
|
|
697
723
|
}
|
|
698
724
|
|
|
699
725
|
/**
|
|
700
|
-
*
|
|
726
|
+
* Normalizes a text string to SCREAMING_CASE (all uppercase with underscores).
|
|
701
727
|
*
|
|
702
|
-
* @param text
|
|
703
|
-
* @returns
|
|
728
|
+
* @param text The text string to be converted to SCREAMING_CASE format.
|
|
729
|
+
* @returns The normalized text in SCREAMING_CASE format.
|
|
704
730
|
* @example 'HELLO_WORLD'
|
|
705
731
|
* @example 'I_LOVE_PROMPTBOOK'
|
|
706
732
|
* @public exported from `@promptbook/utils`
|
|
@@ -752,10 +778,10 @@ function normalizeTo_SCREAMING_CASE(text) {
|
|
|
752
778
|
*/
|
|
753
779
|
|
|
754
780
|
/**
|
|
755
|
-
*
|
|
781
|
+
* Normalizes a text string to snake_case format.
|
|
756
782
|
*
|
|
757
|
-
* @param text
|
|
758
|
-
* @returns
|
|
783
|
+
* @param text The text string to be converted to snake_case format.
|
|
784
|
+
* @returns The normalized text in snake_case format.
|
|
759
785
|
* @example 'hello_world'
|
|
760
786
|
* @example 'i_love_promptbook'
|
|
761
787
|
* @public exported from `@promptbook/utils`
|
|
@@ -765,11 +791,11 @@ function normalizeTo_snake_case(text) {
|
|
|
765
791
|
}
|
|
766
792
|
|
|
767
793
|
/**
|
|
768
|
-
*
|
|
794
|
+
* Global registry for storing and managing registered entities of a given type.
|
|
769
795
|
*
|
|
770
796
|
* Note: `$` is used to indicate that this function is not a pure function - it accesses and adds variables in global scope.
|
|
771
797
|
*
|
|
772
|
-
* @private internal utility, exported are only
|
|
798
|
+
* @private internal utility, exported are only singleton instances of this class
|
|
773
799
|
*/
|
|
774
800
|
class $Register {
|
|
775
801
|
constructor(registerName) {
|
|
@@ -813,10 +839,10 @@ class $Register {
|
|
|
813
839
|
}
|
|
814
840
|
|
|
815
841
|
/**
|
|
816
|
-
*
|
|
842
|
+
* Register for LLM tools metadata.
|
|
817
843
|
*
|
|
818
844
|
* Note: `$` is used to indicate that this interacts with the global scope
|
|
819
|
-
* @singleton Only one instance of each register is created per build, but
|
|
845
|
+
* @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
|
|
820
846
|
* @public exported from `@promptbook/core`
|
|
821
847
|
*/
|
|
822
848
|
const $llmToolsMetadataRegister = new $Register('llm_tools_metadata');
|
|
@@ -825,10 +851,10 @@ const $llmToolsMetadataRegister = new $Register('llm_tools_metadata');
|
|
|
825
851
|
*/
|
|
826
852
|
|
|
827
853
|
/**
|
|
828
|
-
*
|
|
854
|
+
* Register for LLM tools.
|
|
829
855
|
*
|
|
830
856
|
* Note: `$` is used to indicate that this interacts with the global scope
|
|
831
|
-
* @singleton Only one instance of each register is created per build, but
|
|
857
|
+
* @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
|
|
832
858
|
* @public exported from `@promptbook/core`
|
|
833
859
|
*/
|
|
834
860
|
const $llmToolsRegister = new $Register('llm_execution_tools_constructors');
|
|
@@ -1004,6 +1030,42 @@ function $sideEffect(...sideEffectSubjects) {
|
|
|
1004
1030
|
keepUnused(...sideEffectSubjects);
|
|
1005
1031
|
}
|
|
1006
1032
|
|
|
1033
|
+
/**
|
|
1034
|
+
* Converts a JavaScript Object Notation (JSON) string into an object.
|
|
1035
|
+
*
|
|
1036
|
+
* Note: This is wrapper around `JSON.parse()` with better error and type handling
|
|
1037
|
+
*
|
|
1038
|
+
* @public exported from `@promptbook/utils`
|
|
1039
|
+
*/
|
|
1040
|
+
function jsonParse(value) {
|
|
1041
|
+
if (value === undefined) {
|
|
1042
|
+
throw new Error(`Can not parse JSON from undefined value.`);
|
|
1043
|
+
}
|
|
1044
|
+
else if (typeof value !== 'string') {
|
|
1045
|
+
console.error('Can not parse JSON from non-string value.', { text: value });
|
|
1046
|
+
throw new Error(spaceTrim(`
|
|
1047
|
+
Can not parse JSON from non-string value.
|
|
1048
|
+
|
|
1049
|
+
The value type: ${typeof value}
|
|
1050
|
+
See more in console.
|
|
1051
|
+
`));
|
|
1052
|
+
}
|
|
1053
|
+
try {
|
|
1054
|
+
return JSON.parse(value);
|
|
1055
|
+
}
|
|
1056
|
+
catch (error) {
|
|
1057
|
+
if (!(error instanceof Error)) {
|
|
1058
|
+
throw error;
|
|
1059
|
+
}
|
|
1060
|
+
throw new Error(spaceTrim((block) => `
|
|
1061
|
+
${block(error.message)}
|
|
1062
|
+
|
|
1063
|
+
The JSON text:
|
|
1064
|
+
${block(value)}
|
|
1065
|
+
`));
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1007
1069
|
/**
|
|
1008
1070
|
* Convert identification to Promptbook token
|
|
1009
1071
|
*
|
|
@@ -1052,7 +1114,8 @@ function TODO_USE(...value) {
|
|
|
1052
1114
|
}
|
|
1053
1115
|
|
|
1054
1116
|
/**
|
|
1055
|
-
*
|
|
1117
|
+
* Provides filesystem access (for example for Node.js-based scrapers)
|
|
1118
|
+
* Creates a standardized filesystem interface that scrapers can use for file operations.
|
|
1056
1119
|
*
|
|
1057
1120
|
* @public exported from `@promptbook/node`
|
|
1058
1121
|
*/
|
|
@@ -1427,8 +1490,12 @@ function checkSerializableAsJson(options) {
|
|
|
1427
1490
|
*/
|
|
1428
1491
|
|
|
1429
1492
|
/**
|
|
1430
|
-
*
|
|
1493
|
+
* Creates a deep clone of the given object
|
|
1431
1494
|
*
|
|
1495
|
+
* Note: This method only works for objects that are fully serializable to JSON and do not contain functions, Dates, or special types.
|
|
1496
|
+
*
|
|
1497
|
+
* @param objectValue The object to clone.
|
|
1498
|
+
* @returns A deep, writable clone of the input object.
|
|
1432
1499
|
* @public exported from `@promptbook/utils`
|
|
1433
1500
|
*/
|
|
1434
1501
|
function deepClone(objectValue) {
|
|
@@ -1483,6 +1550,26 @@ function exportJson(options) {
|
|
|
1483
1550
|
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
1484
1551
|
*/
|
|
1485
1552
|
|
|
1553
|
+
// <- TODO: Maybe do better levels of trust
|
|
1554
|
+
/**
|
|
1555
|
+
* How is the model provider important?
|
|
1556
|
+
*
|
|
1557
|
+
* @public exported from `@promptbook/core`
|
|
1558
|
+
*/
|
|
1559
|
+
const MODEL_ORDERS = {
|
|
1560
|
+
/**
|
|
1561
|
+
* Top-tier models, e.g. OpenAI, Anthropic,...
|
|
1562
|
+
*/
|
|
1563
|
+
TOP_TIER: 333,
|
|
1564
|
+
/**
|
|
1565
|
+
* Mid-tier models, e.g. Llama, Mistral, etc.
|
|
1566
|
+
*/
|
|
1567
|
+
NORMAL: 100,
|
|
1568
|
+
/**
|
|
1569
|
+
* Low-tier models, e.g. Phi, Tiny, etc.
|
|
1570
|
+
*/
|
|
1571
|
+
LOW_TIER: 0,
|
|
1572
|
+
};
|
|
1486
1573
|
/**
|
|
1487
1574
|
* Order of keys in the pipeline JSON
|
|
1488
1575
|
*
|
|
@@ -1510,13 +1597,19 @@ const ORDER_OF_PIPELINE_JSON = [
|
|
|
1510
1597
|
*/
|
|
1511
1598
|
const REPLACING_NONCE = 'ptbkauk42kV2dzao34faw7FudQUHYPtW';
|
|
1512
1599
|
/**
|
|
1513
|
-
*
|
|
1600
|
+
* Nonce which is used as string which is not occurring in normal text
|
|
1601
|
+
*
|
|
1602
|
+
* @private within the repository
|
|
1603
|
+
*/
|
|
1604
|
+
const SALT_NONCE = 'ptbkghhewbvruets21t54et5';
|
|
1605
|
+
/**
|
|
1606
|
+
* Placeholder value indicating a parameter is missing its value.
|
|
1514
1607
|
*
|
|
1515
1608
|
* @private within the repository
|
|
1516
1609
|
*/
|
|
1517
1610
|
const RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
|
|
1518
1611
|
/**
|
|
1519
|
-
*
|
|
1612
|
+
* Placeholder value indicating a parameter is restricted and cannot be used directly.
|
|
1520
1613
|
*
|
|
1521
1614
|
* @private within the repository
|
|
1522
1615
|
*/
|
|
@@ -1951,10 +2044,10 @@ for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
|
|
|
1951
2044
|
*/
|
|
1952
2045
|
|
|
1953
2046
|
/**
|
|
1954
|
-
*
|
|
2047
|
+
* Removes diacritic marks (accents) from characters in a string.
|
|
1955
2048
|
*
|
|
1956
|
-
* @param input
|
|
1957
|
-
* @returns
|
|
2049
|
+
* @param input The string containing diacritics to be normalized.
|
|
2050
|
+
* @returns The string with diacritics removed or normalized.
|
|
1958
2051
|
* @public exported from `@promptbook/utils`
|
|
1959
2052
|
*/
|
|
1960
2053
|
function removeDiacritics(input) {
|
|
@@ -1968,10 +2061,10 @@ function removeDiacritics(input) {
|
|
|
1968
2061
|
*/
|
|
1969
2062
|
|
|
1970
2063
|
/**
|
|
1971
|
-
*
|
|
2064
|
+
* Converts a given text to kebab-case format.
|
|
1972
2065
|
*
|
|
1973
|
-
* @param text
|
|
1974
|
-
* @returns
|
|
2066
|
+
* @param text The text to be converted.
|
|
2067
|
+
* @returns The kebab-case formatted string.
|
|
1975
2068
|
* @example 'hello-world'
|
|
1976
2069
|
* @example 'i-love-promptbook'
|
|
1977
2070
|
* @public exported from `@promptbook/utils`
|
|
@@ -2019,11 +2112,11 @@ function normalizeToKebabCase(text) {
|
|
|
2019
2112
|
*/
|
|
2020
2113
|
|
|
2021
2114
|
/**
|
|
2022
|
-
*
|
|
2115
|
+
* Converts a title string into a normalized name.
|
|
2023
2116
|
*
|
|
2024
|
-
* @param value
|
|
2025
|
-
* @returns
|
|
2026
|
-
* @example
|
|
2117
|
+
* @param value The title string to be converted to a name.
|
|
2118
|
+
* @returns A normalized name derived from the input title.
|
|
2119
|
+
* @example 'Hello World!' -> 'hello-world'
|
|
2027
2120
|
* @public exported from `@promptbook/utils`
|
|
2028
2121
|
*/
|
|
2029
2122
|
function titleToName(value) {
|
|
@@ -2043,7 +2136,8 @@ function titleToName(value) {
|
|
|
2043
2136
|
}
|
|
2044
2137
|
|
|
2045
2138
|
/**
|
|
2046
|
-
*
|
|
2139
|
+
* Converts a name to a properly formatted subfolder path for cache storage.
|
|
2140
|
+
* Handles normalization and path formatting to create consistent cache directory structures.
|
|
2047
2141
|
*
|
|
2048
2142
|
* @private for `FileCacheStorage`
|
|
2049
2143
|
*/
|
|
@@ -2052,7 +2146,10 @@ function nameToSubfolderPath(name) {
|
|
|
2052
2146
|
}
|
|
2053
2147
|
|
|
2054
2148
|
/**
|
|
2055
|
-
*
|
|
2149
|
+
* A storage implementation that caches data in files organized in a directory structure.
|
|
2150
|
+
* Provides methods for retrieving, storing, and managing cached data on the filesystem.
|
|
2151
|
+
*
|
|
2152
|
+
* This class implements the PromptbookStorage interface for filesystem-based caching.
|
|
2056
2153
|
*
|
|
2057
2154
|
* @public exported from `@promptbook/node`
|
|
2058
2155
|
*/
|
|
@@ -2065,7 +2162,8 @@ class FileCacheStorage {
|
|
|
2065
2162
|
}
|
|
2066
2163
|
}
|
|
2067
2164
|
/**
|
|
2068
|
-
*
|
|
2165
|
+
* Converts a storage key to a filesystem path where the data should be stored.
|
|
2166
|
+
* Creates a consistent, deterministic file path based on the key string.
|
|
2069
2167
|
*/
|
|
2070
2168
|
getFilenameForKey(key) {
|
|
2071
2169
|
// TODO: [👬] DRY
|
|
@@ -2077,7 +2175,8 @@ class FileCacheStorage {
|
|
|
2077
2175
|
...nameToSubfolderPath(hash /* <- TODO: [🎎] Maybe add some SHA256 prefix */), `${name.substring(0, MAX_FILENAME_LENGTH)}.json`);
|
|
2078
2176
|
}
|
|
2079
2177
|
/**
|
|
2080
|
-
*
|
|
2178
|
+
* Returns the current value associated with the given key, or null if the given key does not exist.
|
|
2179
|
+
* Retrieves the cached data from the file system storage.
|
|
2081
2180
|
*/
|
|
2082
2181
|
async getItem(key) {
|
|
2083
2182
|
const filename = this.getFilenameForKey(key);
|
|
@@ -2085,12 +2184,13 @@ class FileCacheStorage {
|
|
|
2085
2184
|
return null;
|
|
2086
2185
|
}
|
|
2087
2186
|
const fileContent = await readFile(filename, 'utf-8');
|
|
2088
|
-
const value =
|
|
2187
|
+
const value = jsonParse(fileContent);
|
|
2089
2188
|
// TODO: [🌗]
|
|
2090
2189
|
return value;
|
|
2091
2190
|
}
|
|
2092
2191
|
/**
|
|
2093
|
-
*
|
|
2192
|
+
* Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
|
|
2193
|
+
* Persists data to the file system, creating necessary directory structure if it doesn't exist.
|
|
2094
2194
|
*/
|
|
2095
2195
|
async setItem(key, value) {
|
|
2096
2196
|
const filename = this.getFilenameForKey(key);
|
|
@@ -2102,7 +2202,8 @@ class FileCacheStorage {
|
|
|
2102
2202
|
await writeFile(filename, fileContent, 'utf-8');
|
|
2103
2203
|
}
|
|
2104
2204
|
/**
|
|
2105
|
-
*
|
|
2205
|
+
* Removes the key/value pair with the given key from the storage, if a key/value pair with the given key exists.
|
|
2206
|
+
* Deletes the corresponding file from the filesystem.
|
|
2106
2207
|
*/
|
|
2107
2208
|
async removeItem(key) {
|
|
2108
2209
|
const filename = this.getFilenameForKey(key);
|
|
@@ -2581,6 +2682,23 @@ class RemoteLlmExecutionTools {
|
|
|
2581
2682
|
* TODO: [🧠] Maybe remove `@promptbook/remote-client` and just use `@promptbook/core`
|
|
2582
2683
|
*/
|
|
2583
2684
|
|
|
2685
|
+
/**
|
|
2686
|
+
* Parses the task and returns the list of all parameter names
|
|
2687
|
+
*
|
|
2688
|
+
* @param template the string template with parameters in {curly} braces
|
|
2689
|
+
* @returns the list of parameter names
|
|
2690
|
+
* @public exported from `@promptbook/utils`
|
|
2691
|
+
*/
|
|
2692
|
+
function extractParameterNames(template) {
|
|
2693
|
+
const matches = template.matchAll(/{\w+}/g);
|
|
2694
|
+
const parameterNames = new Set();
|
|
2695
|
+
for (const match of matches) {
|
|
2696
|
+
const parameterName = match[0].slice(1, -1);
|
|
2697
|
+
parameterNames.add(parameterName);
|
|
2698
|
+
}
|
|
2699
|
+
return parameterNames;
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2584
2702
|
/**
|
|
2585
2703
|
* Stores data in memory (HEAP)
|
|
2586
2704
|
*
|
|
@@ -2670,13 +2788,36 @@ function cacheLlmTools(llmTools, options = {}) {
|
|
|
2670
2788
|
const callCommonModel = async (prompt) => {
|
|
2671
2789
|
const { parameters, content, modelRequirements } = prompt;
|
|
2672
2790
|
// <- Note: These are relevant things from the prompt that the cache key should depend on.
|
|
2791
|
+
// TODO: Maybe some standalone function for normalization of content for cache
|
|
2792
|
+
let normalizedContent = content;
|
|
2793
|
+
normalizedContent = normalizedContent.replace(/\s+/g, ' ');
|
|
2794
|
+
normalizedContent = normalizedContent.split('\r\n').join('\n');
|
|
2795
|
+
normalizedContent = spaceTrim(normalizedContent);
|
|
2796
|
+
// Note: Do not need to save everything in the cache, just the relevant parameters
|
|
2797
|
+
const relevantParameterNames = extractParameterNames(content);
|
|
2798
|
+
const relevantParameters = Object.fromEntries(Object.entries(parameters).filter(([key]) => relevantParameterNames.has(key)));
|
|
2799
|
+
const keyHashBase = { relevantParameters, normalizedContent, modelRequirements };
|
|
2673
2800
|
const key = titleToName(prompt.title.substring(0, MAX_FILENAME_LENGTH - 10) +
|
|
2674
2801
|
'-' +
|
|
2675
|
-
sha256(hexEncoder.parse(JSON.stringify(
|
|
2802
|
+
sha256(hexEncoder.parse(JSON.stringify(keyHashBase)))
|
|
2803
|
+
.toString( /* hex */)
|
|
2804
|
+
.substring(0, 10 - 1));
|
|
2676
2805
|
const cacheItem = !isCacheReloaded ? await storage.getItem(key) : null;
|
|
2677
2806
|
if (cacheItem) {
|
|
2807
|
+
console.log('!!! Cache hit for key:', { key, keyHashBase });
|
|
2678
2808
|
return cacheItem.promptResult;
|
|
2679
2809
|
}
|
|
2810
|
+
console.log('!!! Cache miss for key:', key, {
|
|
2811
|
+
prompt,
|
|
2812
|
+
'prompt.title': prompt.title,
|
|
2813
|
+
MAX_FILENAME_LENGTH,
|
|
2814
|
+
keyHashBase,
|
|
2815
|
+
parameters,
|
|
2816
|
+
relevantParameters,
|
|
2817
|
+
content,
|
|
2818
|
+
normalizedContent,
|
|
2819
|
+
modelRequirements,
|
|
2820
|
+
});
|
|
2680
2821
|
let promptResult;
|
|
2681
2822
|
variant: switch (prompt.modelRequirements.modelVariant) {
|
|
2682
2823
|
case 'CHAT':
|
|
@@ -2697,7 +2838,16 @@ function cacheLlmTools(llmTools, options = {}) {
|
|
|
2697
2838
|
await storage.setItem(key, {
|
|
2698
2839
|
date: $getCurrentDate(),
|
|
2699
2840
|
promptbookVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
2700
|
-
|
|
2841
|
+
bookVersion: BOOK_LANGUAGE_VERSION,
|
|
2842
|
+
prompt: {
|
|
2843
|
+
...prompt,
|
|
2844
|
+
parameters: Object.entries(parameters).length === Object.entries(relevantParameters).length
|
|
2845
|
+
? parameters
|
|
2846
|
+
: {
|
|
2847
|
+
...relevantParameters,
|
|
2848
|
+
note: `<- Note: Only relevant parameters are stored in the cache`,
|
|
2849
|
+
},
|
|
2850
|
+
},
|
|
2701
2851
|
promptResult,
|
|
2702
2852
|
});
|
|
2703
2853
|
return promptResult;
|
|
@@ -2723,9 +2873,9 @@ function cacheLlmTools(llmTools, options = {}) {
|
|
|
2723
2873
|
/**
|
|
2724
2874
|
* TODO: [🧠][💸] Maybe make some common abstraction `interceptLlmTools` and use here (or use javascript Proxy?)
|
|
2725
2875
|
* TODO: [🧠] Is there some meaningfull way how to test this util
|
|
2726
|
-
* TODO: [👷♂️]
|
|
2727
|
-
*
|
|
2728
|
-
*
|
|
2876
|
+
* TODO: [👷♂️] Comprehensive manual about construction of llmTools
|
|
2877
|
+
* Detailed explanation about caching strategies and appropriate storage selection for different use cases
|
|
2878
|
+
* Examples of how to combine multiple interceptors for advanced caching, logging, and usage tracking
|
|
2729
2879
|
*/
|
|
2730
2880
|
|
|
2731
2881
|
/**
|
|
@@ -2915,9 +3065,8 @@ function countUsage(llmTools) {
|
|
|
2915
3065
|
*/
|
|
2916
3066
|
|
|
2917
3067
|
/**
|
|
2918
|
-
*
|
|
3068
|
+
* Provides LLM tools configuration by reading environment variables.
|
|
2919
3069
|
*
|
|
2920
|
-
* @@@ .env
|
|
2921
3070
|
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
2922
3071
|
*
|
|
2923
3072
|
* It looks for environment variables:
|
|
@@ -2925,7 +3074,8 @@ function countUsage(llmTools) {
|
|
|
2925
3074
|
* - `process.env.ANTHROPIC_CLAUDE_API_KEY`
|
|
2926
3075
|
* - ...
|
|
2927
3076
|
*
|
|
2928
|
-
* @
|
|
3077
|
+
* @see Environment variables documentation or .env file for required variables.
|
|
3078
|
+
* @returns A promise that resolves to the LLM tools configuration, or null if configuration is incomplete or missing.
|
|
2929
3079
|
* @public exported from `@promptbook/node`
|
|
2930
3080
|
*/
|
|
2931
3081
|
async function $provideLlmToolsConfigurationFromEnv() {
|
|
@@ -3139,11 +3289,16 @@ function joinLlmExecutionTools(...llmExecutionTools) {
|
|
|
3139
3289
|
*/
|
|
3140
3290
|
|
|
3141
3291
|
/**
|
|
3142
|
-
*
|
|
3292
|
+
* Creates LLM execution tools from provided configuration objects
|
|
3293
|
+
*
|
|
3294
|
+
* Instantiates and configures LLM tool instances for each configuration entry,
|
|
3295
|
+
* combining them into a unified interface via MultipleLlmExecutionTools.
|
|
3143
3296
|
*
|
|
3144
3297
|
* Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
|
|
3145
3298
|
*
|
|
3146
|
-
* @
|
|
3299
|
+
* @param configuration Array of LLM tool configurations to instantiate
|
|
3300
|
+
* @param options Additional options for configuring the LLM tools
|
|
3301
|
+
* @returns A unified interface combining all successfully instantiated LLM tools
|
|
3147
3302
|
* @public exported from `@promptbook/core`
|
|
3148
3303
|
*/
|
|
3149
3304
|
function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
@@ -3182,7 +3337,11 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
3182
3337
|
/**
|
|
3183
3338
|
* TODO: [🎌] Together with `createLlmToolsFromConfiguration` + 'EXECUTION_TOOLS_CLASSES' gets to `@promptbook/core` ALL model providers, make this more efficient
|
|
3184
3339
|
* TODO: [🧠][🎌] Dynamically install required providers
|
|
3185
|
-
* TODO:
|
|
3340
|
+
* TODO: We should implement an interactive configuration wizard that would:
|
|
3341
|
+
* 1. Detect which LLM providers are available in the environment
|
|
3342
|
+
* 2. Guide users through required configuration settings for each provider
|
|
3343
|
+
* 3. Allow testing connections before completing setup
|
|
3344
|
+
* 4. Generate appropriate configuration code for application integration
|
|
3186
3345
|
* TODO: [🧠][🍛] Which name is better `createLlmToolsFromConfig` or `createLlmToolsFromConfiguration`?
|
|
3187
3346
|
* TODO: [🧠] Is there some meaningfull way how to test this util
|
|
3188
3347
|
* TODO: This should be maybe not under `_common` but under `utils`
|
|
@@ -3190,11 +3349,14 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
3190
3349
|
*/
|
|
3191
3350
|
|
|
3192
3351
|
/**
|
|
3193
|
-
*
|
|
3352
|
+
* Automatically configures LLM tools from environment variables in Node.js
|
|
3353
|
+
*
|
|
3354
|
+
* This utility function detects available LLM providers based on environment variables
|
|
3355
|
+
* and creates properly configured LLM execution tools for each detected provider.
|
|
3194
3356
|
*
|
|
3195
3357
|
* Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
|
|
3196
3358
|
*
|
|
3197
|
-
*
|
|
3359
|
+
* Supports environment variables from .env files when dotenv is configured
|
|
3198
3360
|
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
3199
3361
|
*
|
|
3200
3362
|
* It looks for environment variables:
|
|
@@ -3202,7 +3364,8 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
3202
3364
|
* - `process.env.ANTHROPIC_CLAUDE_API_KEY`
|
|
3203
3365
|
* - ...
|
|
3204
3366
|
*
|
|
3205
|
-
* @
|
|
3367
|
+
* @param options Configuration options for the LLM tools
|
|
3368
|
+
* @returns A unified interface containing all detected and configured LLM tools
|
|
3206
3369
|
* @public exported from `@promptbook/node`
|
|
3207
3370
|
*/
|
|
3208
3371
|
async function $provideLlmToolsFromEnv(options = {}) {
|
|
@@ -3228,7 +3391,16 @@ async function $provideLlmToolsFromEnv(options = {}) {
|
|
|
3228
3391
|
return createLlmToolsFromConfiguration(configuration, options);
|
|
3229
3392
|
}
|
|
3230
3393
|
/**
|
|
3231
|
-
* TODO:
|
|
3394
|
+
* TODO: The architecture for LLM tools configuration consists of three key functions:
|
|
3395
|
+
* 1. `$provideLlmToolsFromEnv` - High-level function that detects available providers from env vars and returns ready-to-use LLM tools
|
|
3396
|
+
* 2. `$provideLlmToolsConfigurationFromEnv` - Middle layer that extracts configuration objects from environment variables
|
|
3397
|
+
* 3. `createLlmToolsFromConfiguration` - Low-level function that instantiates LLM tools from explicit configuration
|
|
3398
|
+
*
|
|
3399
|
+
* This layered approach allows flexibility in how tools are configured:
|
|
3400
|
+
* - Use $provideLlmToolsFromEnv for automatic detection and setup in Node.js environments
|
|
3401
|
+
* - Use $provideLlmToolsConfigurationFromEnv to extract config objects for modification before instantiation
|
|
3402
|
+
* - Use createLlmToolsFromConfiguration for explicit control over tool configurations
|
|
3403
|
+
*
|
|
3232
3404
|
* TODO: [🧠][🍛] Which name is better `$provideLlmToolsFromEnv` or `$provideLlmToolsFromEnvironment`?
|
|
3233
3405
|
* TODO: [🧠] Is there some meaningfull way how to test this util
|
|
3234
3406
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
@@ -3396,15 +3568,19 @@ async function $provideLlmToolsForCli(options) {
|
|
|
3396
3568
|
type: 'text',
|
|
3397
3569
|
name: 'username',
|
|
3398
3570
|
message: 'Enter your email:',
|
|
3399
|
-
validate
|
|
3571
|
+
validate(value) {
|
|
3572
|
+
return isValidEmail(value) ? true : 'Valid email is required';
|
|
3573
|
+
},
|
|
3400
3574
|
},
|
|
3401
3575
|
{
|
|
3402
3576
|
type: 'password',
|
|
3403
3577
|
name: 'password',
|
|
3404
3578
|
message: 'Enter your password:',
|
|
3405
|
-
validate
|
|
3406
|
-
|
|
3407
|
-
|
|
3579
|
+
validate(value) {
|
|
3580
|
+
return value.length /* <- TODO: [🧠] Better password validation */ > 0
|
|
3581
|
+
? true
|
|
3582
|
+
: 'Password is required';
|
|
3583
|
+
},
|
|
3408
3584
|
},
|
|
3409
3585
|
]);
|
|
3410
3586
|
const loginUrl = `${remoteServerUrl}/login`;
|
|
@@ -3420,7 +3596,7 @@ async function $provideLlmToolsForCli(options) {
|
|
|
3420
3596
|
password,
|
|
3421
3597
|
}),
|
|
3422
3598
|
});
|
|
3423
|
-
const { isSuccess, message, error, identification } = (await response.
|
|
3599
|
+
const { isSuccess, message, error, identification } = jsonParse(await response.text());
|
|
3424
3600
|
if (message) {
|
|
3425
3601
|
if (isSuccess) {
|
|
3426
3602
|
console.log(colors.green(message));
|
|
@@ -3641,7 +3817,8 @@ function $execCommand(options) {
|
|
|
3641
3817
|
*/
|
|
3642
3818
|
|
|
3643
3819
|
/**
|
|
3644
|
-
*
|
|
3820
|
+
* Attempts to locate the specified application on a Linux system using the 'which' command.
|
|
3821
|
+
* Returns the path to the executable if found, or null otherwise.
|
|
3645
3822
|
*
|
|
3646
3823
|
* @private within the repository
|
|
3647
3824
|
*/
|
|
@@ -3684,7 +3861,8 @@ async function isExecutable(path, fs) {
|
|
|
3684
3861
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
3685
3862
|
const userhome = require('userhome');
|
|
3686
3863
|
/**
|
|
3687
|
-
*
|
|
3864
|
+
* Attempts to locate the specified application on a macOS system by checking standard application paths and using mdfind.
|
|
3865
|
+
* Returns the path to the executable if found, or null otherwise.
|
|
3688
3866
|
*
|
|
3689
3867
|
* @private within the repository
|
|
3690
3868
|
*/
|
|
@@ -3716,7 +3894,8 @@ async function locateAppOnMacOs({ macOsName, }) {
|
|
|
3716
3894
|
*/
|
|
3717
3895
|
|
|
3718
3896
|
/**
|
|
3719
|
-
*
|
|
3897
|
+
* Attempts to locate the specified application on a Windows system by searching common installation directories.
|
|
3898
|
+
* Returns the path to the executable if found, or null otherwise.
|
|
3720
3899
|
*
|
|
3721
3900
|
* @private within the repository
|
|
3722
3901
|
*/
|
|
@@ -3787,7 +3966,8 @@ function locateApp(options) {
|
|
|
3787
3966
|
*/
|
|
3788
3967
|
|
|
3789
3968
|
/**
|
|
3790
|
-
*
|
|
3969
|
+
* Locates the LibreOffice executable on the current system by searching platform-specific paths.
|
|
3970
|
+
* Returns the path to the executable if found, or null otherwise.
|
|
3791
3971
|
*
|
|
3792
3972
|
* @private within the repository
|
|
3793
3973
|
*/
|
|
@@ -3805,7 +3985,8 @@ function locateLibreoffice() {
|
|
|
3805
3985
|
*/
|
|
3806
3986
|
|
|
3807
3987
|
/**
|
|
3808
|
-
*
|
|
3988
|
+
* Locates the Pandoc executable on the current system by searching platform-specific paths.
|
|
3989
|
+
* Returns the path to the executable if found, or null otherwise.
|
|
3809
3990
|
*
|
|
3810
3991
|
* @private within the repository
|
|
3811
3992
|
*/
|
|
@@ -3823,7 +4004,7 @@ function locatePandoc() {
|
|
|
3823
4004
|
*/
|
|
3824
4005
|
|
|
3825
4006
|
/**
|
|
3826
|
-
*
|
|
4007
|
+
* Provides paths to required executables (i.e. as Pandoc and LibreOffice) for Node.js environments.
|
|
3827
4008
|
*
|
|
3828
4009
|
* @public exported from `@promptbook/node`
|
|
3829
4010
|
*/
|
|
@@ -3843,10 +4024,11 @@ async function $provideExecutablesForNode(options) {
|
|
|
3843
4024
|
*/
|
|
3844
4025
|
|
|
3845
4026
|
/**
|
|
3846
|
-
*
|
|
4027
|
+
* Registry for all available scrapers in the system.
|
|
4028
|
+
* Central point for registering and accessing different types of content scrapers.
|
|
3847
4029
|
*
|
|
3848
4030
|
* Note: `$` is used to indicate that this interacts with the global scope
|
|
3849
|
-
* @singleton Only one instance of each register is created per build, but
|
|
4031
|
+
* @singleton Only one instance of each register is created per build, but there can be more than one in different build modules
|
|
3850
4032
|
* @public exported from `@promptbook/core`
|
|
3851
4033
|
*/
|
|
3852
4034
|
const $scrapersRegister = new $Register('scraper_constructors');
|
|
@@ -3855,11 +4037,9 @@ const $scrapersRegister = new $Register('scraper_constructors');
|
|
|
3855
4037
|
*/
|
|
3856
4038
|
|
|
3857
4039
|
/**
|
|
3858
|
-
*
|
|
3859
|
-
*
|
|
3860
|
-
*
|
|
3861
|
-
* 2) @@@
|
|
3862
|
-
*
|
|
4040
|
+
* Provides a collection of scrapers optimized for Node.js environment.
|
|
4041
|
+
* 1) `provideScrapersForNode` use as default
|
|
4042
|
+
* 2) `provideScrapersForBrowser` use in limited browser environment *
|
|
3863
4043
|
* @public exported from `@promptbook/node`
|
|
3864
4044
|
*/
|
|
3865
4045
|
async function $provideScrapersForNode(tools, options) {
|
|
@@ -3884,10 +4064,10 @@ async function $provideScrapersForNode(tools, options) {
|
|
|
3884
4064
|
*/
|
|
3885
4065
|
|
|
3886
4066
|
/**
|
|
3887
|
-
*
|
|
4067
|
+
* Global registry for storing metadata about all available scrapers and converters.
|
|
3888
4068
|
*
|
|
3889
|
-
* Note: `$` is used to indicate that this interacts with the global scope
|
|
3890
|
-
* @singleton Only one instance of each register is created per build, but
|
|
4069
|
+
* Note: `$` is used to indicate that this interacts with the global scope.
|
|
4070
|
+
* @singleton Only one instance of each register is created per build, but there can be more in different contexts (e.g., tests).
|
|
3891
4071
|
* @public exported from `@promptbook/core`
|
|
3892
4072
|
*/
|
|
3893
4073
|
const $scrapersMetadataRegister = new $Register('scrapers_metadata');
|
|
@@ -4451,7 +4631,7 @@ async function loadArchive(filePath, fs) {
|
|
|
4451
4631
|
if (!indexFile) {
|
|
4452
4632
|
throw new UnexpectedError(`Archive does not contain 'index.book.json' file`);
|
|
4453
4633
|
}
|
|
4454
|
-
const collectionJson =
|
|
4634
|
+
const collectionJson = jsonParse(await indexFile.async('text'));
|
|
4455
4635
|
for (const pipeline of collectionJson) {
|
|
4456
4636
|
validatePipeline(pipeline);
|
|
4457
4637
|
}
|
|
@@ -4461,13 +4641,13 @@ async function loadArchive(filePath, fs) {
|
|
|
4461
4641
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
4462
4642
|
*/
|
|
4463
4643
|
|
|
4464
|
-
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"}];
|
|
4644
|
+
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"}];
|
|
4465
4645
|
|
|
4466
4646
|
/**
|
|
4467
4647
|
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
4468
4648
|
*
|
|
4469
4649
|
* @param value The string to check
|
|
4470
|
-
* @returns
|
|
4650
|
+
* @returns `true` if the string is a valid JSON string, false otherwise
|
|
4471
4651
|
*
|
|
4472
4652
|
* @public exported from `@promptbook/utils`
|
|
4473
4653
|
*/
|
|
@@ -4697,23 +4877,6 @@ function taskParameterJsonToString(taskParameterJson) {
|
|
|
4697
4877
|
* TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
|
|
4698
4878
|
*/
|
|
4699
4879
|
|
|
4700
|
-
/**
|
|
4701
|
-
* Parses the task and returns the list of all parameter names
|
|
4702
|
-
*
|
|
4703
|
-
* @param template the string template with parameters in {curly} braces
|
|
4704
|
-
* @returns the list of parameter names
|
|
4705
|
-
* @public exported from `@promptbook/utils`
|
|
4706
|
-
*/
|
|
4707
|
-
function extractParameterNames(template) {
|
|
4708
|
-
const matches = template.matchAll(/{\w+}/g);
|
|
4709
|
-
const parameterNames = new Set();
|
|
4710
|
-
for (const match of matches) {
|
|
4711
|
-
const parameterName = match[0].slice(1, -1);
|
|
4712
|
-
parameterNames.add(parameterName);
|
|
4713
|
-
}
|
|
4714
|
-
return parameterNames;
|
|
4715
|
-
}
|
|
4716
|
-
|
|
4717
4880
|
/**
|
|
4718
4881
|
* Unprepare just strips the preparation data of the pipeline
|
|
4719
4882
|
*
|
|
@@ -4722,7 +4885,7 @@ function extractParameterNames(template) {
|
|
|
4722
4885
|
*/
|
|
4723
4886
|
function unpreparePipeline(pipeline) {
|
|
4724
4887
|
let { personas, knowledgeSources, tasks } = pipeline;
|
|
4725
|
-
personas = personas.map((persona) => ({ ...persona,
|
|
4888
|
+
personas = personas.map((persona) => ({ ...persona, modelsRequirements: undefined, preparationIds: undefined }));
|
|
4726
4889
|
knowledgeSources = knowledgeSources.map((knowledgeSource) => ({ ...knowledgeSource, preparationIds: undefined }));
|
|
4727
4890
|
tasks = tasks.map((task) => {
|
|
4728
4891
|
let { dependentParameterNames } = task;
|
|
@@ -4763,7 +4926,7 @@ class SimplePipelineCollection {
|
|
|
4763
4926
|
/**
|
|
4764
4927
|
* Constructs a pipeline collection from pipelines
|
|
4765
4928
|
*
|
|
4766
|
-
* @param pipelines
|
|
4929
|
+
* @param pipelines Array of pipeline JSON objects to include in the collection
|
|
4767
4930
|
*
|
|
4768
4931
|
* Note: During the construction logic of all pipelines are validated
|
|
4769
4932
|
* Note: It is not recommended to use this constructor directly, use `createCollectionFromJson` *(or other variant)* instead
|
|
@@ -4875,15 +5038,21 @@ function createCollectionFromJson(...promptbooks) {
|
|
|
4875
5038
|
* @public exported from `@promptbook/core`
|
|
4876
5039
|
*/
|
|
4877
5040
|
function isPipelinePrepared(pipeline) {
|
|
4878
|
-
// Note: Ignoring `pipeline.preparations`
|
|
4879
|
-
// Note: Ignoring `pipeline.knowledgePieces`
|
|
5041
|
+
// Note: Ignoring `pipeline.preparations`
|
|
5042
|
+
// Note: Ignoring `pipeline.knowledgePieces`
|
|
4880
5043
|
if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
|
|
5044
|
+
// TODO: !!! Comment this out
|
|
5045
|
+
console.log('Pipeline is not prepared because title is undefined or empty', pipeline);
|
|
4881
5046
|
return false;
|
|
4882
5047
|
}
|
|
4883
|
-
if (!pipeline.personas.every((persona) => persona.
|
|
5048
|
+
if (!pipeline.personas.every((persona) => persona.modelsRequirements !== undefined)) {
|
|
5049
|
+
// TODO: !!! Comment this out
|
|
5050
|
+
console.log('Pipeline is not prepared because personas are not prepared', pipeline.personas);
|
|
4884
5051
|
return false;
|
|
4885
5052
|
}
|
|
4886
5053
|
if (!pipeline.knowledgeSources.every((knowledgeSource) => knowledgeSource.preparationIds !== undefined)) {
|
|
5054
|
+
// TODO: !!! Comment this out
|
|
5055
|
+
console.log('Pipeline is not prepared because knowledge sources are not prepared', pipeline.knowledgeSources);
|
|
4887
5056
|
return false;
|
|
4888
5057
|
}
|
|
4889
5058
|
/*
|
|
@@ -4904,6 +5073,35 @@ function isPipelinePrepared(pipeline) {
|
|
|
4904
5073
|
* - [♨] Are tasks prepared
|
|
4905
5074
|
*/
|
|
4906
5075
|
|
|
5076
|
+
/**
|
|
5077
|
+
* Serializes an error into a [🚉] JSON-serializable object
|
|
5078
|
+
*
|
|
5079
|
+
* @public exported from `@promptbook/utils`
|
|
5080
|
+
*/
|
|
5081
|
+
function serializeError(error) {
|
|
5082
|
+
const { name, message, stack } = error;
|
|
5083
|
+
const { id } = error;
|
|
5084
|
+
if (!Object.keys(ALL_ERRORS).includes(name)) {
|
|
5085
|
+
console.error(spaceTrim((block) => `
|
|
5086
|
+
|
|
5087
|
+
Cannot serialize error with name "${name}"
|
|
5088
|
+
|
|
5089
|
+
Authors of Promptbook probably forgot to add this error into the list of errors:
|
|
5090
|
+
https://github.com/webgptorg/promptbook/blob/main/src/errors/0-index.ts
|
|
5091
|
+
|
|
5092
|
+
|
|
5093
|
+
${block(stack || message)}
|
|
5094
|
+
|
|
5095
|
+
`));
|
|
5096
|
+
}
|
|
5097
|
+
return {
|
|
5098
|
+
name: name,
|
|
5099
|
+
message,
|
|
5100
|
+
stack,
|
|
5101
|
+
id, // Include id in the serialized object
|
|
5102
|
+
};
|
|
5103
|
+
}
|
|
5104
|
+
|
|
4907
5105
|
/**
|
|
4908
5106
|
* Recursively converts JSON strings to JSON objects
|
|
4909
5107
|
|
|
@@ -4922,7 +5120,7 @@ function jsonStringsToJsons(object) {
|
|
|
4922
5120
|
const newObject = { ...object };
|
|
4923
5121
|
for (const [key, value] of Object.entries(object)) {
|
|
4924
5122
|
if (typeof value === 'string' && isValidJsonString(value)) {
|
|
4925
|
-
newObject[key] =
|
|
5123
|
+
newObject[key] = jsonParse(value);
|
|
4926
5124
|
}
|
|
4927
5125
|
else {
|
|
4928
5126
|
newObject[key] = jsonStringsToJsons(value);
|
|
@@ -5073,35 +5271,6 @@ function createTask(options) {
|
|
|
5073
5271
|
* TODO: [🐚] Split into more files and make `PrepareTask` & `RemoteTask` + split the function
|
|
5074
5272
|
*/
|
|
5075
5273
|
|
|
5076
|
-
/**
|
|
5077
|
-
* Serializes an error into a [🚉] JSON-serializable object
|
|
5078
|
-
*
|
|
5079
|
-
* @public exported from `@promptbook/utils`
|
|
5080
|
-
*/
|
|
5081
|
-
function serializeError(error) {
|
|
5082
|
-
const { name, message, stack } = error;
|
|
5083
|
-
const { id } = error;
|
|
5084
|
-
if (!Object.keys(ALL_ERRORS).includes(name)) {
|
|
5085
|
-
console.error(spaceTrim((block) => `
|
|
5086
|
-
|
|
5087
|
-
Cannot serialize error with name "${name}"
|
|
5088
|
-
|
|
5089
|
-
Authors of Promptbook probably forgot to add this error into the list of errors:
|
|
5090
|
-
https://github.com/webgptorg/promptbook/blob/main/src/errors/0-index.ts
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
${block(stack || message)}
|
|
5094
|
-
|
|
5095
|
-
`));
|
|
5096
|
-
}
|
|
5097
|
-
return {
|
|
5098
|
-
name: name,
|
|
5099
|
-
message,
|
|
5100
|
-
stack,
|
|
5101
|
-
id, // Include id in the serialized object
|
|
5102
|
-
};
|
|
5103
|
-
}
|
|
5104
|
-
|
|
5105
5274
|
/**
|
|
5106
5275
|
* Format either small or big number
|
|
5107
5276
|
*
|
|
@@ -5344,7 +5513,7 @@ function union(...sets) {
|
|
|
5344
5513
|
}
|
|
5345
5514
|
|
|
5346
5515
|
/**
|
|
5347
|
-
*
|
|
5516
|
+
* Contains configuration options for parsing and generating CSV files, such as delimiters and quoting rules.
|
|
5348
5517
|
*
|
|
5349
5518
|
* @public exported from `@promptbook/core`
|
|
5350
5519
|
*/
|
|
@@ -5353,11 +5522,29 @@ const MANDATORY_CSV_SETTINGS = Object.freeze({
|
|
|
5353
5522
|
// encoding: 'utf-8',
|
|
5354
5523
|
});
|
|
5355
5524
|
|
|
5525
|
+
/**
|
|
5526
|
+
* Converts a CSV string into an object
|
|
5527
|
+
*
|
|
5528
|
+
* Note: This is wrapper around `papaparse.parse()` with better autohealing
|
|
5529
|
+
*
|
|
5530
|
+
* @private - for now until `@promptbook/csv` is released
|
|
5531
|
+
*/
|
|
5532
|
+
function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO: Make CSV Schemas */) {
|
|
5533
|
+
settings = { ...settings, ...MANDATORY_CSV_SETTINGS };
|
|
5534
|
+
// Note: Autoheal invalid '\n' characters
|
|
5535
|
+
if (settings.newline && !settings.newline.includes('\r') && value.includes('\r')) {
|
|
5536
|
+
console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
|
|
5537
|
+
value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
5538
|
+
}
|
|
5539
|
+
const csv = parse(value, settings);
|
|
5540
|
+
return csv;
|
|
5541
|
+
}
|
|
5542
|
+
|
|
5356
5543
|
/**
|
|
5357
5544
|
* Function to check if a string is valid CSV
|
|
5358
5545
|
*
|
|
5359
5546
|
* @param value The string to check
|
|
5360
|
-
* @returns
|
|
5547
|
+
* @returns `true` if the string is a valid CSV string, false otherwise
|
|
5361
5548
|
*
|
|
5362
5549
|
* @public exported from `@promptbook/utils`
|
|
5363
5550
|
*/
|
|
@@ -5381,7 +5568,7 @@ function isValidCsvString(value) {
|
|
|
5381
5568
|
* @public exported from `@promptbook/core`
|
|
5382
5569
|
* <- TODO: [🏢] Export from package `@promptbook/csv`
|
|
5383
5570
|
*/
|
|
5384
|
-
const
|
|
5571
|
+
const CsvFormatParser = {
|
|
5385
5572
|
formatName: 'CSV',
|
|
5386
5573
|
aliases: ['SPREADSHEET', 'TABLE'],
|
|
5387
5574
|
isValid(value, settings, schema) {
|
|
@@ -5393,12 +5580,12 @@ const CsvFormatDefinition = {
|
|
|
5393
5580
|
heal(value, settings, schema) {
|
|
5394
5581
|
throw new Error('Not implemented');
|
|
5395
5582
|
},
|
|
5396
|
-
|
|
5583
|
+
subvalueParsers: [
|
|
5397
5584
|
{
|
|
5398
5585
|
subvalueName: 'ROW',
|
|
5399
|
-
async mapValues(
|
|
5400
|
-
|
|
5401
|
-
const csv =
|
|
5586
|
+
async mapValues(options) {
|
|
5587
|
+
const { value, outputParameterName, settings, mapCallback, onProgress } = options;
|
|
5588
|
+
const csv = csvParse(value, settings);
|
|
5402
5589
|
if (csv.errors.length !== 0) {
|
|
5403
5590
|
throw new CsvFormatError(spaceTrim((block) => `
|
|
5404
5591
|
CSV parsing error
|
|
@@ -5413,23 +5600,37 @@ const CsvFormatDefinition = {
|
|
|
5413
5600
|
${block(value)}
|
|
5414
5601
|
`));
|
|
5415
5602
|
}
|
|
5416
|
-
const mappedData =
|
|
5603
|
+
const mappedData = [];
|
|
5604
|
+
const length = csv.data.length;
|
|
5605
|
+
for (let index = 0; index < length; index++) {
|
|
5606
|
+
const row = csv.data[index];
|
|
5417
5607
|
if (row[outputParameterName]) {
|
|
5418
5608
|
throw new CsvFormatError(`Can not overwrite existing column "${outputParameterName}" in CSV row`);
|
|
5419
5609
|
}
|
|
5420
|
-
|
|
5610
|
+
const mappedRow = {
|
|
5421
5611
|
...row,
|
|
5422
|
-
[outputParameterName]: await mapCallback(row, index),
|
|
5612
|
+
[outputParameterName]: await mapCallback(row, index, length),
|
|
5423
5613
|
};
|
|
5424
|
-
|
|
5614
|
+
mappedData.push(mappedRow);
|
|
5615
|
+
if (onProgress) {
|
|
5616
|
+
// Note: Report the CSV with all rows mapped so far
|
|
5617
|
+
/*
|
|
5618
|
+
// TODO: [🛕] Report progress with all the rows including the pending ones
|
|
5619
|
+
const progressData = mappedData.map((row, i) =>
|
|
5620
|
+
i > index ? { ...row, [outputParameterName]: PENDING_VALUE_PLACEHOLDER } : row,
|
|
5621
|
+
);
|
|
5622
|
+
*/
|
|
5623
|
+
await onProgress(unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
|
|
5624
|
+
}
|
|
5625
|
+
}
|
|
5425
5626
|
return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
5426
5627
|
},
|
|
5427
5628
|
},
|
|
5428
5629
|
{
|
|
5429
5630
|
subvalueName: 'CELL',
|
|
5430
|
-
async mapValues(
|
|
5431
|
-
|
|
5432
|
-
const csv =
|
|
5631
|
+
async mapValues(options) {
|
|
5632
|
+
const { value, settings, mapCallback, onProgress } = options;
|
|
5633
|
+
const csv = csvParse(value, settings);
|
|
5433
5634
|
if (csv.errors.length !== 0) {
|
|
5434
5635
|
throw new CsvFormatError(spaceTrim((block) => `
|
|
5435
5636
|
CSV parsing error
|
|
@@ -5445,9 +5646,9 @@ const CsvFormatDefinition = {
|
|
|
5445
5646
|
`));
|
|
5446
5647
|
}
|
|
5447
5648
|
const mappedData = await Promise.all(csv.data.map(async (row, rowIndex) => {
|
|
5448
|
-
return /* not await */ Promise.all(Object.entries(row).map(async ([key, value], columnIndex) => {
|
|
5649
|
+
return /* not await */ Promise.all(Object.entries(row).map(async ([key, value], columnIndex, array) => {
|
|
5449
5650
|
const index = rowIndex * Object.keys(row).length + columnIndex;
|
|
5450
|
-
return /* not await */ mapCallback({ [key]: value }, index);
|
|
5651
|
+
return /* not await */ mapCallback({ [key]: value }, index, array.length);
|
|
5451
5652
|
}));
|
|
5452
5653
|
}));
|
|
5453
5654
|
return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
@@ -5456,10 +5657,10 @@ const CsvFormatDefinition = {
|
|
|
5456
5657
|
],
|
|
5457
5658
|
};
|
|
5458
5659
|
/**
|
|
5459
|
-
* TODO: [🍓] In `
|
|
5460
|
-
* TODO: [🍓] In `
|
|
5461
|
-
* TODO: [🍓] In `
|
|
5462
|
-
* TODO: [🍓] In `
|
|
5660
|
+
* TODO: [🍓] In `CsvFormatParser` implement simple `isValid`
|
|
5661
|
+
* TODO: [🍓] In `CsvFormatParser` implement partial `canBeValid`
|
|
5662
|
+
* TODO: [🍓] In `CsvFormatParser` implement `heal
|
|
5663
|
+
* TODO: [🍓] In `CsvFormatParser` implement `subvalueParsers`
|
|
5463
5664
|
* TODO: [🏢] Allow to expect something inside CSV objects and other formats
|
|
5464
5665
|
*/
|
|
5465
5666
|
|
|
@@ -5468,7 +5669,7 @@ const CsvFormatDefinition = {
|
|
|
5468
5669
|
*
|
|
5469
5670
|
* @private still in development [🏢]
|
|
5470
5671
|
*/
|
|
5471
|
-
const
|
|
5672
|
+
const JsonFormatParser = {
|
|
5472
5673
|
formatName: 'JSON',
|
|
5473
5674
|
mimeType: 'application/json',
|
|
5474
5675
|
isValid(value, settings, schema) {
|
|
@@ -5480,28 +5681,28 @@ const JsonFormatDefinition = {
|
|
|
5480
5681
|
heal(value, settings, schema) {
|
|
5481
5682
|
throw new Error('Not implemented');
|
|
5482
5683
|
},
|
|
5483
|
-
|
|
5684
|
+
subvalueParsers: [],
|
|
5484
5685
|
};
|
|
5485
5686
|
/**
|
|
5486
5687
|
* TODO: [🧠] Maybe propper instance of object
|
|
5487
5688
|
* TODO: [0] Make string_serialized_json
|
|
5488
5689
|
* TODO: [1] Make type for JSON Settings and Schema
|
|
5489
5690
|
* TODO: [🧠] What to use for validating JSONs - JSON Schema, ZoD, typescript types/interfaces,...?
|
|
5490
|
-
* TODO: [🍓] In `
|
|
5491
|
-
* TODO: [🍓] In `
|
|
5492
|
-
* TODO: [🍓] In `
|
|
5493
|
-
* TODO: [🍓] In `
|
|
5691
|
+
* TODO: [🍓] In `JsonFormatParser` implement simple `isValid`
|
|
5692
|
+
* TODO: [🍓] In `JsonFormatParser` implement partial `canBeValid`
|
|
5693
|
+
* TODO: [🍓] In `JsonFormatParser` implement `heal
|
|
5694
|
+
* TODO: [🍓] In `JsonFormatParser` implement `subvalueParsers`
|
|
5494
5695
|
* TODO: [🏢] Allow to expect something inside JSON objects and other formats
|
|
5495
5696
|
*/
|
|
5496
5697
|
|
|
5497
5698
|
/**
|
|
5498
5699
|
* Definition for any text - this will be always valid
|
|
5499
5700
|
*
|
|
5500
|
-
* Note: This is not useful for validation, but for splitting and mapping with `
|
|
5701
|
+
* Note: This is not useful for validation, but for splitting and mapping with `subvalueParsers`
|
|
5501
5702
|
*
|
|
5502
5703
|
* @public exported from `@promptbook/core`
|
|
5503
5704
|
*/
|
|
5504
|
-
const
|
|
5705
|
+
const TextFormatParser = {
|
|
5505
5706
|
formatName: 'TEXT',
|
|
5506
5707
|
isValid(value) {
|
|
5507
5708
|
return typeof value === 'string';
|
|
@@ -5510,19 +5711,20 @@ const TextFormatDefinition = {
|
|
|
5510
5711
|
return typeof partialValue === 'string';
|
|
5511
5712
|
},
|
|
5512
5713
|
heal() {
|
|
5513
|
-
throw new UnexpectedError('It does not make sense to call `
|
|
5714
|
+
throw new UnexpectedError('It does not make sense to call `TextFormatParser.heal`');
|
|
5514
5715
|
},
|
|
5515
|
-
|
|
5716
|
+
subvalueParsers: [
|
|
5516
5717
|
{
|
|
5517
5718
|
subvalueName: 'LINE',
|
|
5518
|
-
async mapValues(
|
|
5719
|
+
async mapValues(options) {
|
|
5720
|
+
const { value, mapCallback, onProgress } = options;
|
|
5519
5721
|
const lines = value.split('\n');
|
|
5520
|
-
const mappedLines = await Promise.all(lines.map((lineContent, lineNumber) =>
|
|
5722
|
+
const mappedLines = await Promise.all(lines.map((lineContent, lineNumber, array) =>
|
|
5521
5723
|
// TODO: [🧠] Maybe option to skip empty line
|
|
5522
5724
|
/* not await */ mapCallback({
|
|
5523
5725
|
lineContent,
|
|
5524
5726
|
// TODO: [🧠] Maybe also put here `lineNumber`
|
|
5525
|
-
}, lineNumber)));
|
|
5727
|
+
}, lineNumber, array.length)));
|
|
5526
5728
|
return mappedLines.join('\n');
|
|
5527
5729
|
},
|
|
5528
5730
|
},
|
|
@@ -5532,10 +5734,10 @@ const TextFormatDefinition = {
|
|
|
5532
5734
|
/**
|
|
5533
5735
|
* TODO: [1] Make type for XML Text and Schema
|
|
5534
5736
|
* TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages available as subvalues
|
|
5535
|
-
* TODO: [🍓] In `
|
|
5536
|
-
* TODO: [🍓] In `
|
|
5537
|
-
* TODO: [🍓] In `
|
|
5538
|
-
* TODO: [🍓] In `
|
|
5737
|
+
* TODO: [🍓] In `TextFormatParser` implement simple `isValid`
|
|
5738
|
+
* TODO: [🍓] In `TextFormatParser` implement partial `canBeValid`
|
|
5739
|
+
* TODO: [🍓] In `TextFormatParser` implement `heal
|
|
5740
|
+
* TODO: [🍓] In `TextFormatParser` implement `subvalueParsers`
|
|
5539
5741
|
* TODO: [🏢] Allow to expect something inside each item of list and other formats
|
|
5540
5742
|
*/
|
|
5541
5743
|
|
|
@@ -5543,7 +5745,7 @@ const TextFormatDefinition = {
|
|
|
5543
5745
|
* Function to check if a string is valid XML
|
|
5544
5746
|
*
|
|
5545
5747
|
* @param value
|
|
5546
|
-
* @returns
|
|
5748
|
+
* @returns `true` if the string is a valid XML string, false otherwise
|
|
5547
5749
|
*
|
|
5548
5750
|
* @public exported from `@promptbook/utils`
|
|
5549
5751
|
*/
|
|
@@ -5568,7 +5770,7 @@ function isValidXmlString(value) {
|
|
|
5568
5770
|
*
|
|
5569
5771
|
* @private still in development [🏢]
|
|
5570
5772
|
*/
|
|
5571
|
-
const
|
|
5773
|
+
const XmlFormatParser = {
|
|
5572
5774
|
formatName: 'XML',
|
|
5573
5775
|
mimeType: 'application/xml',
|
|
5574
5776
|
isValid(value, settings, schema) {
|
|
@@ -5580,17 +5782,17 @@ const XmlFormatDefinition = {
|
|
|
5580
5782
|
heal(value, settings, schema) {
|
|
5581
5783
|
throw new Error('Not implemented');
|
|
5582
5784
|
},
|
|
5583
|
-
|
|
5785
|
+
subvalueParsers: [],
|
|
5584
5786
|
};
|
|
5585
5787
|
/**
|
|
5586
5788
|
* TODO: [🧠] Maybe propper instance of object
|
|
5587
5789
|
* TODO: [0] Make string_serialized_xml
|
|
5588
5790
|
* TODO: [1] Make type for XML Settings and Schema
|
|
5589
5791
|
* TODO: [🧠] What to use for validating XMLs - XSD,...
|
|
5590
|
-
* TODO: [🍓] In `
|
|
5591
|
-
* TODO: [🍓] In `
|
|
5592
|
-
* TODO: [🍓] In `
|
|
5593
|
-
* TODO: [🍓] In `
|
|
5792
|
+
* TODO: [🍓] In `XmlFormatParser` implement simple `isValid`
|
|
5793
|
+
* TODO: [🍓] In `XmlFormatParser` implement partial `canBeValid`
|
|
5794
|
+
* TODO: [🍓] In `XmlFormatParser` implement `heal
|
|
5795
|
+
* TODO: [🍓] In `XmlFormatParser` implement `subvalueParsers`
|
|
5594
5796
|
* TODO: [🏢] Allow to expect something inside XML and other formats
|
|
5595
5797
|
*/
|
|
5596
5798
|
|
|
@@ -5599,24 +5801,19 @@ const XmlFormatDefinition = {
|
|
|
5599
5801
|
*
|
|
5600
5802
|
* @private internal index of `...` <- TODO [🏢]
|
|
5601
5803
|
*/
|
|
5602
|
-
const FORMAT_DEFINITIONS = [
|
|
5603
|
-
JsonFormatDefinition,
|
|
5604
|
-
XmlFormatDefinition,
|
|
5605
|
-
TextFormatDefinition,
|
|
5606
|
-
CsvFormatDefinition,
|
|
5607
|
-
];
|
|
5804
|
+
const FORMAT_DEFINITIONS = [JsonFormatParser, XmlFormatParser, TextFormatParser, CsvFormatParser];
|
|
5608
5805
|
/**
|
|
5609
5806
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
5610
5807
|
*/
|
|
5611
5808
|
|
|
5612
5809
|
/**
|
|
5613
|
-
* Maps available parameters to expected parameters
|
|
5810
|
+
* Maps available parameters to expected parameters for a pipeline task.
|
|
5614
5811
|
*
|
|
5615
5812
|
* The strategy is:
|
|
5616
|
-
* 1)
|
|
5617
|
-
* 2)
|
|
5813
|
+
* 1) First, match parameters by name where both available and expected.
|
|
5814
|
+
* 2) Then, if there are unmatched expected and available parameters, map them by order.
|
|
5618
5815
|
*
|
|
5619
|
-
* @throws {PipelineExecutionError}
|
|
5816
|
+
* @throws {PipelineExecutionError} If the number of unmatched expected and available parameters does not match, or mapping is ambiguous.
|
|
5620
5817
|
* @private within the repository used in `createPipelineExecutor`
|
|
5621
5818
|
*/
|
|
5622
5819
|
function mapAvailableToExpectedParameters(options) {
|
|
@@ -5639,7 +5836,7 @@ function mapAvailableToExpectedParameters(options) {
|
|
|
5639
5836
|
else if (!availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) ;
|
|
5640
5837
|
}
|
|
5641
5838
|
if (expectedParameterNames.size === 0) {
|
|
5642
|
-
// Note: [👨👨👧] Now we can freeze `mappedParameters` to prevent
|
|
5839
|
+
// Note: [👨👨👧] Now we can freeze `mappedParameters` to prevent accidental modifications after mapping
|
|
5643
5840
|
Object.freeze(mappedParameters);
|
|
5644
5841
|
return mappedParameters;
|
|
5645
5842
|
}
|
|
@@ -5670,7 +5867,7 @@ function mapAvailableToExpectedParameters(options) {
|
|
|
5670
5867
|
for (let i = 0; i < expectedParameterNames.size; i++) {
|
|
5671
5868
|
mappedParameters[expectedParameterNamesArray[i]] = availableParameters[availableParametersNamesArray[i]];
|
|
5672
5869
|
}
|
|
5673
|
-
// Note: [👨👨👧] Now we can freeze `mappedParameters` to prevent
|
|
5870
|
+
// Note: [👨👨👧] Now we can freeze `mappedParameters` to prevent accidental modifications after mapping
|
|
5674
5871
|
Object.freeze(mappedParameters);
|
|
5675
5872
|
return mappedParameters;
|
|
5676
5873
|
}
|
|
@@ -5774,7 +5971,7 @@ function extractJsonBlock(markdown) {
|
|
|
5774
5971
|
}
|
|
5775
5972
|
/**
|
|
5776
5973
|
* TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
|
|
5777
|
-
* TODO: [🏢] Make this logic part of `
|
|
5974
|
+
* TODO: [🏢] Make this logic part of `JsonFormatParser` or `isValidJsonString`
|
|
5778
5975
|
*/
|
|
5779
5976
|
|
|
5780
5977
|
/**
|
|
@@ -5836,10 +6033,12 @@ function templateParameters(template, parameters) {
|
|
|
5836
6033
|
throw new PipelineExecutionError('Parameter is already opened or not closed');
|
|
5837
6034
|
}
|
|
5838
6035
|
if (parameters[parameterName] === undefined) {
|
|
6036
|
+
console.log('!!! templateParameters 1', { parameterName, template, parameters });
|
|
5839
6037
|
throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
|
|
5840
6038
|
}
|
|
5841
6039
|
let parameterValue = parameters[parameterName];
|
|
5842
6040
|
if (parameterValue === undefined) {
|
|
6041
|
+
console.log('!!! templateParameters 2', { parameterName, template, parameters });
|
|
5843
6042
|
throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
|
|
5844
6043
|
}
|
|
5845
6044
|
parameterValue = valueToString(parameterValue);
|
|
@@ -5995,7 +6194,7 @@ const CountUtils = {
|
|
|
5995
6194
|
PAGES: countPages,
|
|
5996
6195
|
};
|
|
5997
6196
|
/**
|
|
5998
|
-
* TODO: [🧠][🤠] This should be probbably as part of `
|
|
6197
|
+
* TODO: [🧠][🤠] This should be probbably as part of `TextFormatParser`
|
|
5999
6198
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
6000
6199
|
*/
|
|
6001
6200
|
|
|
@@ -6023,13 +6222,17 @@ function checkExpectations(expectations, value) {
|
|
|
6023
6222
|
}
|
|
6024
6223
|
/**
|
|
6025
6224
|
* TODO: [💝] Unite object for expecting amount and format
|
|
6026
|
-
* TODO: [🧠][🤠] This should be part of `
|
|
6225
|
+
* TODO: [🧠][🤠] This should be part of `TextFormatParser`
|
|
6027
6226
|
* Note: [💝] and [🤠] are interconnected together
|
|
6028
6227
|
*/
|
|
6029
6228
|
|
|
6030
6229
|
/**
|
|
6031
|
-
*
|
|
6230
|
+
* Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
|
|
6231
|
+
* (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
|
|
6232
|
+
* Throws errors if execution fails after all attempts.
|
|
6032
6233
|
*
|
|
6234
|
+
* @param options - The options for execution, including task, parameters, pipeline, and configuration.
|
|
6235
|
+
* @returns The result string of the executed task.
|
|
6033
6236
|
* @private internal utility of `createPipelineExecutor`
|
|
6034
6237
|
*/
|
|
6035
6238
|
async function executeAttempts(options) {
|
|
@@ -6251,7 +6454,7 @@ async function executeAttempts(options) {
|
|
|
6251
6454
|
if (task.format) {
|
|
6252
6455
|
if (task.format === 'JSON') {
|
|
6253
6456
|
if (!isValidJsonString($ongoingTaskResult.$resultString || '')) {
|
|
6254
|
-
// TODO: [🏢] Do more universally via `
|
|
6457
|
+
// TODO: [🏢] Do more universally via `FormatParser`
|
|
6255
6458
|
try {
|
|
6256
6459
|
$ongoingTaskResult.$resultString = extractJsonBlock($ongoingTaskResult.$resultString || '');
|
|
6257
6460
|
}
|
|
@@ -6353,12 +6556,16 @@ async function executeAttempts(options) {
|
|
|
6353
6556
|
*/
|
|
6354
6557
|
|
|
6355
6558
|
/**
|
|
6356
|
-
*
|
|
6559
|
+
* Executes a pipeline task that requires mapping or iterating over subvalues of a parameter (such as rows in a CSV).
|
|
6560
|
+
* Handles format and subformat resolution, error handling, and progress reporting.
|
|
6561
|
+
*
|
|
6562
|
+
* @param options - Options for execution, including task details and progress callback.
|
|
6563
|
+
* @returns The result of the subvalue mapping or execution attempts.
|
|
6357
6564
|
*
|
|
6358
6565
|
* @private internal utility of `createPipelineExecutor`
|
|
6359
6566
|
*/
|
|
6360
6567
|
async function executeFormatSubvalues(options) {
|
|
6361
|
-
const { task, jokerParameterNames, parameters, priority, csvSettings, pipelineIdentification } = options;
|
|
6568
|
+
const { task, jokerParameterNames, parameters, priority, csvSettings, onProgress, pipelineIdentification } = options;
|
|
6362
6569
|
if (task.foreach === undefined) {
|
|
6363
6570
|
return /* not await */ executeAttempts(options);
|
|
6364
6571
|
}
|
|
@@ -6389,16 +6596,16 @@ async function executeFormatSubvalues(options) {
|
|
|
6389
6596
|
${block(pipelineIdentification)}
|
|
6390
6597
|
`));
|
|
6391
6598
|
}
|
|
6392
|
-
const
|
|
6393
|
-
if (
|
|
6599
|
+
const subvalueParser = formatDefinition.subvalueParsers.find((subvalueParser) => [subvalueParser.subvalueName, ...(subvalueParser.aliases || [])].includes(task.foreach.subformatName));
|
|
6600
|
+
if (subvalueParser === undefined) {
|
|
6394
6601
|
throw new UnexpectedError(
|
|
6395
6602
|
// <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
|
|
6396
6603
|
spaceTrim((block) => `
|
|
6397
6604
|
Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
|
|
6398
6605
|
|
|
6399
6606
|
Available subformat names for format "${formatDefinition.formatName}":
|
|
6400
|
-
${block(formatDefinition.
|
|
6401
|
-
.map((
|
|
6607
|
+
${block(formatDefinition.subvalueParsers
|
|
6608
|
+
.map((subvalueParser) => subvalueParser.subvalueName)
|
|
6402
6609
|
.map((subvalueName) => `- ${subvalueName}`)
|
|
6403
6610
|
.join('\n'))}
|
|
6404
6611
|
|
|
@@ -6412,53 +6619,83 @@ async function executeFormatSubvalues(options) {
|
|
|
6412
6619
|
formatSettings = csvSettings;
|
|
6413
6620
|
// <- TODO: [🤹♂️] More universal, make simmilar pattern for other formats for example \n vs \r\n in text
|
|
6414
6621
|
}
|
|
6415
|
-
const resultString = await
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6622
|
+
const resultString = await subvalueParser.mapValues({
|
|
6623
|
+
value: parameterValue,
|
|
6624
|
+
outputParameterName: task.foreach.outputSubparameterName,
|
|
6625
|
+
settings: formatSettings,
|
|
6626
|
+
onProgress(partialResultString) {
|
|
6627
|
+
return onProgress(Object.freeze({
|
|
6628
|
+
[task.resultingParameterName]: partialResultString,
|
|
6629
|
+
}));
|
|
6630
|
+
},
|
|
6631
|
+
async mapCallback(subparameters, index, length) {
|
|
6632
|
+
let mappedParameters;
|
|
6633
|
+
try {
|
|
6634
|
+
mappedParameters = mapAvailableToExpectedParameters({
|
|
6635
|
+
expectedParameters: Object.fromEntries(task.foreach.inputSubparameterNames.map((subparameterName) => [subparameterName, null])),
|
|
6636
|
+
availableParameters: subparameters,
|
|
6637
|
+
});
|
|
6428
6638
|
}
|
|
6429
|
-
|
|
6430
|
-
|
|
6639
|
+
catch (error) {
|
|
6640
|
+
if (!(error instanceof PipelineExecutionError)) {
|
|
6641
|
+
throw error;
|
|
6642
|
+
}
|
|
6643
|
+
const highLevelError = new PipelineExecutionError(spaceTrim((block) => `
|
|
6644
|
+
${error.message}
|
|
6431
6645
|
|
|
6432
|
-
|
|
6433
|
-
|
|
6646
|
+
This is error in FOREACH command when mapping ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
|
|
6647
|
+
You have probbably passed wrong data to pipeline or wrong data was generated which are processed by FOREACH command
|
|
6434
6648
|
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6649
|
+
${block(pipelineIdentification)}
|
|
6650
|
+
`));
|
|
6651
|
+
if (length > BIG_DATASET_TRESHOLD) {
|
|
6652
|
+
console.error(highLevelError);
|
|
6653
|
+
return FAILED_VALUE_PLACEHOLDER;
|
|
6654
|
+
}
|
|
6655
|
+
throw highLevelError;
|
|
6656
|
+
}
|
|
6657
|
+
const allSubparameters = {
|
|
6658
|
+
...parameters,
|
|
6659
|
+
...mappedParameters,
|
|
6660
|
+
};
|
|
6661
|
+
Object.freeze(allSubparameters);
|
|
6662
|
+
try {
|
|
6663
|
+
const subresultString = await executeAttempts({
|
|
6664
|
+
...options,
|
|
6665
|
+
priority: priority + index,
|
|
6666
|
+
parameters: allSubparameters,
|
|
6667
|
+
pipelineIdentification: spaceTrim((block) => `
|
|
6668
|
+
${block(pipelineIdentification)}
|
|
6669
|
+
Subparameter index: ${index}
|
|
6670
|
+
`),
|
|
6671
|
+
});
|
|
6672
|
+
return subresultString;
|
|
6673
|
+
}
|
|
6674
|
+
catch (error) {
|
|
6675
|
+
if (length > BIG_DATASET_TRESHOLD) {
|
|
6676
|
+
console.error(spaceTrim((block) => `
|
|
6677
|
+
${error.message}
|
|
6678
|
+
|
|
6679
|
+
This is error in FOREACH command when processing ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
|
|
6680
|
+
|
|
6681
|
+
${block(pipelineIdentification)}
|
|
6682
|
+
`));
|
|
6683
|
+
return FAILED_VALUE_PLACEHOLDER;
|
|
6684
|
+
}
|
|
6685
|
+
throw error;
|
|
6686
|
+
}
|
|
6687
|
+
},
|
|
6455
6688
|
});
|
|
6456
6689
|
return resultString;
|
|
6457
6690
|
}
|
|
6458
6691
|
|
|
6459
6692
|
/**
|
|
6460
|
-
*
|
|
6693
|
+
* Returns the context for a given task, typically used to provide additional information or variables
|
|
6694
|
+
* required for the execution of the task within a pipeline. The context is returned as a string value
|
|
6695
|
+
* that may include markdown formatting.
|
|
6461
6696
|
*
|
|
6697
|
+
* @param task - The task for which the context is being generated. This should be a deeply immutable TaskJson object.
|
|
6698
|
+
* @returns The context as a string, formatted as markdown and parameter value.
|
|
6462
6699
|
* @private internal utility of `createPipelineExecutor`
|
|
6463
6700
|
*/
|
|
6464
6701
|
async function getContextForTask(task) {
|
|
@@ -6466,7 +6703,7 @@ async function getContextForTask(task) {
|
|
|
6466
6703
|
}
|
|
6467
6704
|
|
|
6468
6705
|
/**
|
|
6469
|
-
*
|
|
6706
|
+
* Retrieves example values or templates for a given task, used to guide or validate pipeline execution.
|
|
6470
6707
|
*
|
|
6471
6708
|
* @private internal utility of `createPipelineExecutor`
|
|
6472
6709
|
*/
|
|
@@ -6475,67 +6712,167 @@ async function getExamplesForTask(task) {
|
|
|
6475
6712
|
}
|
|
6476
6713
|
|
|
6477
6714
|
/**
|
|
6478
|
-
*
|
|
6715
|
+
* Computes the cosine similarity between two embedding vectors
|
|
6479
6716
|
*
|
|
6480
|
-
*
|
|
6717
|
+
* Note: This is helping function for RAG (retrieval-augmented generation)
|
|
6718
|
+
*
|
|
6719
|
+
* @param embeddingVector1
|
|
6720
|
+
* @param embeddingVector2
|
|
6721
|
+
* @returns Cosine similarity between the two vectors
|
|
6722
|
+
*
|
|
6723
|
+
* @public exported from `@promptbook/core`
|
|
6481
6724
|
*/
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6725
|
+
function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
|
|
6726
|
+
if (embeddingVector1.length !== embeddingVector2.length) {
|
|
6727
|
+
throw new TypeError('Embedding vectors must have the same length');
|
|
6728
|
+
}
|
|
6729
|
+
const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
|
|
6730
|
+
const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
|
|
6731
|
+
const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
|
|
6732
|
+
return 1 - dotProduct / (magnitude1 * magnitude2);
|
|
6486
6733
|
}
|
|
6487
6734
|
|
|
6488
6735
|
/**
|
|
6489
|
-
*
|
|
6736
|
+
*
|
|
6737
|
+
* @param knowledgePieces
|
|
6738
|
+
* @returns
|
|
6490
6739
|
*
|
|
6491
6740
|
* @private internal utility of `createPipelineExecutor`
|
|
6492
6741
|
*/
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
content: RESERVED_PARAMETER_RESTRICTED,
|
|
6502
|
-
context,
|
|
6503
|
-
knowledge,
|
|
6504
|
-
examples,
|
|
6505
|
-
currentDate,
|
|
6506
|
-
modelName,
|
|
6507
|
-
};
|
|
6508
|
-
// Note: Doublecheck that ALL reserved parameters are defined:
|
|
6509
|
-
for (const parameterName of RESERVED_PARAMETER_NAMES) {
|
|
6510
|
-
if (reservedParameters[parameterName] === undefined) {
|
|
6511
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
6512
|
-
Reserved parameter {${parameterName}} is not defined
|
|
6513
|
-
|
|
6514
|
-
${block(pipelineIdentification)}
|
|
6515
|
-
`));
|
|
6516
|
-
}
|
|
6517
|
-
}
|
|
6518
|
-
return reservedParameters;
|
|
6742
|
+
function knowledgePiecesToString(knowledgePieces) {
|
|
6743
|
+
return knowledgePieces
|
|
6744
|
+
.map((knowledgePiece) => {
|
|
6745
|
+
const { content } = knowledgePiece;
|
|
6746
|
+
return `- ${content}`;
|
|
6747
|
+
})
|
|
6748
|
+
.join('\n');
|
|
6749
|
+
// <- TODO: [🧠] Some smarter aggregation of knowledge pieces, single-line vs multi-line vs mixed
|
|
6519
6750
|
}
|
|
6520
6751
|
|
|
6521
6752
|
/**
|
|
6522
|
-
*
|
|
6753
|
+
* Retrieves the most relevant knowledge pieces for a given task using embedding-based similarity search.
|
|
6754
|
+
* This is where retrieval-augmented generation (RAG) is performed to enhance the task with external knowledge.
|
|
6523
6755
|
*
|
|
6524
6756
|
* @private internal utility of `createPipelineExecutor`
|
|
6525
6757
|
*/
|
|
6526
|
-
async function
|
|
6527
|
-
const {
|
|
6528
|
-
const
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
}
|
|
6758
|
+
async function getKnowledgeForTask(options) {
|
|
6759
|
+
const { tools, preparedPipeline, task, parameters } = options;
|
|
6760
|
+
const firstKnowlegePiece = preparedPipeline.knowledgePieces[0];
|
|
6761
|
+
const firstKnowlegeIndex = firstKnowlegePiece === null || firstKnowlegePiece === void 0 ? void 0 : firstKnowlegePiece.index[0];
|
|
6762
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
|
|
6763
|
+
if (firstKnowlegePiece === undefined || firstKnowlegeIndex === undefined) {
|
|
6764
|
+
return ''; // <- Note: Np knowledge present, return empty string
|
|
6765
|
+
}
|
|
6766
|
+
try {
|
|
6767
|
+
// TODO: [🚐] Make arrayable LLMs -> single LLM DRY
|
|
6768
|
+
const _llms = arrayableToArray(tools.llm);
|
|
6769
|
+
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
6770
|
+
const taskEmbeddingPrompt = {
|
|
6771
|
+
title: 'Knowledge Search',
|
|
6772
|
+
modelRequirements: {
|
|
6773
|
+
modelVariant: 'EMBEDDING',
|
|
6774
|
+
modelName: firstKnowlegeIndex.modelName,
|
|
6775
|
+
},
|
|
6776
|
+
content: task.content,
|
|
6777
|
+
parameters,
|
|
6778
|
+
};
|
|
6779
|
+
const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
|
|
6780
|
+
const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
|
|
6781
|
+
const { index } = knowledgePiece;
|
|
6782
|
+
const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
|
|
6783
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model
|
|
6784
|
+
if (knowledgePieceIndex === undefined) {
|
|
6785
|
+
return {
|
|
6786
|
+
content: knowledgePiece.content,
|
|
6787
|
+
relevance: 0,
|
|
6788
|
+
};
|
|
6789
|
+
}
|
|
6790
|
+
const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
|
|
6791
|
+
return {
|
|
6792
|
+
content: knowledgePiece.content,
|
|
6793
|
+
relevance,
|
|
6794
|
+
};
|
|
6795
|
+
});
|
|
6796
|
+
const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
|
|
6797
|
+
const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
|
|
6798
|
+
console.log('!!! Embedding', {
|
|
6799
|
+
task,
|
|
6800
|
+
taskEmbeddingPrompt,
|
|
6801
|
+
taskEmbeddingResult,
|
|
6802
|
+
firstKnowlegePiece,
|
|
6803
|
+
firstKnowlegeIndex,
|
|
6804
|
+
knowledgePiecesWithRelevance,
|
|
6805
|
+
knowledgePiecesSorted,
|
|
6806
|
+
knowledgePiecesLimited,
|
|
6807
|
+
});
|
|
6808
|
+
return knowledgePiecesToString(knowledgePiecesLimited);
|
|
6809
|
+
}
|
|
6810
|
+
catch (error) {
|
|
6811
|
+
assertsError(error);
|
|
6812
|
+
console.error('Error in `getKnowledgeForTask`', error);
|
|
6813
|
+
// Note: If the LLM fails, just return all knowledge pieces
|
|
6814
|
+
return knowledgePiecesToString(preparedPipeline.knowledgePieces);
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6817
|
+
/**
|
|
6818
|
+
* TODO: !!!! Verify if this is working
|
|
6819
|
+
* TODO: [♨] Implement Better - use keyword search
|
|
6820
|
+
* TODO: [♨] Examples of values
|
|
6821
|
+
*/
|
|
6822
|
+
|
|
6823
|
+
/**
|
|
6824
|
+
* Retrieves all reserved parameters for a given pipeline task, including context, knowledge, examples, and metadata.
|
|
6825
|
+
* Ensures all reserved parameters are defined and throws if any are missing.
|
|
6826
|
+
*
|
|
6827
|
+
* @param options - Options including tools, pipeline, task, and context.
|
|
6828
|
+
* @returns An object containing all reserved parameters for the task.
|
|
6829
|
+
*
|
|
6830
|
+
* @private internal utility of `createPipelineExecutor`
|
|
6831
|
+
*/
|
|
6832
|
+
async function getReservedParametersForTask(options) {
|
|
6833
|
+
const { tools, preparedPipeline, task, parameters, pipelineIdentification } = options;
|
|
6834
|
+
const context = await getContextForTask(); // <- [🏍]
|
|
6835
|
+
const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task, parameters });
|
|
6836
|
+
const examples = await getExamplesForTask();
|
|
6837
|
+
const currentDate = new Date().toISOString(); // <- TODO: [🧠][💩] Better
|
|
6838
|
+
const modelName = RESERVED_PARAMETER_MISSING_VALUE;
|
|
6839
|
+
const reservedParameters = {
|
|
6840
|
+
content: RESERVED_PARAMETER_RESTRICTED,
|
|
6841
|
+
context,
|
|
6842
|
+
knowledge,
|
|
6843
|
+
examples,
|
|
6844
|
+
currentDate,
|
|
6845
|
+
modelName,
|
|
6846
|
+
};
|
|
6847
|
+
// Note: Doublecheck that ALL reserved parameters are defined:
|
|
6848
|
+
for (const parameterName of RESERVED_PARAMETER_NAMES) {
|
|
6849
|
+
if (reservedParameters[parameterName] === undefined) {
|
|
6850
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
6851
|
+
Reserved parameter {${parameterName}} is not defined
|
|
6852
|
+
|
|
6853
|
+
${block(pipelineIdentification)}
|
|
6854
|
+
`));
|
|
6855
|
+
}
|
|
6856
|
+
}
|
|
6857
|
+
return reservedParameters;
|
|
6858
|
+
}
|
|
6859
|
+
|
|
6860
|
+
/**
|
|
6861
|
+
* Executes a single task within a pipeline, handling parameter validation, error checking, and progress reporting.
|
|
6862
|
+
*
|
|
6863
|
+
* @param options - Options for execution, including the task, pipeline, parameters, and callbacks.
|
|
6864
|
+
* @returns The output parameters produced by the task.
|
|
6865
|
+
*
|
|
6866
|
+
* @private internal utility of `createPipelineExecutor`
|
|
6867
|
+
*/
|
|
6868
|
+
async function executeTask(options) {
|
|
6869
|
+
const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled, isNotPreparedWarningSupressed, } = options;
|
|
6870
|
+
const priority = preparedPipeline.tasks.length - preparedPipeline.tasks.indexOf(currentTask);
|
|
6534
6871
|
// Note: Check consistency of used and dependent parameters which was also done in `validatePipeline`, but it’s good to doublecheck
|
|
6535
6872
|
const usedParameterNames = extractParameterNamesFromTask(currentTask);
|
|
6536
6873
|
const dependentParameterNames = new Set(currentTask.dependentParameterNames);
|
|
6537
6874
|
// TODO: [👩🏾🤝👩🏻] Use here `mapAvailableToExpectedParameters`
|
|
6538
|
-
if (union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)).size !== 0) {
|
|
6875
|
+
if (difference(union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)), new Set(RESERVED_PARAMETER_NAMES)).size !== 0) {
|
|
6539
6876
|
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
6540
6877
|
Dependent parameters are not consistent with used parameters:
|
|
6541
6878
|
|
|
@@ -6555,9 +6892,11 @@ async function executeTask(options) {
|
|
|
6555
6892
|
}
|
|
6556
6893
|
const definedParameters = Object.freeze({
|
|
6557
6894
|
...(await getReservedParametersForTask({
|
|
6895
|
+
tools,
|
|
6558
6896
|
preparedPipeline,
|
|
6559
6897
|
task: currentTask,
|
|
6560
6898
|
pipelineIdentification,
|
|
6899
|
+
parameters: parametersToPass,
|
|
6561
6900
|
})),
|
|
6562
6901
|
...parametersToPass,
|
|
6563
6902
|
});
|
|
@@ -6603,6 +6942,7 @@ async function executeTask(options) {
|
|
|
6603
6942
|
preparedPipeline,
|
|
6604
6943
|
tools,
|
|
6605
6944
|
$executionReport,
|
|
6945
|
+
onProgress,
|
|
6606
6946
|
pipelineIdentification,
|
|
6607
6947
|
maxExecutionAttempts,
|
|
6608
6948
|
maxParallelCount,
|
|
@@ -6630,7 +6970,8 @@ async function executeTask(options) {
|
|
|
6630
6970
|
*/
|
|
6631
6971
|
|
|
6632
6972
|
/**
|
|
6633
|
-
*
|
|
6973
|
+
* Filters and returns only the output parameters from the provided pipeline execution options.
|
|
6974
|
+
* Adds warnings for any expected output parameters that are missing.
|
|
6634
6975
|
*
|
|
6635
6976
|
* @private internal utility of `createPipelineExecutor`
|
|
6636
6977
|
*/
|
|
@@ -6655,9 +6996,12 @@ function filterJustOutputParameters(options) {
|
|
|
6655
6996
|
}
|
|
6656
6997
|
|
|
6657
6998
|
/**
|
|
6658
|
-
*
|
|
6999
|
+
* Executes an entire pipeline, resolving tasks in dependency order, handling errors, and reporting progress.
|
|
7000
|
+
*
|
|
7001
|
+
* Note: This is not a `PipelineExecutor` (which is bound to a single pipeline), but a utility function used by `createPipelineExecutor` to create a `PipelineExecutor`.
|
|
6659
7002
|
*
|
|
6660
|
-
*
|
|
7003
|
+
* @param options - Options for execution, including input parameters, pipeline, and callbacks.
|
|
7004
|
+
* @returns The result of the pipeline execution, including output parameters, errors, and usage statistics.
|
|
6661
7005
|
*
|
|
6662
7006
|
* @private internal utility of `createPipelineExecutor`
|
|
6663
7007
|
*/
|
|
@@ -6980,6 +7324,22 @@ function createPipelineExecutor(options) {
|
|
|
6980
7324
|
cacheDirname,
|
|
6981
7325
|
intermediateFilesStrategy,
|
|
6982
7326
|
isAutoInstalled,
|
|
7327
|
+
}).catch((error) => {
|
|
7328
|
+
assertsError(error);
|
|
7329
|
+
return exportJson({
|
|
7330
|
+
name: 'pipelineExecutorResult',
|
|
7331
|
+
message: `Unuccessful PipelineExecutorResult, last catch`,
|
|
7332
|
+
order: [],
|
|
7333
|
+
value: {
|
|
7334
|
+
isSuccessful: false,
|
|
7335
|
+
errors: [serializeError(error)],
|
|
7336
|
+
warnings: [],
|
|
7337
|
+
usage: UNCERTAIN_USAGE,
|
|
7338
|
+
executionReport: null,
|
|
7339
|
+
outputParameters: {},
|
|
7340
|
+
preparedPipeline,
|
|
7341
|
+
},
|
|
7342
|
+
});
|
|
6983
7343
|
});
|
|
6984
7344
|
};
|
|
6985
7345
|
const pipelineExecutor = (inputParameters) => createTask({
|
|
@@ -7040,27 +7400,48 @@ async function preparePersona(personaDescription, tools, options) {
|
|
|
7040
7400
|
pipeline: await collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.book'),
|
|
7041
7401
|
tools,
|
|
7042
7402
|
});
|
|
7043
|
-
// TODO: [🚐] Make arrayable LLMs -> single LLM DRY
|
|
7044
7403
|
const _llms = arrayableToArray(tools.llm);
|
|
7045
7404
|
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
7046
|
-
const availableModels = await llmTools.listModels()
|
|
7047
|
-
const availableModelNames = availableModels
|
|
7405
|
+
const availableModels = (await llmTools.listModels())
|
|
7048
7406
|
.filter(({ modelVariant }) => modelVariant === 'CHAT')
|
|
7049
|
-
.map(({ modelName }) =>
|
|
7050
|
-
|
|
7051
|
-
|
|
7407
|
+
.map(({ modelName, modelDescription }) => ({
|
|
7408
|
+
modelName,
|
|
7409
|
+
modelDescription,
|
|
7410
|
+
// <- Note: `modelTitle` and `modelVariant` is not relevant for this task
|
|
7411
|
+
}));
|
|
7412
|
+
const result = await preparePersonaExecutor({
|
|
7413
|
+
availableModels /* <- Note: Passing as JSON */,
|
|
7414
|
+
personaDescription,
|
|
7415
|
+
}).asPromise();
|
|
7052
7416
|
const { outputParameters } = result;
|
|
7053
|
-
const {
|
|
7054
|
-
|
|
7417
|
+
const { modelsRequirements: modelsRequirementsJson } = outputParameters;
|
|
7418
|
+
let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
|
|
7055
7419
|
if (isVerbose) {
|
|
7056
|
-
console.info(`PERSONA ${personaDescription}`,
|
|
7420
|
+
console.info(`PERSONA ${personaDescription}`, modelsRequirementsUnchecked);
|
|
7057
7421
|
}
|
|
7058
|
-
|
|
7059
|
-
|
|
7422
|
+
if (!Array.isArray(modelsRequirementsUnchecked)) {
|
|
7423
|
+
// <- TODO: Book should have syntax and system to enforce shape of JSON
|
|
7424
|
+
modelsRequirementsUnchecked = [modelsRequirementsUnchecked];
|
|
7425
|
+
/*
|
|
7426
|
+
throw new UnexpectedError(
|
|
7427
|
+
spaceTrim(
|
|
7428
|
+
(block) => `
|
|
7429
|
+
Invalid \`modelsRequirements\`:
|
|
7430
|
+
|
|
7431
|
+
\`\`\`json
|
|
7432
|
+
${block(JSON.stringify(modelsRequirementsUnchecked, null, 4))}
|
|
7433
|
+
\`\`\`
|
|
7434
|
+
`,
|
|
7435
|
+
),
|
|
7436
|
+
);
|
|
7437
|
+
*/
|
|
7438
|
+
}
|
|
7439
|
+
const modelsRequirements = modelsRequirementsUnchecked.map((modelRequirements) => ({
|
|
7060
7440
|
modelVariant: 'CHAT',
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7441
|
+
...modelRequirements,
|
|
7442
|
+
}));
|
|
7443
|
+
return {
|
|
7444
|
+
modelsRequirements,
|
|
7064
7445
|
};
|
|
7065
7446
|
}
|
|
7066
7447
|
/**
|
|
@@ -7122,7 +7503,9 @@ function mimeTypeToExtension(value) {
|
|
|
7122
7503
|
}
|
|
7123
7504
|
|
|
7124
7505
|
/**
|
|
7125
|
-
*
|
|
7506
|
+
* Factory function that creates a handler for processing knowledge sources.
|
|
7507
|
+
* Provides standardized processing of different types of knowledge sources
|
|
7508
|
+
* across various scraper implementations.
|
|
7126
7509
|
*
|
|
7127
7510
|
* @public exported from `@promptbook/core`
|
|
7128
7511
|
*/
|
|
@@ -7229,7 +7612,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
|
7229
7612
|
> },
|
|
7230
7613
|
*/
|
|
7231
7614
|
async asJson() {
|
|
7232
|
-
return
|
|
7615
|
+
return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
|
|
7233
7616
|
},
|
|
7234
7617
|
async asText() {
|
|
7235
7618
|
return await tools.fs.readFile(filename, 'utf-8');
|
|
@@ -7363,9 +7746,12 @@ TODO: [🧊] This is how it can look in future
|
|
|
7363
7746
|
*/
|
|
7364
7747
|
|
|
7365
7748
|
/**
|
|
7366
|
-
*
|
|
7749
|
+
* Prepares tasks by adding knowledge to the prompt and ensuring all necessary parameters are included.
|
|
7367
7750
|
*
|
|
7368
|
-
* @
|
|
7751
|
+
* @param tasks Sequence of tasks that are chained together to form a pipeline
|
|
7752
|
+
* @returns A promise that resolves to the prepared tasks.
|
|
7753
|
+
*
|
|
7754
|
+
* @private internal utility of `preparePipeline`
|
|
7369
7755
|
*/
|
|
7370
7756
|
async function prepareTasks(pipeline, tools, options) {
|
|
7371
7757
|
const { maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT } = options;
|
|
@@ -7487,14 +7873,14 @@ async function preparePipeline(pipeline, tools, options) {
|
|
|
7487
7873
|
// TODO: [🖌][🧠] Implement some `mapAsync` function
|
|
7488
7874
|
const preparedPersonas = new Array(personas.length);
|
|
7489
7875
|
await forEachAsync(personas, { maxParallelCount /* <- TODO: [🪂] When there are subtasks, this maximul limit can be broken */ }, async (persona, index) => {
|
|
7490
|
-
const
|
|
7876
|
+
const { modelsRequirements } = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
|
|
7491
7877
|
rootDirname,
|
|
7492
7878
|
maxParallelCount /* <- TODO: [🪂] */,
|
|
7493
7879
|
isVerbose,
|
|
7494
7880
|
});
|
|
7495
7881
|
const preparedPersona = {
|
|
7496
7882
|
...persona,
|
|
7497
|
-
|
|
7883
|
+
modelsRequirements,
|
|
7498
7884
|
preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id],
|
|
7499
7885
|
// <- TODO: [🍙] Make some standard order of json properties
|
|
7500
7886
|
};
|
|
@@ -7883,7 +8269,7 @@ const sectionCommandParser = {
|
|
|
7883
8269
|
/**
|
|
7884
8270
|
* Parses the boilerplate command
|
|
7885
8271
|
*
|
|
7886
|
-
* Note:
|
|
8272
|
+
* Note: @@ This command is used as boilerplate for new commands - it should NOT be used in any `.book` file
|
|
7887
8273
|
*
|
|
7888
8274
|
* @see `documentationUrl` for more details
|
|
7889
8275
|
* @private within the commands folder
|
|
@@ -8271,11 +8657,11 @@ const expectCommandParser = {
|
|
|
8271
8657
|
};
|
|
8272
8658
|
|
|
8273
8659
|
/**
|
|
8274
|
-
*
|
|
8660
|
+
* Normalizes a given text to camelCase format.
|
|
8275
8661
|
*
|
|
8276
|
-
* @param text
|
|
8277
|
-
* @param _isFirstLetterCapital
|
|
8278
|
-
* @returns
|
|
8662
|
+
* @param text The text to be normalized.
|
|
8663
|
+
* @param _isFirstLetterCapital Whether the first letter should be capitalized.
|
|
8664
|
+
* @returns The camelCase formatted string.
|
|
8279
8665
|
* @example 'helloWorld'
|
|
8280
8666
|
* @example 'iLovePromptbook'
|
|
8281
8667
|
* @public exported from `@promptbook/utils`
|
|
@@ -8346,11 +8732,12 @@ function removeQuotes(text) {
|
|
|
8346
8732
|
}
|
|
8347
8733
|
|
|
8348
8734
|
/**
|
|
8349
|
-
* Function `validateParameterName` will
|
|
8735
|
+
* Function `validateParameterName` will normalize and validate a parameter name for use in pipelines.
|
|
8736
|
+
* It removes diacritics, emojis, and quotes, normalizes to camelCase, and checks for reserved names and invalid characters.
|
|
8350
8737
|
*
|
|
8351
|
-
* @param parameterName
|
|
8352
|
-
* @returns
|
|
8353
|
-
* @throws {ParseError}
|
|
8738
|
+
* @param parameterName The parameter name to validate and normalize.
|
|
8739
|
+
* @returns The validated and normalized parameter name.
|
|
8740
|
+
* @throws {ParseError} If the parameter name is empty, reserved, or contains invalid characters.
|
|
8354
8741
|
* @private within the repository
|
|
8355
8742
|
*/
|
|
8356
8743
|
function validateParameterName(parameterName) {
|
|
@@ -8420,8 +8807,6 @@ function validateParameterName(parameterName) {
|
|
|
8420
8807
|
/**
|
|
8421
8808
|
* Parses the foreach command
|
|
8422
8809
|
*
|
|
8423
|
-
* Note: @@@ This command is used as foreach for new commands - it should NOT be used in any `.book` file
|
|
8424
|
-
*
|
|
8425
8810
|
* @see `documentationUrl` for more details
|
|
8426
8811
|
* @public exported from `@promptbook/editable`
|
|
8427
8812
|
*/
|
|
@@ -8478,14 +8863,14 @@ const foreachCommandParser = {
|
|
|
8478
8863
|
`));
|
|
8479
8864
|
// <- TODO: [🏢] List all supported format names
|
|
8480
8865
|
}
|
|
8481
|
-
const
|
|
8482
|
-
if (
|
|
8866
|
+
const subvalueParser = formatDefinition.subvalueParsers.find((subvalueParser) => [subvalueParser.subvalueName, ...(subvalueParser.aliases || [])].includes(subformatName));
|
|
8867
|
+
if (subvalueParser === undefined) {
|
|
8483
8868
|
throw new ParseError(spaceTrim((block) => `
|
|
8484
8869
|
Unsupported subformat name "${subformatName}" for format "${formatName}"
|
|
8485
8870
|
|
|
8486
8871
|
Available subformat names for format "${formatDefinition.formatName}":
|
|
8487
|
-
${block(formatDefinition.
|
|
8488
|
-
.map((
|
|
8872
|
+
${block(formatDefinition.subvalueParsers
|
|
8873
|
+
.map((subvalueParser) => subvalueParser.subvalueName)
|
|
8489
8874
|
.map((subvalueName) => `- ${subvalueName}`)
|
|
8490
8875
|
.join('\n'))}
|
|
8491
8876
|
`));
|
|
@@ -8662,14 +9047,14 @@ const formatCommandParser = {
|
|
|
8662
9047
|
};
|
|
8663
9048
|
|
|
8664
9049
|
/**
|
|
8665
|
-
*
|
|
9050
|
+
* Chatbot form factor definition for conversational interfaces that interact with users in a chat-like manner.
|
|
8666
9051
|
*
|
|
8667
9052
|
* @public exported from `@promptbook/core`
|
|
8668
9053
|
*/
|
|
8669
9054
|
const ChatbotFormfactorDefinition = {
|
|
8670
9055
|
name: 'CHATBOT',
|
|
8671
9056
|
aliasNames: ['CHAT'],
|
|
8672
|
-
description:
|
|
9057
|
+
description: `A chatbot form factor for conversational user interfaces.`,
|
|
8673
9058
|
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/174`,
|
|
8674
9059
|
pipelineInterface: {
|
|
8675
9060
|
inputParameters: [
|
|
@@ -8696,7 +9081,45 @@ const ChatbotFormfactorDefinition = {
|
|
|
8696
9081
|
};
|
|
8697
9082
|
|
|
8698
9083
|
/**
|
|
8699
|
-
*
|
|
9084
|
+
* Completion is formfactor that emulates completion models
|
|
9085
|
+
*
|
|
9086
|
+
* @public exported from `@promptbook/core`
|
|
9087
|
+
*/
|
|
9088
|
+
const CompletionFormfactorDefinition = {
|
|
9089
|
+
name: 'COMPLETION',
|
|
9090
|
+
description: `Completion is formfactor that emulates completion models`,
|
|
9091
|
+
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/@@`,
|
|
9092
|
+
// <- TODO: https://github.com/webgptorg/promptbook/discussions/new?category=concepts
|
|
9093
|
+
// "🔠 Completion Formfactor"
|
|
9094
|
+
pipelineInterface: {
|
|
9095
|
+
inputParameters: [
|
|
9096
|
+
{
|
|
9097
|
+
name: 'inputText',
|
|
9098
|
+
description: `Input text to be completed`,
|
|
9099
|
+
isInput: true,
|
|
9100
|
+
isOutput: false,
|
|
9101
|
+
},
|
|
9102
|
+
{
|
|
9103
|
+
name: 'instructions',
|
|
9104
|
+
description: `Additional instructions for the model, for example the required length, empty by default`,
|
|
9105
|
+
isInput: true,
|
|
9106
|
+
isOutput: false,
|
|
9107
|
+
},
|
|
9108
|
+
],
|
|
9109
|
+
outputParameters: [
|
|
9110
|
+
{
|
|
9111
|
+
name: 'followingText',
|
|
9112
|
+
description: `Text that follows the input text`,
|
|
9113
|
+
isInput: false,
|
|
9114
|
+
isOutput: true,
|
|
9115
|
+
},
|
|
9116
|
+
],
|
|
9117
|
+
},
|
|
9118
|
+
};
|
|
9119
|
+
|
|
9120
|
+
/**
|
|
9121
|
+
* Generator form factor represents an application that generates content or data based on user input or predefined rules.
|
|
9122
|
+
* This form factor is used for apps that produce outputs, such as text, images, or other media, based on provided input.
|
|
8700
9123
|
*
|
|
8701
9124
|
* @public exported from `@promptbook/core`
|
|
8702
9125
|
*/
|
|
@@ -8725,7 +9148,7 @@ const GeneratorFormfactorDefinition = {
|
|
|
8725
9148
|
};
|
|
8726
9149
|
|
|
8727
9150
|
/**
|
|
8728
|
-
*
|
|
9151
|
+
* Pipeline interface which is equivalent to `any`
|
|
8729
9152
|
*
|
|
8730
9153
|
* @see https://github.com/webgptorg/promptbook/discussions/171
|
|
8731
9154
|
*
|
|
@@ -8740,13 +9163,13 @@ const GENERIC_PIPELINE_INTERFACE = {
|
|
|
8740
9163
|
*/
|
|
8741
9164
|
|
|
8742
9165
|
/**
|
|
8743
|
-
*
|
|
9166
|
+
* A generic pipeline
|
|
8744
9167
|
*
|
|
8745
9168
|
* @public exported from `@promptbook/core`
|
|
8746
9169
|
*/
|
|
8747
9170
|
const GenericFormfactorDefinition = {
|
|
8748
9171
|
name: 'GENERIC',
|
|
8749
|
-
description:
|
|
9172
|
+
description: `A generic pipeline`,
|
|
8750
9173
|
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/173`,
|
|
8751
9174
|
pipelineInterface: GENERIC_PIPELINE_INTERFACE,
|
|
8752
9175
|
};
|
|
@@ -8781,17 +9204,20 @@ const ImageGeneratorFormfactorDefinition = {
|
|
|
8781
9204
|
};
|
|
8782
9205
|
|
|
8783
9206
|
/**
|
|
8784
|
-
* Matcher is form of app that
|
|
9207
|
+
* Matcher is form of app that evaluates (spreadsheet) content against defined criteria or patterns,
|
|
9208
|
+
* determining if it matches or meets specific requirements. Used for classification,
|
|
9209
|
+
* validation, filtering, and quality assessment of inputs.
|
|
8785
9210
|
*
|
|
8786
9211
|
* @public exported from `@promptbook/core`
|
|
8787
9212
|
*/
|
|
8788
9213
|
const MatcherFormfactorDefinition = {
|
|
8789
9214
|
name: 'EXPERIMENTAL_MATCHER',
|
|
8790
|
-
description:
|
|
9215
|
+
description: `An evaluation system that determines whether content meets specific criteria or patterns.
|
|
9216
|
+
Used for content validation, quality assessment, and intelligent filtering tasks. Currently in experimental phase.`,
|
|
8791
9217
|
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/177`,
|
|
8792
9218
|
pipelineInterface: {
|
|
8793
9219
|
inputParameters: [
|
|
8794
|
-
/*
|
|
9220
|
+
/* Input parameters for content to be matched and criteria to match against */
|
|
8795
9221
|
{
|
|
8796
9222
|
name: 'nonce',
|
|
8797
9223
|
description: 'Just to prevent EXPERIMENTAL_MATCHER to be set as implicit formfactor',
|
|
@@ -8800,20 +9226,21 @@ const MatcherFormfactorDefinition = {
|
|
|
8800
9226
|
},
|
|
8801
9227
|
],
|
|
8802
9228
|
outputParameters: [
|
|
8803
|
-
/*
|
|
9229
|
+
/* Output parameters containing match results, confidence scores, and relevant metadata */
|
|
8804
9230
|
],
|
|
8805
9231
|
},
|
|
8806
9232
|
};
|
|
8807
9233
|
|
|
8808
9234
|
/**
|
|
8809
|
-
* Sheets is form of app that
|
|
9235
|
+
* Sheets is form of app that processes tabular data in CSV format, allowing transformation
|
|
9236
|
+
* and analysis of structured data through AI-powered operations
|
|
8810
9237
|
*
|
|
8811
9238
|
* @public exported from `@promptbook/core`
|
|
8812
9239
|
*/
|
|
8813
9240
|
const SheetsFormfactorDefinition = {
|
|
8814
9241
|
name: 'SHEETS',
|
|
8815
9242
|
aliasNames: ['SHEETS', 'SHEET'],
|
|
8816
|
-
description:
|
|
9243
|
+
description: `A formfactor for processing spreadsheet-like data in CSV format, enabling AI transformations on tabular data`,
|
|
8817
9244
|
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/176`,
|
|
8818
9245
|
pipelineInterface: {
|
|
8819
9246
|
inputParameters: [
|
|
@@ -8836,13 +9263,16 @@ const SheetsFormfactorDefinition = {
|
|
|
8836
9263
|
};
|
|
8837
9264
|
|
|
8838
9265
|
/**
|
|
8839
|
-
* Translator is form of app that
|
|
9266
|
+
* Translator is form of app that transforms input text from one form to another,
|
|
9267
|
+
* such as language translation, style conversion, tone modification, or other text transformations.
|
|
8840
9268
|
*
|
|
8841
9269
|
* @public exported from `@promptbook/core`
|
|
8842
9270
|
*/
|
|
8843
9271
|
const TranslatorFormfactorDefinition = {
|
|
8844
9272
|
name: 'TRANSLATOR',
|
|
8845
|
-
description:
|
|
9273
|
+
description: `A text transformation system that converts input content into different forms,
|
|
9274
|
+
including language translations, paraphrasing, style conversions, and tone adjustments.
|
|
9275
|
+
This form factor takes one input and produces one transformed output.`,
|
|
8846
9276
|
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/175`,
|
|
8847
9277
|
pipelineInterface: {
|
|
8848
9278
|
inputParameters: [
|
|
@@ -8879,6 +9309,8 @@ const FORMFACTOR_DEFINITIONS = [
|
|
|
8879
9309
|
MatcherFormfactorDefinition,
|
|
8880
9310
|
GeneratorFormfactorDefinition,
|
|
8881
9311
|
ImageGeneratorFormfactorDefinition,
|
|
9312
|
+
CompletionFormfactorDefinition,
|
|
9313
|
+
// <- [🛬] When making new formfactor, copy the _boilerplate and link it here
|
|
8882
9314
|
];
|
|
8883
9315
|
/**
|
|
8884
9316
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -8887,7 +9319,7 @@ const FORMFACTOR_DEFINITIONS = [
|
|
|
8887
9319
|
/**
|
|
8888
9320
|
* Parses the formfactor command
|
|
8889
9321
|
*
|
|
8890
|
-
* Note:
|
|
9322
|
+
* Note: This command is used as a formfactor for new commands and defines the app type format - it should NOT be used in any `.book` file
|
|
8891
9323
|
*
|
|
8892
9324
|
* @see `documentationUrl` for more details
|
|
8893
9325
|
* @public exported from `@promptbook/editable`
|
|
@@ -8909,7 +9341,7 @@ const formfactorCommandParser = {
|
|
|
8909
9341
|
/**
|
|
8910
9342
|
* Description of the FORMFACTOR command
|
|
8911
9343
|
*/
|
|
8912
|
-
description:
|
|
9344
|
+
description: `Specifies the application type and interface requirements that this promptbook should conform to`,
|
|
8913
9345
|
/**
|
|
8914
9346
|
* Link to documentation
|
|
8915
9347
|
*/
|
|
@@ -9052,8 +9484,7 @@ const jokerCommandParser = {
|
|
|
9052
9484
|
};
|
|
9053
9485
|
|
|
9054
9486
|
/**
|
|
9055
|
-
*
|
|
9056
|
-
*
|
|
9487
|
+
* @see {@link ModelVariant}
|
|
9057
9488
|
* @public exported from `@promptbook/core`
|
|
9058
9489
|
*/
|
|
9059
9490
|
const MODEL_VARIANTS = ['COMPLETION', 'CHAT', 'EMBEDDING' /* <- TODO [🏳] */ /* <- [🤖] */];
|
|
@@ -9485,10 +9916,10 @@ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
|
|
|
9485
9916
|
}
|
|
9486
9917
|
|
|
9487
9918
|
/**
|
|
9488
|
-
*
|
|
9919
|
+
* Checks if the given value is a valid JavaScript identifier name.
|
|
9489
9920
|
*
|
|
9490
|
-
* @param javascriptName
|
|
9491
|
-
* @returns
|
|
9921
|
+
* @param javascriptName The value to check for JavaScript identifier validity.
|
|
9922
|
+
* @returns `true` if the value is a valid JavaScript name, false otherwise.
|
|
9492
9923
|
* @public exported from `@promptbook/utils`
|
|
9493
9924
|
*/
|
|
9494
9925
|
function isValidJavascriptName(javascriptName) {
|
|
@@ -9968,7 +10399,10 @@ function parseCommand(raw, usagePlace) {
|
|
|
9968
10399
|
`));
|
|
9969
10400
|
}
|
|
9970
10401
|
/**
|
|
9971
|
-
*
|
|
10402
|
+
* Generates a markdown-formatted message listing all supported commands
|
|
10403
|
+
* with their descriptions and documentation links
|
|
10404
|
+
*
|
|
10405
|
+
* @returns A formatted markdown string containing all available commands and their details
|
|
9972
10406
|
*/
|
|
9973
10407
|
function getSupportedCommandsMessage() {
|
|
9974
10408
|
return COMMANDS.flatMap(({ name, aliasNames, description, documentationUrl }) =>
|
|
@@ -9979,7 +10413,10 @@ function getSupportedCommandsMessage() {
|
|
|
9979
10413
|
]).join('\n');
|
|
9980
10414
|
}
|
|
9981
10415
|
/**
|
|
9982
|
-
*
|
|
10416
|
+
* Attempts to parse a command variant using the provided input parameters
|
|
10417
|
+
*
|
|
10418
|
+
* @param input Object containing command parsing information including raw command text and normalized values
|
|
10419
|
+
* @returns A parsed Command object if successful, or null if the command cannot be parsed
|
|
9983
10420
|
*/
|
|
9984
10421
|
function parseCommandVariant(input) {
|
|
9985
10422
|
const { commandNameRaw, usagePlace, normalized, args, raw, rawArgs } = input;
|
|
@@ -10026,7 +10463,7 @@ function parseCommandVariant(input) {
|
|
|
10026
10463
|
}
|
|
10027
10464
|
|
|
10028
10465
|
/**
|
|
10029
|
-
*
|
|
10466
|
+
* Extracts the interface (input and output parameters) from a pipeline.
|
|
10030
10467
|
*
|
|
10031
10468
|
* @deprecated https://github.com/webgptorg/promptbook/pull/186
|
|
10032
10469
|
* @see https://github.com/webgptorg/promptbook/discussions/171
|
|
@@ -10059,7 +10496,7 @@ function getPipelineInterface(pipeline) {
|
|
|
10059
10496
|
}
|
|
10060
10497
|
|
|
10061
10498
|
/**
|
|
10062
|
-
*
|
|
10499
|
+
* Checks if two pipeline interfaces are structurally identical.
|
|
10063
10500
|
*
|
|
10064
10501
|
* @deprecated https://github.com/webgptorg/promptbook/pull/186
|
|
10065
10502
|
* @see https://github.com/webgptorg/promptbook/discussions/171
|
|
@@ -10091,10 +10528,11 @@ function isPipelineInterfacesEqual(pipelineInterface1, pipelineInterface2) {
|
|
|
10091
10528
|
}
|
|
10092
10529
|
|
|
10093
10530
|
/**
|
|
10094
|
-
*
|
|
10531
|
+
* Checks if a given pipeline satisfies the requirements of a specified pipeline interface.
|
|
10095
10532
|
*
|
|
10096
10533
|
* @deprecated https://github.com/webgptorg/promptbook/pull/186
|
|
10097
10534
|
* @see https://github.com/webgptorg/promptbook/discussions/171
|
|
10535
|
+
* @returns `true` if the pipeline implements the interface, `false` otherwise.
|
|
10098
10536
|
*
|
|
10099
10537
|
* @public exported from `@promptbook/core`
|
|
10100
10538
|
*/
|
|
@@ -10280,7 +10718,8 @@ function removeMarkdownComments(content) {
|
|
|
10280
10718
|
}
|
|
10281
10719
|
|
|
10282
10720
|
/**
|
|
10283
|
-
*
|
|
10721
|
+
* Utility to determine if a pipeline string is in flat format.
|
|
10722
|
+
* A flat pipeline is a simple text without proper structure (headers, blocks, etc).
|
|
10284
10723
|
*
|
|
10285
10724
|
* @public exported from `@promptbook/editable`
|
|
10286
10725
|
*/
|
|
@@ -10301,7 +10740,10 @@ function isFlatPipeline(pipelineString) {
|
|
|
10301
10740
|
}
|
|
10302
10741
|
|
|
10303
10742
|
/**
|
|
10304
|
-
*
|
|
10743
|
+
* Converts a pipeline structure to its string representation.
|
|
10744
|
+
*
|
|
10745
|
+
* Transforms a flat, simple pipeline into a properly formatted pipeline string
|
|
10746
|
+
* with sections for title, prompt, and return statement.
|
|
10305
10747
|
*
|
|
10306
10748
|
* @public exported from `@promptbook/editable`
|
|
10307
10749
|
*/
|
|
@@ -10358,7 +10800,7 @@ function deflatePipeline(pipelineString) {
|
|
|
10358
10800
|
* Note: It can not work with html syntax and comments
|
|
10359
10801
|
*
|
|
10360
10802
|
* @param markdown any valid markdown
|
|
10361
|
-
* @returns
|
|
10803
|
+
* @returns An array of strings, each representing an individual list item found in the markdown
|
|
10362
10804
|
* @public exported from `@promptbook/markdown-utils`
|
|
10363
10805
|
*/
|
|
10364
10806
|
function extractAllListItemsFromMarkdown(markdown) {
|
|
@@ -11021,45 +11463,43 @@ async function compilePipeline(pipelineString, tools, options) {
|
|
|
11021
11463
|
*/
|
|
11022
11464
|
function renderPromptbookMermaid(pipelineJson, options) {
|
|
11023
11465
|
const { linkTask = () => null } = options || {};
|
|
11466
|
+
const MERMAID_PREFIX = 'pipeline_';
|
|
11467
|
+
const MERMAID_KNOWLEDGE_NAME = MERMAID_PREFIX + 'knowledge';
|
|
11468
|
+
const MERMAID_RESERVED_NAME = MERMAID_PREFIX + 'reserved';
|
|
11469
|
+
const MERMAID_INPUT_NAME = MERMAID_PREFIX + 'input';
|
|
11470
|
+
const MERMAID_OUTPUT_NAME = MERMAID_PREFIX + 'output';
|
|
11024
11471
|
const parameterNameToTaskName = (parameterName) => {
|
|
11472
|
+
if (parameterName === 'knowledge') {
|
|
11473
|
+
return MERMAID_KNOWLEDGE_NAME;
|
|
11474
|
+
}
|
|
11475
|
+
else if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
|
|
11476
|
+
return MERMAID_RESERVED_NAME;
|
|
11477
|
+
}
|
|
11025
11478
|
const parameter = pipelineJson.parameters.find((parameter) => parameter.name === parameterName);
|
|
11026
11479
|
if (!parameter) {
|
|
11027
11480
|
throw new UnexpectedError(`Could not find {${parameterName}}`);
|
|
11028
|
-
// <- TODO:
|
|
11481
|
+
// <- TODO: This causes problems when {knowledge} and other reserved parameters are used
|
|
11029
11482
|
}
|
|
11030
11483
|
if (parameter.isInput) {
|
|
11031
|
-
return
|
|
11484
|
+
return MERMAID_INPUT_NAME;
|
|
11032
11485
|
}
|
|
11033
11486
|
const task = pipelineJson.tasks.find((task) => task.resultingParameterName === parameterName);
|
|
11034
11487
|
if (!task) {
|
|
11035
11488
|
throw new Error(`Could not find task for {${parameterName}}`);
|
|
11036
11489
|
}
|
|
11037
|
-
return task.name || normalizeTo_camelCase('task-' + titleToName(task.title));
|
|
11490
|
+
return MERMAID_PREFIX + (task.name || normalizeTo_camelCase('task-' + titleToName(task.title)));
|
|
11038
11491
|
};
|
|
11039
|
-
const
|
|
11040
|
-
|
|
11041
|
-
%% 🔮 Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually
|
|
11042
|
-
|
|
11043
|
-
flowchart LR
|
|
11044
|
-
subgraph "${pipelineJson.title}"
|
|
11045
|
-
|
|
11046
|
-
direction TB
|
|
11047
|
-
|
|
11048
|
-
input((Input)):::input
|
|
11049
|
-
${block(pipelineJson.tasks
|
|
11492
|
+
const inputAndIntermediateParametersMermaid = pipelineJson.tasks
|
|
11050
11493
|
.flatMap(({ title, dependentParameterNames, resultingParameterName }) => [
|
|
11051
11494
|
`${parameterNameToTaskName(resultingParameterName)}("${title}")`,
|
|
11052
11495
|
...dependentParameterNames.map((dependentParameterName) => `${parameterNameToTaskName(dependentParameterName)}--"{${dependentParameterName}}"-->${parameterNameToTaskName(resultingParameterName)}`),
|
|
11053
11496
|
])
|
|
11054
|
-
.join('\n')
|
|
11055
|
-
|
|
11056
|
-
${block(pipelineJson.parameters
|
|
11497
|
+
.join('\n');
|
|
11498
|
+
const outputParametersMermaid = pipelineJson.parameters
|
|
11057
11499
|
.filter(({ isOutput }) => isOutput)
|
|
11058
|
-
.map(({ name }) => `${parameterNameToTaskName(name)}--"{${name}}"
|
|
11059
|
-
.join('\n')
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
${block(pipelineJson.tasks
|
|
11500
|
+
.map(({ name }) => `${parameterNameToTaskName(name)}--"{${name}}"-->${MERMAID_OUTPUT_NAME}`)
|
|
11501
|
+
.join('\n');
|
|
11502
|
+
const linksMermaid = pipelineJson.tasks
|
|
11063
11503
|
.map((task) => {
|
|
11064
11504
|
const link = linkTask(task);
|
|
11065
11505
|
if (link === null) {
|
|
@@ -11070,10 +11510,44 @@ function renderPromptbookMermaid(pipelineJson, options) {
|
|
|
11070
11510
|
return `click ${taskName} href "${href}" "${title}";`;
|
|
11071
11511
|
})
|
|
11072
11512
|
.filter((line) => line !== '')
|
|
11073
|
-
.join('\n')
|
|
11513
|
+
.join('\n');
|
|
11514
|
+
const interactionPointsMermaid = Object.entries({
|
|
11515
|
+
[MERMAID_INPUT_NAME]: 'Input',
|
|
11516
|
+
[MERMAID_OUTPUT_NAME]: 'Output',
|
|
11517
|
+
[MERMAID_RESERVED_NAME]: 'Other',
|
|
11518
|
+
[MERMAID_KNOWLEDGE_NAME]: 'Knowledge',
|
|
11519
|
+
})
|
|
11520
|
+
.filter(([MERMAID_NAME]) => (inputAndIntermediateParametersMermaid + outputParametersMermaid).includes(MERMAID_NAME))
|
|
11521
|
+
.map(([MERMAID_NAME, title]) => `${MERMAID_NAME}((${title})):::${MERMAID_NAME}`)
|
|
11522
|
+
.join('\n');
|
|
11523
|
+
const promptbookMermaid = spaceTrim$1((block) => `
|
|
11524
|
+
|
|
11525
|
+
%% 🔮 Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually
|
|
11526
|
+
|
|
11527
|
+
flowchart LR
|
|
11528
|
+
subgraph "${pipelineJson.title}"
|
|
11529
|
+
|
|
11530
|
+
%% Basic configuration
|
|
11531
|
+
direction TB
|
|
11074
11532
|
|
|
11075
|
-
|
|
11076
|
-
|
|
11533
|
+
%% Interaction points from pipeline to outside
|
|
11534
|
+
${block(interactionPointsMermaid)}
|
|
11535
|
+
|
|
11536
|
+
%% Input and intermediate parameters
|
|
11537
|
+
${block(inputAndIntermediateParametersMermaid)}
|
|
11538
|
+
|
|
11539
|
+
|
|
11540
|
+
%% Output parameters
|
|
11541
|
+
${block(outputParametersMermaid)}
|
|
11542
|
+
|
|
11543
|
+
%% Links
|
|
11544
|
+
${block(linksMermaid)}
|
|
11545
|
+
|
|
11546
|
+
%% Styles
|
|
11547
|
+
classDef ${MERMAID_INPUT_NAME} color: grey;
|
|
11548
|
+
classDef ${MERMAID_OUTPUT_NAME} color: grey;
|
|
11549
|
+
classDef ${MERMAID_RESERVED_NAME} color: grey;
|
|
11550
|
+
classDef ${MERMAID_KNOWLEDGE_NAME} color: grey;
|
|
11077
11551
|
|
|
11078
11552
|
end;
|
|
11079
11553
|
|
|
@@ -11113,11 +11587,11 @@ function parseKeywordsFromString(input) {
|
|
|
11113
11587
|
}
|
|
11114
11588
|
|
|
11115
11589
|
/**
|
|
11116
|
-
*
|
|
11590
|
+
* Converts a name string into a URI-compatible format.
|
|
11117
11591
|
*
|
|
11118
|
-
* @param name
|
|
11119
|
-
* @returns
|
|
11120
|
-
* @example
|
|
11592
|
+
* @param name The string to be converted to a URI-compatible format.
|
|
11593
|
+
* @returns A URI-compatible string derived from the input name.
|
|
11594
|
+
* @example 'Hello World' -> 'hello-world'
|
|
11121
11595
|
* @public exported from `@promptbook/utils`
|
|
11122
11596
|
*/
|
|
11123
11597
|
function nameToUriPart(name) {
|
|
@@ -11131,11 +11605,11 @@ function nameToUriPart(name) {
|
|
|
11131
11605
|
}
|
|
11132
11606
|
|
|
11133
11607
|
/**
|
|
11134
|
-
*
|
|
11608
|
+
* Converts a given name into URI-compatible parts.
|
|
11135
11609
|
*
|
|
11136
|
-
* @param name
|
|
11137
|
-
* @returns
|
|
11138
|
-
* @example
|
|
11610
|
+
* @param name The name to be converted into URI parts.
|
|
11611
|
+
* @returns An array of URI-compatible parts derived from the name.
|
|
11612
|
+
* @example 'Example Name' -> ['example', 'name']
|
|
11139
11613
|
* @public exported from `@promptbook/utils`
|
|
11140
11614
|
*/
|
|
11141
11615
|
function nameToUriParts(name) {
|
|
@@ -12934,7 +13408,7 @@ function $initializeRunCommand(program) {
|
|
|
12934
13408
|
}
|
|
12935
13409
|
let inputParameters = {};
|
|
12936
13410
|
if (json) {
|
|
12937
|
-
inputParameters =
|
|
13411
|
+
inputParameters = jsonParse(json);
|
|
12938
13412
|
// <- TODO: Maybe check shape of passed JSON and if its valid parameters Record
|
|
12939
13413
|
}
|
|
12940
13414
|
// TODO: DRY [◽]
|
|
@@ -12986,7 +13460,9 @@ function $initializeRunCommand(program) {
|
|
|
12986
13460
|
type: 'text',
|
|
12987
13461
|
name: 'pipelineSource',
|
|
12988
13462
|
message: '',
|
|
12989
|
-
validate
|
|
13463
|
+
validate(value) {
|
|
13464
|
+
return value.length > 0 ? true : 'Pipeline source is required';
|
|
13465
|
+
},
|
|
12990
13466
|
});
|
|
12991
13467
|
if (!response.pipelineSource) {
|
|
12992
13468
|
console.error(colors.red('Pipeline source is required'));
|
|
@@ -13111,10 +13587,10 @@ function $initializeRunCommand(program) {
|
|
|
13111
13587
|
console.info(colors.gray('--- Detailed Result ---'));
|
|
13112
13588
|
console.info({ isSuccessful, errors, warnings, outputParameters, executionReport });
|
|
13113
13589
|
}
|
|
13114
|
-
if (saveReport && saveReport.endsWith('.json')) {
|
|
13590
|
+
if (executionReport !== null && saveReport && saveReport.endsWith('.json')) {
|
|
13115
13591
|
await writeFile(saveReport, JSON.stringify(executionReport, null, 4) + '\n', 'utf-8');
|
|
13116
13592
|
}
|
|
13117
|
-
else if (saveReport && saveReport.endsWith('.md')) {
|
|
13593
|
+
else if (executionReport !== null && saveReport && saveReport.endsWith('.md')) {
|
|
13118
13594
|
const executionReportString = executionReportJsonToString(executionReport);
|
|
13119
13595
|
await writeFile(saveReport, executionReportString, 'utf-8');
|
|
13120
13596
|
}
|
|
@@ -13157,15 +13633,15 @@ function $initializeRunCommand(program) {
|
|
|
13157
13633
|
* TODO: [🖇] What about symlinks? Maybe flag --follow-symlinks
|
|
13158
13634
|
*/
|
|
13159
13635
|
|
|
13160
|
-
// TODO:
|
|
13161
|
-
// TODO:
|
|
13636
|
+
// TODO: [🥺] List running services from REMOTE_SERVER_URLS
|
|
13637
|
+
// TODO: [🥺] Import directly from YML
|
|
13162
13638
|
/**
|
|
13163
|
-
* @private
|
|
13639
|
+
* @private [🥺] Decide how to expose this
|
|
13164
13640
|
*/
|
|
13165
13641
|
const openapiJson = {
|
|
13166
13642
|
openapi: '3.0.0',
|
|
13167
13643
|
info: {
|
|
13168
|
-
title: 'Promptbook Remote Server API (
|
|
13644
|
+
title: 'Promptbook Remote Server API ([🥺] From YML)',
|
|
13169
13645
|
version: '1.0.0',
|
|
13170
13646
|
description: 'API documentation for the Promptbook Remote Server',
|
|
13171
13647
|
},
|
|
@@ -13177,6 +13653,13 @@ const openapiJson = {
|
|
|
13177
13653
|
responses: {
|
|
13178
13654
|
'200': {
|
|
13179
13655
|
description: 'Server details in markdown format.',
|
|
13656
|
+
content: {
|
|
13657
|
+
'text/markdown': {
|
|
13658
|
+
schema: {
|
|
13659
|
+
type: 'string',
|
|
13660
|
+
},
|
|
13661
|
+
},
|
|
13662
|
+
},
|
|
13180
13663
|
},
|
|
13181
13664
|
},
|
|
13182
13665
|
},
|
|
@@ -13207,13 +13690,22 @@ const openapiJson = {
|
|
|
13207
13690
|
},
|
|
13208
13691
|
},
|
|
13209
13692
|
responses: {
|
|
13210
|
-
'
|
|
13693
|
+
'201': {
|
|
13211
13694
|
description: 'Successful login',
|
|
13212
13695
|
content: {
|
|
13213
13696
|
'application/json': {
|
|
13214
13697
|
schema: {
|
|
13215
13698
|
type: 'object',
|
|
13216
13699
|
properties: {
|
|
13700
|
+
isSuccess: {
|
|
13701
|
+
type: 'boolean',
|
|
13702
|
+
},
|
|
13703
|
+
message: {
|
|
13704
|
+
type: 'string',
|
|
13705
|
+
},
|
|
13706
|
+
error: {
|
|
13707
|
+
type: 'object',
|
|
13708
|
+
},
|
|
13217
13709
|
identification: {
|
|
13218
13710
|
type: 'object',
|
|
13219
13711
|
},
|
|
@@ -13222,6 +13714,43 @@ const openapiJson = {
|
|
|
13222
13714
|
},
|
|
13223
13715
|
},
|
|
13224
13716
|
},
|
|
13717
|
+
'400': {
|
|
13718
|
+
description: 'Bad request or login failed',
|
|
13719
|
+
content: {
|
|
13720
|
+
'application/json': {
|
|
13721
|
+
schema: {
|
|
13722
|
+
type: 'object',
|
|
13723
|
+
properties: {
|
|
13724
|
+
error: {
|
|
13725
|
+
type: 'object',
|
|
13726
|
+
},
|
|
13727
|
+
},
|
|
13728
|
+
},
|
|
13729
|
+
},
|
|
13730
|
+
},
|
|
13731
|
+
},
|
|
13732
|
+
'401': {
|
|
13733
|
+
description: 'Authentication error',
|
|
13734
|
+
content: {
|
|
13735
|
+
'application/json': {
|
|
13736
|
+
schema: {
|
|
13737
|
+
type: 'object',
|
|
13738
|
+
properties: {
|
|
13739
|
+
isSuccess: {
|
|
13740
|
+
type: 'boolean',
|
|
13741
|
+
enum: [false],
|
|
13742
|
+
},
|
|
13743
|
+
message: {
|
|
13744
|
+
type: 'string',
|
|
13745
|
+
},
|
|
13746
|
+
error: {
|
|
13747
|
+
type: 'object',
|
|
13748
|
+
},
|
|
13749
|
+
},
|
|
13750
|
+
},
|
|
13751
|
+
},
|
|
13752
|
+
},
|
|
13753
|
+
},
|
|
13225
13754
|
},
|
|
13226
13755
|
},
|
|
13227
13756
|
},
|
|
@@ -13243,6 +13772,16 @@ const openapiJson = {
|
|
|
13243
13772
|
},
|
|
13244
13773
|
},
|
|
13245
13774
|
},
|
|
13775
|
+
'500': {
|
|
13776
|
+
description: 'No collection available',
|
|
13777
|
+
content: {
|
|
13778
|
+
'text/plain': {
|
|
13779
|
+
schema: {
|
|
13780
|
+
type: 'string',
|
|
13781
|
+
},
|
|
13782
|
+
},
|
|
13783
|
+
},
|
|
13784
|
+
},
|
|
13246
13785
|
},
|
|
13247
13786
|
},
|
|
13248
13787
|
},
|
|
@@ -13274,6 +13813,28 @@ const openapiJson = {
|
|
|
13274
13813
|
},
|
|
13275
13814
|
'404': {
|
|
13276
13815
|
description: 'Book not found.',
|
|
13816
|
+
content: {
|
|
13817
|
+
'application/json': {
|
|
13818
|
+
schema: {
|
|
13819
|
+
type: 'object',
|
|
13820
|
+
properties: {
|
|
13821
|
+
error: {
|
|
13822
|
+
type: 'object',
|
|
13823
|
+
},
|
|
13824
|
+
},
|
|
13825
|
+
},
|
|
13826
|
+
},
|
|
13827
|
+
},
|
|
13828
|
+
},
|
|
13829
|
+
'500': {
|
|
13830
|
+
description: 'No collection available',
|
|
13831
|
+
content: {
|
|
13832
|
+
'text/plain': {
|
|
13833
|
+
schema: {
|
|
13834
|
+
type: 'string',
|
|
13835
|
+
},
|
|
13836
|
+
},
|
|
13837
|
+
},
|
|
13277
13838
|
},
|
|
13278
13839
|
},
|
|
13279
13840
|
},
|
|
@@ -13291,6 +13852,28 @@ const openapiJson = {
|
|
|
13291
13852
|
type: 'array',
|
|
13292
13853
|
items: {
|
|
13293
13854
|
type: 'object',
|
|
13855
|
+
properties: {
|
|
13856
|
+
nonce: {
|
|
13857
|
+
type: 'string',
|
|
13858
|
+
},
|
|
13859
|
+
taskId: {
|
|
13860
|
+
type: 'string',
|
|
13861
|
+
},
|
|
13862
|
+
taskType: {
|
|
13863
|
+
type: 'string',
|
|
13864
|
+
},
|
|
13865
|
+
status: {
|
|
13866
|
+
type: 'string',
|
|
13867
|
+
},
|
|
13868
|
+
createdAt: {
|
|
13869
|
+
type: 'string',
|
|
13870
|
+
format: 'date-time',
|
|
13871
|
+
},
|
|
13872
|
+
updatedAt: {
|
|
13873
|
+
type: 'string',
|
|
13874
|
+
format: 'date-time',
|
|
13875
|
+
},
|
|
13876
|
+
},
|
|
13294
13877
|
},
|
|
13295
13878
|
},
|
|
13296
13879
|
},
|
|
@@ -13299,51 +13882,350 @@ const openapiJson = {
|
|
|
13299
13882
|
},
|
|
13300
13883
|
},
|
|
13301
13884
|
},
|
|
13302
|
-
'/executions/
|
|
13303
|
-
|
|
13304
|
-
summary: '
|
|
13305
|
-
description: '
|
|
13306
|
-
requestBody: {
|
|
13307
|
-
required: true,
|
|
13308
|
-
content: {
|
|
13309
|
-
'application/json': {
|
|
13310
|
-
schema: {
|
|
13311
|
-
type: 'object',
|
|
13312
|
-
properties: {
|
|
13313
|
-
pipelineUrl: {
|
|
13314
|
-
type: 'string',
|
|
13315
|
-
},
|
|
13316
|
-
inputParameters: {
|
|
13317
|
-
type: 'object',
|
|
13318
|
-
},
|
|
13319
|
-
identification: {
|
|
13320
|
-
type: 'object',
|
|
13321
|
-
},
|
|
13322
|
-
},
|
|
13323
|
-
},
|
|
13324
|
-
},
|
|
13325
|
-
},
|
|
13326
|
-
},
|
|
13885
|
+
'/executions/last': {
|
|
13886
|
+
get: {
|
|
13887
|
+
summary: 'Get the last execution',
|
|
13888
|
+
description: 'Returns details of the last execution task.',
|
|
13327
13889
|
responses: {
|
|
13328
13890
|
'200': {
|
|
13329
|
-
description: 'The
|
|
13891
|
+
description: 'The last execution task with full details.',
|
|
13330
13892
|
content: {
|
|
13331
13893
|
'application/json': {
|
|
13332
13894
|
schema: {
|
|
13333
13895
|
type: 'object',
|
|
13334
|
-
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13896
|
+
properties: {
|
|
13897
|
+
nonce: {
|
|
13898
|
+
type: 'string',
|
|
13899
|
+
},
|
|
13900
|
+
taskId: {
|
|
13901
|
+
type: 'string',
|
|
13902
|
+
},
|
|
13903
|
+
taskType: {
|
|
13904
|
+
type: 'string',
|
|
13905
|
+
},
|
|
13906
|
+
status: {
|
|
13907
|
+
type: 'string',
|
|
13908
|
+
},
|
|
13909
|
+
errors: {
|
|
13910
|
+
type: 'array',
|
|
13911
|
+
items: {
|
|
13912
|
+
type: 'object',
|
|
13913
|
+
},
|
|
13914
|
+
},
|
|
13915
|
+
warnings: {
|
|
13916
|
+
type: 'array',
|
|
13917
|
+
items: {
|
|
13918
|
+
type: 'object',
|
|
13919
|
+
},
|
|
13920
|
+
},
|
|
13921
|
+
createdAt: {
|
|
13922
|
+
type: 'string',
|
|
13923
|
+
format: 'date-time',
|
|
13924
|
+
},
|
|
13925
|
+
updatedAt: {
|
|
13926
|
+
type: 'string',
|
|
13927
|
+
format: 'date-time',
|
|
13928
|
+
},
|
|
13929
|
+
currentValue: {
|
|
13930
|
+
type: 'object',
|
|
13931
|
+
},
|
|
13932
|
+
},
|
|
13933
|
+
},
|
|
13934
|
+
},
|
|
13935
|
+
},
|
|
13936
|
+
},
|
|
13937
|
+
'404': {
|
|
13938
|
+
description: 'No execution tasks found.',
|
|
13939
|
+
content: {
|
|
13940
|
+
'text/plain': {
|
|
13941
|
+
schema: {
|
|
13942
|
+
type: 'string',
|
|
13943
|
+
},
|
|
13944
|
+
},
|
|
13945
|
+
},
|
|
13946
|
+
},
|
|
13947
|
+
},
|
|
13948
|
+
},
|
|
13949
|
+
},
|
|
13950
|
+
'/executions/{taskId}': {
|
|
13951
|
+
get: {
|
|
13952
|
+
summary: 'Get specific execution',
|
|
13953
|
+
description: 'Returns details of a specific execution task.',
|
|
13954
|
+
parameters: [
|
|
13955
|
+
{
|
|
13956
|
+
in: 'path',
|
|
13957
|
+
name: 'taskId',
|
|
13958
|
+
required: true,
|
|
13959
|
+
schema: {
|
|
13960
|
+
type: 'string',
|
|
13961
|
+
},
|
|
13962
|
+
description: 'The ID of the execution task to retrieve.',
|
|
13963
|
+
},
|
|
13964
|
+
],
|
|
13965
|
+
responses: {
|
|
13966
|
+
'200': {
|
|
13967
|
+
description: 'The execution task with full details.',
|
|
13968
|
+
content: {
|
|
13969
|
+
'application/json': {
|
|
13970
|
+
schema: {
|
|
13971
|
+
type: 'object',
|
|
13972
|
+
properties: {
|
|
13973
|
+
nonce: {
|
|
13974
|
+
type: 'string',
|
|
13975
|
+
},
|
|
13976
|
+
taskId: {
|
|
13977
|
+
type: 'string',
|
|
13978
|
+
},
|
|
13979
|
+
taskType: {
|
|
13980
|
+
type: 'string',
|
|
13981
|
+
},
|
|
13982
|
+
status: {
|
|
13983
|
+
type: 'string',
|
|
13984
|
+
},
|
|
13985
|
+
errors: {
|
|
13986
|
+
type: 'array',
|
|
13987
|
+
items: {
|
|
13988
|
+
type: 'object',
|
|
13989
|
+
},
|
|
13990
|
+
},
|
|
13991
|
+
warnings: {
|
|
13992
|
+
type: 'array',
|
|
13993
|
+
items: {
|
|
13994
|
+
type: 'object',
|
|
13995
|
+
},
|
|
13996
|
+
},
|
|
13997
|
+
createdAt: {
|
|
13998
|
+
type: 'string',
|
|
13999
|
+
format: 'date-time',
|
|
14000
|
+
},
|
|
14001
|
+
updatedAt: {
|
|
14002
|
+
type: 'string',
|
|
14003
|
+
format: 'date-time',
|
|
14004
|
+
},
|
|
14005
|
+
currentValue: {
|
|
14006
|
+
type: 'object',
|
|
14007
|
+
},
|
|
14008
|
+
},
|
|
14009
|
+
},
|
|
14010
|
+
},
|
|
14011
|
+
},
|
|
14012
|
+
},
|
|
14013
|
+
'404': {
|
|
14014
|
+
description: 'Execution task not found.',
|
|
14015
|
+
content: {
|
|
14016
|
+
'text/plain': {
|
|
14017
|
+
schema: {
|
|
14018
|
+
type: 'string',
|
|
14019
|
+
},
|
|
14020
|
+
},
|
|
14021
|
+
},
|
|
14022
|
+
},
|
|
14023
|
+
},
|
|
14024
|
+
},
|
|
14025
|
+
},
|
|
14026
|
+
'/executions/new': {
|
|
14027
|
+
post: {
|
|
14028
|
+
summary: 'Start a new execution',
|
|
14029
|
+
description: 'Starts a new execution task for a given pipeline.',
|
|
14030
|
+
requestBody: {
|
|
14031
|
+
required: true,
|
|
14032
|
+
content: {
|
|
14033
|
+
'application/json': {
|
|
14034
|
+
schema: {
|
|
14035
|
+
type: 'object',
|
|
14036
|
+
properties: {
|
|
14037
|
+
pipelineUrl: {
|
|
14038
|
+
type: 'string',
|
|
14039
|
+
description: 'URL of the pipeline to execute',
|
|
14040
|
+
},
|
|
14041
|
+
book: {
|
|
14042
|
+
type: 'string',
|
|
14043
|
+
description: 'Alternative field for pipelineUrl',
|
|
14044
|
+
},
|
|
14045
|
+
inputParameters: {
|
|
14046
|
+
type: 'object',
|
|
14047
|
+
description: 'Parameters for pipeline execution',
|
|
14048
|
+
},
|
|
14049
|
+
identification: {
|
|
14050
|
+
type: 'object',
|
|
14051
|
+
description: 'User identification data',
|
|
14052
|
+
},
|
|
14053
|
+
},
|
|
14054
|
+
},
|
|
14055
|
+
},
|
|
14056
|
+
},
|
|
14057
|
+
},
|
|
14058
|
+
responses: {
|
|
14059
|
+
'200': {
|
|
14060
|
+
description: 'The newly created execution task.',
|
|
14061
|
+
content: {
|
|
14062
|
+
'application/json': {
|
|
14063
|
+
schema: {
|
|
14064
|
+
type: 'object',
|
|
14065
|
+
},
|
|
14066
|
+
},
|
|
14067
|
+
},
|
|
14068
|
+
},
|
|
14069
|
+
'400': {
|
|
14070
|
+
description: 'Invalid input.',
|
|
14071
|
+
content: {
|
|
14072
|
+
'application/json': {
|
|
14073
|
+
schema: {
|
|
14074
|
+
type: 'object',
|
|
14075
|
+
properties: {
|
|
14076
|
+
error: {
|
|
14077
|
+
type: 'object',
|
|
14078
|
+
},
|
|
14079
|
+
},
|
|
14080
|
+
},
|
|
14081
|
+
},
|
|
14082
|
+
},
|
|
14083
|
+
},
|
|
14084
|
+
'404': {
|
|
14085
|
+
description: 'Pipeline not found.',
|
|
14086
|
+
content: {
|
|
14087
|
+
'text/plain': {
|
|
14088
|
+
schema: {
|
|
14089
|
+
type: 'string',
|
|
14090
|
+
},
|
|
14091
|
+
},
|
|
14092
|
+
},
|
|
14093
|
+
},
|
|
14094
|
+
},
|
|
14095
|
+
},
|
|
14096
|
+
},
|
|
14097
|
+
'/api-docs': {
|
|
14098
|
+
get: {
|
|
14099
|
+
summary: 'API documentation UI',
|
|
14100
|
+
description: 'Swagger UI for API documentation',
|
|
14101
|
+
responses: {
|
|
14102
|
+
'200': {
|
|
14103
|
+
description: 'HTML Swagger UI',
|
|
14104
|
+
},
|
|
14105
|
+
},
|
|
14106
|
+
},
|
|
14107
|
+
},
|
|
14108
|
+
'/swagger': {
|
|
14109
|
+
get: {
|
|
14110
|
+
summary: 'API documentation UI (alternative path)',
|
|
14111
|
+
description: 'Swagger UI for API documentation',
|
|
14112
|
+
responses: {
|
|
14113
|
+
'200': {
|
|
14114
|
+
description: 'HTML Swagger UI',
|
|
14115
|
+
},
|
|
14116
|
+
},
|
|
14117
|
+
},
|
|
14118
|
+
},
|
|
14119
|
+
'/openapi': {
|
|
14120
|
+
get: {
|
|
14121
|
+
summary: 'OpenAPI specification',
|
|
14122
|
+
description: 'Returns the OpenAPI JSON specification',
|
|
14123
|
+
responses: {
|
|
14124
|
+
'200': {
|
|
14125
|
+
description: 'OpenAPI specification',
|
|
14126
|
+
content: {
|
|
14127
|
+
'application/json': {
|
|
14128
|
+
schema: {
|
|
14129
|
+
type: 'object',
|
|
14130
|
+
},
|
|
14131
|
+
},
|
|
14132
|
+
},
|
|
13340
14133
|
},
|
|
13341
14134
|
},
|
|
13342
14135
|
},
|
|
13343
14136
|
},
|
|
13344
14137
|
},
|
|
13345
|
-
components: {
|
|
13346
|
-
|
|
14138
|
+
components: {
|
|
14139
|
+
schemas: {
|
|
14140
|
+
Error: {
|
|
14141
|
+
type: 'object',
|
|
14142
|
+
properties: {
|
|
14143
|
+
error: {
|
|
14144
|
+
type: 'object',
|
|
14145
|
+
},
|
|
14146
|
+
},
|
|
14147
|
+
},
|
|
14148
|
+
ExecutionTaskSummary: {
|
|
14149
|
+
type: 'object',
|
|
14150
|
+
properties: {
|
|
14151
|
+
nonce: {
|
|
14152
|
+
type: 'string',
|
|
14153
|
+
},
|
|
14154
|
+
taskId: {
|
|
14155
|
+
type: 'string',
|
|
14156
|
+
},
|
|
14157
|
+
taskType: {
|
|
14158
|
+
type: 'string',
|
|
14159
|
+
},
|
|
14160
|
+
status: {
|
|
14161
|
+
type: 'string',
|
|
14162
|
+
},
|
|
14163
|
+
createdAt: {
|
|
14164
|
+
type: 'string',
|
|
14165
|
+
format: 'date-time',
|
|
14166
|
+
},
|
|
14167
|
+
updatedAt: {
|
|
14168
|
+
type: 'string',
|
|
14169
|
+
format: 'date-time',
|
|
14170
|
+
},
|
|
14171
|
+
},
|
|
14172
|
+
},
|
|
14173
|
+
ExecutionTaskFull: {
|
|
14174
|
+
type: 'object',
|
|
14175
|
+
properties: {
|
|
14176
|
+
nonce: {
|
|
14177
|
+
type: 'string',
|
|
14178
|
+
},
|
|
14179
|
+
taskId: {
|
|
14180
|
+
type: 'string',
|
|
14181
|
+
},
|
|
14182
|
+
taskType: {
|
|
14183
|
+
type: 'string',
|
|
14184
|
+
},
|
|
14185
|
+
status: {
|
|
14186
|
+
type: 'string',
|
|
14187
|
+
},
|
|
14188
|
+
errors: {
|
|
14189
|
+
type: 'array',
|
|
14190
|
+
items: {
|
|
14191
|
+
type: 'object',
|
|
14192
|
+
},
|
|
14193
|
+
},
|
|
14194
|
+
warnings: {
|
|
14195
|
+
type: 'array',
|
|
14196
|
+
items: {
|
|
14197
|
+
type: 'object',
|
|
14198
|
+
},
|
|
14199
|
+
},
|
|
14200
|
+
createdAt: {
|
|
14201
|
+
type: 'string',
|
|
14202
|
+
format: 'date-time',
|
|
14203
|
+
},
|
|
14204
|
+
updatedAt: {
|
|
14205
|
+
type: 'string',
|
|
14206
|
+
format: 'date-time',
|
|
14207
|
+
},
|
|
14208
|
+
currentValue: {
|
|
14209
|
+
type: 'object',
|
|
14210
|
+
},
|
|
14211
|
+
},
|
|
14212
|
+
},
|
|
14213
|
+
},
|
|
14214
|
+
},
|
|
14215
|
+
tags: [
|
|
14216
|
+
{
|
|
14217
|
+
name: 'Books',
|
|
14218
|
+
description: 'Operations related to books and pipelines',
|
|
14219
|
+
},
|
|
14220
|
+
{
|
|
14221
|
+
name: 'Executions',
|
|
14222
|
+
description: 'Operations related to execution tasks',
|
|
14223
|
+
},
|
|
14224
|
+
{
|
|
14225
|
+
name: 'Authentication',
|
|
14226
|
+
description: 'Authentication operations',
|
|
14227
|
+
},
|
|
14228
|
+
],
|
|
13347
14229
|
};
|
|
13348
14230
|
/**
|
|
13349
14231
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -13417,7 +14299,7 @@ function startRemoteServer(options) {
|
|
|
13417
14299
|
response.setHeader('X-Powered-By', 'Promptbook engine');
|
|
13418
14300
|
next();
|
|
13419
14301
|
});
|
|
13420
|
-
// TODO:
|
|
14302
|
+
// TODO: [🥺] Expose openapiJson to consumer and also allow to add new routes
|
|
13421
14303
|
app.use(OpenApiValidator.middleware({
|
|
13422
14304
|
apiSpec: openapiJson,
|
|
13423
14305
|
ignorePaths(path) {
|
|
@@ -13714,6 +14596,7 @@ function startRemoteServer(options) {
|
|
|
13714
14596
|
promptResult = await llm.callCompletionModel(prompt);
|
|
13715
14597
|
break;
|
|
13716
14598
|
case 'EMBEDDING':
|
|
14599
|
+
console.log('!!! llm (EMBEDDING)', llm);
|
|
13717
14600
|
if (llm.callEmbeddingModel === undefined) {
|
|
13718
14601
|
// Note: [0] This check should not be a thing
|
|
13719
14602
|
throw new PipelineExecutionError(`Embedding model is not available`);
|
|
@@ -13988,7 +14871,7 @@ function $initializeTestCommand(program) {
|
|
|
13988
14871
|
}
|
|
13989
14872
|
}
|
|
13990
14873
|
if (filename.endsWith('.bookc')) {
|
|
13991
|
-
pipeline =
|
|
14874
|
+
pipeline = jsonParse(await readFile(filename, 'utf-8'));
|
|
13992
14875
|
}
|
|
13993
14876
|
else {
|
|
13994
14877
|
if (isVerbose) {
|
|
@@ -14111,9 +14994,11 @@ const _AnthropicClaudeMetadataRegistration = $llmToolsMetadataRegister.register(
|
|
|
14111
14994
|
packageName: '@promptbook/anthropic-claude',
|
|
14112
14995
|
className: 'AnthropicClaudeExecutionTools',
|
|
14113
14996
|
envVariables: ['ANTHROPIC_CLAUDE_API_KEY'],
|
|
14997
|
+
trustLevel: 'CLOSED',
|
|
14998
|
+
order: MODEL_ORDERS.TOP_TIER,
|
|
14114
14999
|
getBoilerplateConfiguration() {
|
|
14115
15000
|
return {
|
|
14116
|
-
title: 'Anthropic Claude
|
|
15001
|
+
title: 'Anthropic Claude',
|
|
14117
15002
|
packageName: '@promptbook/anthropic-claude',
|
|
14118
15003
|
className: 'AnthropicClaudeExecutionTools',
|
|
14119
15004
|
options: {
|
|
@@ -14155,7 +15040,7 @@ function computeUsage(value) {
|
|
|
14155
15040
|
/**
|
|
14156
15041
|
* List of available Anthropic Claude models with pricing
|
|
14157
15042
|
*
|
|
14158
|
-
* Note: Done at
|
|
15043
|
+
* Note: Done at 2025-05-06
|
|
14159
15044
|
*
|
|
14160
15045
|
* @see https://docs.anthropic.com/en/docs/models-overview
|
|
14161
15046
|
* @public exported from `@promptbook/anthropic-claude`
|
|
@@ -14169,8 +15054,8 @@ const ANTHROPIC_CLAUDE_MODELS = exportJson({
|
|
|
14169
15054
|
modelName: 'claude-3-5-sonnet-20240620',
|
|
14170
15055
|
modelDescription: 'Latest Claude model with great reasoning, coding, and language understanding capabilities. 200K context window. Optimized balance of intelligence and speed.',
|
|
14171
15056
|
pricing: {
|
|
14172
|
-
prompt: computeUsage(`$
|
|
14173
|
-
output: computeUsage(`$
|
|
15057
|
+
prompt: computeUsage(`$2.50 / 1M tokens`),
|
|
15058
|
+
output: computeUsage(`$12.50 / 1M tokens`),
|
|
14174
15059
|
},
|
|
14175
15060
|
},
|
|
14176
15061
|
{
|
|
@@ -14179,8 +15064,8 @@ const ANTHROPIC_CLAUDE_MODELS = exportJson({
|
|
|
14179
15064
|
modelName: 'claude-3-opus-20240229',
|
|
14180
15065
|
modelDescription: 'Most capable Claude model excelling at complex reasoning, coding, and detailed instruction following. 200K context window. Best for sophisticated tasks requiring nuanced understanding.',
|
|
14181
15066
|
pricing: {
|
|
14182
|
-
prompt: computeUsage(`$
|
|
14183
|
-
output: computeUsage(`$
|
|
15067
|
+
prompt: computeUsage(`$12.00 / 1M tokens`),
|
|
15068
|
+
output: computeUsage(`$60.00 / 1M tokens`),
|
|
14184
15069
|
},
|
|
14185
15070
|
},
|
|
14186
15071
|
{
|
|
@@ -14225,7 +15110,7 @@ const ANTHROPIC_CLAUDE_MODELS = exportJson({
|
|
|
14225
15110
|
},
|
|
14226
15111
|
{
|
|
14227
15112
|
modelVariant: 'CHAT',
|
|
14228
|
-
modelTitle: '
|
|
15113
|
+
modelTitle: 'Claude Instant 1.2',
|
|
14229
15114
|
modelName: 'claude-instant-1.2',
|
|
14230
15115
|
modelDescription: 'Older, faster Claude model optimized for high throughput applications. Lower cost but less capable than newer models. 100K context window.',
|
|
14231
15116
|
pricing: {
|
|
@@ -14239,8 +15124,8 @@ const ANTHROPIC_CLAUDE_MODELS = exportJson({
|
|
|
14239
15124
|
modelName: 'claude-3-7-sonnet-20250219',
|
|
14240
15125
|
modelDescription: 'Latest generation Claude model with advanced reasoning and language understanding. Enhanced capabilities over 3.5 with improved domain knowledge. 200K context window.',
|
|
14241
15126
|
pricing: {
|
|
14242
|
-
prompt: computeUsage(`$
|
|
14243
|
-
output: computeUsage(`$
|
|
15127
|
+
prompt: computeUsage(`$2.50 / 1M tokens`),
|
|
15128
|
+
output: computeUsage(`$12.50 / 1M tokens`),
|
|
14244
15129
|
},
|
|
14245
15130
|
},
|
|
14246
15131
|
{
|
|
@@ -14287,14 +15172,18 @@ function computeUsageCounts(content) {
|
|
|
14287
15172
|
/**
|
|
14288
15173
|
* Make UncertainNumber
|
|
14289
15174
|
*
|
|
14290
|
-
* @param value
|
|
15175
|
+
* @param value value of the uncertain number, if `NaN` or `undefined`, it will be set to 0 and `isUncertain=true`
|
|
15176
|
+
* @param isUncertain if `true`, the value is uncertain, otherwise depends on the value
|
|
14291
15177
|
*
|
|
14292
15178
|
* @private utility for initializating UncertainNumber
|
|
14293
15179
|
*/
|
|
14294
|
-
function uncertainNumber(value) {
|
|
15180
|
+
function uncertainNumber(value, isUncertain) {
|
|
14295
15181
|
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
14296
15182
|
return UNCERTAIN_ZERO_VALUE;
|
|
14297
15183
|
}
|
|
15184
|
+
if (isUncertain === true) {
|
|
15185
|
+
return { value, isUncertain };
|
|
15186
|
+
}
|
|
14298
15187
|
return { value };
|
|
14299
15188
|
}
|
|
14300
15189
|
|
|
@@ -14649,9 +15538,11 @@ const _AzureOpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
14649
15538
|
packageName: '@promptbook/azure-openai',
|
|
14650
15539
|
className: 'AzureOpenAiExecutionTools',
|
|
14651
15540
|
envVariables: ['AZUREOPENAI_RESOURCE_NAME', 'AZUREOPENAI_DEPLOYMENT_NAME', 'AZUREOPENAI_API_KEY'],
|
|
15541
|
+
trustLevel: 'CLOSED_BUSINESS',
|
|
15542
|
+
order: MODEL_ORDERS.NORMAL,
|
|
14652
15543
|
getBoilerplateConfiguration() {
|
|
14653
15544
|
return {
|
|
14654
|
-
title: 'Azure Open AI
|
|
15545
|
+
title: 'Azure Open AI',
|
|
14655
15546
|
packageName: '@promptbook/azure-openai',
|
|
14656
15547
|
className: 'AzureOpenAiExecutionTools',
|
|
14657
15548
|
options: {
|
|
@@ -14706,7 +15597,7 @@ const _AzureOpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
14706
15597
|
/**
|
|
14707
15598
|
* List of available OpenAI models with pricing
|
|
14708
15599
|
*
|
|
14709
|
-
* Note: Done at
|
|
15600
|
+
* Note: Done at 2025-05-06
|
|
14710
15601
|
*
|
|
14711
15602
|
* @see https://platform.openai.com/docs/models/
|
|
14712
15603
|
* @see https://openai.com/api/pricing/
|
|
@@ -14735,7 +15626,7 @@ const OPENAI_MODELS = exportJson({
|
|
|
14735
15626
|
modelDescription: 'Legacy completion model with strong performance on text generation tasks. Optimized for complex instructions and longer outputs.',
|
|
14736
15627
|
pricing: {
|
|
14737
15628
|
prompt: computeUsage(`$2.00 / 1M tokens`),
|
|
14738
|
-
output: computeUsage(`$2.00 / 1M tokens`),
|
|
15629
|
+
output: computeUsage(`$2.00 / 1M tokens`),
|
|
14739
15630
|
},
|
|
14740
15631
|
},
|
|
14741
15632
|
/**/
|
|
@@ -14877,8 +15768,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
14877
15768
|
modelName: 'gpt-3.5-turbo',
|
|
14878
15769
|
modelDescription: 'Latest version of GPT-3.5 Turbo with improved performance and instruction following capabilities. Default 4K context window with options for 16K.',
|
|
14879
15770
|
pricing: {
|
|
14880
|
-
prompt: computeUsage(`$
|
|
14881
|
-
output: computeUsage(`$
|
|
15771
|
+
prompt: computeUsage(`$0.50 / 1M tokens`),
|
|
15772
|
+
output: computeUsage(`$1.50 / 1M tokens`),
|
|
14882
15773
|
},
|
|
14883
15774
|
},
|
|
14884
15775
|
/**/
|
|
@@ -14902,7 +15793,7 @@ const OPENAI_MODELS = exportJson({
|
|
|
14902
15793
|
modelDescription: 'Efficient legacy completion model with a good balance of performance and speed. Suitable for straightforward text generation tasks.',
|
|
14903
15794
|
pricing: {
|
|
14904
15795
|
prompt: computeUsage(`$0.40 / 1M tokens`),
|
|
14905
|
-
output: computeUsage(`$0.40 / 1M tokens`),
|
|
15796
|
+
output: computeUsage(`$0.40 / 1M tokens`),
|
|
14906
15797
|
},
|
|
14907
15798
|
},
|
|
14908
15799
|
/**/
|
|
@@ -14956,7 +15847,7 @@ const OPENAI_MODELS = exportJson({
|
|
|
14956
15847
|
modelDescription: 'Preview version of GPT-4 Turbo that points to the latest model version. Features improved instruction following, 128K token context window and lower latency.',
|
|
14957
15848
|
pricing: {
|
|
14958
15849
|
prompt: computeUsage(`$10.00 / 1M tokens`),
|
|
14959
|
-
output: computeUsage(`$30.00 / 1M tokens`),
|
|
15850
|
+
output: computeUsage(`$30.00 / 1M tokens`),
|
|
14960
15851
|
},
|
|
14961
15852
|
},
|
|
14962
15853
|
/**/
|
|
@@ -14967,7 +15858,7 @@ const OPENAI_MODELS = exportJson({
|
|
|
14967
15858
|
modelName: 'text-embedding-3-large',
|
|
14968
15859
|
modelDescription: "OpenAI's most capable text embedding model designed for high-quality embeddings for complex similarity tasks and information retrieval.",
|
|
14969
15860
|
pricing: {
|
|
14970
|
-
prompt: computeUsage(`$0.13
|
|
15861
|
+
prompt: computeUsage(`$0.13 / 1M tokens`),
|
|
14971
15862
|
// TODO: [🏏] Leverage the batch API @see https://platform.openai.com/docs/guides/batch
|
|
14972
15863
|
output: 0, // <- Note: [🆖] In Embedding models you dont pay for output
|
|
14973
15864
|
},
|
|
@@ -15060,8 +15951,8 @@ const OPENAI_MODELS = exportJson({
|
|
|
15060
15951
|
modelName: 'gpt-4o-mini',
|
|
15061
15952
|
modelDescription: 'Smaller, more cost-effective version of GPT-4o with good performance across text, vision, and audio tasks at reduced complexity.',
|
|
15062
15953
|
pricing: {
|
|
15063
|
-
prompt: computeUsage(`$
|
|
15064
|
-
output: computeUsage(`$
|
|
15954
|
+
prompt: computeUsage(`$0.15 / 1M tokens`),
|
|
15955
|
+
output: computeUsage(`$0.60 / 1M tokens`),
|
|
15065
15956
|
},
|
|
15066
15957
|
},
|
|
15067
15958
|
/**/
|
|
@@ -15107,10 +15998,10 @@ const OPENAI_MODELS = exportJson({
|
|
|
15107
15998
|
modelVariant: 'CHAT',
|
|
15108
15999
|
modelTitle: 'o1',
|
|
15109
16000
|
modelName: 'o1',
|
|
16001
|
+
modelDescription: "OpenAI's advanced reasoning model focused on logic and problem-solving. Designed for complex analytical tasks with rigorous step-by-step reasoning. 128K context window.",
|
|
15110
16002
|
pricing: {
|
|
15111
|
-
prompt: computeUsage(`$
|
|
15112
|
-
output: computeUsage(`$
|
|
15113
|
-
// <- TODO: !! Unsure, check the pricing
|
|
16003
|
+
prompt: computeUsage(`$15.00 / 1M tokens`),
|
|
16004
|
+
output: computeUsage(`$60.00 / 1M tokens`),
|
|
15114
16005
|
},
|
|
15115
16006
|
},
|
|
15116
16007
|
/**/
|
|
@@ -15119,7 +16010,7 @@ const OPENAI_MODELS = exportJson({
|
|
|
15119
16010
|
modelVariant: 'CHAT',
|
|
15120
16011
|
modelTitle: 'o3-mini',
|
|
15121
16012
|
modelName: 'o3-mini',
|
|
15122
|
-
modelDescription: '
|
|
16013
|
+
modelDescription: 'Cost-effective reasoning model optimized for academic and scientific problem-solving. Efficient performance on STEM tasks with deep mathematical and scientific knowledge. 128K context window.',
|
|
15123
16014
|
pricing: {
|
|
15124
16015
|
prompt: computeUsage(`$3.00 / 1M tokens`),
|
|
15125
16016
|
output: computeUsage(`$12.00 / 1M tokens`),
|
|
@@ -15186,6 +16077,10 @@ class AzureOpenAiExecutionTools {
|
|
|
15186
16077
|
* OpenAI Azure API client.
|
|
15187
16078
|
*/
|
|
15188
16079
|
this.client = null;
|
|
16080
|
+
// TODO: Allow configuring rate limits via options
|
|
16081
|
+
this.limiter = new Bottleneck({
|
|
16082
|
+
minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
|
|
16083
|
+
});
|
|
15189
16084
|
}
|
|
15190
16085
|
get title() {
|
|
15191
16086
|
return 'Azure OpenAI';
|
|
@@ -15263,7 +16158,9 @@ class AzureOpenAiExecutionTools {
|
|
|
15263
16158
|
console.info(colors.bgWhite('messages'), JSON.stringify(messages, null, 4));
|
|
15264
16159
|
}
|
|
15265
16160
|
const rawRequest = [modelName, messages, modelSettings];
|
|
15266
|
-
const rawResponse = await this.
|
|
16161
|
+
const rawResponse = await this.limiter
|
|
16162
|
+
.schedule(() => this.withTimeout(client.getChatCompletions(...rawRequest)))
|
|
16163
|
+
.catch((error) => {
|
|
15267
16164
|
if (this.options.isVerbose) {
|
|
15268
16165
|
console.info(colors.bgRed('error'), error);
|
|
15269
16166
|
}
|
|
@@ -15359,7 +16256,9 @@ class AzureOpenAiExecutionTools {
|
|
|
15359
16256
|
[rawPromptContent],
|
|
15360
16257
|
modelSettings,
|
|
15361
16258
|
];
|
|
15362
|
-
const rawResponse = await this.
|
|
16259
|
+
const rawResponse = await this.limiter
|
|
16260
|
+
.schedule(() => this.withTimeout(client.getCompletions(...rawRequest)))
|
|
16261
|
+
.catch((error) => {
|
|
15363
16262
|
if (this.options.isVerbose) {
|
|
15364
16263
|
console.info(colors.bgRed('error'), error);
|
|
15365
16264
|
}
|
|
@@ -15499,9 +16398,11 @@ const _DeepseekMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
15499
16398
|
packageName: '@promptbook/deepseek',
|
|
15500
16399
|
className: 'DeepseekExecutionTools',
|
|
15501
16400
|
envVariables: ['DEEPSEEK_GENERATIVE_AI_API_KEY'],
|
|
16401
|
+
trustLevel: 'UNTRUSTED',
|
|
16402
|
+
order: MODEL_ORDERS.NORMAL,
|
|
15502
16403
|
getBoilerplateConfiguration() {
|
|
15503
16404
|
return {
|
|
15504
|
-
title: 'Deepseek
|
|
16405
|
+
title: 'Deepseek',
|
|
15505
16406
|
packageName: '@promptbook/deepseek',
|
|
15506
16407
|
className: 'DeepseekExecutionTools',
|
|
15507
16408
|
options: {
|
|
@@ -15698,6 +16599,67 @@ function createExecutionToolsFromVercelProvider(options) {
|
|
|
15698
16599
|
};
|
|
15699
16600
|
}
|
|
15700
16601
|
|
|
16602
|
+
/**
|
|
16603
|
+
* List of available Deepseek models with descriptions
|
|
16604
|
+
*
|
|
16605
|
+
* Note: Done at 2025-05-06
|
|
16606
|
+
*
|
|
16607
|
+
* @see https://www.deepseek.com/models
|
|
16608
|
+
* @public exported from `@promptbook/deepseek`
|
|
16609
|
+
*/
|
|
16610
|
+
const DEEPSEEK_MODELS = exportJson({
|
|
16611
|
+
name: 'DEEPSEEK_MODELS',
|
|
16612
|
+
value: [
|
|
16613
|
+
{
|
|
16614
|
+
modelVariant: 'CHAT',
|
|
16615
|
+
modelTitle: 'Deepseek Chat',
|
|
16616
|
+
modelName: 'deepseek-chat',
|
|
16617
|
+
modelDescription: 'General-purpose language model with strong performance across conversation, reasoning, and content generation. 128K context window with excellent instruction following capabilities.',
|
|
16618
|
+
pricing: {
|
|
16619
|
+
prompt: computeUsage(`$0.80 / 1M tokens`),
|
|
16620
|
+
output: computeUsage(`$1.60 / 1M tokens`),
|
|
16621
|
+
},
|
|
16622
|
+
},
|
|
16623
|
+
{
|
|
16624
|
+
modelVariant: 'CHAT',
|
|
16625
|
+
modelTitle: 'Deepseek Reasoner',
|
|
16626
|
+
modelName: 'deepseek-reasoner',
|
|
16627
|
+
modelDescription: 'Specialized model focused on complex reasoning tasks like mathematical problem-solving and logical analysis. Enhanced step-by-step reasoning with explicit chain-of-thought processes. 128K context window.',
|
|
16628
|
+
pricing: {
|
|
16629
|
+
prompt: computeUsage(`$3.50 / 1M tokens`),
|
|
16630
|
+
output: computeUsage(`$7.00 / 1M tokens`),
|
|
16631
|
+
},
|
|
16632
|
+
},
|
|
16633
|
+
{
|
|
16634
|
+
modelVariant: 'CHAT',
|
|
16635
|
+
modelTitle: 'DeepSeek V3',
|
|
16636
|
+
modelName: 'deepseek-v3-0324',
|
|
16637
|
+
modelDescription: 'Advanced general-purpose model with improved reasoning, coding abilities, and multimodal understanding. Built on the latest DeepSeek architecture with enhanced knowledge representation.',
|
|
16638
|
+
pricing: {
|
|
16639
|
+
prompt: computeUsage(`$1.50 / 1M tokens`),
|
|
16640
|
+
output: computeUsage(`$3.00 / 1M tokens`),
|
|
16641
|
+
},
|
|
16642
|
+
},
|
|
16643
|
+
{
|
|
16644
|
+
modelVariant: 'CHAT',
|
|
16645
|
+
modelTitle: 'DeepSeek R1',
|
|
16646
|
+
modelName: 'deepseek-r1',
|
|
16647
|
+
modelDescription: 'Research-focused model optimized for scientific problem-solving and analytical tasks. Excellent performance on tasks requiring domain-specific expertise and critical thinking.',
|
|
16648
|
+
pricing: {
|
|
16649
|
+
prompt: computeUsage(`$5.00 / 1M tokens`),
|
|
16650
|
+
output: computeUsage(`$10.00 / 1M tokens`),
|
|
16651
|
+
},
|
|
16652
|
+
},
|
|
16653
|
+
// <- [🕕]
|
|
16654
|
+
],
|
|
16655
|
+
});
|
|
16656
|
+
/**
|
|
16657
|
+
* TODO: [🧠] Add information about context window sizes, capabilities, and relative performance characteristics
|
|
16658
|
+
* TODO: [🎰] Some mechanism to auto-update available models
|
|
16659
|
+
* TODO: [🧠] Verify pricing information is current with Deepseek's official documentation
|
|
16660
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
16661
|
+
*/
|
|
16662
|
+
|
|
15701
16663
|
/**
|
|
15702
16664
|
* Execution Tools for calling Deepseek API.
|
|
15703
16665
|
*
|
|
@@ -15719,18 +16681,7 @@ const createDeepseekExecutionTools = Object.assign((options) => {
|
|
|
15719
16681
|
title: 'Deepseek',
|
|
15720
16682
|
description: 'Implementation of Deepseek models',
|
|
15721
16683
|
vercelProvider: deepseekVercelProvider,
|
|
15722
|
-
availableModels:
|
|
15723
|
-
{
|
|
15724
|
-
modelName: 'deepseek-chat',
|
|
15725
|
-
modelVariant: 'CHAT',
|
|
15726
|
-
},
|
|
15727
|
-
{
|
|
15728
|
-
modelName: 'deepseek-reasoner',
|
|
15729
|
-
modelVariant: 'CHAT',
|
|
15730
|
-
},
|
|
15731
|
-
// <- [🕕]
|
|
15732
|
-
// <- TODO: How picking of the default model looks like in `createExecutionToolsFromVercelProvider`
|
|
15733
|
-
],
|
|
16684
|
+
availableModels: DEEPSEEK_MODELS,
|
|
15734
16685
|
...options,
|
|
15735
16686
|
});
|
|
15736
16687
|
}, {
|
|
@@ -15770,9 +16721,11 @@ const _GoogleMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
15770
16721
|
packageName: '@promptbook/google',
|
|
15771
16722
|
className: 'GoogleExecutionTools',
|
|
15772
16723
|
envVariables: ['GOOGLE_GENERATIVE_AI_API_KEY'],
|
|
16724
|
+
trustLevel: 'CLOSED',
|
|
16725
|
+
order: MODEL_ORDERS.NORMAL,
|
|
15773
16726
|
getBoilerplateConfiguration() {
|
|
15774
16727
|
return {
|
|
15775
|
-
title: 'Google Gemini
|
|
16728
|
+
title: 'Google Gemini',
|
|
15776
16729
|
packageName: '@promptbook/google',
|
|
15777
16730
|
className: 'GoogleExecutionTools',
|
|
15778
16731
|
options: {
|
|
@@ -15805,6 +16758,173 @@ const _GoogleMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
15805
16758
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
15806
16759
|
*/
|
|
15807
16760
|
|
|
16761
|
+
/**
|
|
16762
|
+
* List of available Google models with descriptions
|
|
16763
|
+
*
|
|
16764
|
+
* Note: Done at 2025-05-06
|
|
16765
|
+
*
|
|
16766
|
+
* @see https://ai.google.dev/models/gemini
|
|
16767
|
+
* @public exported from `@promptbook/google`
|
|
16768
|
+
*/
|
|
16769
|
+
const GOOGLE_MODELS = exportJson({
|
|
16770
|
+
name: 'GOOGLE_MODELS',
|
|
16771
|
+
value: [
|
|
16772
|
+
{
|
|
16773
|
+
modelVariant: 'CHAT',
|
|
16774
|
+
modelTitle: 'Gemini 2.5 Pro',
|
|
16775
|
+
modelName: 'gemini-2.5-pro-preview-03-25',
|
|
16776
|
+
modelDescription: 'Latest advanced multimodal model with exceptional reasoning, tool use, and instruction following. 1M token context window with improved vision capabilities for complex visual tasks.',
|
|
16777
|
+
pricing: {
|
|
16778
|
+
prompt: computeUsage(`$8.00 / 1M tokens`),
|
|
16779
|
+
output: computeUsage(`$24.00 / 1M tokens`),
|
|
16780
|
+
},
|
|
16781
|
+
},
|
|
16782
|
+
{
|
|
16783
|
+
modelVariant: 'CHAT',
|
|
16784
|
+
modelTitle: 'Gemini 2.0 Flash',
|
|
16785
|
+
modelName: 'gemini-2.0-flash',
|
|
16786
|
+
modelDescription: 'Fast, efficient model optimized for rapid response times. Good balance between performance and cost, with strong capabilities across text, code, and reasoning tasks. 128K context window.',
|
|
16787
|
+
pricing: {
|
|
16788
|
+
prompt: computeUsage(`$0.35 / 1M tokens`),
|
|
16789
|
+
output: computeUsage(`$1.05 / 1M tokens`),
|
|
16790
|
+
},
|
|
16791
|
+
},
|
|
16792
|
+
{
|
|
16793
|
+
modelVariant: 'CHAT',
|
|
16794
|
+
modelTitle: 'Gemini 2.0 Flash Lite',
|
|
16795
|
+
modelName: 'gemini-2.0-flash-lite',
|
|
16796
|
+
modelDescription: 'Streamlined version of Gemini 2.0 Flash, designed for extremely low-latency applications and edge deployments. Optimized for efficiency while maintaining core capabilities.',
|
|
16797
|
+
pricing: {
|
|
16798
|
+
prompt: computeUsage(`$0.20 / 1M tokens`),
|
|
16799
|
+
output: computeUsage(`$0.60 / 1M tokens`),
|
|
16800
|
+
},
|
|
16801
|
+
},
|
|
16802
|
+
{
|
|
16803
|
+
modelVariant: 'CHAT',
|
|
16804
|
+
modelTitle: 'Gemini 2.0 Flash Thinking',
|
|
16805
|
+
modelName: 'gemini-2.0-flash-thinking-exp-01-21',
|
|
16806
|
+
modelDescription: 'Experimental model focused on enhanced reasoning with explicit chain-of-thought processes. Designed for tasks requiring structured thinking and problem-solving approaches.',
|
|
16807
|
+
pricing: {
|
|
16808
|
+
prompt: computeUsage(`$0.35 / 1M tokens`),
|
|
16809
|
+
output: computeUsage(`$1.05 / 1M tokens`),
|
|
16810
|
+
},
|
|
16811
|
+
},
|
|
16812
|
+
{
|
|
16813
|
+
modelVariant: 'CHAT',
|
|
16814
|
+
modelTitle: 'Gemini 1.5 Flash',
|
|
16815
|
+
modelName: 'gemini-1.5-flash',
|
|
16816
|
+
modelDescription: 'Efficient model balancing speed and quality for general-purpose applications. 1M token context window with good multimodal capabilities and quick response times.',
|
|
16817
|
+
pricing: {
|
|
16818
|
+
prompt: computeUsage(`$0.25 / 1M tokens`),
|
|
16819
|
+
output: computeUsage(`$0.75 / 1M tokens`),
|
|
16820
|
+
},
|
|
16821
|
+
},
|
|
16822
|
+
{
|
|
16823
|
+
modelVariant: 'CHAT',
|
|
16824
|
+
modelTitle: 'Gemini 1.5 Flash Latest',
|
|
16825
|
+
modelName: 'gemini-1.5-flash-latest',
|
|
16826
|
+
modelDescription: 'Points to the latest version of Gemini 1.5 Flash, ensuring access to the most recent improvements and bug fixes while maintaining stable interfaces.',
|
|
16827
|
+
},
|
|
16828
|
+
{
|
|
16829
|
+
modelVariant: 'CHAT',
|
|
16830
|
+
modelTitle: 'Gemini 1.5 Flash 001',
|
|
16831
|
+
modelName: 'gemini-1.5-flash-001',
|
|
16832
|
+
modelDescription: 'First stable release of Gemini 1.5 Flash model with reliable performance characteristics for production applications. 1M token context window.',
|
|
16833
|
+
},
|
|
16834
|
+
{
|
|
16835
|
+
modelVariant: 'CHAT',
|
|
16836
|
+
modelTitle: 'Gemini 1.5 Flash 002',
|
|
16837
|
+
modelName: 'gemini-1.5-flash-002',
|
|
16838
|
+
modelDescription: 'Improved version of Gemini 1.5 Flash with enhanced instruction following and more consistent outputs. Refined for better application integration.',
|
|
16839
|
+
},
|
|
16840
|
+
{
|
|
16841
|
+
modelVariant: 'CHAT',
|
|
16842
|
+
modelTitle: 'Gemini 1.5 Flash Exp',
|
|
16843
|
+
modelName: 'gemini-1.5-flash-exp-0827',
|
|
16844
|
+
modelDescription: 'Experimental version of Gemini 1.5 Flash with new capabilities being tested. May offer improved performance but with potential behavior differences from stable releases.',
|
|
16845
|
+
},
|
|
16846
|
+
{
|
|
16847
|
+
modelVariant: 'CHAT',
|
|
16848
|
+
modelTitle: 'Gemini 1.5 Flash 8B',
|
|
16849
|
+
modelName: 'gemini-1.5-flash-8b',
|
|
16850
|
+
modelDescription: 'Compact 8B parameter model optimized for efficiency and deployment in resource-constrained environments. Good performance despite smaller size.',
|
|
16851
|
+
},
|
|
16852
|
+
{
|
|
16853
|
+
modelVariant: 'CHAT',
|
|
16854
|
+
modelTitle: 'Gemini 1.5 Flash 8B Latest',
|
|
16855
|
+
modelName: 'gemini-1.5-flash-8b-latest',
|
|
16856
|
+
modelDescription: 'Points to the most recent version of the compact 8B parameter model, providing latest improvements while maintaining a small footprint.',
|
|
16857
|
+
},
|
|
16858
|
+
{
|
|
16859
|
+
modelVariant: 'CHAT',
|
|
16860
|
+
modelTitle: 'Gemini 1.5 Flash 8B Exp',
|
|
16861
|
+
modelName: 'gemini-1.5-flash-8b-exp-0924',
|
|
16862
|
+
modelDescription: 'Experimental version of the 8B parameter model with new capabilities and optimizations being evaluated for future stable releases.',
|
|
16863
|
+
},
|
|
16864
|
+
{
|
|
16865
|
+
modelVariant: 'CHAT',
|
|
16866
|
+
modelTitle: 'Gemini 1.5 Flash 8B Exp',
|
|
16867
|
+
modelName: 'gemini-1.5-flash-8b-exp-0827',
|
|
16868
|
+
modelDescription: 'August experimental release of the efficient 8B parameter model with specific improvements to reasoning capabilities and response quality.',
|
|
16869
|
+
},
|
|
16870
|
+
{
|
|
16871
|
+
modelVariant: 'CHAT',
|
|
16872
|
+
modelTitle: 'Gemini 1.5 Pro Latest',
|
|
16873
|
+
modelName: 'gemini-1.5-pro-latest',
|
|
16874
|
+
modelDescription: 'Points to the most recent version of the flagship Gemini 1.5 Pro model, ensuring access to the latest capabilities and improvements.',
|
|
16875
|
+
pricing: {
|
|
16876
|
+
prompt: computeUsage(`$7.00 / 1M tokens`),
|
|
16877
|
+
output: computeUsage(`$21.00 / 1M tokens`),
|
|
16878
|
+
},
|
|
16879
|
+
},
|
|
16880
|
+
{
|
|
16881
|
+
modelVariant: 'CHAT',
|
|
16882
|
+
modelTitle: 'Gemini 1.5 Pro',
|
|
16883
|
+
modelName: 'gemini-1.5-pro',
|
|
16884
|
+
modelDescription: 'Flagship multimodal model with strong performance across text, code, vision, and audio tasks. 1M token context window with excellent reasoning capabilities.',
|
|
16885
|
+
pricing: {
|
|
16886
|
+
prompt: computeUsage(`$6.00 / 1M tokens`),
|
|
16887
|
+
output: computeUsage(`$18.00 / 1M tokens`),
|
|
16888
|
+
},
|
|
16889
|
+
},
|
|
16890
|
+
{
|
|
16891
|
+
modelVariant: 'CHAT',
|
|
16892
|
+
modelTitle: 'Gemini 1.5 Pro 001',
|
|
16893
|
+
modelName: 'gemini-1.5-pro-001',
|
|
16894
|
+
modelDescription: 'First stable release of Gemini 1.5 Pro with consistent performance characteristics and reliable behavior for production applications.',
|
|
16895
|
+
},
|
|
16896
|
+
{
|
|
16897
|
+
modelVariant: 'CHAT',
|
|
16898
|
+
modelTitle: 'Gemini 1.5 Pro 002',
|
|
16899
|
+
modelName: 'gemini-1.5-pro-002',
|
|
16900
|
+
modelDescription: 'Refined version of Gemini 1.5 Pro with improved instruction following, better multimodal understanding, and more consistent outputs.',
|
|
16901
|
+
},
|
|
16902
|
+
{
|
|
16903
|
+
modelVariant: 'CHAT',
|
|
16904
|
+
modelTitle: 'Gemini 1.5 Pro Exp',
|
|
16905
|
+
modelName: 'gemini-1.5-pro-exp-0827',
|
|
16906
|
+
modelDescription: 'Experimental version of Gemini 1.5 Pro with new capabilities and optimizations being tested before wider release. May offer improved performance.',
|
|
16907
|
+
},
|
|
16908
|
+
{
|
|
16909
|
+
modelVariant: 'CHAT',
|
|
16910
|
+
modelTitle: 'Gemini 1.0 Pro',
|
|
16911
|
+
modelName: 'gemini-1.0-pro',
|
|
16912
|
+
modelDescription: 'Original Gemini series foundation model with solid multimodal capabilities. 32K context window with good performance on text, code, and basic vision tasks.',
|
|
16913
|
+
pricing: {
|
|
16914
|
+
prompt: computeUsage(`$0.35 / 1M tokens`),
|
|
16915
|
+
output: computeUsage(`$1.05 / 1M tokens`),
|
|
16916
|
+
},
|
|
16917
|
+
},
|
|
16918
|
+
// <- [🕕]
|
|
16919
|
+
],
|
|
16920
|
+
});
|
|
16921
|
+
/**
|
|
16922
|
+
* TODO: [🧠] Add information about context window sizes, capabilities, and relative performance characteristics
|
|
16923
|
+
* TODO: [🎰] Some mechanism to auto-update available models
|
|
16924
|
+
* TODO: [🧠] Verify pricing information is current with Google's official documentation
|
|
16925
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
16926
|
+
*/
|
|
16927
|
+
|
|
15808
16928
|
/**
|
|
15809
16929
|
* Execution Tools for calling Google Gemini API.
|
|
15810
16930
|
*
|
|
@@ -15826,29 +16946,7 @@ const createGoogleExecutionTools = Object.assign((options) => {
|
|
|
15826
16946
|
title: 'Google',
|
|
15827
16947
|
description: 'Implementation of Google models',
|
|
15828
16948
|
vercelProvider: googleGeminiVercelProvider,
|
|
15829
|
-
availableModels:
|
|
15830
|
-
// TODO: [🕘] Maybe list models in same way as in other providers - in separate file with metadata
|
|
15831
|
-
'gemini-2.5-pro-preview-03-25',
|
|
15832
|
-
'gemini-2.0-flash',
|
|
15833
|
-
'gemini-2.0-flash-lite',
|
|
15834
|
-
'gemini-2.0-flash-thinking-exp-01-21',
|
|
15835
|
-
'gemini-1.5-flash',
|
|
15836
|
-
'gemini-1.5-flash-latest',
|
|
15837
|
-
'gemini-1.5-flash-001',
|
|
15838
|
-
'gemini-1.5-flash-002',
|
|
15839
|
-
'gemini-1.5-flash-exp-0827',
|
|
15840
|
-
'gemini-1.5-flash-8b',
|
|
15841
|
-
'gemini-1.5-flash-8b-latest',
|
|
15842
|
-
'gemini-1.5-flash-8b-exp-0924',
|
|
15843
|
-
'gemini-1.5-flash-8b-exp-0827',
|
|
15844
|
-
'gemini-1.5-pro-latest',
|
|
15845
|
-
'gemini-1.5-pro',
|
|
15846
|
-
'gemini-1.5-pro-001',
|
|
15847
|
-
'gemini-1.5-pro-002',
|
|
15848
|
-
'gemini-1.5-pro-exp-0827',
|
|
15849
|
-
'gemini-1.0-pro',
|
|
15850
|
-
// <- [🕕]
|
|
15851
|
-
].map((modelName) => ({ modelName, modelVariant: 'CHAT' })),
|
|
16949
|
+
availableModels: GOOGLE_MODELS,
|
|
15852
16950
|
...options,
|
|
15853
16951
|
});
|
|
15854
16952
|
}, {
|
|
@@ -15888,13 +16986,16 @@ const _OpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
15888
16986
|
packageName: '@promptbook/openai',
|
|
15889
16987
|
className: 'OpenAiExecutionTools',
|
|
15890
16988
|
envVariables: ['OPENAI_API_KEY'],
|
|
16989
|
+
trustLevel: 'CLOSED',
|
|
16990
|
+
order: MODEL_ORDERS.TOP_TIER,
|
|
15891
16991
|
getBoilerplateConfiguration() {
|
|
15892
16992
|
return {
|
|
15893
|
-
title: 'Open AI
|
|
16993
|
+
title: 'Open AI',
|
|
15894
16994
|
packageName: '@promptbook/openai',
|
|
15895
16995
|
className: 'OpenAiExecutionTools',
|
|
15896
16996
|
options: {
|
|
15897
16997
|
apiKey: 'sk-',
|
|
16998
|
+
maxRequestsPerMinute: DEFAULT_MAX_REQUESTS_PER_MINUTE,
|
|
15898
16999
|
},
|
|
15899
17000
|
};
|
|
15900
17001
|
},
|
|
@@ -15914,9 +17015,9 @@ const _OpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
15914
17015
|
},
|
|
15915
17016
|
});
|
|
15916
17017
|
/**
|
|
15917
|
-
*
|
|
17018
|
+
* Registration of the OpenAI Assistant metadata
|
|
15918
17019
|
*
|
|
15919
|
-
* Note: [🏐] Configurations registrations are done in
|
|
17020
|
+
* Note: [🏐] Configurations registrations are done in the metadata registration section, but the constructor registration is handled separately.
|
|
15920
17021
|
*
|
|
15921
17022
|
* @public exported from `@promptbook/core`
|
|
15922
17023
|
* @public exported from `@promptbook/wizzard`
|
|
@@ -15928,9 +17029,11 @@ const _OpenAiAssistantMetadataRegistration = $llmToolsMetadataRegister.register(
|
|
|
15928
17029
|
className: 'OpenAiAssistantExecutionTools',
|
|
15929
17030
|
envVariables: null,
|
|
15930
17031
|
// <- TODO: ['OPENAI_API_KEY', 'OPENAI_ASSISTANT_ID']
|
|
17032
|
+
trustLevel: 'CLOSED',
|
|
17033
|
+
order: MODEL_ORDERS.NORMAL,
|
|
15931
17034
|
getBoilerplateConfiguration() {
|
|
15932
17035
|
return {
|
|
15933
|
-
title: 'Open AI Assistant
|
|
17036
|
+
title: 'Open AI Assistant',
|
|
15934
17037
|
packageName: '@promptbook/openai',
|
|
15935
17038
|
className: 'OpenAiAssistantExecutionTools',
|
|
15936
17039
|
options: {
|
|
@@ -15975,20 +17078,39 @@ function computeOpenAiUsage(promptContent, // <- Note: Intentionally using [] to
|
|
|
15975
17078
|
resultContent, rawResponse) {
|
|
15976
17079
|
var _a, _b;
|
|
15977
17080
|
if (rawResponse.usage === undefined) {
|
|
17081
|
+
console.log('!!! computeOpenAiUsage', 'The usage is not defined in the response from OpenAI');
|
|
15978
17082
|
throw new PipelineExecutionError('The usage is not defined in the response from OpenAI');
|
|
15979
17083
|
}
|
|
15980
17084
|
if (((_a = rawResponse.usage) === null || _a === void 0 ? void 0 : _a.prompt_tokens) === undefined) {
|
|
17085
|
+
console.log('!!! computeOpenAiUsage', 'In OpenAI response `usage.prompt_tokens` not defined');
|
|
15981
17086
|
throw new PipelineExecutionError('In OpenAI response `usage.prompt_tokens` not defined');
|
|
15982
17087
|
}
|
|
15983
17088
|
const inputTokens = rawResponse.usage.prompt_tokens;
|
|
15984
17089
|
const outputTokens = ((_b = rawResponse.usage) === null || _b === void 0 ? void 0 : _b.completion_tokens) || 0;
|
|
15985
|
-
|
|
17090
|
+
let isUncertain = false;
|
|
17091
|
+
let modelInfo = OPENAI_MODELS.find((model) => model.modelName === rawResponse.model);
|
|
17092
|
+
if (modelInfo === undefined) {
|
|
17093
|
+
// Note: Model is not in the list of known models, fallback to the family of the models and mark price as uncertain
|
|
17094
|
+
modelInfo = OPENAI_MODELS.find((model) => (rawResponse.model || SALT_NONCE).startsWith(model.modelName));
|
|
17095
|
+
if (modelInfo !== undefined) {
|
|
17096
|
+
isUncertain = true;
|
|
17097
|
+
}
|
|
17098
|
+
}
|
|
17099
|
+
console.log('!!! computeOpenAiUsage', {
|
|
17100
|
+
inputTokens,
|
|
17101
|
+
outputTokens,
|
|
17102
|
+
rawResponse,
|
|
17103
|
+
'rawResponse.model': rawResponse.model,
|
|
17104
|
+
OPENAI_MODELS,
|
|
17105
|
+
resultContent,
|
|
17106
|
+
modelInfo,
|
|
17107
|
+
});
|
|
15986
17108
|
let price;
|
|
15987
17109
|
if (modelInfo === undefined || modelInfo.pricing === undefined) {
|
|
15988
17110
|
price = uncertainNumber();
|
|
15989
17111
|
}
|
|
15990
17112
|
else {
|
|
15991
|
-
price = uncertainNumber(inputTokens * modelInfo.pricing.prompt + outputTokens * modelInfo.pricing.output);
|
|
17113
|
+
price = uncertainNumber(inputTokens * modelInfo.pricing.prompt + outputTokens * modelInfo.pricing.output, isUncertain);
|
|
15992
17114
|
}
|
|
15993
17115
|
return {
|
|
15994
17116
|
price,
|
|
@@ -16023,6 +17145,10 @@ class OpenAiExecutionTools {
|
|
|
16023
17145
|
* OpenAI API client.
|
|
16024
17146
|
*/
|
|
16025
17147
|
this.client = null;
|
|
17148
|
+
// TODO: Allow configuring rate limits via options
|
|
17149
|
+
this.limiter = new Bottleneck({
|
|
17150
|
+
minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
|
|
17151
|
+
});
|
|
16026
17152
|
}
|
|
16027
17153
|
get title() {
|
|
16028
17154
|
return 'OpenAI';
|
|
@@ -16126,7 +17252,9 @@ class OpenAiExecutionTools {
|
|
|
16126
17252
|
if (this.options.isVerbose) {
|
|
16127
17253
|
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
16128
17254
|
}
|
|
16129
|
-
const rawResponse = await
|
|
17255
|
+
const rawResponse = await this.limiter
|
|
17256
|
+
.schedule(() => client.chat.completions.create(rawRequest))
|
|
17257
|
+
.catch((error) => {
|
|
16130
17258
|
assertsError(error);
|
|
16131
17259
|
if (this.options.isVerbose) {
|
|
16132
17260
|
console.info(colors.bgRed('error'), error);
|
|
@@ -16203,7 +17331,9 @@ class OpenAiExecutionTools {
|
|
|
16203
17331
|
if (this.options.isVerbose) {
|
|
16204
17332
|
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
16205
17333
|
}
|
|
16206
|
-
const rawResponse = await
|
|
17334
|
+
const rawResponse = await this.limiter
|
|
17335
|
+
.schedule(() => client.completions.create(rawRequest))
|
|
17336
|
+
.catch((error) => {
|
|
16207
17337
|
assertsError(error);
|
|
16208
17338
|
if (this.options.isVerbose) {
|
|
16209
17339
|
console.info(colors.bgRed('error'), error);
|
|
@@ -16267,7 +17397,9 @@ class OpenAiExecutionTools {
|
|
|
16267
17397
|
if (this.options.isVerbose) {
|
|
16268
17398
|
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
16269
17399
|
}
|
|
16270
|
-
const rawResponse = await
|
|
17400
|
+
const rawResponse = await this.limiter
|
|
17401
|
+
.schedule(() => client.embeddings.create(rawRequest))
|
|
17402
|
+
.catch((error) => {
|
|
16271
17403
|
assertsError(error);
|
|
16272
17404
|
if (this.options.isVerbose) {
|
|
16273
17405
|
console.info(colors.bgRed('error'), error);
|
|
@@ -16365,6 +17497,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
16365
17497
|
constructor(options) {
|
|
16366
17498
|
super(options);
|
|
16367
17499
|
this.assistantId = options.assistantId;
|
|
17500
|
+
// TODO: [👱] Make limiter same as in `OpenAiExecutionTools`
|
|
16368
17501
|
}
|
|
16369
17502
|
get title() {
|
|
16370
17503
|
return 'OpenAI Assistant';
|
|
@@ -16566,9 +17699,9 @@ const createOpenAiExecutionTools = Object.assign((options) => {
|
|
|
16566
17699
|
*/
|
|
16567
17700
|
const _OpenAiRegistration = $llmToolsRegister.register(createOpenAiExecutionTools);
|
|
16568
17701
|
/**
|
|
16569
|
-
*
|
|
17702
|
+
* Registration of the OpenAI Assistant provider
|
|
16570
17703
|
*
|
|
16571
|
-
* Note: [🏐] Configurations registrations are done in
|
|
17704
|
+
* Note: [🏐] Configurations registrations are done in register-constructor.ts BUT constructor register-constructor.ts
|
|
16572
17705
|
*
|
|
16573
17706
|
* @public exported from `@promptbook/openai`
|
|
16574
17707
|
* @public exported from `@promptbook/wizzard`
|
|
@@ -16581,9 +17714,8 @@ const _OpenAiAssistantRegistration = $llmToolsRegister.register(createOpenAiAssi
|
|
|
16581
17714
|
*/
|
|
16582
17715
|
|
|
16583
17716
|
/**
|
|
16584
|
-
*
|
|
16585
|
-
*
|
|
16586
|
-
* Note: It also checks if directory exists and creates it if not
|
|
17717
|
+
* Retrieves an intermediate source for a scraper based on the knowledge source.
|
|
17718
|
+
* Manages the caching and retrieval of intermediate scraper results for optimized performance.
|
|
16587
17719
|
*
|
|
16588
17720
|
* @private as internal utility for scrapers
|
|
16589
17721
|
*/
|
|
@@ -16810,14 +17942,14 @@ const boilerplateScraperMetadata = $deepFreeze({
|
|
|
16810
17942
|
packageName: '@promptbook/boilerplate',
|
|
16811
17943
|
className: 'BoilerplateScraper',
|
|
16812
17944
|
mimeTypes: [
|
|
16813
|
-
'
|
|
16814
|
-
// <- TODO:
|
|
17945
|
+
'@@/@@',
|
|
17946
|
+
// <- TODO: @@ Add compatible mime types with Boilerplate scraper
|
|
16815
17947
|
],
|
|
16816
|
-
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions
|
|
17948
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
16817
17949
|
isAvilableInBrowser: false,
|
|
16818
17950
|
// <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
16819
17951
|
requiredExecutables: [
|
|
16820
|
-
/*
|
|
17952
|
+
/* @@ 'Pandoc' */
|
|
16821
17953
|
],
|
|
16822
17954
|
}); /* <- Note: [🤛] */
|
|
16823
17955
|
/**
|
|
@@ -16835,7 +17967,7 @@ const _BoilerplateScraperMetadataRegistration = $scrapersMetadataRegister.regist
|
|
|
16835
17967
|
*/
|
|
16836
17968
|
|
|
16837
17969
|
/**
|
|
16838
|
-
* Scraper of
|
|
17970
|
+
* Scraper of @@ files
|
|
16839
17971
|
*
|
|
16840
17972
|
* @see `documentationUrl` for more details
|
|
16841
17973
|
* @public exported from `@promptbook/boilerplate`
|
|
@@ -16853,30 +17985,30 @@ class BoilerplateScraper {
|
|
|
16853
17985
|
this.markdownScraper = new MarkdownScraper(tools, options);
|
|
16854
17986
|
}
|
|
16855
17987
|
/**
|
|
16856
|
-
* Convert the
|
|
17988
|
+
* Convert the `.@@` to `.md` file and returns intermediate source
|
|
16857
17989
|
*
|
|
16858
17990
|
* Note: `$` is used to indicate that this function is not a pure function - it leaves files on the disk and you are responsible for cleaning them by calling `destroy` method of returned object
|
|
16859
17991
|
*/
|
|
16860
17992
|
async $convert(source) {
|
|
16861
17993
|
var _a;
|
|
16862
17994
|
const { rootDirname = process.cwd(), cacheDirname = DEFAULT_SCRAPE_CACHE_DIRNAME, intermediateFilesStrategy = DEFAULT_INTERMEDIATE_FILES_STRATEGY, isVerbose = DEFAULT_IS_VERBOSE, } = this.options;
|
|
16863
|
-
// TODO:
|
|
17995
|
+
// TODO: @@ Preserve or delete
|
|
16864
17996
|
if (!$isRunningInNode()) {
|
|
16865
17997
|
throw new KnowledgeScrapeError('BoilerplateScraper is only supported in Node environment');
|
|
16866
17998
|
}
|
|
16867
|
-
// TODO:
|
|
17999
|
+
// TODO: @@ Preserve or delete
|
|
16868
18000
|
if (this.tools.fs === undefined) {
|
|
16869
18001
|
throw new EnvironmentMismatchError('Can not scrape boilerplates without filesystem tools');
|
|
16870
18002
|
// <- TODO: [🧠] What is the best error type here`
|
|
16871
18003
|
}
|
|
16872
|
-
// TODO:
|
|
18004
|
+
// TODO: @@ Preserve, delete or modify
|
|
16873
18005
|
if (((_a = this.tools.executables) === null || _a === void 0 ? void 0 : _a.pandocPath) === undefined) {
|
|
16874
18006
|
throw new MissingToolsError('Pandoc is required for scraping .docx files');
|
|
16875
18007
|
}
|
|
16876
|
-
// TODO:
|
|
18008
|
+
// TODO: @@ Preserve, delete or modify
|
|
16877
18009
|
if (source.filename === null) {
|
|
16878
18010
|
// TODO: [🧠] Maybe save file as temporary
|
|
16879
|
-
throw new KnowledgeScrapeError('When parsing
|
|
18011
|
+
throw new KnowledgeScrapeError('When parsing .@@ file, it must be real file in the file system');
|
|
16880
18012
|
}
|
|
16881
18013
|
const extension = getFileExtension(source.filename);
|
|
16882
18014
|
const cacheFilehandler = await getScraperIntermediateSource(source, {
|
|
@@ -16886,7 +18018,7 @@ class BoilerplateScraper {
|
|
|
16886
18018
|
extension: 'md',
|
|
16887
18019
|
isVerbose,
|
|
16888
18020
|
});
|
|
16889
|
-
// TODO:
|
|
18021
|
+
// TODO: @@ Preserve, delete or modify
|
|
16890
18022
|
// Note: Running Pandoc ONLY if the file in the cache does not exist
|
|
16891
18023
|
if (!(await isFileExisting(cacheFilehandler.filename, this.tools.fs))) {
|
|
16892
18024
|
const command = `"${this.tools.executables.pandocPath}" -f ${extension} -t markdown "${source.filename}" -o "${cacheFilehandler.filename}"`;
|
|
@@ -16912,7 +18044,7 @@ class BoilerplateScraper {
|
|
|
16912
18044
|
*/
|
|
16913
18045
|
async scrape(source) {
|
|
16914
18046
|
const cacheFilehandler = await this.$convert(source);
|
|
16915
|
-
// TODO:
|
|
18047
|
+
// TODO: @@ Preserve, delete or modify
|
|
16916
18048
|
const markdownSource = {
|
|
16917
18049
|
source: source.source,
|
|
16918
18050
|
filename: cacheFilehandler.filename,
|
|
@@ -16943,7 +18075,7 @@ class BoilerplateScraper {
|
|
|
16943
18075
|
* TODO: [👣] Converted documents can act as cached items - there is no need to run conversion each time
|
|
16944
18076
|
* TODO: [🪂] Do it in parallel
|
|
16945
18077
|
* Note: No need to aggregate usage here, it is done by intercepting the llmTools
|
|
16946
|
-
*
|
|
18078
|
+
* @@ Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
16947
18079
|
*/
|
|
16948
18080
|
|
|
16949
18081
|
/**
|
|
@@ -17277,7 +18409,8 @@ class LegacyDocumentScraper {
|
|
|
17277
18409
|
*/
|
|
17278
18410
|
|
|
17279
18411
|
/**
|
|
17280
|
-
*
|
|
18412
|
+
* Creates a scraper for legacy document formats (.doc, .rtf, etc).
|
|
18413
|
+
* Uses LibreOffice for conversion to extract content from older document formats.
|
|
17281
18414
|
*
|
|
17282
18415
|
* @public exported from `@promptbook/legacy-documents`
|
|
17283
18416
|
*/
|
|
@@ -17304,7 +18437,7 @@ const _LegacyDocumentScraperRegistration = $scrapersRegister.register(createLega
|
|
|
17304
18437
|
*/
|
|
17305
18438
|
|
|
17306
18439
|
/**
|
|
17307
|
-
*
|
|
18440
|
+
* Creates a scraper for document content.
|
|
17308
18441
|
*
|
|
17309
18442
|
* @public exported from `@promptbook/documents`
|
|
17310
18443
|
*/
|
|
@@ -17331,7 +18464,7 @@ const _DocumentScraperRegistration = $scrapersRegister.register(createDocumentSc
|
|
|
17331
18464
|
*/
|
|
17332
18465
|
|
|
17333
18466
|
/**
|
|
17334
|
-
*
|
|
18467
|
+
* Creates a scraper for markdown content.
|
|
17335
18468
|
*
|
|
17336
18469
|
* @public exported from `@promptbook/markdown-utils`
|
|
17337
18470
|
*/
|
|
@@ -17437,8 +18570,8 @@ class MarkitdownScraper {
|
|
|
17437
18570
|
extension: 'md',
|
|
17438
18571
|
isVerbose,
|
|
17439
18572
|
});
|
|
17440
|
-
// TODO:
|
|
17441
|
-
// Note: Running
|
|
18573
|
+
// TODO: Determine if Markitdown conversion should run only if the cache file doesn't exist, or always.
|
|
18574
|
+
// Note: Running Markitdown conversion ONLY if the file in the cache does not exist
|
|
17442
18575
|
if (!(await isFileExisting(cacheFilehandler.filename, this.tools.fs))) {
|
|
17443
18576
|
const src = source.filename || source.url || null;
|
|
17444
18577
|
// console.log('!!', { src, source, cacheFilehandler });
|
|
@@ -17460,11 +18593,11 @@ class MarkitdownScraper {
|
|
|
17460
18593
|
return cacheFilehandler;
|
|
17461
18594
|
}
|
|
17462
18595
|
/**
|
|
17463
|
-
* Scrapes the
|
|
18596
|
+
* Scrapes the source document (PDF, DOCX, etc.) and returns the knowledge pieces or `null` if it can't scrape it.
|
|
17464
18597
|
*/
|
|
17465
18598
|
async scrape(source) {
|
|
17466
18599
|
const cacheFilehandler = await this.$convert(source);
|
|
17467
|
-
// TODO:
|
|
18600
|
+
// TODO: Ensure this correctly creates the source object for the internal MarkdownScraper using the converted file.
|
|
17468
18601
|
const markdownSource = {
|
|
17469
18602
|
source: source.source,
|
|
17470
18603
|
filename: cacheFilehandler.filename,
|
|
@@ -17608,7 +18741,8 @@ class PdfScraper {
|
|
|
17608
18741
|
*/
|
|
17609
18742
|
|
|
17610
18743
|
/**
|
|
17611
|
-
*
|
|
18744
|
+
* Factory function to create an instance of PdfScraper.
|
|
18745
|
+
* It bundles the scraper class with its metadata.
|
|
17612
18746
|
*
|
|
17613
18747
|
* @public exported from `@promptbook/pdf`
|
|
17614
18748
|
*/
|
|
@@ -17784,7 +18918,8 @@ class WebsiteScraper {
|
|
|
17784
18918
|
*/
|
|
17785
18919
|
|
|
17786
18920
|
/**
|
|
17787
|
-
*
|
|
18921
|
+
* Factory function to create an instance of WebsiteScraper.
|
|
18922
|
+
* It bundles the scraper class with its metadata.
|
|
17788
18923
|
*
|
|
17789
18924
|
* @public exported from `@promptbook/website-crawler`
|
|
17790
18925
|
*/
|