@promptbook/node 0.94.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 +6 -2
- package/esm/index.es.js +300 -237
- 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 +14 -4
- package/esm/typings/src/_packages/{wizzard.index.d.ts → wizard.index.d.ts} +6 -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/config.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/$OngoingTaskResult.d.ts +8 -0
- 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/execution/utils/validatePromptResult.d.ts +53 -0
- package/esm/typings/src/llm-providers/_common/register/{$provideLlmToolsForWizzardOrCli.d.ts → $provideLlmToolsForWizardOrCli.d.ts} +2 -2
- 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/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/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 +13 -2
- package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +16 -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 +2 -14
- package/umd/index.umd.js +300 -237
- package/umd/index.umd.js.map +1 -1
package/esm/index.es.js
CHANGED
|
@@ -30,7 +30,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
30
30
|
* @generated
|
|
31
31
|
* @see https://github.com/webgptorg/promptbook
|
|
32
32
|
*/
|
|
33
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
33
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.98.0-10';
|
|
34
34
|
/**
|
|
35
35
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
36
36
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -174,7 +174,7 @@ const DEFAULT_MAX_PARALLEL_COUNT = 5; // <- TODO: [🤹♂️]
|
|
|
174
174
|
*
|
|
175
175
|
* @public exported from `@promptbook/core`
|
|
176
176
|
*/
|
|
177
|
-
const DEFAULT_MAX_EXECUTION_ATTEMPTS =
|
|
177
|
+
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 7; // <- TODO: [🤹♂️]
|
|
178
178
|
// <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
|
|
179
179
|
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
180
180
|
/**
|
|
@@ -196,11 +196,11 @@ const DEFAULT_SCRAPE_CACHE_DIRNAME = './.promptbook/scrape-cache';
|
|
|
196
196
|
/*
|
|
197
197
|
TODO: [🌃]
|
|
198
198
|
/**
|
|
199
|
-
* Id of application for the
|
|
199
|
+
* Id of application for the wizard when using remote server
|
|
200
200
|
*
|
|
201
201
|
* @public exported from `@promptbook/core`
|
|
202
202
|
* /
|
|
203
|
-
ex-port const
|
|
203
|
+
ex-port const WIZARD_APP_ID: string_app_id = 'wizard';
|
|
204
204
|
*/
|
|
205
205
|
/**
|
|
206
206
|
* The name of the builded pipeline collection made by CLI `ptbk make` and for lookup in `createCollectionFromDirectory`
|
|
@@ -344,7 +344,7 @@ function jsonParse(value) {
|
|
|
344
344
|
throw new Error(spaceTrim((block) => `
|
|
345
345
|
${block(error.message)}
|
|
346
346
|
|
|
347
|
-
The JSON text:
|
|
347
|
+
The expected JSON text:
|
|
348
348
|
${block(value)}
|
|
349
349
|
`));
|
|
350
350
|
}
|
|
@@ -522,7 +522,7 @@ function checkSerializableAsJson(options) {
|
|
|
522
522
|
else {
|
|
523
523
|
for (const [subName, subValue] of Object.entries(value)) {
|
|
524
524
|
if (subValue === undefined) {
|
|
525
|
-
// Note: undefined in object is serializable - it is just
|
|
525
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
526
526
|
continue;
|
|
527
527
|
}
|
|
528
528
|
checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
|
|
@@ -1131,7 +1131,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1131
1131
|
* @param fs Filesystem tools
|
|
1132
1132
|
* @returns Pipelines loaded from the archive
|
|
1133
1133
|
*
|
|
1134
|
-
* @private utility of
|
|
1134
|
+
* @private utility of Promptbook
|
|
1135
1135
|
*/
|
|
1136
1136
|
async function loadArchive(filePath, fs) {
|
|
1137
1137
|
if (!filePath.endsWith('.bookc')) {
|
|
@@ -1153,7 +1153,7 @@ async function loadArchive(filePath, fs) {
|
|
|
1153
1153
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
1154
1154
|
*/
|
|
1155
1155
|
|
|
1156
|
-
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"}];
|
|
1156
|
+
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"}];
|
|
1157
1157
|
|
|
1158
1158
|
/**
|
|
1159
1159
|
* Checks if value is valid email
|
|
@@ -1295,7 +1295,7 @@ function prettifyMarkdown(content) {
|
|
|
1295
1295
|
});
|
|
1296
1296
|
}
|
|
1297
1297
|
catch (error) {
|
|
1298
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
1298
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
1299
1299
|
console.error('There was an error with prettifying the markdown, using the original as the fallback', {
|
|
1300
1300
|
error,
|
|
1301
1301
|
html: content,
|
|
@@ -1586,7 +1586,7 @@ class SimplePipelineCollection {
|
|
|
1586
1586
|
|
|
1587
1587
|
Note: You have probably forgotten to run "ptbk make" to update the collection
|
|
1588
1588
|
Note: Pipelines with the same URL are not allowed
|
|
1589
|
-
Only
|
|
1589
|
+
Only exception is when the pipelines are identical
|
|
1590
1590
|
|
|
1591
1591
|
`));
|
|
1592
1592
|
}
|
|
@@ -3075,13 +3075,13 @@ function joinLlmExecutionTools(...llmExecutionTools) {
|
|
|
3075
3075
|
|
|
3076
3076
|
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.
|
|
3077
3077
|
`);
|
|
3078
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
3078
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
3079
3079
|
console.warn(warningMessage);
|
|
3080
3080
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3081
3081
|
/*
|
|
3082
3082
|
return {
|
|
3083
3083
|
async listModels() {
|
|
3084
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
3084
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
3085
3085
|
console.warn(
|
|
3086
3086
|
spaceTrim(
|
|
3087
3087
|
(block) => `
|
|
@@ -3105,108 +3105,6 @@ function joinLlmExecutionTools(...llmExecutionTools) {
|
|
|
3105
3105
|
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
3106
3106
|
*/
|
|
3107
3107
|
|
|
3108
|
-
/**
|
|
3109
|
-
* Extracts all code blocks from markdown.
|
|
3110
|
-
*
|
|
3111
|
-
* Note: There are multiple similar functions:
|
|
3112
|
-
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
3113
|
-
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3114
|
-
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3115
|
-
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3116
|
-
*
|
|
3117
|
-
* @param markdown any valid markdown
|
|
3118
|
-
* @returns code blocks with language and content
|
|
3119
|
-
* @throws {ParseError} if block is not closed properly
|
|
3120
|
-
* @public exported from `@promptbook/markdown-utils`
|
|
3121
|
-
*/
|
|
3122
|
-
function extractAllBlocksFromMarkdown(markdown) {
|
|
3123
|
-
const codeBlocks = [];
|
|
3124
|
-
const lines = markdown.split('\n');
|
|
3125
|
-
// Note: [0] Ensure that the last block notated by gt > will be closed
|
|
3126
|
-
lines.push('');
|
|
3127
|
-
let currentCodeBlock = null;
|
|
3128
|
-
for (const line of lines) {
|
|
3129
|
-
if (line.startsWith('> ') || line === '>') {
|
|
3130
|
-
if (currentCodeBlock === null) {
|
|
3131
|
-
currentCodeBlock = { blockNotation: '>', language: null, content: '' };
|
|
3132
|
-
} /* not else */
|
|
3133
|
-
if (currentCodeBlock.blockNotation === '>') {
|
|
3134
|
-
if (currentCodeBlock.content !== '') {
|
|
3135
|
-
currentCodeBlock.content += '\n';
|
|
3136
|
-
}
|
|
3137
|
-
currentCodeBlock.content += line.slice(2);
|
|
3138
|
-
}
|
|
3139
|
-
}
|
|
3140
|
-
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
|
|
3141
|
-
codeBlocks.push(currentCodeBlock);
|
|
3142
|
-
currentCodeBlock = null;
|
|
3143
|
-
}
|
|
3144
|
-
/* not else */
|
|
3145
|
-
if (line.startsWith('```')) {
|
|
3146
|
-
const language = line.slice(3).trim() || null;
|
|
3147
|
-
if (currentCodeBlock === null) {
|
|
3148
|
-
currentCodeBlock = { blockNotation: '```', language, content: '' };
|
|
3149
|
-
}
|
|
3150
|
-
else {
|
|
3151
|
-
if (language !== null) {
|
|
3152
|
-
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
|
|
3153
|
-
}
|
|
3154
|
-
codeBlocks.push(currentCodeBlock);
|
|
3155
|
-
currentCodeBlock = null;
|
|
3156
|
-
}
|
|
3157
|
-
}
|
|
3158
|
-
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
|
|
3159
|
-
if (currentCodeBlock.content !== '') {
|
|
3160
|
-
currentCodeBlock.content += '\n';
|
|
3161
|
-
}
|
|
3162
|
-
currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
|
|
3163
|
-
}
|
|
3164
|
-
}
|
|
3165
|
-
if (currentCodeBlock !== null) {
|
|
3166
|
-
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
|
|
3167
|
-
}
|
|
3168
|
-
return codeBlocks;
|
|
3169
|
-
}
|
|
3170
|
-
/**
|
|
3171
|
-
* TODO: Maybe name for `blockNotation` instead of '```' and '>'
|
|
3172
|
-
*/
|
|
3173
|
-
|
|
3174
|
-
/**
|
|
3175
|
-
* Extracts extracts exactly one valid JSON code block
|
|
3176
|
-
*
|
|
3177
|
-
* - When given string is a valid JSON as it is, it just returns it
|
|
3178
|
-
* - When there is no JSON code block the function throws a `ParseError`
|
|
3179
|
-
* - When there are multiple JSON code blocks the function throws a `ParseError`
|
|
3180
|
-
*
|
|
3181
|
-
* Note: It is not important if marked as ```json BUT if it is VALID JSON
|
|
3182
|
-
* Note: There are multiple similar function:
|
|
3183
|
-
* - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
|
|
3184
|
-
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3185
|
-
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3186
|
-
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3187
|
-
*
|
|
3188
|
-
* @public exported from `@promptbook/markdown-utils`
|
|
3189
|
-
* @throws {ParseError} if there is no valid JSON block in the markdown
|
|
3190
|
-
*/
|
|
3191
|
-
function extractJsonBlock(markdown) {
|
|
3192
|
-
if (isValidJsonString(markdown)) {
|
|
3193
|
-
return markdown;
|
|
3194
|
-
}
|
|
3195
|
-
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
3196
|
-
const jsonBlocks = codeBlocks.filter(({ content }) => isValidJsonString(content));
|
|
3197
|
-
if (jsonBlocks.length === 0) {
|
|
3198
|
-
throw new Error('There is no valid JSON block in the markdown');
|
|
3199
|
-
}
|
|
3200
|
-
if (jsonBlocks.length > 1) {
|
|
3201
|
-
throw new Error('There are multiple JSON code blocks in the markdown');
|
|
3202
|
-
}
|
|
3203
|
-
return jsonBlocks[0].content;
|
|
3204
|
-
}
|
|
3205
|
-
/**
|
|
3206
|
-
* TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
|
|
3207
|
-
* TODO: [🏢] Make this logic part of `JsonFormatParser` or `isValidJsonString`
|
|
3208
|
-
*/
|
|
3209
|
-
|
|
3210
3108
|
/**
|
|
3211
3109
|
* Takes an item or an array of items and returns an array of items
|
|
3212
3110
|
*
|
|
@@ -3314,6 +3212,108 @@ function templateParameters(template, parameters) {
|
|
|
3314
3212
|
return replacedTemplates;
|
|
3315
3213
|
}
|
|
3316
3214
|
|
|
3215
|
+
/**
|
|
3216
|
+
* Extracts all code blocks from markdown.
|
|
3217
|
+
*
|
|
3218
|
+
* Note: There are multiple similar functions:
|
|
3219
|
+
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
3220
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3221
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3222
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3223
|
+
*
|
|
3224
|
+
* @param markdown any valid markdown
|
|
3225
|
+
* @returns code blocks with language and content
|
|
3226
|
+
* @throws {ParseError} if block is not closed properly
|
|
3227
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
3228
|
+
*/
|
|
3229
|
+
function extractAllBlocksFromMarkdown(markdown) {
|
|
3230
|
+
const codeBlocks = [];
|
|
3231
|
+
const lines = markdown.split('\n');
|
|
3232
|
+
// Note: [0] Ensure that the last block notated by gt > will be closed
|
|
3233
|
+
lines.push('');
|
|
3234
|
+
let currentCodeBlock = null;
|
|
3235
|
+
for (const line of lines) {
|
|
3236
|
+
if (line.startsWith('> ') || line === '>') {
|
|
3237
|
+
if (currentCodeBlock === null) {
|
|
3238
|
+
currentCodeBlock = { blockNotation: '>', language: null, content: '' };
|
|
3239
|
+
} /* not else */
|
|
3240
|
+
if (currentCodeBlock.blockNotation === '>') {
|
|
3241
|
+
if (currentCodeBlock.content !== '') {
|
|
3242
|
+
currentCodeBlock.content += '\n';
|
|
3243
|
+
}
|
|
3244
|
+
currentCodeBlock.content += line.slice(2);
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
|
|
3248
|
+
codeBlocks.push(currentCodeBlock);
|
|
3249
|
+
currentCodeBlock = null;
|
|
3250
|
+
}
|
|
3251
|
+
/* not else */
|
|
3252
|
+
if (line.startsWith('```')) {
|
|
3253
|
+
const language = line.slice(3).trim() || null;
|
|
3254
|
+
if (currentCodeBlock === null) {
|
|
3255
|
+
currentCodeBlock = { blockNotation: '```', language, content: '' };
|
|
3256
|
+
}
|
|
3257
|
+
else {
|
|
3258
|
+
if (language !== null) {
|
|
3259
|
+
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
|
|
3260
|
+
}
|
|
3261
|
+
codeBlocks.push(currentCodeBlock);
|
|
3262
|
+
currentCodeBlock = null;
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
|
|
3266
|
+
if (currentCodeBlock.content !== '') {
|
|
3267
|
+
currentCodeBlock.content += '\n';
|
|
3268
|
+
}
|
|
3269
|
+
currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
if (currentCodeBlock !== null) {
|
|
3273
|
+
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
|
|
3274
|
+
}
|
|
3275
|
+
return codeBlocks;
|
|
3276
|
+
}
|
|
3277
|
+
/**
|
|
3278
|
+
* TODO: Maybe name for `blockNotation` instead of '```' and '>'
|
|
3279
|
+
*/
|
|
3280
|
+
|
|
3281
|
+
/**
|
|
3282
|
+
* Extracts extracts exactly one valid JSON code block
|
|
3283
|
+
*
|
|
3284
|
+
* - When given string is a valid JSON as it is, it just returns it
|
|
3285
|
+
* - When there is no JSON code block the function throws a `ParseError`
|
|
3286
|
+
* - When there are multiple JSON code blocks the function throws a `ParseError`
|
|
3287
|
+
*
|
|
3288
|
+
* Note: It is not important if marked as ```json BUT if it is VALID JSON
|
|
3289
|
+
* Note: There are multiple similar function:
|
|
3290
|
+
* - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
|
|
3291
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3292
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3293
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3294
|
+
*
|
|
3295
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
3296
|
+
* @throws {ParseError} if there is no valid JSON block in the markdown
|
|
3297
|
+
*/
|
|
3298
|
+
function extractJsonBlock(markdown) {
|
|
3299
|
+
if (isValidJsonString(markdown)) {
|
|
3300
|
+
return markdown;
|
|
3301
|
+
}
|
|
3302
|
+
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
3303
|
+
const jsonBlocks = codeBlocks.filter(({ content }) => isValidJsonString(content));
|
|
3304
|
+
if (jsonBlocks.length === 0) {
|
|
3305
|
+
throw new Error('There is no valid JSON block in the markdown');
|
|
3306
|
+
}
|
|
3307
|
+
if (jsonBlocks.length > 1) {
|
|
3308
|
+
throw new Error('There are multiple JSON code blocks in the markdown');
|
|
3309
|
+
}
|
|
3310
|
+
return jsonBlocks[0].content;
|
|
3311
|
+
}
|
|
3312
|
+
/**
|
|
3313
|
+
* TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
|
|
3314
|
+
* TODO: [🏢] Make this logic part of `JsonFormatParser` or `isValidJsonString`
|
|
3315
|
+
*/
|
|
3316
|
+
|
|
3317
3317
|
/**
|
|
3318
3318
|
* Counts number of characters in the text
|
|
3319
3319
|
*
|
|
@@ -3735,6 +3735,68 @@ function checkExpectations(expectations, value) {
|
|
|
3735
3735
|
* Note: [💝] and [🤠] are interconnected together
|
|
3736
3736
|
*/
|
|
3737
3737
|
|
|
3738
|
+
/**
|
|
3739
|
+
* Validates a prompt result against expectations and format requirements.
|
|
3740
|
+
* This function provides a common abstraction for result validation that can be used
|
|
3741
|
+
* by both execution logic and caching logic to ensure consistency.
|
|
3742
|
+
*
|
|
3743
|
+
* @param options - The validation options including result string, expectations, and format
|
|
3744
|
+
* @returns Validation result with processed string and validity status
|
|
3745
|
+
* @private internal function of `createPipelineExecutor` and `cacheLlmTools`
|
|
3746
|
+
*/
|
|
3747
|
+
function validatePromptResult(options) {
|
|
3748
|
+
const { resultString, expectations, format } = options;
|
|
3749
|
+
let processedResultString = resultString;
|
|
3750
|
+
let validationError;
|
|
3751
|
+
try {
|
|
3752
|
+
// TODO: [💝] Unite object for expecting amount and format
|
|
3753
|
+
if (format) {
|
|
3754
|
+
if (format === 'JSON') {
|
|
3755
|
+
if (!isValidJsonString(processedResultString)) {
|
|
3756
|
+
// TODO: [🏢] Do more universally via `FormatParser`
|
|
3757
|
+
try {
|
|
3758
|
+
processedResultString = extractJsonBlock(processedResultString);
|
|
3759
|
+
}
|
|
3760
|
+
catch (error) {
|
|
3761
|
+
keepUnused(error);
|
|
3762
|
+
throw new ExpectError(spaceTrim$1((block) => `
|
|
3763
|
+
Expected valid JSON string
|
|
3764
|
+
|
|
3765
|
+
The expected JSON text:
|
|
3766
|
+
${block(processedResultString)}
|
|
3767
|
+
`));
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
else {
|
|
3772
|
+
throw new UnexpectedError(`Unknown format "${format}"`);
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
// TODO: [💝] Unite object for expecting amount and format
|
|
3776
|
+
if (expectations) {
|
|
3777
|
+
checkExpectations(expectations, processedResultString);
|
|
3778
|
+
}
|
|
3779
|
+
return {
|
|
3780
|
+
isValid: true,
|
|
3781
|
+
processedResultString,
|
|
3782
|
+
};
|
|
3783
|
+
}
|
|
3784
|
+
catch (error) {
|
|
3785
|
+
if (error instanceof ExpectError) {
|
|
3786
|
+
validationError = error;
|
|
3787
|
+
}
|
|
3788
|
+
else {
|
|
3789
|
+
// Re-throw non-ExpectError errors (like UnexpectedError)
|
|
3790
|
+
throw error;
|
|
3791
|
+
}
|
|
3792
|
+
return {
|
|
3793
|
+
isValid: false,
|
|
3794
|
+
processedResultString,
|
|
3795
|
+
error: validationError,
|
|
3796
|
+
};
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3738
3800
|
/**
|
|
3739
3801
|
* Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
|
|
3740
3802
|
* (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
|
|
@@ -3752,17 +3814,18 @@ async function executeAttempts(options) {
|
|
|
3752
3814
|
$resultString: null,
|
|
3753
3815
|
$expectError: null,
|
|
3754
3816
|
$scriptPipelineExecutionErrors: [],
|
|
3817
|
+
$failedResults: [], // Track all failed attempts
|
|
3755
3818
|
};
|
|
3756
3819
|
// TODO: [🚐] Make arrayable LLMs -> single LLM DRY
|
|
3757
3820
|
const _llms = arrayableToArray(tools.llm);
|
|
3758
3821
|
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
3759
|
-
attempts: for (let
|
|
3760
|
-
const isJokerAttempt =
|
|
3761
|
-
const jokerParameterName = jokerParameterNames[jokerParameterNames.length +
|
|
3822
|
+
attempts: for (let attemptIndex = -jokerParameterNames.length; attemptIndex < maxAttempts; attemptIndex++) {
|
|
3823
|
+
const isJokerAttempt = attemptIndex < 0;
|
|
3824
|
+
const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attemptIndex];
|
|
3762
3825
|
// TODO: [🧠][🍭] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
|
|
3763
3826
|
if (isJokerAttempt && !jokerParameterName) {
|
|
3764
3827
|
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
3765
|
-
Joker not found in attempt ${
|
|
3828
|
+
Joker not found in attempt ${attemptIndex}
|
|
3766
3829
|
|
|
3767
3830
|
${block(pipelineIdentification)}
|
|
3768
3831
|
`));
|
|
@@ -3960,35 +4023,18 @@ async function executeAttempts(options) {
|
|
|
3960
4023
|
}
|
|
3961
4024
|
}
|
|
3962
4025
|
// TODO: [💝] Unite object for expecting amount and format
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
throw new ExpectError(spaceTrim$1((block) => `
|
|
3973
|
-
Expected valid JSON string
|
|
3974
|
-
|
|
3975
|
-
${block(
|
|
3976
|
-
/*<- Note: No need for `pipelineIdentification`, it will be catched and added later */ '')}
|
|
3977
|
-
`));
|
|
3978
|
-
}
|
|
3979
|
-
}
|
|
3980
|
-
}
|
|
3981
|
-
else {
|
|
3982
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
3983
|
-
Unknown format "${task.format}"
|
|
3984
|
-
|
|
3985
|
-
${block(pipelineIdentification)}
|
|
3986
|
-
`));
|
|
4026
|
+
// Use the common validation function for both format and expectations
|
|
4027
|
+
if (task.format || task.expectations) {
|
|
4028
|
+
const validationResult = validatePromptResult({
|
|
4029
|
+
resultString: $ongoingTaskResult.$resultString || '',
|
|
4030
|
+
expectations: task.expectations,
|
|
4031
|
+
format: task.format,
|
|
4032
|
+
});
|
|
4033
|
+
if (!validationResult.isValid) {
|
|
4034
|
+
throw validationResult.error;
|
|
3987
4035
|
}
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
if (task.expectations) {
|
|
3991
|
-
checkExpectations(task.expectations, $ongoingTaskResult.$resultString || '');
|
|
4036
|
+
// Update the result string in case format processing modified it (e.g., JSON extraction)
|
|
4037
|
+
$ongoingTaskResult.$resultString = validationResult.processedResultString;
|
|
3992
4038
|
}
|
|
3993
4039
|
break attempts;
|
|
3994
4040
|
}
|
|
@@ -3997,6 +4043,15 @@ async function executeAttempts(options) {
|
|
|
3997
4043
|
throw error;
|
|
3998
4044
|
}
|
|
3999
4045
|
$ongoingTaskResult.$expectError = error;
|
|
4046
|
+
// Store each failed attempt
|
|
4047
|
+
if (!Array.isArray($ongoingTaskResult.$failedResults)) {
|
|
4048
|
+
$ongoingTaskResult.$failedResults = [];
|
|
4049
|
+
}
|
|
4050
|
+
$ongoingTaskResult.$failedResults.push({
|
|
4051
|
+
attemptIndex,
|
|
4052
|
+
result: $ongoingTaskResult.$resultString,
|
|
4053
|
+
error: error,
|
|
4054
|
+
});
|
|
4000
4055
|
}
|
|
4001
4056
|
finally {
|
|
4002
4057
|
if (!isJokerAttempt &&
|
|
@@ -4018,35 +4073,41 @@ async function executeAttempts(options) {
|
|
|
4018
4073
|
});
|
|
4019
4074
|
}
|
|
4020
4075
|
}
|
|
4021
|
-
if ($ongoingTaskResult.$expectError !== null &&
|
|
4076
|
+
if ($ongoingTaskResult.$expectError !== null && attemptIndex === maxAttempts - 1) {
|
|
4077
|
+
// Note: Create a summary of all failures
|
|
4078
|
+
const failuresSummary = $ongoingTaskResult.$failedResults
|
|
4079
|
+
.map((failure) => spaceTrim$1((block) => {
|
|
4080
|
+
var _a, _b;
|
|
4081
|
+
return `
|
|
4082
|
+
Attempt ${failure.attemptIndex + 1}:
|
|
4083
|
+
Error ${((_a = failure.error) === null || _a === void 0 ? void 0 : _a.name) || ''}:
|
|
4084
|
+
${block((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message.split('\n').map((line) => `> ${line}`).join('\n'))}
|
|
4085
|
+
|
|
4086
|
+
Result:
|
|
4087
|
+
${block(failure.result === null
|
|
4088
|
+
? 'null'
|
|
4089
|
+
: spaceTrim$1(failure.result)
|
|
4090
|
+
.split('\n')
|
|
4091
|
+
.map((line) => `> ${line}`)
|
|
4092
|
+
.join('\n'))}
|
|
4093
|
+
`;
|
|
4094
|
+
}))
|
|
4095
|
+
.join('\n\n---\n\n');
|
|
4022
4096
|
throw new PipelineExecutionError(spaceTrim$1((block) => {
|
|
4023
|
-
var _a
|
|
4097
|
+
var _a;
|
|
4024
4098
|
return `
|
|
4025
4099
|
LLM execution failed ${maxExecutionAttempts}x
|
|
4026
4100
|
|
|
4027
4101
|
${block(pipelineIdentification)}
|
|
4028
4102
|
|
|
4029
|
-
---
|
|
4030
4103
|
The Prompt:
|
|
4031
4104
|
${block((((_a = $ongoingTaskResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || '')
|
|
4032
4105
|
.split('\n')
|
|
4033
4106
|
.map((line) => `> ${line}`)
|
|
4034
4107
|
.join('\n'))}
|
|
4035
4108
|
|
|
4036
|
-
|
|
4037
|
-
${block(
|
|
4038
|
-
.split('\n')
|
|
4039
|
-
.map((line) => `> ${line}`)
|
|
4040
|
-
.join('\n'))}
|
|
4041
|
-
|
|
4042
|
-
Last result:
|
|
4043
|
-
${block($ongoingTaskResult.$resultString === null
|
|
4044
|
-
? 'null'
|
|
4045
|
-
: spaceTrim$1($ongoingTaskResult.$resultString)
|
|
4046
|
-
.split('\n')
|
|
4047
|
-
.map((line) => `> ${line}`)
|
|
4048
|
-
.join('\n'))}
|
|
4049
|
-
---
|
|
4109
|
+
All Failed Attempts:
|
|
4110
|
+
${block(failuresSummary)}
|
|
4050
4111
|
`;
|
|
4051
4112
|
}));
|
|
4052
4113
|
}
|
|
@@ -4266,10 +4327,10 @@ function knowledgePiecesToString(knowledgePieces) {
|
|
|
4266
4327
|
*/
|
|
4267
4328
|
async function getKnowledgeForTask(options) {
|
|
4268
4329
|
const { tools, preparedPipeline, task, parameters } = options;
|
|
4269
|
-
const
|
|
4270
|
-
const
|
|
4330
|
+
const firstKnowledgePiece = preparedPipeline.knowledgePieces[0];
|
|
4331
|
+
const firstKnowledgeIndex = firstKnowledgePiece === null || firstKnowledgePiece === void 0 ? void 0 : firstKnowledgePiece.index[0];
|
|
4271
4332
|
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
|
|
4272
|
-
if (
|
|
4333
|
+
if (firstKnowledgePiece === undefined || firstKnowledgeIndex === undefined) {
|
|
4273
4334
|
return ''; // <- Note: Np knowledge present, return empty string
|
|
4274
4335
|
}
|
|
4275
4336
|
try {
|
|
@@ -4280,7 +4341,7 @@ async function getKnowledgeForTask(options) {
|
|
|
4280
4341
|
title: 'Knowledge Search',
|
|
4281
4342
|
modelRequirements: {
|
|
4282
4343
|
modelVariant: 'EMBEDDING',
|
|
4283
|
-
modelName:
|
|
4344
|
+
modelName: firstKnowledgeIndex.modelName,
|
|
4284
4345
|
},
|
|
4285
4346
|
content: task.content,
|
|
4286
4347
|
parameters,
|
|
@@ -4288,7 +4349,7 @@ async function getKnowledgeForTask(options) {
|
|
|
4288
4349
|
const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
|
|
4289
4350
|
const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
|
|
4290
4351
|
const { index } = knowledgePiece;
|
|
4291
|
-
const knowledgePieceIndex = index.find((i) => i.modelName ===
|
|
4352
|
+
const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowledgeIndex.modelName);
|
|
4292
4353
|
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model
|
|
4293
4354
|
if (knowledgePieceIndex === undefined) {
|
|
4294
4355
|
return {
|
|
@@ -4309,8 +4370,8 @@ async function getKnowledgeForTask(options) {
|
|
|
4309
4370
|
task,
|
|
4310
4371
|
taskEmbeddingPrompt,
|
|
4311
4372
|
taskEmbeddingResult,
|
|
4312
|
-
|
|
4313
|
-
|
|
4373
|
+
firstKnowledgePiece,
|
|
4374
|
+
firstKnowledgeIndex,
|
|
4314
4375
|
knowledgePiecesWithRelevance,
|
|
4315
4376
|
knowledgePiecesSorted,
|
|
4316
4377
|
knowledgePiecesLimited,
|
|
@@ -4379,7 +4440,7 @@ async function getReservedParametersForTask(options) {
|
|
|
4379
4440
|
* @private internal utility of `createPipelineExecutor`
|
|
4380
4441
|
*/
|
|
4381
4442
|
async function executeTask(options) {
|
|
4382
|
-
const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled,
|
|
4443
|
+
const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled, isNotPreparedWarningSuppressed, } = options;
|
|
4383
4444
|
const priority = preparedPipeline.tasks.length - preparedPipeline.tasks.indexOf(currentTask);
|
|
4384
4445
|
// Note: Check consistency of used and dependent parameters which was also done in `validatePipeline`, but it’s good to doublecheck
|
|
4385
4446
|
const usedParameterNames = extractParameterNamesFromTask(currentTask);
|
|
@@ -4467,7 +4528,7 @@ async function executeTask(options) {
|
|
|
4467
4528
|
cacheDirname,
|
|
4468
4529
|
intermediateFilesStrategy,
|
|
4469
4530
|
isAutoInstalled,
|
|
4470
|
-
|
|
4531
|
+
isNotPreparedWarningSuppressed,
|
|
4471
4532
|
});
|
|
4472
4533
|
await onProgress({
|
|
4473
4534
|
outputParameters: {
|
|
@@ -4562,7 +4623,7 @@ async function executePipeline(options) {
|
|
|
4562
4623
|
}
|
|
4563
4624
|
return exportJson({
|
|
4564
4625
|
name: `executionReport`,
|
|
4565
|
-
message: `
|
|
4626
|
+
message: `Unsuccessful PipelineExecutorResult (with missing parameter {${parameter.name}}) PipelineExecutorResult`,
|
|
4566
4627
|
order: [],
|
|
4567
4628
|
value: {
|
|
4568
4629
|
isSuccessful: false,
|
|
@@ -4599,7 +4660,7 @@ async function executePipeline(options) {
|
|
|
4599
4660
|
return exportJson({
|
|
4600
4661
|
name: 'pipelineExecutorResult',
|
|
4601
4662
|
message: spaceTrim$1((block) => `
|
|
4602
|
-
|
|
4663
|
+
Unsuccessful PipelineExecutorResult (with extra parameter {${parameter.name}}) PipelineExecutorResult
|
|
4603
4664
|
|
|
4604
4665
|
${block(pipelineIdentification)}
|
|
4605
4666
|
`),
|
|
@@ -4740,7 +4801,7 @@ async function executePipeline(options) {
|
|
|
4740
4801
|
}
|
|
4741
4802
|
return exportJson({
|
|
4742
4803
|
name: 'pipelineExecutorResult',
|
|
4743
|
-
message: `
|
|
4804
|
+
message: `Unsuccessful PipelineExecutorResult (with misc errors) PipelineExecutorResult`,
|
|
4744
4805
|
order: [],
|
|
4745
4806
|
value: {
|
|
4746
4807
|
isSuccessful: false,
|
|
@@ -4791,7 +4852,7 @@ async function executePipeline(options) {
|
|
|
4791
4852
|
* @public exported from `@promptbook/core`
|
|
4792
4853
|
*/
|
|
4793
4854
|
function createPipelineExecutor(options) {
|
|
4794
|
-
const { pipeline, tools, maxExecutionAttempts = DEFAULT_MAX_EXECUTION_ATTEMPTS, maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT, csvSettings = DEFAULT_CSV_SETTINGS, isVerbose = DEFAULT_IS_VERBOSE,
|
|
4855
|
+
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;
|
|
4795
4856
|
validatePipeline(pipeline);
|
|
4796
4857
|
const pipelineIdentification = (() => {
|
|
4797
4858
|
// Note: This is a 😐 implementation of [🚞]
|
|
@@ -4808,7 +4869,7 @@ function createPipelineExecutor(options) {
|
|
|
4808
4869
|
if (isPipelinePrepared(pipeline)) {
|
|
4809
4870
|
preparedPipeline = pipeline;
|
|
4810
4871
|
}
|
|
4811
|
-
else if (
|
|
4872
|
+
else if (isNotPreparedWarningSuppressed !== true) {
|
|
4812
4873
|
console.warn(spaceTrim$1((block) => `
|
|
4813
4874
|
Pipeline is not prepared
|
|
4814
4875
|
|
|
@@ -4841,7 +4902,7 @@ function createPipelineExecutor(options) {
|
|
|
4841
4902
|
maxParallelCount,
|
|
4842
4903
|
csvSettings,
|
|
4843
4904
|
isVerbose,
|
|
4844
|
-
|
|
4905
|
+
isNotPreparedWarningSuppressed,
|
|
4845
4906
|
rootDirname,
|
|
4846
4907
|
cacheDirname,
|
|
4847
4908
|
intermediateFilesStrategy,
|
|
@@ -4850,7 +4911,7 @@ function createPipelineExecutor(options) {
|
|
|
4850
4911
|
assertsError(error);
|
|
4851
4912
|
return exportJson({
|
|
4852
4913
|
name: 'pipelineExecutorResult',
|
|
4853
|
-
message: `
|
|
4914
|
+
message: `Unsuccessful PipelineExecutorResult, last catch`,
|
|
4854
4915
|
order: [],
|
|
4855
4916
|
value: {
|
|
4856
4917
|
isSuccessful: false,
|
|
@@ -4920,12 +4981,12 @@ function countUsage(llmTools) {
|
|
|
4920
4981
|
get title() {
|
|
4921
4982
|
return `${llmTools.title} (+usage)`;
|
|
4922
4983
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
4923
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
4984
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
|
|
4924
4985
|
},
|
|
4925
4986
|
get description() {
|
|
4926
4987
|
return `${llmTools.description} (+usage)`;
|
|
4927
4988
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
4928
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
4989
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
|
|
4929
4990
|
},
|
|
4930
4991
|
checkConfiguration() {
|
|
4931
4992
|
return /* not await */ llmTools.checkConfiguration();
|
|
@@ -5212,17 +5273,17 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
5212
5273
|
* Mixes registered scrapers from $scrapersMetadataRegister and $scrapersRegister
|
|
5213
5274
|
*/
|
|
5214
5275
|
const all = [];
|
|
5215
|
-
for (const { packageName, className, mimeTypes, documentationUrl,
|
|
5276
|
+
for (const { packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser, } of $scrapersMetadataRegister.list()) {
|
|
5216
5277
|
if (all.some((item) => item.packageName === packageName && item.className === className)) {
|
|
5217
5278
|
continue;
|
|
5218
5279
|
}
|
|
5219
|
-
all.push({ packageName, className, mimeTypes, documentationUrl,
|
|
5280
|
+
all.push({ packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser });
|
|
5220
5281
|
}
|
|
5221
|
-
for (const { packageName, className, mimeTypes, documentationUrl,
|
|
5282
|
+
for (const { packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser, } of $scrapersRegister.list()) {
|
|
5222
5283
|
if (all.some((item) => item.packageName === packageName && item.className === className)) {
|
|
5223
5284
|
continue;
|
|
5224
5285
|
}
|
|
5225
|
-
all.push({ packageName, className, mimeTypes, documentationUrl,
|
|
5286
|
+
all.push({ packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser });
|
|
5226
5287
|
}
|
|
5227
5288
|
for (const { metadata } of availableScrapers) {
|
|
5228
5289
|
all.push(metadata);
|
|
@@ -5234,8 +5295,8 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
5234
5295
|
const isInstalled = $scrapersRegister
|
|
5235
5296
|
.list()
|
|
5236
5297
|
.find(({ packageName, className }) => metadata.packageName === packageName && metadata.className === className);
|
|
5237
|
-
const
|
|
5238
|
-
return { ...metadata, isMetadataAviailable, isInstalled,
|
|
5298
|
+
const isAvailableInTools = availableScrapers.some(({ metadata: { packageName, className } }) => metadata.packageName === packageName && metadata.className === className);
|
|
5299
|
+
return { ...metadata, isMetadataAviailable, isInstalled, isAvailableInTools };
|
|
5239
5300
|
});
|
|
5240
5301
|
if (metadata.length === 0) {
|
|
5241
5302
|
return spaceTrim(`
|
|
@@ -5248,7 +5309,7 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
5248
5309
|
return spaceTrim((block) => `
|
|
5249
5310
|
Available scrapers are:
|
|
5250
5311
|
${block(metadata
|
|
5251
|
-
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes,
|
|
5312
|
+
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvailableInBrowser, isAvailableInTools, }, i) => {
|
|
5252
5313
|
const more = [];
|
|
5253
5314
|
// TODO: [🧠] Maybe use `documentationUrl`
|
|
5254
5315
|
if (isMetadataAviailable) {
|
|
@@ -5257,16 +5318,16 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
5257
5318
|
if (isInstalled) {
|
|
5258
5319
|
more.push(`🟩 Installed`);
|
|
5259
5320
|
} // not else
|
|
5260
|
-
if (
|
|
5321
|
+
if (isAvailableInTools) {
|
|
5261
5322
|
more.push(`🟦 Available in tools`);
|
|
5262
5323
|
} // not else
|
|
5263
5324
|
if (!isMetadataAviailable && isInstalled) {
|
|
5264
5325
|
more.push(`When no metadata registered but scraper is installed, it is an unexpected behavior`);
|
|
5265
5326
|
} // not else
|
|
5266
|
-
if (!isInstalled &&
|
|
5327
|
+
if (!isInstalled && isAvailableInTools) {
|
|
5267
5328
|
more.push(`When the scraper is not installed but available in tools, it is an unexpected compatibility behavior`);
|
|
5268
5329
|
} // not else
|
|
5269
|
-
if (!
|
|
5330
|
+
if (!isAvailableInBrowser) {
|
|
5270
5331
|
more.push(`Not usable in browser`);
|
|
5271
5332
|
}
|
|
5272
5333
|
const moreText = more.length === 0 ? '' : ` *(${more.join('; ')})*`;
|
|
@@ -5732,7 +5793,7 @@ TODO: [🧊] This is how it can look in future
|
|
|
5732
5793
|
/**
|
|
5733
5794
|
* TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
|
|
5734
5795
|
* Put `knowledgePieces` into `PrepareKnowledgeOptions`
|
|
5735
|
-
* TODO: [🪂] More than max things can run in parallel by
|
|
5796
|
+
* TODO: [🪂] More than max things can run in parallel by accident [1,[2a,2b,_],[3a,3b,_]]
|
|
5736
5797
|
* TODO: [🧠][❎] Do here proper M:N mapping
|
|
5737
5798
|
* [x] One source can make multiple pieces
|
|
5738
5799
|
* [ ] One piece can have multiple sources
|
|
@@ -6620,7 +6681,7 @@ const expectCommandParser = {
|
|
|
6620
6681
|
$taskJson.expectations[unit] = $taskJson.expectations[unit] || {};
|
|
6621
6682
|
if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
|
|
6622
6683
|
if ($taskJson.expectations[unit].min !== undefined) {
|
|
6623
|
-
throw new ParseError(`Already defined
|
|
6684
|
+
throw new ParseError(`Already defined minimum ${$taskJson.expectations[unit].min} ${command.unit.toLowerCase()}, now trying to redefine it to ${command.amount}`);
|
|
6624
6685
|
}
|
|
6625
6686
|
$taskJson.expectations[unit].min = command.amount;
|
|
6626
6687
|
} /* not else */
|
|
@@ -10117,6 +10178,46 @@ async function $provideLlmToolsConfigurationFromEnv() {
|
|
|
10117
10178
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
10118
10179
|
*/
|
|
10119
10180
|
|
|
10181
|
+
/**
|
|
10182
|
+
* Detects if the code is running in a browser environment in main thread (Not in a web worker)
|
|
10183
|
+
*
|
|
10184
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10185
|
+
*
|
|
10186
|
+
* @public exported from `@promptbook/utils`
|
|
10187
|
+
*/
|
|
10188
|
+
const $isRunningInBrowser = new Function(`
|
|
10189
|
+
try {
|
|
10190
|
+
return this === window;
|
|
10191
|
+
} catch (e) {
|
|
10192
|
+
return false;
|
|
10193
|
+
}
|
|
10194
|
+
`);
|
|
10195
|
+
/**
|
|
10196
|
+
* TODO: [🎺]
|
|
10197
|
+
*/
|
|
10198
|
+
|
|
10199
|
+
/**
|
|
10200
|
+
* Detects if the code is running in a web worker
|
|
10201
|
+
*
|
|
10202
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10203
|
+
*
|
|
10204
|
+
* @public exported from `@promptbook/utils`
|
|
10205
|
+
*/
|
|
10206
|
+
const $isRunningInWebWorker = new Function(`
|
|
10207
|
+
try {
|
|
10208
|
+
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
|
|
10209
|
+
return true;
|
|
10210
|
+
} else {
|
|
10211
|
+
return false;
|
|
10212
|
+
}
|
|
10213
|
+
} catch (e) {
|
|
10214
|
+
return false;
|
|
10215
|
+
}
|
|
10216
|
+
`);
|
|
10217
|
+
/**
|
|
10218
|
+
* TODO: [🎺]
|
|
10219
|
+
*/
|
|
10220
|
+
|
|
10120
10221
|
/**
|
|
10121
10222
|
* Creates LLM execution tools from provided configuration objects
|
|
10122
10223
|
*
|
|
@@ -10137,8 +10238,10 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
10137
10238
|
.list()
|
|
10138
10239
|
.find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
|
|
10139
10240
|
if (registeredItem === undefined) {
|
|
10241
|
+
console.log('!!! $llmToolsRegister.list()', $llmToolsRegister.list());
|
|
10140
10242
|
throw new Error(spaceTrim((block) => `
|
|
10141
10243
|
There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
|
|
10244
|
+
Running in ${!$isRunningInBrowser() ? '' : 'browser environment'}${!$isRunningInNode() ? '' : 'node environment'}${!$isRunningInWebWorker() ? '' : 'worker environment'}
|
|
10142
10245
|
|
|
10143
10246
|
You have probably forgotten install and import the provider package.
|
|
10144
10247
|
To fix this issue, you can:
|
|
@@ -10265,24 +10368,6 @@ async function $provideScrapersForNode(tools, options) {
|
|
|
10265
10368
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
10266
10369
|
*/
|
|
10267
10370
|
|
|
10268
|
-
/**
|
|
10269
|
-
* Detects if the code is running in a browser environment in main thread (Not in a web worker)
|
|
10270
|
-
*
|
|
10271
|
-
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10272
|
-
*
|
|
10273
|
-
* @public exported from `@promptbook/utils`
|
|
10274
|
-
*/
|
|
10275
|
-
new Function(`
|
|
10276
|
-
try {
|
|
10277
|
-
return this === window;
|
|
10278
|
-
} catch (e) {
|
|
10279
|
-
return false;
|
|
10280
|
-
}
|
|
10281
|
-
`);
|
|
10282
|
-
/**
|
|
10283
|
-
* TODO: [🎺]
|
|
10284
|
-
*/
|
|
10285
|
-
|
|
10286
10371
|
/**
|
|
10287
10372
|
* Detects if the code is running in jest environment
|
|
10288
10373
|
*
|
|
@@ -10301,28 +10386,6 @@ new Function(`
|
|
|
10301
10386
|
* TODO: [🎺]
|
|
10302
10387
|
*/
|
|
10303
10388
|
|
|
10304
|
-
/**
|
|
10305
|
-
* Detects if the code is running in a web worker
|
|
10306
|
-
*
|
|
10307
|
-
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10308
|
-
*
|
|
10309
|
-
* @public exported from `@promptbook/utils`
|
|
10310
|
-
*/
|
|
10311
|
-
new Function(`
|
|
10312
|
-
try {
|
|
10313
|
-
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
|
|
10314
|
-
return true;
|
|
10315
|
-
} else {
|
|
10316
|
-
return false;
|
|
10317
|
-
}
|
|
10318
|
-
} catch (e) {
|
|
10319
|
-
return false;
|
|
10320
|
-
}
|
|
10321
|
-
`);
|
|
10322
|
-
/**
|
|
10323
|
-
* TODO: [🎺]
|
|
10324
|
-
*/
|
|
10325
|
-
|
|
10326
10389
|
/**
|
|
10327
10390
|
* Makes first letter of a string uppercase
|
|
10328
10391
|
*
|
|
@@ -10873,7 +10936,7 @@ async function listAllFiles(path, isRecursive, fs) {
|
|
|
10873
10936
|
return fileNames;
|
|
10874
10937
|
}
|
|
10875
10938
|
/**
|
|
10876
|
-
* TODO: [😶] Unite
|
|
10939
|
+
* TODO: [😶] Unite folder listing
|
|
10877
10940
|
* Note: Not [~🟢~] because it is not directly dependent on `fs
|
|
10878
10941
|
* TODO: [🖇] What about symlinks?
|
|
10879
10942
|
*/
|
|
@@ -11020,7 +11083,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
11020
11083
|
if (isCrashedOnError) {
|
|
11021
11084
|
throw new CollectionError(wrappedErrorMessage);
|
|
11022
11085
|
}
|
|
11023
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
11086
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
11024
11087
|
console.error(wrappedErrorMessage);
|
|
11025
11088
|
}
|
|
11026
11089
|
}
|
|
@@ -11087,7 +11150,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
11087
11150
|
|
|
11088
11151
|
Note: You have probably forgotten to run "ptbk make" to update the collection
|
|
11089
11152
|
Note: Pipelines with the same URL are not allowed
|
|
11090
|
-
Only
|
|
11153
|
+
Only exception is when the pipelines are identical
|
|
11091
11154
|
|
|
11092
11155
|
`));
|
|
11093
11156
|
}
|
|
@@ -11111,7 +11174,7 @@ async function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
11111
11174
|
if (isCrashedOnError) {
|
|
11112
11175
|
throw new CollectionError(wrappedErrorMessage);
|
|
11113
11176
|
}
|
|
11114
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
11177
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
11115
11178
|
console.error(wrappedErrorMessage);
|
|
11116
11179
|
}
|
|
11117
11180
|
}
|