@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/umd/index.umd.js
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
* @generated
|
|
47
47
|
* @see https://github.com/webgptorg/promptbook
|
|
48
48
|
*/
|
|
49
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
49
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.98.0-10';
|
|
50
50
|
/**
|
|
51
51
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
52
52
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
*
|
|
191
191
|
* @public exported from `@promptbook/core`
|
|
192
192
|
*/
|
|
193
|
-
const DEFAULT_MAX_EXECUTION_ATTEMPTS =
|
|
193
|
+
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 7; // <- TODO: [🤹♂️]
|
|
194
194
|
// <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
|
|
195
195
|
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
196
196
|
/**
|
|
@@ -212,11 +212,11 @@
|
|
|
212
212
|
/*
|
|
213
213
|
TODO: [🌃]
|
|
214
214
|
/**
|
|
215
|
-
* Id of application for the
|
|
215
|
+
* Id of application for the wizard when using remote server
|
|
216
216
|
*
|
|
217
217
|
* @public exported from `@promptbook/core`
|
|
218
218
|
* /
|
|
219
|
-
ex-port const
|
|
219
|
+
ex-port const WIZARD_APP_ID: string_app_id = 'wizard';
|
|
220
220
|
*/
|
|
221
221
|
/**
|
|
222
222
|
* The name of the builded pipeline collection made by CLI `ptbk make` and for lookup in `createCollectionFromDirectory`
|
|
@@ -360,7 +360,7 @@
|
|
|
360
360
|
throw new Error(spaceTrim__default["default"]((block) => `
|
|
361
361
|
${block(error.message)}
|
|
362
362
|
|
|
363
|
-
The JSON text:
|
|
363
|
+
The expected JSON text:
|
|
364
364
|
${block(value)}
|
|
365
365
|
`));
|
|
366
366
|
}
|
|
@@ -538,7 +538,7 @@
|
|
|
538
538
|
else {
|
|
539
539
|
for (const [subName, subValue] of Object.entries(value)) {
|
|
540
540
|
if (subValue === undefined) {
|
|
541
|
-
// Note: undefined in object is serializable - it is just
|
|
541
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
542
542
|
continue;
|
|
543
543
|
}
|
|
544
544
|
checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
|
|
@@ -1147,7 +1147,7 @@
|
|
|
1147
1147
|
* @param fs Filesystem tools
|
|
1148
1148
|
* @returns Pipelines loaded from the archive
|
|
1149
1149
|
*
|
|
1150
|
-
* @private utility of
|
|
1150
|
+
* @private utility of Promptbook
|
|
1151
1151
|
*/
|
|
1152
1152
|
async function loadArchive(filePath, fs) {
|
|
1153
1153
|
if (!filePath.endsWith('.bookc')) {
|
|
@@ -1169,7 +1169,7 @@
|
|
|
1169
1169
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
1170
1170
|
*/
|
|
1171
1171
|
|
|
1172
|
-
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"}];
|
|
1172
|
+
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"}];
|
|
1173
1173
|
|
|
1174
1174
|
/**
|
|
1175
1175
|
* Checks if value is valid email
|
|
@@ -1311,7 +1311,7 @@
|
|
|
1311
1311
|
});
|
|
1312
1312
|
}
|
|
1313
1313
|
catch (error) {
|
|
1314
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
1314
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
1315
1315
|
console.error('There was an error with prettifying the markdown, using the original as the fallback', {
|
|
1316
1316
|
error,
|
|
1317
1317
|
html: content,
|
|
@@ -1602,7 +1602,7 @@
|
|
|
1602
1602
|
|
|
1603
1603
|
Note: You have probably forgotten to run "ptbk make" to update the collection
|
|
1604
1604
|
Note: Pipelines with the same URL are not allowed
|
|
1605
|
-
Only
|
|
1605
|
+
Only exception is when the pipelines are identical
|
|
1606
1606
|
|
|
1607
1607
|
`));
|
|
1608
1608
|
}
|
|
@@ -3091,13 +3091,13 @@
|
|
|
3091
3091
|
|
|
3092
3092
|
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.
|
|
3093
3093
|
`);
|
|
3094
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
3094
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
3095
3095
|
console.warn(warningMessage);
|
|
3096
3096
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3097
3097
|
/*
|
|
3098
3098
|
return {
|
|
3099
3099
|
async listModels() {
|
|
3100
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
3100
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
3101
3101
|
console.warn(
|
|
3102
3102
|
spaceTrim(
|
|
3103
3103
|
(block) => `
|
|
@@ -3121,108 +3121,6 @@
|
|
|
3121
3121
|
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
3122
3122
|
*/
|
|
3123
3123
|
|
|
3124
|
-
/**
|
|
3125
|
-
* Extracts all code blocks from markdown.
|
|
3126
|
-
*
|
|
3127
|
-
* Note: There are multiple similar functions:
|
|
3128
|
-
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
3129
|
-
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3130
|
-
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3131
|
-
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3132
|
-
*
|
|
3133
|
-
* @param markdown any valid markdown
|
|
3134
|
-
* @returns code blocks with language and content
|
|
3135
|
-
* @throws {ParseError} if block is not closed properly
|
|
3136
|
-
* @public exported from `@promptbook/markdown-utils`
|
|
3137
|
-
*/
|
|
3138
|
-
function extractAllBlocksFromMarkdown(markdown) {
|
|
3139
|
-
const codeBlocks = [];
|
|
3140
|
-
const lines = markdown.split('\n');
|
|
3141
|
-
// Note: [0] Ensure that the last block notated by gt > will be closed
|
|
3142
|
-
lines.push('');
|
|
3143
|
-
let currentCodeBlock = null;
|
|
3144
|
-
for (const line of lines) {
|
|
3145
|
-
if (line.startsWith('> ') || line === '>') {
|
|
3146
|
-
if (currentCodeBlock === null) {
|
|
3147
|
-
currentCodeBlock = { blockNotation: '>', language: null, content: '' };
|
|
3148
|
-
} /* not else */
|
|
3149
|
-
if (currentCodeBlock.blockNotation === '>') {
|
|
3150
|
-
if (currentCodeBlock.content !== '') {
|
|
3151
|
-
currentCodeBlock.content += '\n';
|
|
3152
|
-
}
|
|
3153
|
-
currentCodeBlock.content += line.slice(2);
|
|
3154
|
-
}
|
|
3155
|
-
}
|
|
3156
|
-
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
|
|
3157
|
-
codeBlocks.push(currentCodeBlock);
|
|
3158
|
-
currentCodeBlock = null;
|
|
3159
|
-
}
|
|
3160
|
-
/* not else */
|
|
3161
|
-
if (line.startsWith('```')) {
|
|
3162
|
-
const language = line.slice(3).trim() || null;
|
|
3163
|
-
if (currentCodeBlock === null) {
|
|
3164
|
-
currentCodeBlock = { blockNotation: '```', language, content: '' };
|
|
3165
|
-
}
|
|
3166
|
-
else {
|
|
3167
|
-
if (language !== null) {
|
|
3168
|
-
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
|
|
3169
|
-
}
|
|
3170
|
-
codeBlocks.push(currentCodeBlock);
|
|
3171
|
-
currentCodeBlock = null;
|
|
3172
|
-
}
|
|
3173
|
-
}
|
|
3174
|
-
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
|
|
3175
|
-
if (currentCodeBlock.content !== '') {
|
|
3176
|
-
currentCodeBlock.content += '\n';
|
|
3177
|
-
}
|
|
3178
|
-
currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
|
|
3179
|
-
}
|
|
3180
|
-
}
|
|
3181
|
-
if (currentCodeBlock !== null) {
|
|
3182
|
-
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
|
|
3183
|
-
}
|
|
3184
|
-
return codeBlocks;
|
|
3185
|
-
}
|
|
3186
|
-
/**
|
|
3187
|
-
* TODO: Maybe name for `blockNotation` instead of '```' and '>'
|
|
3188
|
-
*/
|
|
3189
|
-
|
|
3190
|
-
/**
|
|
3191
|
-
* Extracts extracts exactly one valid JSON code block
|
|
3192
|
-
*
|
|
3193
|
-
* - When given string is a valid JSON as it is, it just returns it
|
|
3194
|
-
* - When there is no JSON code block the function throws a `ParseError`
|
|
3195
|
-
* - When there are multiple JSON code blocks the function throws a `ParseError`
|
|
3196
|
-
*
|
|
3197
|
-
* Note: It is not important if marked as ```json BUT if it is VALID JSON
|
|
3198
|
-
* Note: There are multiple similar function:
|
|
3199
|
-
* - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
|
|
3200
|
-
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3201
|
-
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3202
|
-
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3203
|
-
*
|
|
3204
|
-
* @public exported from `@promptbook/markdown-utils`
|
|
3205
|
-
* @throws {ParseError} if there is no valid JSON block in the markdown
|
|
3206
|
-
*/
|
|
3207
|
-
function extractJsonBlock(markdown) {
|
|
3208
|
-
if (isValidJsonString(markdown)) {
|
|
3209
|
-
return markdown;
|
|
3210
|
-
}
|
|
3211
|
-
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
3212
|
-
const jsonBlocks = codeBlocks.filter(({ content }) => isValidJsonString(content));
|
|
3213
|
-
if (jsonBlocks.length === 0) {
|
|
3214
|
-
throw new Error('There is no valid JSON block in the markdown');
|
|
3215
|
-
}
|
|
3216
|
-
if (jsonBlocks.length > 1) {
|
|
3217
|
-
throw new Error('There are multiple JSON code blocks in the markdown');
|
|
3218
|
-
}
|
|
3219
|
-
return jsonBlocks[0].content;
|
|
3220
|
-
}
|
|
3221
|
-
/**
|
|
3222
|
-
* TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
|
|
3223
|
-
* TODO: [🏢] Make this logic part of `JsonFormatParser` or `isValidJsonString`
|
|
3224
|
-
*/
|
|
3225
|
-
|
|
3226
3124
|
/**
|
|
3227
3125
|
* Takes an item or an array of items and returns an array of items
|
|
3228
3126
|
*
|
|
@@ -3330,6 +3228,108 @@
|
|
|
3330
3228
|
return replacedTemplates;
|
|
3331
3229
|
}
|
|
3332
3230
|
|
|
3231
|
+
/**
|
|
3232
|
+
* Extracts all code blocks from markdown.
|
|
3233
|
+
*
|
|
3234
|
+
* Note: There are multiple similar functions:
|
|
3235
|
+
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
3236
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3237
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3238
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3239
|
+
*
|
|
3240
|
+
* @param markdown any valid markdown
|
|
3241
|
+
* @returns code blocks with language and content
|
|
3242
|
+
* @throws {ParseError} if block is not closed properly
|
|
3243
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
3244
|
+
*/
|
|
3245
|
+
function extractAllBlocksFromMarkdown(markdown) {
|
|
3246
|
+
const codeBlocks = [];
|
|
3247
|
+
const lines = markdown.split('\n');
|
|
3248
|
+
// Note: [0] Ensure that the last block notated by gt > will be closed
|
|
3249
|
+
lines.push('');
|
|
3250
|
+
let currentCodeBlock = null;
|
|
3251
|
+
for (const line of lines) {
|
|
3252
|
+
if (line.startsWith('> ') || line === '>') {
|
|
3253
|
+
if (currentCodeBlock === null) {
|
|
3254
|
+
currentCodeBlock = { blockNotation: '>', language: null, content: '' };
|
|
3255
|
+
} /* not else */
|
|
3256
|
+
if (currentCodeBlock.blockNotation === '>') {
|
|
3257
|
+
if (currentCodeBlock.content !== '') {
|
|
3258
|
+
currentCodeBlock.content += '\n';
|
|
3259
|
+
}
|
|
3260
|
+
currentCodeBlock.content += line.slice(2);
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
|
|
3264
|
+
codeBlocks.push(currentCodeBlock);
|
|
3265
|
+
currentCodeBlock = null;
|
|
3266
|
+
}
|
|
3267
|
+
/* not else */
|
|
3268
|
+
if (line.startsWith('```')) {
|
|
3269
|
+
const language = line.slice(3).trim() || null;
|
|
3270
|
+
if (currentCodeBlock === null) {
|
|
3271
|
+
currentCodeBlock = { blockNotation: '```', language, content: '' };
|
|
3272
|
+
}
|
|
3273
|
+
else {
|
|
3274
|
+
if (language !== null) {
|
|
3275
|
+
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
|
|
3276
|
+
}
|
|
3277
|
+
codeBlocks.push(currentCodeBlock);
|
|
3278
|
+
currentCodeBlock = null;
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
|
|
3282
|
+
if (currentCodeBlock.content !== '') {
|
|
3283
|
+
currentCodeBlock.content += '\n';
|
|
3284
|
+
}
|
|
3285
|
+
currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
if (currentCodeBlock !== null) {
|
|
3289
|
+
throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
|
|
3290
|
+
}
|
|
3291
|
+
return codeBlocks;
|
|
3292
|
+
}
|
|
3293
|
+
/**
|
|
3294
|
+
* TODO: Maybe name for `blockNotation` instead of '```' and '>'
|
|
3295
|
+
*/
|
|
3296
|
+
|
|
3297
|
+
/**
|
|
3298
|
+
* Extracts extracts exactly one valid JSON code block
|
|
3299
|
+
*
|
|
3300
|
+
* - When given string is a valid JSON as it is, it just returns it
|
|
3301
|
+
* - When there is no JSON code block the function throws a `ParseError`
|
|
3302
|
+
* - When there are multiple JSON code blocks the function throws a `ParseError`
|
|
3303
|
+
*
|
|
3304
|
+
* Note: It is not important if marked as ```json BUT if it is VALID JSON
|
|
3305
|
+
* Note: There are multiple similar function:
|
|
3306
|
+
* - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
|
|
3307
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
3308
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
3309
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
3310
|
+
*
|
|
3311
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
3312
|
+
* @throws {ParseError} if there is no valid JSON block in the markdown
|
|
3313
|
+
*/
|
|
3314
|
+
function extractJsonBlock(markdown) {
|
|
3315
|
+
if (isValidJsonString(markdown)) {
|
|
3316
|
+
return markdown;
|
|
3317
|
+
}
|
|
3318
|
+
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
3319
|
+
const jsonBlocks = codeBlocks.filter(({ content }) => isValidJsonString(content));
|
|
3320
|
+
if (jsonBlocks.length === 0) {
|
|
3321
|
+
throw new Error('There is no valid JSON block in the markdown');
|
|
3322
|
+
}
|
|
3323
|
+
if (jsonBlocks.length > 1) {
|
|
3324
|
+
throw new Error('There are multiple JSON code blocks in the markdown');
|
|
3325
|
+
}
|
|
3326
|
+
return jsonBlocks[0].content;
|
|
3327
|
+
}
|
|
3328
|
+
/**
|
|
3329
|
+
* TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
|
|
3330
|
+
* TODO: [🏢] Make this logic part of `JsonFormatParser` or `isValidJsonString`
|
|
3331
|
+
*/
|
|
3332
|
+
|
|
3333
3333
|
/**
|
|
3334
3334
|
* Counts number of characters in the text
|
|
3335
3335
|
*
|
|
@@ -3751,6 +3751,68 @@
|
|
|
3751
3751
|
* Note: [💝] and [🤠] are interconnected together
|
|
3752
3752
|
*/
|
|
3753
3753
|
|
|
3754
|
+
/**
|
|
3755
|
+
* Validates a prompt result against expectations and format requirements.
|
|
3756
|
+
* This function provides a common abstraction for result validation that can be used
|
|
3757
|
+
* by both execution logic and caching logic to ensure consistency.
|
|
3758
|
+
*
|
|
3759
|
+
* @param options - The validation options including result string, expectations, and format
|
|
3760
|
+
* @returns Validation result with processed string and validity status
|
|
3761
|
+
* @private internal function of `createPipelineExecutor` and `cacheLlmTools`
|
|
3762
|
+
*/
|
|
3763
|
+
function validatePromptResult(options) {
|
|
3764
|
+
const { resultString, expectations, format } = options;
|
|
3765
|
+
let processedResultString = resultString;
|
|
3766
|
+
let validationError;
|
|
3767
|
+
try {
|
|
3768
|
+
// TODO: [💝] Unite object for expecting amount and format
|
|
3769
|
+
if (format) {
|
|
3770
|
+
if (format === 'JSON') {
|
|
3771
|
+
if (!isValidJsonString(processedResultString)) {
|
|
3772
|
+
// TODO: [🏢] Do more universally via `FormatParser`
|
|
3773
|
+
try {
|
|
3774
|
+
processedResultString = extractJsonBlock(processedResultString);
|
|
3775
|
+
}
|
|
3776
|
+
catch (error) {
|
|
3777
|
+
keepUnused(error);
|
|
3778
|
+
throw new ExpectError(spaceTrim.spaceTrim((block) => `
|
|
3779
|
+
Expected valid JSON string
|
|
3780
|
+
|
|
3781
|
+
The expected JSON text:
|
|
3782
|
+
${block(processedResultString)}
|
|
3783
|
+
`));
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
else {
|
|
3788
|
+
throw new UnexpectedError(`Unknown format "${format}"`);
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
// TODO: [💝] Unite object for expecting amount and format
|
|
3792
|
+
if (expectations) {
|
|
3793
|
+
checkExpectations(expectations, processedResultString);
|
|
3794
|
+
}
|
|
3795
|
+
return {
|
|
3796
|
+
isValid: true,
|
|
3797
|
+
processedResultString,
|
|
3798
|
+
};
|
|
3799
|
+
}
|
|
3800
|
+
catch (error) {
|
|
3801
|
+
if (error instanceof ExpectError) {
|
|
3802
|
+
validationError = error;
|
|
3803
|
+
}
|
|
3804
|
+
else {
|
|
3805
|
+
// Re-throw non-ExpectError errors (like UnexpectedError)
|
|
3806
|
+
throw error;
|
|
3807
|
+
}
|
|
3808
|
+
return {
|
|
3809
|
+
isValid: false,
|
|
3810
|
+
processedResultString,
|
|
3811
|
+
error: validationError,
|
|
3812
|
+
};
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
|
|
3754
3816
|
/**
|
|
3755
3817
|
* Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
|
|
3756
3818
|
* (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
|
|
@@ -3768,17 +3830,18 @@
|
|
|
3768
3830
|
$resultString: null,
|
|
3769
3831
|
$expectError: null,
|
|
3770
3832
|
$scriptPipelineExecutionErrors: [],
|
|
3833
|
+
$failedResults: [], // Track all failed attempts
|
|
3771
3834
|
};
|
|
3772
3835
|
// TODO: [🚐] Make arrayable LLMs -> single LLM DRY
|
|
3773
3836
|
const _llms = arrayableToArray(tools.llm);
|
|
3774
3837
|
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
3775
|
-
attempts: for (let
|
|
3776
|
-
const isJokerAttempt =
|
|
3777
|
-
const jokerParameterName = jokerParameterNames[jokerParameterNames.length +
|
|
3838
|
+
attempts: for (let attemptIndex = -jokerParameterNames.length; attemptIndex < maxAttempts; attemptIndex++) {
|
|
3839
|
+
const isJokerAttempt = attemptIndex < 0;
|
|
3840
|
+
const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attemptIndex];
|
|
3778
3841
|
// TODO: [🧠][🍭] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
|
|
3779
3842
|
if (isJokerAttempt && !jokerParameterName) {
|
|
3780
3843
|
throw new UnexpectedError(spaceTrim.spaceTrim((block) => `
|
|
3781
|
-
Joker not found in attempt ${
|
|
3844
|
+
Joker not found in attempt ${attemptIndex}
|
|
3782
3845
|
|
|
3783
3846
|
${block(pipelineIdentification)}
|
|
3784
3847
|
`));
|
|
@@ -3976,35 +4039,18 @@
|
|
|
3976
4039
|
}
|
|
3977
4040
|
}
|
|
3978
4041
|
// TODO: [💝] Unite object for expecting amount and format
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
throw new ExpectError(spaceTrim.spaceTrim((block) => `
|
|
3989
|
-
Expected valid JSON string
|
|
3990
|
-
|
|
3991
|
-
${block(
|
|
3992
|
-
/*<- Note: No need for `pipelineIdentification`, it will be catched and added later */ '')}
|
|
3993
|
-
`));
|
|
3994
|
-
}
|
|
3995
|
-
}
|
|
3996
|
-
}
|
|
3997
|
-
else {
|
|
3998
|
-
throw new UnexpectedError(spaceTrim.spaceTrim((block) => `
|
|
3999
|
-
Unknown format "${task.format}"
|
|
4000
|
-
|
|
4001
|
-
${block(pipelineIdentification)}
|
|
4002
|
-
`));
|
|
4042
|
+
// Use the common validation function for both format and expectations
|
|
4043
|
+
if (task.format || task.expectations) {
|
|
4044
|
+
const validationResult = validatePromptResult({
|
|
4045
|
+
resultString: $ongoingTaskResult.$resultString || '',
|
|
4046
|
+
expectations: task.expectations,
|
|
4047
|
+
format: task.format,
|
|
4048
|
+
});
|
|
4049
|
+
if (!validationResult.isValid) {
|
|
4050
|
+
throw validationResult.error;
|
|
4003
4051
|
}
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
if (task.expectations) {
|
|
4007
|
-
checkExpectations(task.expectations, $ongoingTaskResult.$resultString || '');
|
|
4052
|
+
// Update the result string in case format processing modified it (e.g., JSON extraction)
|
|
4053
|
+
$ongoingTaskResult.$resultString = validationResult.processedResultString;
|
|
4008
4054
|
}
|
|
4009
4055
|
break attempts;
|
|
4010
4056
|
}
|
|
@@ -4013,6 +4059,15 @@
|
|
|
4013
4059
|
throw error;
|
|
4014
4060
|
}
|
|
4015
4061
|
$ongoingTaskResult.$expectError = error;
|
|
4062
|
+
// Store each failed attempt
|
|
4063
|
+
if (!Array.isArray($ongoingTaskResult.$failedResults)) {
|
|
4064
|
+
$ongoingTaskResult.$failedResults = [];
|
|
4065
|
+
}
|
|
4066
|
+
$ongoingTaskResult.$failedResults.push({
|
|
4067
|
+
attemptIndex,
|
|
4068
|
+
result: $ongoingTaskResult.$resultString,
|
|
4069
|
+
error: error,
|
|
4070
|
+
});
|
|
4016
4071
|
}
|
|
4017
4072
|
finally {
|
|
4018
4073
|
if (!isJokerAttempt &&
|
|
@@ -4034,35 +4089,41 @@
|
|
|
4034
4089
|
});
|
|
4035
4090
|
}
|
|
4036
4091
|
}
|
|
4037
|
-
if ($ongoingTaskResult.$expectError !== null &&
|
|
4092
|
+
if ($ongoingTaskResult.$expectError !== null && attemptIndex === maxAttempts - 1) {
|
|
4093
|
+
// Note: Create a summary of all failures
|
|
4094
|
+
const failuresSummary = $ongoingTaskResult.$failedResults
|
|
4095
|
+
.map((failure) => spaceTrim.spaceTrim((block) => {
|
|
4096
|
+
var _a, _b;
|
|
4097
|
+
return `
|
|
4098
|
+
Attempt ${failure.attemptIndex + 1}:
|
|
4099
|
+
Error ${((_a = failure.error) === null || _a === void 0 ? void 0 : _a.name) || ''}:
|
|
4100
|
+
${block((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message.split('\n').map((line) => `> ${line}`).join('\n'))}
|
|
4101
|
+
|
|
4102
|
+
Result:
|
|
4103
|
+
${block(failure.result === null
|
|
4104
|
+
? 'null'
|
|
4105
|
+
: spaceTrim.spaceTrim(failure.result)
|
|
4106
|
+
.split('\n')
|
|
4107
|
+
.map((line) => `> ${line}`)
|
|
4108
|
+
.join('\n'))}
|
|
4109
|
+
`;
|
|
4110
|
+
}))
|
|
4111
|
+
.join('\n\n---\n\n');
|
|
4038
4112
|
throw new PipelineExecutionError(spaceTrim.spaceTrim((block) => {
|
|
4039
|
-
var _a
|
|
4113
|
+
var _a;
|
|
4040
4114
|
return `
|
|
4041
4115
|
LLM execution failed ${maxExecutionAttempts}x
|
|
4042
4116
|
|
|
4043
4117
|
${block(pipelineIdentification)}
|
|
4044
4118
|
|
|
4045
|
-
---
|
|
4046
4119
|
The Prompt:
|
|
4047
4120
|
${block((((_a = $ongoingTaskResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || '')
|
|
4048
4121
|
.split('\n')
|
|
4049
4122
|
.map((line) => `> ${line}`)
|
|
4050
4123
|
.join('\n'))}
|
|
4051
4124
|
|
|
4052
|
-
|
|
4053
|
-
${block(
|
|
4054
|
-
.split('\n')
|
|
4055
|
-
.map((line) => `> ${line}`)
|
|
4056
|
-
.join('\n'))}
|
|
4057
|
-
|
|
4058
|
-
Last result:
|
|
4059
|
-
${block($ongoingTaskResult.$resultString === null
|
|
4060
|
-
? 'null'
|
|
4061
|
-
: spaceTrim.spaceTrim($ongoingTaskResult.$resultString)
|
|
4062
|
-
.split('\n')
|
|
4063
|
-
.map((line) => `> ${line}`)
|
|
4064
|
-
.join('\n'))}
|
|
4065
|
-
---
|
|
4125
|
+
All Failed Attempts:
|
|
4126
|
+
${block(failuresSummary)}
|
|
4066
4127
|
`;
|
|
4067
4128
|
}));
|
|
4068
4129
|
}
|
|
@@ -4282,10 +4343,10 @@
|
|
|
4282
4343
|
*/
|
|
4283
4344
|
async function getKnowledgeForTask(options) {
|
|
4284
4345
|
const { tools, preparedPipeline, task, parameters } = options;
|
|
4285
|
-
const
|
|
4286
|
-
const
|
|
4346
|
+
const firstKnowledgePiece = preparedPipeline.knowledgePieces[0];
|
|
4347
|
+
const firstKnowledgeIndex = firstKnowledgePiece === null || firstKnowledgePiece === void 0 ? void 0 : firstKnowledgePiece.index[0];
|
|
4287
4348
|
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
|
|
4288
|
-
if (
|
|
4349
|
+
if (firstKnowledgePiece === undefined || firstKnowledgeIndex === undefined) {
|
|
4289
4350
|
return ''; // <- Note: Np knowledge present, return empty string
|
|
4290
4351
|
}
|
|
4291
4352
|
try {
|
|
@@ -4296,7 +4357,7 @@
|
|
|
4296
4357
|
title: 'Knowledge Search',
|
|
4297
4358
|
modelRequirements: {
|
|
4298
4359
|
modelVariant: 'EMBEDDING',
|
|
4299
|
-
modelName:
|
|
4360
|
+
modelName: firstKnowledgeIndex.modelName,
|
|
4300
4361
|
},
|
|
4301
4362
|
content: task.content,
|
|
4302
4363
|
parameters,
|
|
@@ -4304,7 +4365,7 @@
|
|
|
4304
4365
|
const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
|
|
4305
4366
|
const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
|
|
4306
4367
|
const { index } = knowledgePiece;
|
|
4307
|
-
const knowledgePieceIndex = index.find((i) => i.modelName ===
|
|
4368
|
+
const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowledgeIndex.modelName);
|
|
4308
4369
|
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model
|
|
4309
4370
|
if (knowledgePieceIndex === undefined) {
|
|
4310
4371
|
return {
|
|
@@ -4325,8 +4386,8 @@
|
|
|
4325
4386
|
task,
|
|
4326
4387
|
taskEmbeddingPrompt,
|
|
4327
4388
|
taskEmbeddingResult,
|
|
4328
|
-
|
|
4329
|
-
|
|
4389
|
+
firstKnowledgePiece,
|
|
4390
|
+
firstKnowledgeIndex,
|
|
4330
4391
|
knowledgePiecesWithRelevance,
|
|
4331
4392
|
knowledgePiecesSorted,
|
|
4332
4393
|
knowledgePiecesLimited,
|
|
@@ -4395,7 +4456,7 @@
|
|
|
4395
4456
|
* @private internal utility of `createPipelineExecutor`
|
|
4396
4457
|
*/
|
|
4397
4458
|
async function executeTask(options) {
|
|
4398
|
-
const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled,
|
|
4459
|
+
const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled, isNotPreparedWarningSuppressed, } = options;
|
|
4399
4460
|
const priority = preparedPipeline.tasks.length - preparedPipeline.tasks.indexOf(currentTask);
|
|
4400
4461
|
// Note: Check consistency of used and dependent parameters which was also done in `validatePipeline`, but it’s good to doublecheck
|
|
4401
4462
|
const usedParameterNames = extractParameterNamesFromTask(currentTask);
|
|
@@ -4483,7 +4544,7 @@
|
|
|
4483
4544
|
cacheDirname,
|
|
4484
4545
|
intermediateFilesStrategy,
|
|
4485
4546
|
isAutoInstalled,
|
|
4486
|
-
|
|
4547
|
+
isNotPreparedWarningSuppressed,
|
|
4487
4548
|
});
|
|
4488
4549
|
await onProgress({
|
|
4489
4550
|
outputParameters: {
|
|
@@ -4578,7 +4639,7 @@
|
|
|
4578
4639
|
}
|
|
4579
4640
|
return exportJson({
|
|
4580
4641
|
name: `executionReport`,
|
|
4581
|
-
message: `
|
|
4642
|
+
message: `Unsuccessful PipelineExecutorResult (with missing parameter {${parameter.name}}) PipelineExecutorResult`,
|
|
4582
4643
|
order: [],
|
|
4583
4644
|
value: {
|
|
4584
4645
|
isSuccessful: false,
|
|
@@ -4615,7 +4676,7 @@
|
|
|
4615
4676
|
return exportJson({
|
|
4616
4677
|
name: 'pipelineExecutorResult',
|
|
4617
4678
|
message: spaceTrim.spaceTrim((block) => `
|
|
4618
|
-
|
|
4679
|
+
Unsuccessful PipelineExecutorResult (with extra parameter {${parameter.name}}) PipelineExecutorResult
|
|
4619
4680
|
|
|
4620
4681
|
${block(pipelineIdentification)}
|
|
4621
4682
|
`),
|
|
@@ -4756,7 +4817,7 @@
|
|
|
4756
4817
|
}
|
|
4757
4818
|
return exportJson({
|
|
4758
4819
|
name: 'pipelineExecutorResult',
|
|
4759
|
-
message: `
|
|
4820
|
+
message: `Unsuccessful PipelineExecutorResult (with misc errors) PipelineExecutorResult`,
|
|
4760
4821
|
order: [],
|
|
4761
4822
|
value: {
|
|
4762
4823
|
isSuccessful: false,
|
|
@@ -4807,7 +4868,7 @@
|
|
|
4807
4868
|
* @public exported from `@promptbook/core`
|
|
4808
4869
|
*/
|
|
4809
4870
|
function createPipelineExecutor(options) {
|
|
4810
|
-
const { pipeline, tools, maxExecutionAttempts = DEFAULT_MAX_EXECUTION_ATTEMPTS, maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT, csvSettings = DEFAULT_CSV_SETTINGS, isVerbose = DEFAULT_IS_VERBOSE,
|
|
4871
|
+
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;
|
|
4811
4872
|
validatePipeline(pipeline);
|
|
4812
4873
|
const pipelineIdentification = (() => {
|
|
4813
4874
|
// Note: This is a 😐 implementation of [🚞]
|
|
@@ -4824,7 +4885,7 @@
|
|
|
4824
4885
|
if (isPipelinePrepared(pipeline)) {
|
|
4825
4886
|
preparedPipeline = pipeline;
|
|
4826
4887
|
}
|
|
4827
|
-
else if (
|
|
4888
|
+
else if (isNotPreparedWarningSuppressed !== true) {
|
|
4828
4889
|
console.warn(spaceTrim.spaceTrim((block) => `
|
|
4829
4890
|
Pipeline is not prepared
|
|
4830
4891
|
|
|
@@ -4857,7 +4918,7 @@
|
|
|
4857
4918
|
maxParallelCount,
|
|
4858
4919
|
csvSettings,
|
|
4859
4920
|
isVerbose,
|
|
4860
|
-
|
|
4921
|
+
isNotPreparedWarningSuppressed,
|
|
4861
4922
|
rootDirname,
|
|
4862
4923
|
cacheDirname,
|
|
4863
4924
|
intermediateFilesStrategy,
|
|
@@ -4866,7 +4927,7 @@
|
|
|
4866
4927
|
assertsError(error);
|
|
4867
4928
|
return exportJson({
|
|
4868
4929
|
name: 'pipelineExecutorResult',
|
|
4869
|
-
message: `
|
|
4930
|
+
message: `Unsuccessful PipelineExecutorResult, last catch`,
|
|
4870
4931
|
order: [],
|
|
4871
4932
|
value: {
|
|
4872
4933
|
isSuccessful: false,
|
|
@@ -4936,12 +4997,12 @@
|
|
|
4936
4997
|
get title() {
|
|
4937
4998
|
return `${llmTools.title} (+usage)`;
|
|
4938
4999
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
4939
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
5000
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
|
|
4940
5001
|
},
|
|
4941
5002
|
get description() {
|
|
4942
5003
|
return `${llmTools.description} (+usage)`;
|
|
4943
5004
|
// <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
|
|
4944
|
-
// <- TODO: [🧈][🧠] Does it make
|
|
5005
|
+
// <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
|
|
4945
5006
|
},
|
|
4946
5007
|
checkConfiguration() {
|
|
4947
5008
|
return /* not await */ llmTools.checkConfiguration();
|
|
@@ -5228,17 +5289,17 @@
|
|
|
5228
5289
|
* Mixes registered scrapers from $scrapersMetadataRegister and $scrapersRegister
|
|
5229
5290
|
*/
|
|
5230
5291
|
const all = [];
|
|
5231
|
-
for (const { packageName, className, mimeTypes, documentationUrl,
|
|
5292
|
+
for (const { packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser, } of $scrapersMetadataRegister.list()) {
|
|
5232
5293
|
if (all.some((item) => item.packageName === packageName && item.className === className)) {
|
|
5233
5294
|
continue;
|
|
5234
5295
|
}
|
|
5235
|
-
all.push({ packageName, className, mimeTypes, documentationUrl,
|
|
5296
|
+
all.push({ packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser });
|
|
5236
5297
|
}
|
|
5237
|
-
for (const { packageName, className, mimeTypes, documentationUrl,
|
|
5298
|
+
for (const { packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser, } of $scrapersRegister.list()) {
|
|
5238
5299
|
if (all.some((item) => item.packageName === packageName && item.className === className)) {
|
|
5239
5300
|
continue;
|
|
5240
5301
|
}
|
|
5241
|
-
all.push({ packageName, className, mimeTypes, documentationUrl,
|
|
5302
|
+
all.push({ packageName, className, mimeTypes, documentationUrl, isAvailableInBrowser });
|
|
5242
5303
|
}
|
|
5243
5304
|
for (const { metadata } of availableScrapers) {
|
|
5244
5305
|
all.push(metadata);
|
|
@@ -5250,8 +5311,8 @@
|
|
|
5250
5311
|
const isInstalled = $scrapersRegister
|
|
5251
5312
|
.list()
|
|
5252
5313
|
.find(({ packageName, className }) => metadata.packageName === packageName && metadata.className === className);
|
|
5253
|
-
const
|
|
5254
|
-
return { ...metadata, isMetadataAviailable, isInstalled,
|
|
5314
|
+
const isAvailableInTools = availableScrapers.some(({ metadata: { packageName, className } }) => metadata.packageName === packageName && metadata.className === className);
|
|
5315
|
+
return { ...metadata, isMetadataAviailable, isInstalled, isAvailableInTools };
|
|
5255
5316
|
});
|
|
5256
5317
|
if (metadata.length === 0) {
|
|
5257
5318
|
return spaceTrim__default["default"](`
|
|
@@ -5264,7 +5325,7 @@
|
|
|
5264
5325
|
return spaceTrim__default["default"]((block) => `
|
|
5265
5326
|
Available scrapers are:
|
|
5266
5327
|
${block(metadata
|
|
5267
|
-
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes,
|
|
5328
|
+
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvailableInBrowser, isAvailableInTools, }, i) => {
|
|
5268
5329
|
const more = [];
|
|
5269
5330
|
// TODO: [🧠] Maybe use `documentationUrl`
|
|
5270
5331
|
if (isMetadataAviailable) {
|
|
@@ -5273,16 +5334,16 @@
|
|
|
5273
5334
|
if (isInstalled) {
|
|
5274
5335
|
more.push(`🟩 Installed`);
|
|
5275
5336
|
} // not else
|
|
5276
|
-
if (
|
|
5337
|
+
if (isAvailableInTools) {
|
|
5277
5338
|
more.push(`🟦 Available in tools`);
|
|
5278
5339
|
} // not else
|
|
5279
5340
|
if (!isMetadataAviailable && isInstalled) {
|
|
5280
5341
|
more.push(`When no metadata registered but scraper is installed, it is an unexpected behavior`);
|
|
5281
5342
|
} // not else
|
|
5282
|
-
if (!isInstalled &&
|
|
5343
|
+
if (!isInstalled && isAvailableInTools) {
|
|
5283
5344
|
more.push(`When the scraper is not installed but available in tools, it is an unexpected compatibility behavior`);
|
|
5284
5345
|
} // not else
|
|
5285
|
-
if (!
|
|
5346
|
+
if (!isAvailableInBrowser) {
|
|
5286
5347
|
more.push(`Not usable in browser`);
|
|
5287
5348
|
}
|
|
5288
5349
|
const moreText = more.length === 0 ? '' : ` *(${more.join('; ')})*`;
|
|
@@ -5748,7 +5809,7 @@
|
|
|
5748
5809
|
/**
|
|
5749
5810
|
* TODO: [🧊] In future one preparation can take data from previous preparation and save tokens and time
|
|
5750
5811
|
* Put `knowledgePieces` into `PrepareKnowledgeOptions`
|
|
5751
|
-
* TODO: [🪂] More than max things can run in parallel by
|
|
5812
|
+
* TODO: [🪂] More than max things can run in parallel by accident [1,[2a,2b,_],[3a,3b,_]]
|
|
5752
5813
|
* TODO: [🧠][❎] Do here proper M:N mapping
|
|
5753
5814
|
* [x] One source can make multiple pieces
|
|
5754
5815
|
* [ ] One piece can have multiple sources
|
|
@@ -6636,7 +6697,7 @@
|
|
|
6636
6697
|
$taskJson.expectations[unit] = $taskJson.expectations[unit] || {};
|
|
6637
6698
|
if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
|
|
6638
6699
|
if ($taskJson.expectations[unit].min !== undefined) {
|
|
6639
|
-
throw new ParseError(`Already defined
|
|
6700
|
+
throw new ParseError(`Already defined minimum ${$taskJson.expectations[unit].min} ${command.unit.toLowerCase()}, now trying to redefine it to ${command.amount}`);
|
|
6640
6701
|
}
|
|
6641
6702
|
$taskJson.expectations[unit].min = command.amount;
|
|
6642
6703
|
} /* not else */
|
|
@@ -10133,6 +10194,46 @@
|
|
|
10133
10194
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
10134
10195
|
*/
|
|
10135
10196
|
|
|
10197
|
+
/**
|
|
10198
|
+
* Detects if the code is running in a browser environment in main thread (Not in a web worker)
|
|
10199
|
+
*
|
|
10200
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10201
|
+
*
|
|
10202
|
+
* @public exported from `@promptbook/utils`
|
|
10203
|
+
*/
|
|
10204
|
+
const $isRunningInBrowser = new Function(`
|
|
10205
|
+
try {
|
|
10206
|
+
return this === window;
|
|
10207
|
+
} catch (e) {
|
|
10208
|
+
return false;
|
|
10209
|
+
}
|
|
10210
|
+
`);
|
|
10211
|
+
/**
|
|
10212
|
+
* TODO: [🎺]
|
|
10213
|
+
*/
|
|
10214
|
+
|
|
10215
|
+
/**
|
|
10216
|
+
* Detects if the code is running in a web worker
|
|
10217
|
+
*
|
|
10218
|
+
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10219
|
+
*
|
|
10220
|
+
* @public exported from `@promptbook/utils`
|
|
10221
|
+
*/
|
|
10222
|
+
const $isRunningInWebWorker = new Function(`
|
|
10223
|
+
try {
|
|
10224
|
+
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
|
|
10225
|
+
return true;
|
|
10226
|
+
} else {
|
|
10227
|
+
return false;
|
|
10228
|
+
}
|
|
10229
|
+
} catch (e) {
|
|
10230
|
+
return false;
|
|
10231
|
+
}
|
|
10232
|
+
`);
|
|
10233
|
+
/**
|
|
10234
|
+
* TODO: [🎺]
|
|
10235
|
+
*/
|
|
10236
|
+
|
|
10136
10237
|
/**
|
|
10137
10238
|
* Creates LLM execution tools from provided configuration objects
|
|
10138
10239
|
*
|
|
@@ -10153,8 +10254,10 @@
|
|
|
10153
10254
|
.list()
|
|
10154
10255
|
.find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
|
|
10155
10256
|
if (registeredItem === undefined) {
|
|
10257
|
+
console.log('!!! $llmToolsRegister.list()', $llmToolsRegister.list());
|
|
10156
10258
|
throw new Error(spaceTrim__default["default"]((block) => `
|
|
10157
10259
|
There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
|
|
10260
|
+
Running in ${!$isRunningInBrowser() ? '' : 'browser environment'}${!$isRunningInNode() ? '' : 'node environment'}${!$isRunningInWebWorker() ? '' : 'worker environment'}
|
|
10158
10261
|
|
|
10159
10262
|
You have probably forgotten install and import the provider package.
|
|
10160
10263
|
To fix this issue, you can:
|
|
@@ -10281,24 +10384,6 @@
|
|
|
10281
10384
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
10282
10385
|
*/
|
|
10283
10386
|
|
|
10284
|
-
/**
|
|
10285
|
-
* Detects if the code is running in a browser environment in main thread (Not in a web worker)
|
|
10286
|
-
*
|
|
10287
|
-
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10288
|
-
*
|
|
10289
|
-
* @public exported from `@promptbook/utils`
|
|
10290
|
-
*/
|
|
10291
|
-
new Function(`
|
|
10292
|
-
try {
|
|
10293
|
-
return this === window;
|
|
10294
|
-
} catch (e) {
|
|
10295
|
-
return false;
|
|
10296
|
-
}
|
|
10297
|
-
`);
|
|
10298
|
-
/**
|
|
10299
|
-
* TODO: [🎺]
|
|
10300
|
-
*/
|
|
10301
|
-
|
|
10302
10387
|
/**
|
|
10303
10388
|
* Detects if the code is running in jest environment
|
|
10304
10389
|
*
|
|
@@ -10317,28 +10402,6 @@
|
|
|
10317
10402
|
* TODO: [🎺]
|
|
10318
10403
|
*/
|
|
10319
10404
|
|
|
10320
|
-
/**
|
|
10321
|
-
* Detects if the code is running in a web worker
|
|
10322
|
-
*
|
|
10323
|
-
* Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
|
|
10324
|
-
*
|
|
10325
|
-
* @public exported from `@promptbook/utils`
|
|
10326
|
-
*/
|
|
10327
|
-
new Function(`
|
|
10328
|
-
try {
|
|
10329
|
-
if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
|
|
10330
|
-
return true;
|
|
10331
|
-
} else {
|
|
10332
|
-
return false;
|
|
10333
|
-
}
|
|
10334
|
-
} catch (e) {
|
|
10335
|
-
return false;
|
|
10336
|
-
}
|
|
10337
|
-
`);
|
|
10338
|
-
/**
|
|
10339
|
-
* TODO: [🎺]
|
|
10340
|
-
*/
|
|
10341
|
-
|
|
10342
10405
|
/**
|
|
10343
10406
|
* Makes first letter of a string uppercase
|
|
10344
10407
|
*
|
|
@@ -10889,7 +10952,7 @@
|
|
|
10889
10952
|
return fileNames;
|
|
10890
10953
|
}
|
|
10891
10954
|
/**
|
|
10892
|
-
* TODO: [😶] Unite
|
|
10955
|
+
* TODO: [😶] Unite folder listing
|
|
10893
10956
|
* Note: Not [~🟢~] because it is not directly dependent on `fs
|
|
10894
10957
|
* TODO: [🖇] What about symlinks?
|
|
10895
10958
|
*/
|
|
@@ -11036,7 +11099,7 @@
|
|
|
11036
11099
|
if (isCrashedOnError) {
|
|
11037
11100
|
throw new CollectionError(wrappedErrorMessage);
|
|
11038
11101
|
}
|
|
11039
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
11102
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
11040
11103
|
console.error(wrappedErrorMessage);
|
|
11041
11104
|
}
|
|
11042
11105
|
}
|
|
@@ -11103,7 +11166,7 @@
|
|
|
11103
11166
|
|
|
11104
11167
|
Note: You have probably forgotten to run "ptbk make" to update the collection
|
|
11105
11168
|
Note: Pipelines with the same URL are not allowed
|
|
11106
|
-
Only
|
|
11169
|
+
Only exception is when the pipelines are identical
|
|
11107
11170
|
|
|
11108
11171
|
`));
|
|
11109
11172
|
}
|
|
@@ -11127,7 +11190,7 @@
|
|
|
11127
11190
|
if (isCrashedOnError) {
|
|
11128
11191
|
throw new CollectionError(wrappedErrorMessage);
|
|
11129
11192
|
}
|
|
11130
|
-
// TODO: [🟥] Detect browser / node and make it
|
|
11193
|
+
// TODO: [🟥] Detect browser / node and make it colorful
|
|
11131
11194
|
console.error(wrappedErrorMessage);
|
|
11132
11195
|
}
|
|
11133
11196
|
}
|