@promptbook/cli 0.94.0 → 0.98.0-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/esm/index.es.js +193 -115
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/types.index.d.ts +2 -2
- package/esm/typings/src/_packages/{wizzard.index.d.ts → wizard.index.d.ts} +2 -2
- package/esm/typings/src/cli/cli-commands/prettify.d.ts +1 -1
- package/esm/typings/src/cli/cli-commands/test-command.d.ts +1 -1
- package/esm/typings/src/conversion/archive/loadArchive.d.ts +1 -1
- package/esm/typings/src/conversion/archive/saveArchive.d.ts +2 -2
- package/esm/typings/src/conversion/prettify/renderPipelineMermaidOptions.d.ts +1 -1
- package/esm/typings/src/dialogs/callback/CallbackInterfaceTools.d.ts +1 -1
- package/esm/typings/src/execution/AbstractTaskResult.d.ts +2 -2
- package/esm/typings/src/execution/createPipelineExecutor/00-CreatePipelineExecutorOptions.d.ts +1 -1
- package/esm/typings/src/execution/execution-report/ExecutionPromptReportJson.d.ts +2 -2
- package/esm/typings/src/execution/translation/automatic-translate/translateMessages.d.ts +1 -1
- package/esm/typings/src/llm-providers/_common/register/{$provideLlmToolsForWizzardOrCli.d.ts → $provideLlmToolsForWizardOrCli.d.ts} +2 -2
- package/esm/typings/src/llm-providers/anthropic-claude/register-configuration.d.ts +1 -1
- package/esm/typings/src/llm-providers/anthropic-claude/register-constructor.d.ts +1 -1
- package/esm/typings/src/llm-providers/azure-openai/register-configuration.d.ts +1 -1
- package/esm/typings/src/llm-providers/azure-openai/register-constructor.d.ts +1 -1
- package/esm/typings/src/llm-providers/deepseek/register-configuration.d.ts +1 -1
- package/esm/typings/src/llm-providers/deepseek/register-constructor.d.ts +1 -1
- package/esm/typings/src/llm-providers/google/register-configuration.d.ts +1 -1
- package/esm/typings/src/llm-providers/google/register-constructor.d.ts +1 -1
- package/esm/typings/src/llm-providers/ollama/register-configuration.d.ts +1 -1
- package/esm/typings/src/llm-providers/ollama/register-constructor.d.ts +1 -1
- package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.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/remote-server/socket-types/listModels/PromptbookServer_ListModels_Request.d.ts +1 -1
- package/esm/typings/src/scrapers/_boilerplate/createBoilerplateScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/_boilerplate/register-constructor.d.ts +1 -1
- package/esm/typings/src/scrapers/_boilerplate/register-metadata.d.ts +2 -2
- package/esm/typings/src/scrapers/_common/prepareKnowledgePieces.d.ts +1 -1
- package/esm/typings/src/scrapers/_common/register/ScraperAndConverterMetadata.d.ts +1 -1
- package/esm/typings/src/scrapers/document/createDocumentScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/document/register-constructor.d.ts +1 -1
- package/esm/typings/src/scrapers/document/register-metadata.d.ts +2 -2
- package/esm/typings/src/scrapers/document-legacy/createLegacyDocumentScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/document-legacy/register-constructor.d.ts +1 -1
- package/esm/typings/src/scrapers/document-legacy/register-metadata.d.ts +2 -2
- package/esm/typings/src/scrapers/markdown/createMarkdownScraper.d.ts +1 -4
- package/esm/typings/src/scrapers/markdown/register-constructor.d.ts +1 -1
- package/esm/typings/src/scrapers/markdown/register-metadata.d.ts +2 -2
- package/esm/typings/src/scrapers/markitdown/createMarkitdownScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/markitdown/register-constructor.d.ts +1 -1
- package/esm/typings/src/scrapers/markitdown/register-metadata.d.ts +2 -2
- package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/pdf/register-constructor.d.ts +1 -1
- package/esm/typings/src/scrapers/pdf/register-metadata.d.ts +2 -2
- package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +1 -1
- package/esm/typings/src/scrapers/website/register-constructor.d.ts +1 -1
- package/esm/typings/src/scrapers/website/register-metadata.d.ts +2 -2
- package/esm/typings/src/types/typeAliases.d.ts +1 -1
- package/esm/typings/src/utils/files/listAllFiles.d.ts +1 -1
- package/esm/typings/src/version.d.ts +1 -1
- package/esm/typings/src/{wizzard → wizard}/$getCompiledBook.d.ts +2 -2
- package/esm/typings/src/{wizzard/wizzard.d.ts → wizard/wizard.d.ts} +6 -6
- package/package.json +1 -13
- package/umd/index.umd.js +193 -115
- package/umd/index.umd.js.map +1 -1
package/esm/index.es.js
CHANGED
|
@@ -47,7 +47,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
47
47
|
* @generated
|
|
48
48
|
* @see https://github.com/webgptorg/promptbook
|
|
49
49
|
*/
|
|
50
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
50
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.98.0-2';
|
|
51
51
|
/**
|
|
52
52
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
53
53
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -305,11 +305,11 @@ const CLI_APP_ID = 'cli';
|
|
|
305
305
|
/*
|
|
306
306
|
TODO: [🌃]
|
|
307
307
|
/**
|
|
308
|
-
* Id of application for the
|
|
308
|
+
* Id of application for the wizard when using remote server
|
|
309
309
|
*
|
|
310
310
|
* @public exported from `@promptbook/core`
|
|
311
311
|
* /
|
|
312
|
-
ex-port const
|
|
312
|
+
ex-port const WIZARD_APP_ID: string_app_id = 'wizard';
|
|
313
313
|
*/
|
|
314
314
|
/**
|
|
315
315
|
* The name of the builded pipeline collection made by CLI `ptbk make` and for lookup in `createCollectionFromDirectory`
|
|
@@ -1433,7 +1433,7 @@ function checkSerializableAsJson(options) {
|
|
|
1433
1433
|
else {
|
|
1434
1434
|
for (const [subName, subValue] of Object.entries(value)) {
|
|
1435
1435
|
if (subValue === undefined) {
|
|
1436
|
-
// Note: undefined in object is serializable - it is just
|
|
1436
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
1437
1437
|
continue;
|
|
1438
1438
|
}
|
|
1439
1439
|
checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
|
|
@@ -2775,12 +2775,12 @@ function cacheLlmTools(llmTools, options = {}) {
|
|
|
2775
2775
|
get title() {
|
|
2776
2776
|
return `${llmTools.title} (cached)`;
|
|
2777
2777
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
2778
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
2778
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(cached)"?
|
|
2779
2779
|
},
|
|
2780
2780
|
get description() {
|
|
2781
2781
|
return `${llmTools.description} (cached)`;
|
|
2782
2782
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
2783
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
2783
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(cached)"?
|
|
2784
2784
|
},
|
|
2785
2785
|
listModels() {
|
|
2786
2786
|
// TODO: [🧠] Should be model listing also cached?
|
|
@@ -2838,21 +2838,39 @@ function cacheLlmTools(llmTools, options = {}) {
|
|
|
2838
2838
|
}
|
|
2839
2839
|
// TODO: [🧠] !!5 How to do timing in mixed cache / non-cache situation
|
|
2840
2840
|
// promptResult.timing: FromtoItems
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2841
|
+
// Check if the result is valid and should be cached
|
|
2842
|
+
// A result is considered failed if:
|
|
2843
|
+
// 1. It has a content property that is null or undefined
|
|
2844
|
+
// 2. It has an error property that is truthy
|
|
2845
|
+
// 3. It has a success property that is explicitly false
|
|
2846
|
+
const isFailedResult = promptResult.content === null ||
|
|
2847
|
+
promptResult.content === undefined ||
|
|
2848
|
+
promptResult.error ||
|
|
2849
|
+
promptResult.success === false;
|
|
2850
|
+
if (!isFailedResult) {
|
|
2851
|
+
await storage.setItem(key, {
|
|
2852
|
+
date: $getCurrentDate(),
|
|
2853
|
+
promptbookVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
2854
|
+
bookVersion: BOOK_LANGUAGE_VERSION,
|
|
2855
|
+
prompt: {
|
|
2856
|
+
...prompt,
|
|
2857
|
+
parameters: Object.entries(parameters).length === Object.entries(relevantParameters).length
|
|
2858
|
+
? parameters
|
|
2859
|
+
: {
|
|
2860
|
+
...relevantParameters,
|
|
2861
|
+
note: `<- Note: Only relevant parameters are stored in the cache`,
|
|
2862
|
+
},
|
|
2863
|
+
},
|
|
2864
|
+
promptResult,
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
else if (isVerbose) {
|
|
2868
|
+
console.info('Not caching failed result for key:', key, {
|
|
2869
|
+
content: promptResult.content,
|
|
2870
|
+
error: promptResult.error,
|
|
2871
|
+
success: promptResult.success,
|
|
2872
|
+
});
|
|
2873
|
+
}
|
|
2856
2874
|
return promptResult;
|
|
2857
2875
|
};
|
|
2858
2876
|
if (llmTools.callChatModel !== undefined) {
|
|
@@ -3010,12 +3028,12 @@ function countUsage(llmTools) {
|
|
|
3010
3028
|
get title() {
|
|
3011
3029
|
return `${llmTools.title} (+usage)`;
|
|
3012
3030
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
3013
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
3031
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
|
|
3014
3032
|
},
|
|
3015
3033
|
get description() {
|
|
3016
3034
|
return `${llmTools.description} (+usage)`;
|
|
3017
3035
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
3018
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
3036
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
|
|
3019
3037
|
},
|
|
3020
3038
|
checkConfiguration() {
|
|
3021
3039
|
return /* not await */ llmTools.checkConfiguration();
|
|
@@ -3274,13 +3292,13 @@ function joinLlmExecutionTools(...llmExecutionTools) {
|
|
|
3274
3292
|
|
|
3275
3293
|
Technically, it's not an error, but it's probably not what you want because it does not make sense to use Promptbook without language models.
|
|
3276
3294
|
`);
|
|
3277
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
3295
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
3278
3296
|
console.warn(warningMessage);
|
|
3279
3297
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3280
3298
|
/*
|
|
3281
3299
|
return {
|
|
3282
3300
|
async listModels() {
|
|
3283
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
3301
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
3284
3302
|
console.warn(
|
|
3285
3303
|
spaceTrim(
|
|
3286
3304
|
(block) => `
|
|
@@ -3432,9 +3450,9 @@ async function $provideLlmToolsFromEnv(options = {}) {
|
|
|
3432
3450
|
*
|
|
3433
3451
|
* @private within the repository - for CLI utils
|
|
3434
3452
|
*/
|
|
3435
|
-
async function $
|
|
3453
|
+
async function $provideLlmToolsForWizardOrCli(options) {
|
|
3436
3454
|
if (!$isRunningInNode()) {
|
|
3437
|
-
throw new EnvironmentMismatchError('Function `$
|
|
3455
|
+
throw new EnvironmentMismatchError('Function `$provideLlmToolsForWizardOrCli` works only in Node.js environment');
|
|
3438
3456
|
}
|
|
3439
3457
|
options = options !== null && options !== void 0 ? options : { strategy: 'BRING_YOUR_OWN_KEYS' };
|
|
3440
3458
|
const { isLoginloaded, strategy, isCacheReloaded } = options;
|
|
@@ -3468,7 +3486,7 @@ async function $provideLlmToolsForWizzardOrCli(options) {
|
|
|
3468
3486
|
llmExecutionTools = await $provideLlmToolsFromEnv();
|
|
3469
3487
|
}
|
|
3470
3488
|
else {
|
|
3471
|
-
throw new UnexpectedError(`\`$
|
|
3489
|
+
throw new UnexpectedError(`\`$provideLlmToolsForWizardOrCli\` wrong strategy "${strategy}"`);
|
|
3472
3490
|
}
|
|
3473
3491
|
return cacheLlmTools(countUsage(
|
|
3474
3492
|
// <- TODO: [🌯] We dont use countUsage at all, maybe just unwrap it
|
|
@@ -3555,7 +3573,7 @@ async function $provideLlmToolsForCli(options) {
|
|
|
3555
3573
|
if (isLoginloaded) {
|
|
3556
3574
|
throw new UnexpectedError(`\`$provideLlmToolsForCli\` isLoginloaded is not supported for strategy "BRING_YOUR_OWN_KEYS"`);
|
|
3557
3575
|
}
|
|
3558
|
-
const llm = await $
|
|
3576
|
+
const llm = await $provideLlmToolsForWizardOrCli({ strategy, ...options });
|
|
3559
3577
|
return { strategy, llm };
|
|
3560
3578
|
}
|
|
3561
3579
|
else if (strategy === 'REMOTE_SERVER') {
|
|
@@ -3564,7 +3582,7 @@ async function $provideLlmToolsForCli(options) {
|
|
|
3564
3582
|
process.exit(1);
|
|
3565
3583
|
}
|
|
3566
3584
|
const remoteServerUrl = remoteServerUrlRaw.endsWith('/') ? remoteServerUrlRaw.slice(0, -1) : remoteServerUrlRaw;
|
|
3567
|
-
const llm = await $
|
|
3585
|
+
const llm = await $provideLlmToolsForWizardOrCli({
|
|
3568
3586
|
isLoginloaded,
|
|
3569
3587
|
strategy,
|
|
3570
3588
|
appId: CLI_APP_ID,
|
|
@@ -4103,17 +4121,17 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
4103
4121
|
* Mixes registered scrapers from $scrapersMetadataRegister and $scrapersRegister
|
|
4104
4122
|
*/
|
|
4105
4123
|
const all = [];
|
|
4106
|
-
for (const { packageName, className, mimeTypes, documentationUrl,
|
|
4124
|
+
for (const { packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser, } of $scrapersMetadataRegister.list()) {
|
|
4107
4125
|
if (all.some((item) => item.packageName === packageName && item.className === className)) {
|
|
4108
4126
|
continue;
|
|
4109
4127
|
}
|
|
4110
|
-
all.push({ packageName, className, mimeTypes, documentationUrl,
|
|
4128
|
+
all.push({ packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser });
|
|
4111
4129
|
}
|
|
4112
|
-
for (const { packageName, className, mimeTypes, documentationUrl,
|
|
4130
|
+
for (const { packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser, } of $scrapersRegister.list()) {
|
|
4113
4131
|
if (all.some((item) => item.packageName === packageName && item.className === className)) {
|
|
4114
4132
|
continue;
|
|
4115
4133
|
}
|
|
4116
|
-
all.push({ packageName, className, mimeTypes, documentationUrl,
|
|
4134
|
+
all.push({ packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser });
|
|
4117
4135
|
}
|
|
4118
4136
|
for (const { metadata } of availableScrapers) {
|
|
4119
4137
|
all.push(metadata);
|
|
@@ -4125,8 +4143,8 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
4125
4143
|
const isInstalled = $scrapersRegister
|
|
4126
4144
|
.list()
|
|
4127
4145
|
.find(({ packageName, className }) => metadata.packageName === packageName && metadata.className === className);
|
|
4128
|
-
const
|
|
4129
|
-
return { ...metadata, isMetadataAviailable, isInstalled,
|
|
4146
|
+
const isAvailableInTools = availableScrapers.some(({ metadata: { packageName, className } }) => metadata.packageName === packageName && metadata.className === className);
|
|
4147
|
+
return { ...metadata, isMetadataAviailable, isInstalled, isAvailableInTools };
|
|
4130
4148
|
});
|
|
4131
4149
|
if (metadata.length === 0) {
|
|
4132
4150
|
return spaceTrim(`
|
|
@@ -4139,7 +4157,7 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
4139
4157
|
return spaceTrim((block) => `
|
|
4140
4158
|
Available scrapers are:
|
|
4141
4159
|
${block(metadata
|
|
4142
|
-
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes,
|
|
4160
|
+
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvailableInBrowser, isAvailableInTools, }, i) => {
|
|
4143
4161
|
const more = [];
|
|
4144
4162
|
// TODO: [🧠] Maybe use `documentationUrl`
|
|
4145
4163
|
if (isMetadataAviailable) {
|
|
@@ -4148,16 +4166,16 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
4148
4166
|
if (isInstalled) {
|
|
4149
4167
|
more.push(`🟩 Installed`);
|
|
4150
4168
|
} // not else
|
|
4151
|
-
if (
|
|
4169
|
+
if (isAvailableInTools) {
|
|
4152
4170
|
more.push(`🟦 Available in tools`);
|
|
4153
4171
|
} // not else
|
|
4154
4172
|
if (!isMetadataAviailable && isInstalled) {
|
|
4155
4173
|
more.push(`When no metadata registered but scraper is installed, it is an unexpected behavior`);
|
|
4156
4174
|
} // not else
|
|
4157
|
-
if (!isInstalled &&
|
|
4175
|
+
if (!isInstalled && isAvailableInTools) {
|
|
4158
4176
|
more.push(`When the scraper is not installed but available in tools, it is an unexpected compatibility behavior`);
|
|
4159
4177
|
} // not else
|
|
4160
|
-
if (!
|
|
4178
|
+
if (!isAvailableInBrowser) {
|
|
4161
4179
|
more.push(`Not usable in browser`);
|
|
4162
4180
|
}
|
|
4163
4181
|
const moreText = more.length === 0 ? '' : ` *(${more.join('; ')})*`;
|
|
@@ -4635,7 +4653,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
4635
4653
|
* @param fs Filesystem tools
|
|
4636
4654
|
* @returns Pipelines loaded from the archive
|
|
4637
4655
|
*
|
|
4638
|
-
* @private utility of
|
|
4656
|
+
* @private utility of Promptbook
|
|
4639
4657
|
*/
|
|
4640
4658
|
async function loadArchive(filePath, fs) {
|
|
4641
4659
|
if (!filePath.endsWith('.bookc')) {
|
|
@@ -4657,7 +4675,7 @@ async function loadArchive(filePath, fs) {
|
|
|
4657
4675
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
4658
4676
|
*/
|
|
4659
4677
|
|
|
4660
|
-
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"}];
|
|
4678
|
+
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 helpful 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 helpful 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"}];
|
|
4661
4679
|
|
|
4662
4680
|
/**
|
|
4663
4681
|
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
@@ -4735,7 +4753,7 @@ function prettifyMarkdown(content) {
|
|
|
4735
4753
|
});
|
|
4736
4754
|
}
|
|
4737
4755
|
catch (error) {
|
|
4738
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
4756
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
4739
4757
|
console.error('There was an error with prettifying the markdown, using the original as the fallback', {
|
|
4740
4758
|
error,
|
|
4741
4759
|
html: content,
|
|
@@ -4983,7 +5001,7 @@ class SimplePipelineCollection {
|
|
|
4983
5001
|
|
|
4984
5002
|
Note: You have probably forgotten to run "ptbk make" to update the collection
|
|
4985
5003
|
Note: Pipelines with the same URL are not allowed
|
|
4986
|
-
Only
|
|
5004
|
+
Only exception is when the pipelines are identical
|
|
4987
5005
|
|
|
4988
5006
|
`));
|
|
4989
5007
|
}
|
|
@@ -6780,10 +6798,10 @@ function knowledgePiecesToString(knowledgePieces) {
|
|
|
6780
6798
|
*/
|
|
6781
6799
|
async function getKnowledgeForTask(options) {
|
|
6782
6800
|
const { tools, preparedPipeline, task, parameters } = options;
|
|
6783
|
-
const
|
|
6784
|
-
const
|
|
6801
|
+
const firstKnowledgePiece = preparedPipeline.knowledgePieces[0];
|
|
6802
|
+
const firstKnowledgeIndex = firstKnowledgePiece === null || firstKnowledgePiece === void 0 ? void 0 : firstKnowledgePiece.index[0];
|
|
6785
6803
|
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
|
|
6786
|
-
if (
|
|
6804
|
+
if (firstKnowledgePiece === undefined || firstKnowledgeIndex === undefined) {
|
|
6787
6805
|
return ''; // <- Note: Np knowledge present, return empty string
|
|
6788
6806
|
}
|
|
6789
6807
|
try {
|
|
@@ -6794,7 +6812,7 @@ async function getKnowledgeForTask(options) {
|
|
|
6794
6812
|
title: 'Knowledge Search',
|
|
6795
6813
|
modelRequirements: {
|
|
6796
6814
|
modelVariant: 'EMBEDDING',
|
|
6797
|
-
modelName:
|
|
6815
|
+
modelName: firstKnowledgeIndex.modelName,
|
|
6798
6816
|
},
|
|
6799
6817
|
content: task.content,
|
|
6800
6818
|
parameters,
|
|
@@ -6802,7 +6820,7 @@ async function getKnowledgeForTask(options) {
|
|
|
6802
6820
|
const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
|
|
6803
6821
|
const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
|
|
6804
6822
|
const { index } = knowledgePiece;
|
|
6805
|
-
const knowledgePieceIndex = index.find((i) => i.modelName ===
|
|
6823
|
+
const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowledgeIndex.modelName);
|
|
6806
6824
|
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model
|
|
6807
6825
|
if (knowledgePieceIndex === undefined) {
|
|
6808
6826
|
return {
|
|
@@ -6823,8 +6841,8 @@ async function getKnowledgeForTask(options) {
|
|
|
6823
6841
|
task,
|
|
6824
6842
|
taskEmbeddingPrompt,
|
|
6825
6843
|
taskEmbeddingResult,
|
|
6826
|
-
|
|
6827
|
-
|
|
6844
|
+
firstKnowledgePiece,
|
|
6845
|
+
firstKnowledgeIndex,
|
|
6828
6846
|
knowledgePiecesWithRelevance,
|
|
6829
6847
|
knowledgePiecesSorted,
|
|
6830
6848
|
knowledgePiecesLimited,
|
|
@@ -6893,7 +6911,7 @@ async function getReservedParametersForTask(options) {
|
|
|
6893
6911
|
* @private internal utility of `createPipelineExecutor`
|
|
6894
6912
|
*/
|
|
6895
6913
|
async function executeTask(options) {
|
|
6896
|
-
const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled,
|
|
6914
|
+
const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled, isNotPreparedWarningSuppressed, } = options;
|
|
6897
6915
|
const priority = preparedPipeline.tasks.length - preparedPipeline.tasks.indexOf(currentTask);
|
|
6898
6916
|
// Note: Check consistency of used and dependent parameters which was also done in `validatePipeline`, but it’s good to doublecheck
|
|
6899
6917
|
const usedParameterNames = extractParameterNamesFromTask(currentTask);
|
|
@@ -6981,7 +6999,7 @@ async function executeTask(options) {
|
|
|
6981
6999
|
cacheDirname,
|
|
6982
7000
|
intermediateFilesStrategy,
|
|
6983
7001
|
isAutoInstalled,
|
|
6984
|
-
|
|
7002
|
+
isNotPreparedWarningSuppressed,
|
|
6985
7003
|
});
|
|
6986
7004
|
await onProgress({
|
|
6987
7005
|
outputParameters: {
|
|
@@ -7076,7 +7094,7 @@ async function executePipeline(options) {
|
|
|
7076
7094
|
}
|
|
7077
7095
|
return exportJson({
|
|
7078
7096
|
name: `executionReport`,
|
|
7079
|
-
message: `
|
|
7097
|
+
message: `Unsuccessful PipelineExecutorResult (with missing parameter {${parameter.name}}) PipelineExecutorResult`,
|
|
7080
7098
|
order: [],
|
|
7081
7099
|
value: {
|
|
7082
7100
|
isSuccessful: false,
|
|
@@ -7113,7 +7131,7 @@ async function executePipeline(options) {
|
|
|
7113
7131
|
return exportJson({
|
|
7114
7132
|
name: 'pipelineExecutorResult',
|
|
7115
7133
|
message: spaceTrim$1((block) => `
|
|
7116
|
-
|
|
7134
|
+
Unsuccessful PipelineExecutorResult (with extra parameter {${parameter.name}}) PipelineExecutorResult
|
|
7117
7135
|
|
|
7118
7136
|
${block(pipelineIdentification)}
|
|
7119
7137
|
`),
|
|
@@ -7254,7 +7272,7 @@ async function executePipeline(options) {
|
|
|
7254
7272
|
}
|
|
7255
7273
|
return exportJson({
|
|
7256
7274
|
name: 'pipelineExecutorResult',
|
|
7257
|
-
message: `
|
|
7275
|
+
message: `Unsuccessful PipelineExecutorResult (with misc errors) PipelineExecutorResult`,
|
|
7258
7276
|
order: [],
|
|
7259
7277
|
value: {
|
|
7260
7278
|
isSuccessful: false,
|
|
@@ -7305,7 +7323,7 @@ async function executePipeline(options) {
|
|
|
7305
7323
|
* @public exported from `@promptbook/core`
|
|
7306
7324
|
*/
|
|
7307
7325
|
function createPipelineExecutor(options) {
|
|
7308
|
-
const { pipeline, tools, maxExecutionAttempts = DEFAULT_MAX_EXECUTION_ATTEMPTS, maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT, csvSettings = DEFAULT_CSV_SETTINGS, isVerbose = DEFAULT_IS_VERBOSE,
|
|
7326
|
+
const { pipeline, tools, maxExecutionAttempts = DEFAULT_MAX_EXECUTION_ATTEMPTS, maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT, csvSettings = DEFAULT_CSV_SETTINGS, isVerbose = DEFAULT_IS_VERBOSE, isNotPreparedWarningSuppressed = false, cacheDirname = DEFAULT_SCRAPE_CACHE_DIRNAME, intermediateFilesStrategy = DEFAULT_INTERMEDIATE_FILES_STRATEGY, isAutoInstalled = DEFAULT_IS_AUTO_INSTALLED, rootDirname = null, } = options;
|
|
7309
7327
|
validatePipeline(pipeline);
|
|
7310
7328
|
const pipelineIdentification = (() => {
|
|
7311
7329
|
// Note: This is a 😐 implementation of [🚞]
|
|
@@ -7322,7 +7340,7 @@ function createPipelineExecutor(options) {
|
|
|
7322
7340
|
if (isPipelinePrepared(pipeline)) {
|
|
7323
7341
|
preparedPipeline = pipeline;
|
|
7324
7342
|
}
|
|
7325
|
-
else if (
|
|
7343
|
+
else if (isNotPreparedWarningSuppressed !== true) {
|
|
7326
7344
|
console.warn(spaceTrim$1((block) => `
|
|
7327
7345
|
Pipeline is not prepared
|
|
7328
7346
|
|
|
@@ -7355,7 +7373,7 @@ function createPipelineExecutor(options) {
|
|
|
7355
7373
|
maxParallelCount,
|
|
7356
7374
|
csvSettings,
|
|
7357
7375
|
isVerbose,
|
|
7358
|
-
|
|
7376
|
+
isNotPreparedWarningSuppressed,
|
|
7359
7377
|
rootDirname,
|
|
7360
7378
|
cacheDirname,
|
|
7361
7379
|
intermediateFilesStrategy,
|
|
@@ -7364,7 +7382,7 @@ function createPipelineExecutor(options) {
|
|
|
7364
7382
|
assertsError(error);
|
|
7365
7383
|
return exportJson({
|
|
7366
7384
|
name: 'pipelineExecutorResult',
|
|
7367
|
-
message: `
|
|
7385
|
+
message: `Unsuccessful PipelineExecutorResult, last catch`,
|
|
7368
7386
|
order: [],
|
|
7369
7387
|
value: {
|
|
7370
7388
|
isSuccessful: false,
|
|
@@ -7776,7 +7794,7 @@ TODO: [🧊] This is how it can look in future
|
|
|
7776
7794
|
/**
|
|
7777
7795
|
* TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
|
|
7778
7796
|
* Put `knowledgePieces` into `PrepareKnowledgeOptions`
|
|
7779
|
-
* TODO: [🪂] More than max things can run in parallel by
|
|
7797
|
+
* TODO: [🪂] More than max things can run in parallel by accident [1,[2a,2b,_],[3a,3b,_]]
|
|
7780
7798
|
* TODO: [🧠][❎] Do here proper M:N mapping
|
|
7781
7799
|
* [x] One source can make multiple pieces
|
|
7782
7800
|
* [ ] One piece can have multiple sources
|
|
@@ -8664,7 +8682,7 @@ const expectCommandParser = {
|
|
|
8664
8682
|
$taskJson.expectations[unit] = $taskJson.expectations[unit] || {};
|
|
8665
8683
|
if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
|
|
8666
8684
|
if ($taskJson.expectations[unit].min !== undefined) {
|
|
8667
|
-
throw new ParseError(`Already defined
|
|
8685
|
+
throw new ParseError(`Already defined minimum ${$taskJson.expectations[unit].min} ${command.unit.toLowerCase()}, now trying to redefine it to ${command.amount}`);
|
|
8668
8686
|
}
|
|
8669
8687
|
$taskJson.expectations[unit].min = command.amount;
|
|
8670
8688
|
} /* not else */
|
|
@@ -12126,7 +12144,7 @@ async function listAllFiles(path, isRecursive, fs) {
|
|
|
12126
12144
|
return fileNames;
|
|
12127
12145
|
}
|
|
12128
12146
|
/**
|
|
12129
|
-
* TODO: [😶] Unite
|
|
12147
|
+
* TODO: [😶] Unite folder listing
|
|
12130
12148
|
* Note: Not [~🟢~] because it is not directly dependent on `fs
|
|
12131
12149
|
* TODO: [🖇] What about symlinks?
|
|
12132
12150
|
*/
|
|
@@ -12273,7 +12291,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12273
12291
|
if (isCrashedOnError) {
|
|
12274
12292
|
throw new CollectionError(wrappedErrorMessage);
|
|
12275
12293
|
}
|
|
12276
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
12294
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
12277
12295
|
console.error(wrappedErrorMessage);
|
|
12278
12296
|
}
|
|
12279
12297
|
}
|
|
@@ -12340,7 +12358,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12340
12358
|
|
|
12341
12359
|
Note: You have probably forgotten to run "ptbk make" to update the collection
|
|
12342
12360
|
Note: Pipelines with the same URL are not allowed
|
|
12343
|
-
Only
|
|
12361
|
+
Only exception is when the pipelines are identical
|
|
12344
12362
|
|
|
12345
12363
|
`));
|
|
12346
12364
|
}
|
|
@@ -12364,7 +12382,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12364
12382
|
if (isCrashedOnError) {
|
|
12365
12383
|
throw new CollectionError(wrappedErrorMessage);
|
|
12366
12384
|
}
|
|
12367
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
12385
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
12368
12386
|
console.error(wrappedErrorMessage);
|
|
12369
12387
|
}
|
|
12370
12388
|
}
|
|
@@ -12387,7 +12405,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12387
12405
|
* @param books Pipelines to be saved in the archive
|
|
12388
12406
|
* @param fs Filesystem tools
|
|
12389
12407
|
*
|
|
12390
|
-
* @private utility of
|
|
12408
|
+
* @private utility of Promptbook
|
|
12391
12409
|
*/
|
|
12392
12410
|
async function saveArchive(filePath, collectionJson, fs) {
|
|
12393
12411
|
if (!filePath.endsWith('.bookc')) {
|
|
@@ -12871,7 +12889,7 @@ function $initializePrettifyCommand(program) {
|
|
|
12871
12889
|
}));
|
|
12872
12890
|
}
|
|
12873
12891
|
/**
|
|
12874
|
-
* TODO: [😶] Unite
|
|
12892
|
+
* TODO: [😶] Unite folder listing
|
|
12875
12893
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
12876
12894
|
* Note: [🟡] Code in this file should never be published outside of `@promptbook/cli`
|
|
12877
12895
|
* TODO: [🖇] What about symlinks? Maybe flag --follow-symlinks
|
|
@@ -13188,9 +13206,9 @@ function isValidPipelineString(pipelineString) {
|
|
|
13188
13206
|
*/
|
|
13189
13207
|
|
|
13190
13208
|
/**
|
|
13191
|
-
* @see ./
|
|
13209
|
+
* @see ./wizard.ts `getPipeline` method
|
|
13192
13210
|
*
|
|
13193
|
-
* @private usable through `ptbk run` and `@
|
|
13211
|
+
* @private usable through `ptbk run` and `@promptbook/wizard`
|
|
13194
13212
|
*/
|
|
13195
13213
|
async function $getCompiledBook(tools, pipelineSource, options) {
|
|
13196
13214
|
const { fs, fetch } = tools;
|
|
@@ -13405,7 +13423,7 @@ async function runInteractiveChatbot(options) {
|
|
|
13405
13423
|
}
|
|
13406
13424
|
catch (error) {
|
|
13407
13425
|
assertsError(error);
|
|
13408
|
-
// TODO: Allow to
|
|
13426
|
+
// TODO: Allow to resurrect the chatbot after an error - prompt the user to continue
|
|
13409
13427
|
console.error(colors.red(error.stack || error.message));
|
|
13410
13428
|
return process.exit(1);
|
|
13411
13429
|
}
|
|
@@ -13550,7 +13568,7 @@ function $initializeRunCommand(program) {
|
|
|
13550
13568
|
const pipelineExecutor = createPipelineExecutor({
|
|
13551
13569
|
pipeline,
|
|
13552
13570
|
tools,
|
|
13553
|
-
|
|
13571
|
+
isNotPreparedWarningSuppressed: true,
|
|
13554
13572
|
maxExecutionAttempts: DEFAULT_MAX_EXECUTION_ATTEMPTS,
|
|
13555
13573
|
// <- TODO: Why "LLM execution failed undefinedx"
|
|
13556
13574
|
maxParallelCount: 1, // <- TODO: Pass CLI argument
|
|
@@ -14339,6 +14357,66 @@ function startRemoteServer(options) {
|
|
|
14339
14357
|
response.setHeader('X-Powered-By', 'Promptbook engine');
|
|
14340
14358
|
next();
|
|
14341
14359
|
});
|
|
14360
|
+
// Note: OpenAI-compatible chat completions endpoint
|
|
14361
|
+
app.post('/v1/chat/completions', async (request, response) => {
|
|
14362
|
+
// TODO: !!!! Make more promptbook-native:
|
|
14363
|
+
try {
|
|
14364
|
+
const params = request.body;
|
|
14365
|
+
const { model, messages } = params;
|
|
14366
|
+
// Convert messages to a single prompt
|
|
14367
|
+
const prompt = messages
|
|
14368
|
+
.map((message) => `${message.role}: ${message.content}`)
|
|
14369
|
+
.join('\n');
|
|
14370
|
+
// Get pipeline for the book
|
|
14371
|
+
if (!collection) {
|
|
14372
|
+
throw new Error('No collection available');
|
|
14373
|
+
}
|
|
14374
|
+
const pipeline = await collection.getPipelineByUrl(model);
|
|
14375
|
+
const pipelineExecutor = createPipelineExecutor({
|
|
14376
|
+
pipeline,
|
|
14377
|
+
tools: await getExecutionToolsFromIdentification({
|
|
14378
|
+
isAnonymous: true,
|
|
14379
|
+
llmToolsConfiguration: [],
|
|
14380
|
+
}),
|
|
14381
|
+
});
|
|
14382
|
+
// Execute the pipeline with the prompt content as input
|
|
14383
|
+
const result = await pipelineExecutor({ prompt }).asPromise({ isCrashedOnError: true });
|
|
14384
|
+
if (!result.isSuccessful) {
|
|
14385
|
+
throw new Error(`Failed to execute book: ${result.errors.join(', ')}`);
|
|
14386
|
+
}
|
|
14387
|
+
// Return the result in OpenAI-compatible format
|
|
14388
|
+
response.json({
|
|
14389
|
+
id: 'chatcmpl-' + Math.random().toString(36).substring(2),
|
|
14390
|
+
object: 'chat.completion',
|
|
14391
|
+
created: Math.floor(Date.now() / 1000),
|
|
14392
|
+
model,
|
|
14393
|
+
choices: [
|
|
14394
|
+
{
|
|
14395
|
+
index: 0,
|
|
14396
|
+
message: {
|
|
14397
|
+
role: 'assistant',
|
|
14398
|
+
content: result.outputParameters.response,
|
|
14399
|
+
},
|
|
14400
|
+
finish_reason: 'stop',
|
|
14401
|
+
},
|
|
14402
|
+
],
|
|
14403
|
+
usage: {
|
|
14404
|
+
prompt_tokens: 0,
|
|
14405
|
+
completion_tokens: 0,
|
|
14406
|
+
total_tokens: 0,
|
|
14407
|
+
},
|
|
14408
|
+
});
|
|
14409
|
+
}
|
|
14410
|
+
catch (error) {
|
|
14411
|
+
response.status(500).json({
|
|
14412
|
+
error: {
|
|
14413
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
14414
|
+
type: 'server_error',
|
|
14415
|
+
code: 'internal_error',
|
|
14416
|
+
},
|
|
14417
|
+
});
|
|
14418
|
+
}
|
|
14419
|
+
});
|
|
14342
14420
|
// TODO: [🥺] Expose openapiJson to consumer and also allow to add new routes
|
|
14343
14421
|
app.use(OpenApiValidator.middleware({
|
|
14344
14422
|
apiSpec: openapiJson,
|
|
@@ -14797,7 +14875,7 @@ function $initializeStartServerCommand(program) {
|
|
|
14797
14875
|
}
|
|
14798
14876
|
const url = !rawUrl ? null : new URL(rawUrl);
|
|
14799
14877
|
if (url !== null && url.port !== port.toString()) {
|
|
14800
|
-
console.warn(colors.yellow(`Port in --url is different from --port which the server will listen on, this is ok only if you proxy from one port to another, for
|
|
14878
|
+
console.warn(colors.yellow(`Port in --url is different from --port which the server will listen on, this is ok only if you proxy from one port to another, for example via nginx or docker`));
|
|
14801
14879
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
14802
14880
|
}
|
|
14803
14881
|
let rootUrl = undefined;
|
|
@@ -14938,7 +15016,7 @@ function $initializeTestCommand(program) {
|
|
|
14938
15016
|
}));
|
|
14939
15017
|
}
|
|
14940
15018
|
/**
|
|
14941
|
-
* TODO: [😶] Unite
|
|
15019
|
+
* TODO: [😶] Unite folder listing
|
|
14942
15020
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
14943
15021
|
* Note: [🟡] Code in this file should never be published outside of `@promptbook/cli`
|
|
14944
15022
|
* TODO: [🖇] What about symlinks? Maybe flag --follow-symlinks
|
|
@@ -15027,7 +15105,7 @@ const _CLI = {
|
|
|
15027
15105
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
15028
15106
|
*
|
|
15029
15107
|
* @public exported from `@promptbook/core`
|
|
15030
|
-
* @public exported from `@promptbook/
|
|
15108
|
+
* @public exported from `@promptbook/wizard`
|
|
15031
15109
|
* @public exported from `@promptbook/cli`
|
|
15032
15110
|
*/
|
|
15033
15111
|
const _AnthropicClaudeMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
@@ -15551,7 +15629,7 @@ const createAnthropicClaudeExecutionTools = Object.assign((options) => {
|
|
|
15551
15629
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
15552
15630
|
*
|
|
15553
15631
|
* @public exported from `@promptbook/anthropic-claude`
|
|
15554
|
-
* @public exported from `@promptbook/
|
|
15632
|
+
* @public exported from `@promptbook/wizard`
|
|
15555
15633
|
* @public exported from `@promptbook/cli`
|
|
15556
15634
|
*
|
|
15557
15635
|
*/
|
|
@@ -15567,7 +15645,7 @@ const _AnthropicClaudeRegistration = $llmToolsRegister.register(createAnthropicC
|
|
|
15567
15645
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
15568
15646
|
*
|
|
15569
15647
|
* @public exported from `@promptbook/core`
|
|
15570
|
-
* @public exported from `@promptbook/
|
|
15648
|
+
* @public exported from `@promptbook/wizard`
|
|
15571
15649
|
* @public exported from `@promptbook/cli`
|
|
15572
15650
|
*/
|
|
15573
15651
|
const _AzureOpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
@@ -16245,7 +16323,7 @@ class AzureOpenAiExecutionTools {
|
|
|
16245
16323
|
rawResponse: {
|
|
16246
16324
|
...rawResponse,
|
|
16247
16325
|
created: rawResponse.created.toISOString(),
|
|
16248
|
-
// <- TODO: Put `created` at
|
|
16326
|
+
// <- TODO: Put `created` at beginning
|
|
16249
16327
|
},
|
|
16250
16328
|
// <- [🗯]
|
|
16251
16329
|
},
|
|
@@ -16340,7 +16418,7 @@ class AzureOpenAiExecutionTools {
|
|
|
16340
16418
|
rawResponse: {
|
|
16341
16419
|
...rawResponse,
|
|
16342
16420
|
created: rawResponse.created.toISOString(),
|
|
16343
|
-
// <- TODO: Put `created` at
|
|
16421
|
+
// <- TODO: Put `created` at beginning
|
|
16344
16422
|
},
|
|
16345
16423
|
// <- [🗯]
|
|
16346
16424
|
},
|
|
@@ -16410,7 +16488,7 @@ const createAzureOpenAiExecutionTools = Object.assign((options) => {
|
|
|
16410
16488
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
16411
16489
|
*
|
|
16412
16490
|
* @public exported from `@promptbook/azure-openai`
|
|
16413
|
-
* @public exported from `@promptbook/
|
|
16491
|
+
* @public exported from `@promptbook/wizard`
|
|
16414
16492
|
* @public exported from `@promptbook/cli`
|
|
16415
16493
|
*/
|
|
16416
16494
|
const _AzureOpenAiRegistration = $llmToolsRegister.register(createAzureOpenAiExecutionTools);
|
|
@@ -16425,7 +16503,7 @@ const _AzureOpenAiRegistration = $llmToolsRegister.register(createAzureOpenAiExe
|
|
|
16425
16503
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
16426
16504
|
*
|
|
16427
16505
|
* @public exported from `@promptbook/core`
|
|
16428
|
-
* @public exported from `@promptbook/
|
|
16506
|
+
* @public exported from `@promptbook/wizard`
|
|
16429
16507
|
* @public exported from `@promptbook/cli`
|
|
16430
16508
|
*/
|
|
16431
16509
|
const _DeepseekMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
@@ -16825,7 +16903,7 @@ const createDeepseekExecutionTools = Object.assign((options) => {
|
|
|
16825
16903
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
16826
16904
|
*
|
|
16827
16905
|
* @public exported from `@promptbook/deepseek`
|
|
16828
|
-
* @public exported from `@promptbook/
|
|
16906
|
+
* @public exported from `@promptbook/wizard`
|
|
16829
16907
|
* @public exported from `@promptbook/cli`
|
|
16830
16908
|
*/
|
|
16831
16909
|
const _DeepseekRegistration = $llmToolsRegister.register(createDeepseekExecutionTools);
|
|
@@ -16840,7 +16918,7 @@ const _DeepseekRegistration = $llmToolsRegister.register(createDeepseekExecution
|
|
|
16840
16918
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
16841
16919
|
*
|
|
16842
16920
|
* @public exported from `@promptbook/core`
|
|
16843
|
-
* @public exported from `@promptbook/
|
|
16921
|
+
* @public exported from `@promptbook/wizard`
|
|
16844
16922
|
* @public exported from `@promptbook/cli`
|
|
16845
16923
|
*/
|
|
16846
16924
|
const _GoogleMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
@@ -17110,7 +17188,7 @@ const createGoogleExecutionTools = Object.assign((options) => {
|
|
|
17110
17188
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
17111
17189
|
*
|
|
17112
17190
|
* @public exported from `@promptbook/google`
|
|
17113
|
-
* @public exported from `@promptbook/
|
|
17191
|
+
* @public exported from `@promptbook/wizard`
|
|
17114
17192
|
* @public exported from `@promptbook/cli`
|
|
17115
17193
|
*/
|
|
17116
17194
|
const _GoogleRegistration = $llmToolsRegister.register(createGoogleExecutionTools);
|
|
@@ -17132,7 +17210,7 @@ const DEFAULT_OLLAMA_BASE_URL = 'http://localhost:11434/v1';
|
|
|
17132
17210
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
17133
17211
|
*
|
|
17134
17212
|
* @public exported from `@promptbook/core`
|
|
17135
|
-
* @public exported from `@promptbook/
|
|
17213
|
+
* @public exported from `@promptbook/wizard`
|
|
17136
17214
|
* @public exported from `@promptbook/cli`
|
|
17137
17215
|
*/
|
|
17138
17216
|
const _OllamaMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
@@ -17867,7 +17945,7 @@ const createOllamaExecutionTools = Object.assign((options) => {
|
|
|
17867
17945
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
17868
17946
|
*
|
|
17869
17947
|
* @public exported from `@promptbook/ollama`
|
|
17870
|
-
* @public exported from `@promptbook/
|
|
17948
|
+
* @public exported from `@promptbook/wizard`
|
|
17871
17949
|
* @public exported from `@promptbook/cli`
|
|
17872
17950
|
*/
|
|
17873
17951
|
const _OllamaRegistration = $llmToolsRegister.register(createOllamaExecutionTools);
|
|
@@ -17882,7 +17960,7 @@ const _OllamaRegistration = $llmToolsRegister.register(createOllamaExecutionTool
|
|
|
17882
17960
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
17883
17961
|
*
|
|
17884
17962
|
* @public exported from `@promptbook/core`
|
|
17885
|
-
* @public exported from `@promptbook/
|
|
17963
|
+
* @public exported from `@promptbook/wizard`
|
|
17886
17964
|
* @public exported from `@promptbook/cli`
|
|
17887
17965
|
*/
|
|
17888
17966
|
const _OpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
@@ -17924,7 +18002,7 @@ const _OpenAiMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
|
17924
18002
|
* Note: [🏐] Configurations registrations are done in the metadata registration section, but the constructor registration is handled separately.
|
|
17925
18003
|
*
|
|
17926
18004
|
* @public exported from `@promptbook/core`
|
|
17927
|
-
* @public exported from `@promptbook/
|
|
18005
|
+
* @public exported from `@promptbook/wizard`
|
|
17928
18006
|
* @public exported from `@promptbook/cli`
|
|
17929
18007
|
*/
|
|
17930
18008
|
const _OpenAiAssistantMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
@@ -18104,7 +18182,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
18104
18182
|
});
|
|
18105
18183
|
const rawRequest = {
|
|
18106
18184
|
// TODO: [👨👨👧👧] ...modelSettings,
|
|
18107
|
-
// TODO: [👨👨👧👧][🧠] What about system message for assistants, does it make
|
|
18185
|
+
// TODO: [👨👨👧👧][🧠] What about system message for assistants, does it make sense - combination of OpenAI assistants with Promptbook Personas
|
|
18108
18186
|
assistant_id: this.assistantId,
|
|
18109
18187
|
thread: {
|
|
18110
18188
|
messages: [
|
|
@@ -18192,7 +18270,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
18192
18270
|
}
|
|
18193
18271
|
}
|
|
18194
18272
|
/**
|
|
18195
|
-
* TODO: [🧠][🧙♂️] Maybe there can be some
|
|
18273
|
+
* TODO: [🧠][🧙♂️] Maybe there can be some wizard for those who want to use just OpenAI
|
|
18196
18274
|
* TODO: Maybe make custom OpenAiError
|
|
18197
18275
|
* TODO: [🧠][🈁] Maybe use `isDeterministic` from options
|
|
18198
18276
|
* TODO: [🧠][🌰] Allow to pass `title` for tracking purposes
|
|
@@ -18245,7 +18323,7 @@ const createOpenAiExecutionTools = Object.assign((options) => {
|
|
|
18245
18323
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available LLM tools
|
|
18246
18324
|
*
|
|
18247
18325
|
* @public exported from `@promptbook/openai`
|
|
18248
|
-
* @public exported from `@promptbook/
|
|
18326
|
+
* @public exported from `@promptbook/wizard`
|
|
18249
18327
|
* @public exported from `@promptbook/cli`
|
|
18250
18328
|
*/
|
|
18251
18329
|
const _OpenAiRegistration = $llmToolsRegister.register(createOpenAiExecutionTools);
|
|
@@ -18255,7 +18333,7 @@ const _OpenAiRegistration = $llmToolsRegister.register(createOpenAiExecutionTool
|
|
|
18255
18333
|
* Note: [🏐] Configurations registrations are done in register-constructor.ts BUT constructor register-constructor.ts
|
|
18256
18334
|
*
|
|
18257
18335
|
* @public exported from `@promptbook/openai`
|
|
18258
|
-
* @public exported from `@promptbook/
|
|
18336
|
+
* @public exported from `@promptbook/wizard`
|
|
18259
18337
|
* @public exported from `@promptbook/cli`
|
|
18260
18338
|
*/
|
|
18261
18339
|
const _OpenAiAssistantRegistration = $llmToolsRegister.register(createOpenAiAssistantExecutionTools);
|
|
@@ -18328,7 +18406,7 @@ const markdownScraperMetadata = $deepFreeze({
|
|
|
18328
18406
|
className: 'MarkdownScraper',
|
|
18329
18407
|
mimeTypes: ['text/markdown', 'text/plain'],
|
|
18330
18408
|
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
18331
|
-
|
|
18409
|
+
isAvailableInBrowser: true,
|
|
18332
18410
|
// <- Note: [🌏] This is the only scraper which makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
18333
18411
|
requiredExecutables: [],
|
|
18334
18412
|
}); /* <- Note: [🤛] */
|
|
@@ -18338,7 +18416,7 @@ const markdownScraperMetadata = $deepFreeze({
|
|
|
18338
18416
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
18339
18417
|
*
|
|
18340
18418
|
* @public exported from `@promptbook/core`
|
|
18341
|
-
* @public exported from `@promptbook/
|
|
18419
|
+
* @public exported from `@promptbook/wizard`
|
|
18342
18420
|
* @public exported from `@promptbook/cli`
|
|
18343
18421
|
*/
|
|
18344
18422
|
const _MarkdownScraperMetadataRegistration = $scrapersMetadataRegister.register(markdownScraperMetadata);
|
|
@@ -18437,7 +18515,7 @@ class MarkdownScraper {
|
|
|
18437
18515
|
}
|
|
18438
18516
|
// ---
|
|
18439
18517
|
if (!llmTools.callEmbeddingModel) {
|
|
18440
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
18518
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
18441
18519
|
console.error('No callEmbeddingModel function provided');
|
|
18442
18520
|
}
|
|
18443
18521
|
else {
|
|
@@ -18463,7 +18541,7 @@ class MarkdownScraper {
|
|
|
18463
18541
|
if (!(error instanceof PipelineExecutionError)) {
|
|
18464
18542
|
throw error;
|
|
18465
18543
|
}
|
|
18466
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
18544
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
18467
18545
|
console.error(error, "<- Note: This error is not critical to prepare the pipeline, just knowledge pieces won't have embeddings");
|
|
18468
18546
|
}
|
|
18469
18547
|
return {
|
|
@@ -18497,7 +18575,7 @@ const boilerplateScraperMetadata = $deepFreeze({
|
|
|
18497
18575
|
// <- TODO: @@ Add compatible mime types with Boilerplate scraper
|
|
18498
18576
|
],
|
|
18499
18577
|
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
18500
|
-
|
|
18578
|
+
isAvailableInBrowser: false,
|
|
18501
18579
|
// <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
18502
18580
|
requiredExecutables: [
|
|
18503
18581
|
/* @@ 'Pandoc' */
|
|
@@ -18509,7 +18587,7 @@ const boilerplateScraperMetadata = $deepFreeze({
|
|
|
18509
18587
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
18510
18588
|
*
|
|
18511
18589
|
* @public exported from `@promptbook/core`
|
|
18512
|
-
* @public exported from `@promptbook/
|
|
18590
|
+
* @public exported from `@promptbook/wizard`
|
|
18513
18591
|
* @public exported from `@promptbook/cli`
|
|
18514
18592
|
*/
|
|
18515
18593
|
const _BoilerplateScraperMetadataRegistration = $scrapersMetadataRegister.register(boilerplateScraperMetadata);
|
|
@@ -18647,7 +18725,7 @@ const createBoilerplateScraper = Object.assign((tools, options) => {
|
|
|
18647
18725
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
18648
18726
|
*
|
|
18649
18727
|
* @public exported from `@promptbook/boilerplate`
|
|
18650
|
-
* @public exported from `@promptbook/
|
|
18728
|
+
* @public exported from `@promptbook/wizard`
|
|
18651
18729
|
* @public exported from `@promptbook/cli`
|
|
18652
18730
|
*/
|
|
18653
18731
|
const _BoilerplateScraperRegistration = $scrapersRegister.register(createBoilerplateScraper);
|
|
@@ -18667,7 +18745,7 @@ const documentScraperMetadata = $deepFreeze({
|
|
|
18667
18745
|
className: 'DocumentScraper',
|
|
18668
18746
|
mimeTypes: ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
|
|
18669
18747
|
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
18670
|
-
|
|
18748
|
+
isAvailableInBrowser: false,
|
|
18671
18749
|
// <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
18672
18750
|
requiredExecutables: ['Pandoc'],
|
|
18673
18751
|
}); /* <- Note: [🤛] */
|
|
@@ -18677,7 +18755,7 @@ const documentScraperMetadata = $deepFreeze({
|
|
|
18677
18755
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
18678
18756
|
*
|
|
18679
18757
|
* @public exported from `@promptbook/core`
|
|
18680
|
-
* @public exported from `@promptbook/
|
|
18758
|
+
* @public exported from `@promptbook/wizard`
|
|
18681
18759
|
* @public exported from `@promptbook/cli`
|
|
18682
18760
|
*/
|
|
18683
18761
|
const _DocumentScraperMetadataRegistration = $scrapersMetadataRegister.register(documentScraperMetadata);
|
|
@@ -18803,7 +18881,7 @@ const legacyDocumentScraperMetadata = $deepFreeze({
|
|
|
18803
18881
|
className: 'LegacyDocumentScraper',
|
|
18804
18882
|
mimeTypes: ['application/msword', 'text/rtf'],
|
|
18805
18883
|
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
18806
|
-
|
|
18884
|
+
isAvailableInBrowser: false,
|
|
18807
18885
|
// <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
18808
18886
|
requiredExecutables: [
|
|
18809
18887
|
'Pandoc',
|
|
@@ -18817,7 +18895,7 @@ const legacyDocumentScraperMetadata = $deepFreeze({
|
|
|
18817
18895
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
18818
18896
|
*
|
|
18819
18897
|
* @public exported from `@promptbook/core`
|
|
18820
|
-
* @public exported from `@promptbook/
|
|
18898
|
+
* @public exported from `@promptbook/wizard`
|
|
18821
18899
|
* @public exported from `@promptbook/cli`
|
|
18822
18900
|
*/
|
|
18823
18901
|
const _LegacyDocumentScraperMetadataRegistration = $scrapersMetadataRegister.register(legacyDocumentScraperMetadata);
|
|
@@ -18978,7 +19056,7 @@ const createLegacyDocumentScraper = Object.assign((tools, options) => {
|
|
|
18978
19056
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
18979
19057
|
*
|
|
18980
19058
|
* @public exported from `@promptbook/legacy-documents`
|
|
18981
|
-
* @public exported from `@promptbook/
|
|
19059
|
+
* @public exported from `@promptbook/wizard`
|
|
18982
19060
|
* @public exported from `@promptbook/cli`
|
|
18983
19061
|
*/
|
|
18984
19062
|
const _LegacyDocumentScraperRegistration = $scrapersRegister.register(createLegacyDocumentScraper);
|
|
@@ -19005,7 +19083,7 @@ const createDocumentScraper = Object.assign((tools, options) => {
|
|
|
19005
19083
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
19006
19084
|
*
|
|
19007
19085
|
* @public exported from `@promptbook/documents`
|
|
19008
|
-
* @public exported from `@promptbook/
|
|
19086
|
+
* @public exported from `@promptbook/wizard`
|
|
19009
19087
|
* @public exported from `@promptbook/cli`
|
|
19010
19088
|
*/
|
|
19011
19089
|
const _DocumentScraperRegistration = $scrapersRegister.register(createDocumentScraper);
|
|
@@ -19032,7 +19110,7 @@ const createMarkdownScraper = Object.assign((tools, options) => {
|
|
|
19032
19110
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
19033
19111
|
*
|
|
19034
19112
|
* @public exported from `@promptbook/markdown-utils`
|
|
19035
|
-
* @public exported from `@promptbook/
|
|
19113
|
+
* @public exported from `@promptbook/wizard`
|
|
19036
19114
|
* @public exported from `@promptbook/cli`
|
|
19037
19115
|
*/
|
|
19038
19116
|
const _MarkdownScraperRegistration = $scrapersRegister.register(createMarkdownScraper);
|
|
@@ -19057,7 +19135,7 @@ const markitdownScraperMetadata = $deepFreeze({
|
|
|
19057
19135
|
// 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
19058
19136
|
],
|
|
19059
19137
|
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
19060
|
-
|
|
19138
|
+
isAvailableInBrowser: false,
|
|
19061
19139
|
// <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
19062
19140
|
requiredExecutables: [],
|
|
19063
19141
|
}); /* <- Note: [🤛] */
|
|
@@ -19067,7 +19145,7 @@ const markitdownScraperMetadata = $deepFreeze({
|
|
|
19067
19145
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
19068
19146
|
*
|
|
19069
19147
|
* @public exported from `@promptbook/core`
|
|
19070
|
-
* @public exported from `@promptbook/
|
|
19148
|
+
* @public exported from `@promptbook/wizard`
|
|
19071
19149
|
* @public exported from `@promptbook/cli`
|
|
19072
19150
|
*/
|
|
19073
19151
|
const _MarkitdownScraperMetadataRegistration = $scrapersMetadataRegister.register(markitdownScraperMetadata);
|
|
@@ -19204,7 +19282,7 @@ const createMarkitdownScraper = Object.assign((tools, options) => {
|
|
|
19204
19282
|
*
|
|
19205
19283
|
* @public exported from `@promptbook/markitdown`
|
|
19206
19284
|
* @public exported from `@promptbook/pdf`
|
|
19207
|
-
* @public exported from `@promptbook/
|
|
19285
|
+
* @public exported from `@promptbook/wizard`
|
|
19208
19286
|
* @public exported from `@promptbook/cli`
|
|
19209
19287
|
*/
|
|
19210
19288
|
const _MarkitdownScraperRegistration = $scrapersRegister.register(createMarkitdownScraper);
|
|
@@ -19225,7 +19303,7 @@ const pdfScraperMetadata = $deepFreeze({
|
|
|
19225
19303
|
className: 'PdfScraper',
|
|
19226
19304
|
mimeTypes: ['application/pdf-DISABLED'],
|
|
19227
19305
|
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
19228
|
-
|
|
19306
|
+
isAvailableInBrowser: false,
|
|
19229
19307
|
// <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
19230
19308
|
requiredExecutables: [],
|
|
19231
19309
|
}); /* <- Note: [🤛] */
|
|
@@ -19235,7 +19313,7 @@ const pdfScraperMetadata = $deepFreeze({
|
|
|
19235
19313
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
19236
19314
|
*
|
|
19237
19315
|
* @public exported from `@promptbook/core`
|
|
19238
|
-
* @public exported from `@promptbook/
|
|
19316
|
+
* @public exported from `@promptbook/wizard`
|
|
19239
19317
|
* @public exported from `@promptbook/cli`
|
|
19240
19318
|
*/
|
|
19241
19319
|
const _PdfScraperMetadataRegistration = $scrapersMetadataRegister.register(pdfScraperMetadata);
|
|
@@ -19310,7 +19388,7 @@ const createPdfScraper = Object.assign((tools, options) => {
|
|
|
19310
19388
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
19311
19389
|
*
|
|
19312
19390
|
* @public exported from `@promptbook/pdf`
|
|
19313
|
-
* @public exported from `@promptbook/
|
|
19391
|
+
* @public exported from `@promptbook/wizard`
|
|
19314
19392
|
* @public exported from `@promptbook/cli`
|
|
19315
19393
|
*/
|
|
19316
19394
|
const _PdfScraperRegistration = $scrapersRegister.register(createPdfScraper);
|
|
@@ -19330,7 +19408,7 @@ const websiteScraperMetadata = $deepFreeze({
|
|
|
19330
19408
|
className: 'WebsiteScraper',
|
|
19331
19409
|
mimeTypes: ['text/html'],
|
|
19332
19410
|
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
19333
|
-
|
|
19411
|
+
isAvailableInBrowser: false,
|
|
19334
19412
|
// <- Note: [🌏] Only `MarkdownScraper` makes sense to be available in the browser, for scraping non-markdown sources in the browser use a remote server
|
|
19335
19413
|
requiredExecutables: [],
|
|
19336
19414
|
}); /* <- Note: [🤛] */
|
|
@@ -19340,7 +19418,7 @@ const websiteScraperMetadata = $deepFreeze({
|
|
|
19340
19418
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
19341
19419
|
*
|
|
19342
19420
|
* @public exported from `@promptbook/core`
|
|
19343
|
-
* @public exported from `@promptbook/
|
|
19421
|
+
* @public exported from `@promptbook/wizard`
|
|
19344
19422
|
* @public exported from `@promptbook/cli`
|
|
19345
19423
|
*/
|
|
19346
19424
|
const _WebsiteScraperMetadataRegistration = $scrapersMetadataRegister.register(websiteScraperMetadata);
|
|
@@ -19487,7 +19565,7 @@ const createWebsiteScraper = Object.assign((tools, options) => {
|
|
|
19487
19565
|
* Warning: This is not useful for the end user, it is just a side effect of the mechanism that handles all available known scrapers
|
|
19488
19566
|
*
|
|
19489
19567
|
* @public exported from `@promptbook/website-crawler`
|
|
19490
|
-
* @public exported from `@promptbook/
|
|
19568
|
+
* @public exported from `@promptbook/wizard`
|
|
19491
19569
|
* @public exported from `@promptbook/cli`
|
|
19492
19570
|
*/
|
|
19493
19571
|
const _WebsiteScraperRegistration = $scrapersRegister.register(createWebsiteScraper);
|