@promptbook/core 0.95.0 โ 0.98.0-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/esm/index.es.js +359 -170
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/anthropic-claude.index.d.ts +2 -2
- package/esm/typings/src/_packages/cli.index.d.ts +4 -0
- package/esm/typings/src/_packages/core.index.d.ts +2 -0
- package/esm/typings/src/_packages/openai.index.d.ts +10 -0
- package/esm/typings/src/_packages/types.index.d.ts +12 -2
- package/esm/typings/src/_packages/wizard.index.d.ts +4 -0
- package/esm/typings/src/config.d.ts +1 -1
- package/esm/typings/src/execution/createPipelineExecutor/$OngoingTaskResult.d.ts +8 -0
- package/esm/typings/src/execution/utils/validatePromptResult.d.ts +53 -0
- package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +3 -3
- package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionToolsOptions.d.ts +2 -2
- package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionToolsOptions.d.ts +2 -2
- package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +4 -4
- package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionToolsOptions.d.ts +52 -0
- package/esm/typings/src/llm-providers/openai/OpenAiExecutionToolsOptions.d.ts +3 -5
- package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +74 -0
- package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +11 -0
- package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +14 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +359 -169
- package/umd/index.umd.js.map +1 -1
package/umd/index.umd.js
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* @generated
|
|
28
28
|
* @see https://github.com/webgptorg/promptbook
|
|
29
29
|
*/
|
|
30
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
30
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.98.0-10';
|
|
31
31
|
/**
|
|
32
32
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
33
33
|
* Note: [๐] Ignore a discrepancy between file name and entity name
|
|
@@ -354,7 +354,7 @@
|
|
|
354
354
|
*
|
|
355
355
|
* @public exported from `@promptbook/core`
|
|
356
356
|
*/
|
|
357
|
-
const DEFAULT_MAX_EXECUTION_ATTEMPTS =
|
|
357
|
+
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 7; // <- TODO: [๐คนโโ๏ธ]
|
|
358
358
|
/**
|
|
359
359
|
* The maximum depth to which knowledge sources will be scraped when building a knowledge base.
|
|
360
360
|
* This prevents infinite recursion and limits resource usage.
|
|
@@ -2255,7 +2255,7 @@
|
|
|
2255
2255
|
throw new Error(spaceTrim__default["default"]((block) => `
|
|
2256
2256
|
${block(error.message)}
|
|
2257
2257
|
|
|
2258
|
-
The JSON text:
|
|
2258
|
+
The expected JSON text:
|
|
2259
2259
|
${block(value)}
|
|
2260
2260
|
`));
|
|
2261
2261
|
}
|
|
@@ -3387,108 +3387,6 @@
|
|
|
3387
3387
|
* TODO: [๐ทโโ๏ธ] @@@ Manual about construction of llmTools
|
|
3388
3388
|
*/
|
|
3389
3389
|
|
|
3390
|
-
/**
|
|
3391
|
-
* Extracts all code blocks from markdown.
|
|
3392
|
-
*
|
|
3393
|
-
* Note: There are multiple similar functions:
|
|
3394
|
-
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
3395
|
-
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3396
|
-
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3397
|
-
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3398
|
-
*
|
|
3399
|
-
* @param markdown any valid markdown
|
|
3400
|
-
* @returns code blocks with language and content
|
|
3401
|
-
* @throws {ParseError} if block is not closed properly
|
|
3402
|
-
* @public exported from `@promptbook/markdown-utils`
|
|
3403
|
-
*/
|
|
3404
|
-
function extractAllBlocksFromMarkdown(markdown) {
|
|
3405
|
-
const codeBlocks = [];
|
|
3406
|
-
const lines = markdown.split('\n');
|
|
3407
|
-
// Note: [0] Ensure that the last block notated by gt > will be closed
|
|
3408
|
-
lines.push('');
|
|
3409
|
-
let currentCodeBlock = null;
|
|
3410
|
-
for (const line of lines) {
|
|
3411
|
-
if (line.startsWith('> ') || line === '>') {
|
|
3412
|
-
if (currentCodeBlock === null) {
|
|
3413
|
-
currentCodeBlock = { blockNotation: '>', language: null, content: '' };
|
|
3414
|
-
} /* not else */
|
|
3415
|
-
if (currentCodeBlock.blockNotation === '>') {
|
|
3416
|
-
if (currentCodeBlock.content !== '') {
|
|
3417
|
-
currentCodeBlock.content += '\n';
|
|
3418
|
-
}
|
|
3419
|
-
currentCodeBlock.content += line.slice(2);
|
|
3420
|
-
}
|
|
3421
|
-
}
|
|
3422
|
-
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
|
|
3423
|
-
codeBlocks.push(currentCodeBlock);
|
|
3424
|
-
currentCodeBlock = null;
|
|
3425
|
-
}
|
|
3426
|
-
/* not else */
|
|
3427
|
-
if (line.startsWith('```')) {
|
|
3428
|
-
const language = line.slice(3).trim() || null;
|
|
3429
|
-
if (currentCodeBlock === null) {
|
|
3430
|
-
currentCodeBlock = { blockNotation: '```', language, content: '' };
|
|
3431
|
-
}
|
|
3432
|
-
else {
|
|
3433
|
-
if (language !== null) {
|
|
3434
|
-
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
|
|
3435
|
-
}
|
|
3436
|
-
codeBlocks.push(currentCodeBlock);
|
|
3437
|
-
currentCodeBlock = null;
|
|
3438
|
-
}
|
|
3439
|
-
}
|
|
3440
|
-
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
|
|
3441
|
-
if (currentCodeBlock.content !== '') {
|
|
3442
|
-
currentCodeBlock.content += '\n';
|
|
3443
|
-
}
|
|
3444
|
-
currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
|
|
3445
|
-
}
|
|
3446
|
-
}
|
|
3447
|
-
if (currentCodeBlock !== null) {
|
|
3448
|
-
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
|
|
3449
|
-
}
|
|
3450
|
-
return codeBlocks;
|
|
3451
|
-
}
|
|
3452
|
-
/**
|
|
3453
|
-
* TODO: Maybe name for `blockNotation` instead of '```' and '>'
|
|
3454
|
-
*/
|
|
3455
|
-
|
|
3456
|
-
/**
|
|
3457
|
-
* Extracts extracts exactly one valid JSON code block
|
|
3458
|
-
*
|
|
3459
|
-
* - When given string is a valid JSON as it is, it just returns it
|
|
3460
|
-
* - When there is no JSON code block the function throws a `ParseError`
|
|
3461
|
-
* - When there are multiple JSON code blocks the function throws a `ParseError`
|
|
3462
|
-
*
|
|
3463
|
-
* Note: It is not important if marked as ```json BUT if it is VALID JSON
|
|
3464
|
-
* Note: There are multiple similar function:
|
|
3465
|
-
* - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
|
|
3466
|
-
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3467
|
-
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3468
|
-
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3469
|
-
*
|
|
3470
|
-
* @public exported from `@promptbook/markdown-utils`
|
|
3471
|
-
* @throws {ParseError} if there is no valid JSON block in the markdown
|
|
3472
|
-
*/
|
|
3473
|
-
function extractJsonBlock(markdown) {
|
|
3474
|
-
if (isValidJsonString(markdown)) {
|
|
3475
|
-
return markdown;
|
|
3476
|
-
}
|
|
3477
|
-
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
3478
|
-
const jsonBlocks = codeBlocks.filter(({ content }) => isValidJsonString(content));
|
|
3479
|
-
if (jsonBlocks.length === 0) {
|
|
3480
|
-
throw new Error('There is no valid JSON block in the markdown');
|
|
3481
|
-
}
|
|
3482
|
-
if (jsonBlocks.length > 1) {
|
|
3483
|
-
throw new Error('There are multiple JSON code blocks in the markdown');
|
|
3484
|
-
}
|
|
3485
|
-
return jsonBlocks[0].content;
|
|
3486
|
-
}
|
|
3487
|
-
/**
|
|
3488
|
-
* TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
|
|
3489
|
-
* TODO: [๐ข] Make this logic part of `JsonFormatParser` or `isValidJsonString`
|
|
3490
|
-
*/
|
|
3491
|
-
|
|
3492
3390
|
/**
|
|
3493
3391
|
* Takes an item or an array of items and returns an array of items
|
|
3494
3392
|
*
|
|
@@ -3596,6 +3494,108 @@
|
|
|
3596
3494
|
return replacedTemplates;
|
|
3597
3495
|
}
|
|
3598
3496
|
|
|
3497
|
+
/**
|
|
3498
|
+
* Extracts all code blocks from markdown.
|
|
3499
|
+
*
|
|
3500
|
+
* Note: There are multiple similar functions:
|
|
3501
|
+
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
3502
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3503
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3504
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3505
|
+
*
|
|
3506
|
+
* @param markdown any valid markdown
|
|
3507
|
+
* @returns code blocks with language and content
|
|
3508
|
+
* @throws {ParseError} if block is not closed properly
|
|
3509
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
3510
|
+
*/
|
|
3511
|
+
function extractAllBlocksFromMarkdown(markdown) {
|
|
3512
|
+
const codeBlocks = [];
|
|
3513
|
+
const lines = markdown.split('\n');
|
|
3514
|
+
// Note: [0] Ensure that the last block notated by gt > will be closed
|
|
3515
|
+
lines.push('');
|
|
3516
|
+
let currentCodeBlock = null;
|
|
3517
|
+
for (const line of lines) {
|
|
3518
|
+
if (line.startsWith('> ') || line === '>') {
|
|
3519
|
+
if (currentCodeBlock === null) {
|
|
3520
|
+
currentCodeBlock = { blockNotation: '>', language: null, content: '' };
|
|
3521
|
+
} /* not else */
|
|
3522
|
+
if (currentCodeBlock.blockNotation === '>') {
|
|
3523
|
+
if (currentCodeBlock.content !== '') {
|
|
3524
|
+
currentCodeBlock.content += '\n';
|
|
3525
|
+
}
|
|
3526
|
+
currentCodeBlock.content += line.slice(2);
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
|
|
3530
|
+
codeBlocks.push(currentCodeBlock);
|
|
3531
|
+
currentCodeBlock = null;
|
|
3532
|
+
}
|
|
3533
|
+
/* not else */
|
|
3534
|
+
if (line.startsWith('```')) {
|
|
3535
|
+
const language = line.slice(3).trim() || null;
|
|
3536
|
+
if (currentCodeBlock === null) {
|
|
3537
|
+
currentCodeBlock = { blockNotation: '```', language, content: '' };
|
|
3538
|
+
}
|
|
3539
|
+
else {
|
|
3540
|
+
if (language !== null) {
|
|
3541
|
+
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
|
|
3542
|
+
}
|
|
3543
|
+
codeBlocks.push(currentCodeBlock);
|
|
3544
|
+
currentCodeBlock = null;
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
|
|
3548
|
+
if (currentCodeBlock.content !== '') {
|
|
3549
|
+
currentCodeBlock.content += '\n';
|
|
3550
|
+
}
|
|
3551
|
+
currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3554
|
+
if (currentCodeBlock !== null) {
|
|
3555
|
+
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
|
|
3556
|
+
}
|
|
3557
|
+
return codeBlocks;
|
|
3558
|
+
}
|
|
3559
|
+
/**
|
|
3560
|
+
* TODO: Maybe name for `blockNotation` instead of '```' and '>'
|
|
3561
|
+
*/
|
|
3562
|
+
|
|
3563
|
+
/**
|
|
3564
|
+
* Extracts extracts exactly one valid JSON code block
|
|
3565
|
+
*
|
|
3566
|
+
* - When given string is a valid JSON as it is, it just returns it
|
|
3567
|
+
* - When there is no JSON code block the function throws a `ParseError`
|
|
3568
|
+
* - When there are multiple JSON code blocks the function throws a `ParseError`
|
|
3569
|
+
*
|
|
3570
|
+
* Note: It is not important if marked as ```json BUT if it is VALID JSON
|
|
3571
|
+
* Note: There are multiple similar function:
|
|
3572
|
+
* - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
|
|
3573
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3574
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3575
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3576
|
+
*
|
|
3577
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
3578
|
+
* @throws {ParseError} if there is no valid JSON block in the markdown
|
|
3579
|
+
*/
|
|
3580
|
+
function extractJsonBlock(markdown) {
|
|
3581
|
+
if (isValidJsonString(markdown)) {
|
|
3582
|
+
return markdown;
|
|
3583
|
+
}
|
|
3584
|
+
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
3585
|
+
const jsonBlocks = codeBlocks.filter(({ content }) => isValidJsonString(content));
|
|
3586
|
+
if (jsonBlocks.length === 0) {
|
|
3587
|
+
throw new Error('There is no valid JSON block in the markdown');
|
|
3588
|
+
}
|
|
3589
|
+
if (jsonBlocks.length > 1) {
|
|
3590
|
+
throw new Error('There are multiple JSON code blocks in the markdown');
|
|
3591
|
+
}
|
|
3592
|
+
return jsonBlocks[0].content;
|
|
3593
|
+
}
|
|
3594
|
+
/**
|
|
3595
|
+
* TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
|
|
3596
|
+
* TODO: [๐ข] Make this logic part of `JsonFormatParser` or `isValidJsonString`
|
|
3597
|
+
*/
|
|
3598
|
+
|
|
3599
3599
|
/**
|
|
3600
3600
|
* Counts number of characters in the text
|
|
3601
3601
|
*
|
|
@@ -4039,6 +4039,68 @@
|
|
|
4039
4039
|
* Note: [๐] and [๐ค ] are interconnected together
|
|
4040
4040
|
*/
|
|
4041
4041
|
|
|
4042
|
+
/**
|
|
4043
|
+
* Validates a prompt result against expectations and format requirements.
|
|
4044
|
+
* This function provides a common abstraction for result validation that can be used
|
|
4045
|
+
* by both execution logic and caching logic to ensure consistency.
|
|
4046
|
+
*
|
|
4047
|
+
* @param options - The validation options including result string, expectations, and format
|
|
4048
|
+
* @returns Validation result with processed string and validity status
|
|
4049
|
+
* @private internal function of `createPipelineExecutor` and `cacheLlmTools`
|
|
4050
|
+
*/
|
|
4051
|
+
function validatePromptResult(options) {
|
|
4052
|
+
const { resultString, expectations, format } = options;
|
|
4053
|
+
let processedResultString = resultString;
|
|
4054
|
+
let validationError;
|
|
4055
|
+
try {
|
|
4056
|
+
// TODO: [๐] Unite object for expecting amount and format
|
|
4057
|
+
if (format) {
|
|
4058
|
+
if (format === 'JSON') {
|
|
4059
|
+
if (!isValidJsonString(processedResultString)) {
|
|
4060
|
+
// TODO: [๐ข] Do more universally via `FormatParser`
|
|
4061
|
+
try {
|
|
4062
|
+
processedResultString = extractJsonBlock(processedResultString);
|
|
4063
|
+
}
|
|
4064
|
+
catch (error) {
|
|
4065
|
+
keepUnused(error);
|
|
4066
|
+
throw new ExpectError(spaceTrim.spaceTrim((block) => `
|
|
4067
|
+
Expected valid JSON string
|
|
4068
|
+
|
|
4069
|
+
The expected JSON text:
|
|
4070
|
+
${block(processedResultString)}
|
|
4071
|
+
`));
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
else {
|
|
4076
|
+
throw new UnexpectedError(`Unknown format "${format}"`);
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
// TODO: [๐] Unite object for expecting amount and format
|
|
4080
|
+
if (expectations) {
|
|
4081
|
+
checkExpectations(expectations, processedResultString);
|
|
4082
|
+
}
|
|
4083
|
+
return {
|
|
4084
|
+
isValid: true,
|
|
4085
|
+
processedResultString,
|
|
4086
|
+
};
|
|
4087
|
+
}
|
|
4088
|
+
catch (error) {
|
|
4089
|
+
if (error instanceof ExpectError) {
|
|
4090
|
+
validationError = error;
|
|
4091
|
+
}
|
|
4092
|
+
else {
|
|
4093
|
+
// Re-throw non-ExpectError errors (like UnexpectedError)
|
|
4094
|
+
throw error;
|
|
4095
|
+
}
|
|
4096
|
+
return {
|
|
4097
|
+
isValid: false,
|
|
4098
|
+
processedResultString,
|
|
4099
|
+
error: validationError,
|
|
4100
|
+
};
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4042
4104
|
/**
|
|
4043
4105
|
* Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
|
|
4044
4106
|
* (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
|
|
@@ -4056,17 +4118,18 @@
|
|
|
4056
4118
|
$resultString: null,
|
|
4057
4119
|
$expectError: null,
|
|
4058
4120
|
$scriptPipelineExecutionErrors: [],
|
|
4121
|
+
$failedResults: [], // Track all failed attempts
|
|
4059
4122
|
};
|
|
4060
4123
|
// TODO: [๐] Make arrayable LLMs -> single LLM DRY
|
|
4061
4124
|
const _llms = arrayableToArray(tools.llm);
|
|
4062
4125
|
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
4063
|
-
attempts: for (let
|
|
4064
|
-
const isJokerAttempt =
|
|
4065
|
-
const jokerParameterName = jokerParameterNames[jokerParameterNames.length +
|
|
4126
|
+
attempts: for (let attemptIndex = -jokerParameterNames.length; attemptIndex < maxAttempts; attemptIndex++) {
|
|
4127
|
+
const isJokerAttempt = attemptIndex < 0;
|
|
4128
|
+
const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attemptIndex];
|
|
4066
4129
|
// TODO: [๐ง ][๐ญ] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
|
|
4067
4130
|
if (isJokerAttempt && !jokerParameterName) {
|
|
4068
4131
|
throw new UnexpectedError(spaceTrim.spaceTrim((block) => `
|
|
4069
|
-
Joker not found in attempt ${
|
|
4132
|
+
Joker not found in attempt ${attemptIndex}
|
|
4070
4133
|
|
|
4071
4134
|
${block(pipelineIdentification)}
|
|
4072
4135
|
`));
|
|
@@ -4264,35 +4327,18 @@
|
|
|
4264
4327
|
}
|
|
4265
4328
|
}
|
|
4266
4329
|
// TODO: [๐] Unite object for expecting amount and format
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
throw new ExpectError(spaceTrim.spaceTrim((block) => `
|
|
4277
|
-
Expected valid JSON string
|
|
4278
|
-
|
|
4279
|
-
${block(
|
|
4280
|
-
/*<- Note: No need for `pipelineIdentification`, it will be catched and added later */ '')}
|
|
4281
|
-
`));
|
|
4282
|
-
}
|
|
4283
|
-
}
|
|
4284
|
-
}
|
|
4285
|
-
else {
|
|
4286
|
-
throw new UnexpectedError(spaceTrim.spaceTrim((block) => `
|
|
4287
|
-
Unknown format "${task.format}"
|
|
4288
|
-
|
|
4289
|
-
${block(pipelineIdentification)}
|
|
4290
|
-
`));
|
|
4330
|
+
// Use the common validation function for both format and expectations
|
|
4331
|
+
if (task.format || task.expectations) {
|
|
4332
|
+
const validationResult = validatePromptResult({
|
|
4333
|
+
resultString: $ongoingTaskResult.$resultString || '',
|
|
4334
|
+
expectations: task.expectations,
|
|
4335
|
+
format: task.format,
|
|
4336
|
+
});
|
|
4337
|
+
if (!validationResult.isValid) {
|
|
4338
|
+
throw validationResult.error;
|
|
4291
4339
|
}
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
if (task.expectations) {
|
|
4295
|
-
checkExpectations(task.expectations, $ongoingTaskResult.$resultString || '');
|
|
4340
|
+
// Update the result string in case format processing modified it (e.g., JSON extraction)
|
|
4341
|
+
$ongoingTaskResult.$resultString = validationResult.processedResultString;
|
|
4296
4342
|
}
|
|
4297
4343
|
break attempts;
|
|
4298
4344
|
}
|
|
@@ -4301,6 +4347,15 @@
|
|
|
4301
4347
|
throw error;
|
|
4302
4348
|
}
|
|
4303
4349
|
$ongoingTaskResult.$expectError = error;
|
|
4350
|
+
// Store each failed attempt
|
|
4351
|
+
if (!Array.isArray($ongoingTaskResult.$failedResults)) {
|
|
4352
|
+
$ongoingTaskResult.$failedResults = [];
|
|
4353
|
+
}
|
|
4354
|
+
$ongoingTaskResult.$failedResults.push({
|
|
4355
|
+
attemptIndex,
|
|
4356
|
+
result: $ongoingTaskResult.$resultString,
|
|
4357
|
+
error: error,
|
|
4358
|
+
});
|
|
4304
4359
|
}
|
|
4305
4360
|
finally {
|
|
4306
4361
|
if (!isJokerAttempt &&
|
|
@@ -4322,35 +4377,41 @@
|
|
|
4322
4377
|
});
|
|
4323
4378
|
}
|
|
4324
4379
|
}
|
|
4325
|
-
if ($ongoingTaskResult.$expectError !== null &&
|
|
4380
|
+
if ($ongoingTaskResult.$expectError !== null && attemptIndex === maxAttempts - 1) {
|
|
4381
|
+
// Note: Create a summary of all failures
|
|
4382
|
+
const failuresSummary = $ongoingTaskResult.$failedResults
|
|
4383
|
+
.map((failure) => spaceTrim.spaceTrim((block) => {
|
|
4384
|
+
var _a, _b;
|
|
4385
|
+
return `
|
|
4386
|
+
Attempt ${failure.attemptIndex + 1}:
|
|
4387
|
+
Error ${((_a = failure.error) === null || _a === void 0 ? void 0 : _a.name) || ''}:
|
|
4388
|
+
${block((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message.split('\n').map((line) => `> ${line}`).join('\n'))}
|
|
4389
|
+
|
|
4390
|
+
Result:
|
|
4391
|
+
${block(failure.result === null
|
|
4392
|
+
? 'null'
|
|
4393
|
+
: spaceTrim.spaceTrim(failure.result)
|
|
4394
|
+
.split('\n')
|
|
4395
|
+
.map((line) => `> ${line}`)
|
|
4396
|
+
.join('\n'))}
|
|
4397
|
+
`;
|
|
4398
|
+
}))
|
|
4399
|
+
.join('\n\n---\n\n');
|
|
4326
4400
|
throw new PipelineExecutionError(spaceTrim.spaceTrim((block) => {
|
|
4327
|
-
var _a
|
|
4401
|
+
var _a;
|
|
4328
4402
|
return `
|
|
4329
4403
|
LLM execution failed ${maxExecutionAttempts}x
|
|
4330
4404
|
|
|
4331
4405
|
${block(pipelineIdentification)}
|
|
4332
4406
|
|
|
4333
|
-
---
|
|
4334
4407
|
The Prompt:
|
|
4335
4408
|
${block((((_a = $ongoingTaskResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || '')
|
|
4336
4409
|
.split('\n')
|
|
4337
4410
|
.map((line) => `> ${line}`)
|
|
4338
4411
|
.join('\n'))}
|
|
4339
4412
|
|
|
4340
|
-
|
|
4341
|
-
${block(
|
|
4342
|
-
.split('\n')
|
|
4343
|
-
.map((line) => `> ${line}`)
|
|
4344
|
-
.join('\n'))}
|
|
4345
|
-
|
|
4346
|
-
Last result:
|
|
4347
|
-
${block($ongoingTaskResult.$resultString === null
|
|
4348
|
-
? 'null'
|
|
4349
|
-
: spaceTrim.spaceTrim($ongoingTaskResult.$resultString)
|
|
4350
|
-
.split('\n')
|
|
4351
|
-
.map((line) => `> ${line}`)
|
|
4352
|
-
.join('\n'))}
|
|
4353
|
-
---
|
|
4413
|
+
All Failed Attempts:
|
|
4414
|
+
${block(failuresSummary)}
|
|
4354
4415
|
`;
|
|
4355
4416
|
}));
|
|
4356
4417
|
}
|
|
@@ -10468,6 +10529,24 @@
|
|
|
10468
10529
|
* TODO: [ยฎ] DRY Register logic
|
|
10469
10530
|
*/
|
|
10470
10531
|
|
|
10532
|
+
/**
|
|
10533
|
+
* Detects if the code is running in a browser environment in main thread (Not in a web worker)
|
|
10534
|
+
*
|
|
10535
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10536
|
+
*
|
|
10537
|
+
* @public exported from `@promptbook/utils`
|
|
10538
|
+
*/
|
|
10539
|
+
const $isRunningInBrowser = new Function(`
|
|
10540
|
+
try {
|
|
10541
|
+
return this === window;
|
|
10542
|
+
} catch (e) {
|
|
10543
|
+
return false;
|
|
10544
|
+
}
|
|
10545
|
+
`);
|
|
10546
|
+
/**
|
|
10547
|
+
* TODO: [๐บ]
|
|
10548
|
+
*/
|
|
10549
|
+
|
|
10471
10550
|
/**
|
|
10472
10551
|
* Detects if the code is running in a Node.js environment
|
|
10473
10552
|
*
|
|
@@ -10486,6 +10565,28 @@
|
|
|
10486
10565
|
* TODO: [๐บ]
|
|
10487
10566
|
*/
|
|
10488
10567
|
|
|
10568
|
+
/**
|
|
10569
|
+
* Detects if the code is running in a web worker
|
|
10570
|
+
*
|
|
10571
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10572
|
+
*
|
|
10573
|
+
* @public exported from `@promptbook/utils`
|
|
10574
|
+
*/
|
|
10575
|
+
const $isRunningInWebWorker = new Function(`
|
|
10576
|
+
try {
|
|
10577
|
+
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
|
|
10578
|
+
return true;
|
|
10579
|
+
} else {
|
|
10580
|
+
return false;
|
|
10581
|
+
}
|
|
10582
|
+
} catch (e) {
|
|
10583
|
+
return false;
|
|
10584
|
+
}
|
|
10585
|
+
`);
|
|
10586
|
+
/**
|
|
10587
|
+
* TODO: [๐บ]
|
|
10588
|
+
*/
|
|
10589
|
+
|
|
10489
10590
|
/**
|
|
10490
10591
|
* Creates a message with all registered LLM tools
|
|
10491
10592
|
*
|
|
@@ -10630,8 +10731,10 @@
|
|
|
10630
10731
|
.list()
|
|
10631
10732
|
.find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
|
|
10632
10733
|
if (registeredItem === undefined) {
|
|
10734
|
+
console.log('!!! $llmToolsRegister.list()', $llmToolsRegister.list());
|
|
10633
10735
|
throw new Error(spaceTrim__default["default"]((block) => `
|
|
10634
10736
|
There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
|
|
10737
|
+
Running in ${!$isRunningInBrowser() ? '' : 'browser environment'}${!$isRunningInNode() ? '' : 'node environment'}${!$isRunningInWebWorker() ? '' : 'worker environment'}
|
|
10635
10738
|
|
|
10636
10739
|
You have probably forgotten install and import the provider package.
|
|
10637
10740
|
To fix this issue, you can:
|
|
@@ -10759,6 +10862,7 @@
|
|
|
10759
10862
|
},
|
|
10760
10863
|
};
|
|
10761
10864
|
const callCommonModel = async (prompt) => {
|
|
10865
|
+
var _a;
|
|
10762
10866
|
const { parameters, content, modelRequirements } = prompt;
|
|
10763
10867
|
// <- Note: These are relevant things from the prompt that the cache key should depend on.
|
|
10764
10868
|
// TODO: Maybe some standalone function for normalization of content for cache
|
|
@@ -10809,21 +10913,70 @@
|
|
|
10809
10913
|
}
|
|
10810
10914
|
// TODO: [๐ง ] !!5 How to do timing in mixed cache / non-cache situation
|
|
10811
10915
|
// promptResult.timing: FromtoItems
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10818
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
10826
|
-
|
|
10916
|
+
// Check if the result is valid and should be cached
|
|
10917
|
+
// A result is considered failed if:
|
|
10918
|
+
// 1. It has a content property that is null or undefined
|
|
10919
|
+
// 2. It has an error property that is truthy
|
|
10920
|
+
// 3. It has a success property that is explicitly false
|
|
10921
|
+
// 4. It doesn't meet the prompt's expectations or format requirements
|
|
10922
|
+
const isBasicFailedResult = promptResult.content === null ||
|
|
10923
|
+
promptResult.content === undefined ||
|
|
10924
|
+
promptResult.error ||
|
|
10925
|
+
promptResult.success === false;
|
|
10926
|
+
let shouldCache = !isBasicFailedResult;
|
|
10927
|
+
// If the basic result is valid, check against expectations and format
|
|
10928
|
+
if (shouldCache && promptResult.content) {
|
|
10929
|
+
try {
|
|
10930
|
+
const validationResult = validatePromptResult({
|
|
10931
|
+
resultString: promptResult.content,
|
|
10932
|
+
expectations: prompt.expectations,
|
|
10933
|
+
format: prompt.format,
|
|
10934
|
+
});
|
|
10935
|
+
shouldCache = validationResult.isValid;
|
|
10936
|
+
if (!shouldCache && isVerbose) {
|
|
10937
|
+
console.info('Not caching result that fails expectations/format validation for key:', key, {
|
|
10938
|
+
content: promptResult.content,
|
|
10939
|
+
expectations: prompt.expectations,
|
|
10940
|
+
format: prompt.format,
|
|
10941
|
+
validationError: (_a = validationResult.error) === null || _a === void 0 ? void 0 : _a.message,
|
|
10942
|
+
});
|
|
10943
|
+
}
|
|
10944
|
+
}
|
|
10945
|
+
catch (error) {
|
|
10946
|
+
// If validation throws an unexpected error, don't cache
|
|
10947
|
+
shouldCache = false;
|
|
10948
|
+
if (isVerbose) {
|
|
10949
|
+
console.info('Not caching result due to validation error for key:', key, {
|
|
10950
|
+
content: promptResult.content,
|
|
10951
|
+
validationError: error instanceof Error ? error.message : String(error),
|
|
10952
|
+
});
|
|
10953
|
+
}
|
|
10954
|
+
}
|
|
10955
|
+
}
|
|
10956
|
+
if (shouldCache) {
|
|
10957
|
+
await storage.setItem(key, {
|
|
10958
|
+
date: $getCurrentDate(),
|
|
10959
|
+
promptbookVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
10960
|
+
bookVersion: BOOK_LANGUAGE_VERSION,
|
|
10961
|
+
prompt: {
|
|
10962
|
+
...prompt,
|
|
10963
|
+
parameters: Object.entries(parameters).length === Object.entries(relevantParameters).length
|
|
10964
|
+
? parameters
|
|
10965
|
+
: {
|
|
10966
|
+
...relevantParameters,
|
|
10967
|
+
note: `<- Note: Only relevant parameters are stored in the cache`,
|
|
10968
|
+
},
|
|
10969
|
+
},
|
|
10970
|
+
promptResult,
|
|
10971
|
+
});
|
|
10972
|
+
}
|
|
10973
|
+
else if (isVerbose && isBasicFailedResult) {
|
|
10974
|
+
console.info('Not caching failed result for key:', key, {
|
|
10975
|
+
content: promptResult.content,
|
|
10976
|
+
error: promptResult.error,
|
|
10977
|
+
success: promptResult.success,
|
|
10978
|
+
});
|
|
10979
|
+
}
|
|
10827
10980
|
return promptResult;
|
|
10828
10981
|
};
|
|
10829
10982
|
if (llmTools.callChatModel !== undefined) {
|
|
@@ -11273,6 +11426,42 @@
|
|
|
11273
11426
|
*/
|
|
11274
11427
|
},
|
|
11275
11428
|
});
|
|
11429
|
+
/**
|
|
11430
|
+
* Registration of the OpenAI Compatible metadata
|
|
11431
|
+
*
|
|
11432
|
+
* Note: OpenAiCompatibleExecutionTools is an abstract class and cannot be instantiated directly.
|
|
11433
|
+
* It serves as a base class for OpenAiExecutionTools and other compatible implementations.
|
|
11434
|
+
*
|
|
11435
|
+
* @public exported from `@promptbook/core`
|
|
11436
|
+
* @public exported from `@promptbook/wizard`
|
|
11437
|
+
* @public exported from `@promptbook/cli`
|
|
11438
|
+
*/
|
|
11439
|
+
const _OpenAiCompatibleMetadataRegistration = $llmToolsMetadataRegister.register({
|
|
11440
|
+
title: 'Open AI Compatible',
|
|
11441
|
+
packageName: '@promptbook/openai',
|
|
11442
|
+
className: 'OpenAiCompatibleExecutionTools',
|
|
11443
|
+
envVariables: ['OPENAI_API_KEY', 'OPENAI_BASE_URL'],
|
|
11444
|
+
trustLevel: 'CLOSED',
|
|
11445
|
+
order: MODEL_ORDERS.TOP_TIER,
|
|
11446
|
+
getBoilerplateConfiguration() {
|
|
11447
|
+
return {
|
|
11448
|
+
title: 'Open AI Compatible',
|
|
11449
|
+
packageName: '@promptbook/openai',
|
|
11450
|
+
className: 'OpenAiCompatibleExecutionTools',
|
|
11451
|
+
options: {
|
|
11452
|
+
apiKey: 'sk-',
|
|
11453
|
+
baseURL: 'https://api.openai.com/v1',
|
|
11454
|
+
defaultModelName: 'gpt-4-turbo',
|
|
11455
|
+
isProxied: false,
|
|
11456
|
+
remoteServerUrl: DEFAULT_REMOTE_SERVER_URL,
|
|
11457
|
+
maxRequestsPerMinute: DEFAULT_MAX_REQUESTS_PER_MINUTE,
|
|
11458
|
+
},
|
|
11459
|
+
};
|
|
11460
|
+
},
|
|
11461
|
+
createConfigurationFromEnv(env) {
|
|
11462
|
+
return null;
|
|
11463
|
+
},
|
|
11464
|
+
});
|
|
11276
11465
|
/**
|
|
11277
11466
|
* Note: [๐] Ignore a discrepancy between file name and entity name
|
|
11278
11467
|
*/
|
|
@@ -11857,6 +12046,7 @@
|
|
|
11857
12046
|
exports._MarkitdownScraperMetadataRegistration = _MarkitdownScraperMetadataRegistration;
|
|
11858
12047
|
exports._OllamaMetadataRegistration = _OllamaMetadataRegistration;
|
|
11859
12048
|
exports._OpenAiAssistantMetadataRegistration = _OpenAiAssistantMetadataRegistration;
|
|
12049
|
+
exports._OpenAiCompatibleMetadataRegistration = _OpenAiCompatibleMetadataRegistration;
|
|
11860
12050
|
exports._OpenAiMetadataRegistration = _OpenAiMetadataRegistration;
|
|
11861
12051
|
exports._PdfScraperMetadataRegistration = _PdfScraperMetadataRegistration;
|
|
11862
12052
|
exports._WebsiteScraperMetadataRegistration = _WebsiteScraperMetadataRegistration;
|