@promptbook/ollama 0.112.0-72 → 0.112.0-73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/index.es.js +1615 -1484
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-components/Chat/save/_common/chatExportRendering.d.ts +28 -0
- package/esm/src/book-components/Chat/save/_common/getPromptbookExportBranding.d.ts +18 -0
- package/esm/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +1 -1
- package/esm/src/book-components/Chat/save/html/htmlSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/save/index.d.ts +4 -4
- package/esm/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +1 -1
- package/esm/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -2
- package/esm/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +2 -2
- package/esm/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/save/react/reactSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/renderMarkdown.d.ts +26 -0
- package/esm/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +2 -0
- package/esm/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/handleActionErrors.d.ts +9 -4
- package/esm/src/conversion/pipelineJsonToString/appendMarkdownBlock.d.ts +7 -0
- package/esm/src/conversion/pipelineJsonToString/createPipelineCommands.d.ts +7 -0
- package/esm/src/conversion/pipelineJsonToString/createPipelineIntroduction.d.ts +8 -0
- package/esm/src/conversion/pipelineJsonToString/createTaskSerialization.d.ts +23 -0
- package/esm/src/conversion/pipelineJsonToString/stringifyCommands.d.ts +7 -0
- package/esm/src/conversion/pipelineJsonToString/stringifyTask.d.ts +8 -0
- package/esm/src/conversion/pipelineJsonToString.test.d.ts +1 -0
- package/esm/src/execution/createPipelineExecutor/executeSingleAttempt.d.ts +31 -0
- package/esm/src/execution/createPipelineExecutor/handleAttemptFailure.d.ts +40 -0
- package/esm/src/execution/createPipelineExecutor/reportPromptExecution.d.ts +34 -0
- package/esm/src/execution/resolveTaskTldr.d.ts +32 -0
- package/esm/src/execution/resolveTaskTldr.test.d.ts +1 -0
- package/esm/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +22 -63
- package/esm/src/llm-providers/agent/AgentLlmExecutionToolsAgentKitRunner.d.ts +51 -0
- package/esm/src/llm-providers/agent/AgentLlmExecutionToolsOpenAiAssistantRunner.d.ts +43 -0
- package/esm/src/llm-providers/agent/AgentLlmExecutionToolsPromptPreparer.d.ts +41 -0
- package/esm/src/llm-providers/agent/emitAgentLlmExecutionToolsAssistantPreparationProgress.d.ts +26 -0
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +16 -93
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsInputBuilder.d.ts +41 -0
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsOutputTypeMapper.d.ts +56 -0
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.d.ts +99 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +24 -120
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsProgressReporter.d.ts +62 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsPromptBuilder.d.ts +29 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsStreamRunner.d.ts +63 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.d.ts +89 -0
- package/esm/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +9 -28
- package/esm/src/llm-providers/openai/OpenAiCompatibleModelCatalog.d.ts +31 -0
- package/esm/src/llm-providers/openai/OpenAiCompatibleNonChatPromptCaller.d.ts +57 -0
- package/esm/src/llm-providers/openai/OpenAiCompatibleRequestManager.d.ts +29 -0
- package/esm/src/llm-providers/openai/OpenAiVectorStoreFileBatchHandler.d.ts +51 -0
- package/esm/src/llm-providers/openai/OpenAiVectorStoreFileBatchPoller.d.ts +75 -0
- package/esm/src/llm-providers/openai/OpenAiVectorStoreHandler.d.ts +1 -98
- package/esm/src/llm-providers/openai/OpenAiVectorStoreKnowledgeSourcePreparer.d.ts +44 -0
- package/esm/src/llm-providers/openai/utils/OpenAiCompatibleChatProgressReporter.d.ts +86 -0
- package/esm/src/llm-providers/openai/utils/OpenAiCompatibleChatPromptBuilder.d.ts +57 -0
- package/esm/src/llm-providers/openai/utils/OpenAiCompatibleChatToolCaller.d.ts +57 -0
- package/esm/src/remote-server/startRemoteServer/RemoteServerRuntime.d.ts +14 -0
- package/esm/src/remote-server/startRemoteServer/SocketResponse.d.ts +9 -0
- package/esm/src/remote-server/startRemoteServer/StartRemoteServerConfiguration.d.ts +18 -0
- package/esm/src/remote-server/startRemoteServer/createRemoteServerExpressApp.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/createRemoteServerHandle.d.ts +11 -0
- package/esm/src/remote-server/startRemoteServer/createSocketServer.d.ts +9 -0
- package/esm/src/remote-server/startRemoteServer/getExecutionToolsFromIdentification.d.ts +12 -0
- package/esm/src/remote-server/startRemoteServer/registerBookRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerExecutionRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerListModelsSocketHandler.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerLoginRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerNotFoundRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerOpenAiCompatibleChatCompletionsRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerOpenApiRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerPreparePipelineSocketHandler.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerPromptSocketHandler.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerRemoteServerHttpRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerRemoteServerSocketHandlers.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerServerIndexRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/resolveStartRemoteServerConfiguration.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/respondToSocketRequest.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/startListening.d.ts +9 -0
- package/esm/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +14 -1
- package/esm/src/utils/serialization/serializeToPromptbookJavascript.d.ts +2 -0
- package/esm/src/utils/serialization/serializeToPromptbookJavascript.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +1618 -1487
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-components/Chat/save/_common/chatExportRendering.d.ts +28 -0
- package/umd/src/book-components/Chat/save/_common/getPromptbookExportBranding.d.ts +18 -0
- package/umd/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +1 -1
- package/umd/src/book-components/Chat/save/html/htmlSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/save/index.d.ts +4 -4
- package/umd/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +1 -1
- package/umd/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -2
- package/umd/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +2 -2
- package/umd/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/save/react/reactSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/renderMarkdown.d.ts +26 -0
- package/umd/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +2 -0
- package/umd/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/handleActionErrors.d.ts +9 -4
- package/umd/src/conversion/pipelineJsonToString/appendMarkdownBlock.d.ts +7 -0
- package/umd/src/conversion/pipelineJsonToString/createPipelineCommands.d.ts +7 -0
- package/umd/src/conversion/pipelineJsonToString/createPipelineIntroduction.d.ts +8 -0
- package/umd/src/conversion/pipelineJsonToString/createTaskSerialization.d.ts +23 -0
- package/umd/src/conversion/pipelineJsonToString/stringifyCommands.d.ts +7 -0
- package/umd/src/conversion/pipelineJsonToString/stringifyTask.d.ts +8 -0
- package/umd/src/conversion/pipelineJsonToString.test.d.ts +1 -0
- package/umd/src/execution/createPipelineExecutor/executeSingleAttempt.d.ts +31 -0
- package/umd/src/execution/createPipelineExecutor/handleAttemptFailure.d.ts +40 -0
- package/umd/src/execution/createPipelineExecutor/reportPromptExecution.d.ts +34 -0
- package/umd/src/execution/resolveTaskTldr.d.ts +32 -0
- package/umd/src/execution/resolveTaskTldr.test.d.ts +1 -0
- package/umd/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +22 -63
- package/umd/src/llm-providers/agent/AgentLlmExecutionToolsAgentKitRunner.d.ts +51 -0
- package/umd/src/llm-providers/agent/AgentLlmExecutionToolsOpenAiAssistantRunner.d.ts +43 -0
- package/umd/src/llm-providers/agent/AgentLlmExecutionToolsPromptPreparer.d.ts +41 -0
- package/umd/src/llm-providers/agent/emitAgentLlmExecutionToolsAssistantPreparationProgress.d.ts +26 -0
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +16 -93
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsInputBuilder.d.ts +41 -0
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsOutputTypeMapper.d.ts +56 -0
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.d.ts +99 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +24 -120
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsProgressReporter.d.ts +62 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsPromptBuilder.d.ts +29 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsStreamRunner.d.ts +63 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.d.ts +89 -0
- package/umd/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +9 -28
- package/umd/src/llm-providers/openai/OpenAiCompatibleModelCatalog.d.ts +31 -0
- package/umd/src/llm-providers/openai/OpenAiCompatibleNonChatPromptCaller.d.ts +57 -0
- package/umd/src/llm-providers/openai/OpenAiCompatibleRequestManager.d.ts +29 -0
- package/umd/src/llm-providers/openai/OpenAiVectorStoreFileBatchHandler.d.ts +51 -0
- package/umd/src/llm-providers/openai/OpenAiVectorStoreFileBatchPoller.d.ts +75 -0
- package/umd/src/llm-providers/openai/OpenAiVectorStoreHandler.d.ts +1 -98
- package/umd/src/llm-providers/openai/OpenAiVectorStoreKnowledgeSourcePreparer.d.ts +44 -0
- package/umd/src/llm-providers/openai/utils/OpenAiCompatibleChatProgressReporter.d.ts +86 -0
- package/umd/src/llm-providers/openai/utils/OpenAiCompatibleChatPromptBuilder.d.ts +57 -0
- package/umd/src/llm-providers/openai/utils/OpenAiCompatibleChatToolCaller.d.ts +57 -0
- package/umd/src/remote-server/startRemoteServer/RemoteServerRuntime.d.ts +14 -0
- package/umd/src/remote-server/startRemoteServer/SocketResponse.d.ts +9 -0
- package/umd/src/remote-server/startRemoteServer/StartRemoteServerConfiguration.d.ts +18 -0
- package/umd/src/remote-server/startRemoteServer/createRemoteServerExpressApp.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/createRemoteServerHandle.d.ts +11 -0
- package/umd/src/remote-server/startRemoteServer/createSocketServer.d.ts +9 -0
- package/umd/src/remote-server/startRemoteServer/getExecutionToolsFromIdentification.d.ts +12 -0
- package/umd/src/remote-server/startRemoteServer/registerBookRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerExecutionRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerListModelsSocketHandler.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerLoginRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerNotFoundRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerOpenAiCompatibleChatCompletionsRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerOpenApiRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerPreparePipelineSocketHandler.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerPromptSocketHandler.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerRemoteServerHttpRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerRemoteServerSocketHandlers.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerServerIndexRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/resolveStartRemoteServerConfiguration.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/respondToSocketRequest.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/startListening.d.ts +9 -0
- package/umd/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +14 -1
- package/umd/src/utils/serialization/serializeToPromptbookJavascript.d.ts +2 -0
- package/umd/src/utils/serialization/serializeToPromptbookJavascript.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
2
2
|
import { randomBytes } from 'crypto';
|
|
3
|
-
import Bottleneck from 'bottleneck';
|
|
4
3
|
import colors from 'colors';
|
|
4
|
+
import Bottleneck from 'bottleneck';
|
|
5
5
|
import OpenAI from 'openai';
|
|
6
6
|
|
|
7
7
|
// ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
|
|
@@ -18,7 +18,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
18
18
|
* @generated
|
|
19
19
|
* @see https://github.com/webgptorg/promptbook
|
|
20
20
|
*/
|
|
21
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
21
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-73';
|
|
22
22
|
/**
|
|
23
23
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
24
24
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -2814,6 +2814,68 @@ resultContent, rawResponse, duration = ZERO_VALUE) {
|
|
|
2814
2814
|
}
|
|
2815
2815
|
// TODO: [🤝] DRY Maybe some common abstraction between `computeOpenAiUsage` and `computeAnthropicClaudeUsage`
|
|
2816
2816
|
|
|
2817
|
+
/**
|
|
2818
|
+
* Finds the best hardcoded-model match for one API-listed model identifier.
|
|
2819
|
+
*/
|
|
2820
|
+
function findHardcodedModelMatch(hardcodedModels, modelId) {
|
|
2821
|
+
return hardcodedModels.find(({ modelName }) => modelName === modelId || modelName.startsWith(modelId) || modelId.startsWith(modelName));
|
|
2822
|
+
}
|
|
2823
|
+
/**
|
|
2824
|
+
* Creates the fallback model entry used when the API returns an unknown model.
|
|
2825
|
+
*/
|
|
2826
|
+
function createFallbackModel(modelId) {
|
|
2827
|
+
return {
|
|
2828
|
+
modelVariant: 'CHAT',
|
|
2829
|
+
modelTitle: modelId,
|
|
2830
|
+
modelName: modelId,
|
|
2831
|
+
modelDescription: '',
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
/**
|
|
2835
|
+
* Resolves model lists and default-model lookup for OpenAI-compatible execution tools.
|
|
2836
|
+
*
|
|
2837
|
+
* @private helper of `OpenAiCompatibleExecutionTools`
|
|
2838
|
+
*/
|
|
2839
|
+
class OpenAiCompatibleModelCatalog {
|
|
2840
|
+
constructor(options) {
|
|
2841
|
+
this.options = options;
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* Lists available models by merging the live API list with hardcoded metadata when possible.
|
|
2845
|
+
*/
|
|
2846
|
+
async listModels() {
|
|
2847
|
+
const client = await this.options.getClient();
|
|
2848
|
+
const rawModelsList = await client.models.list();
|
|
2849
|
+
const hardcodedModels = this.options.getHardcodedModels();
|
|
2850
|
+
return rawModelsList.data
|
|
2851
|
+
.sort((a, b) => (a.created > b.created ? 1 : -1))
|
|
2852
|
+
.map((modelFromApi) => {
|
|
2853
|
+
const modelId = modelFromApi.id;
|
|
2854
|
+
return findHardcodedModelMatch(hardcodedModels, modelId) || createFallbackModel(modelId);
|
|
2855
|
+
});
|
|
2856
|
+
}
|
|
2857
|
+
/**
|
|
2858
|
+
* Resolves one default model by exact or family-prefix name.
|
|
2859
|
+
*/
|
|
2860
|
+
getDefaultModel(defaultModelName) {
|
|
2861
|
+
const model = this.options
|
|
2862
|
+
.getHardcodedModels()
|
|
2863
|
+
.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
|
|
2864
|
+
if (model === undefined) {
|
|
2865
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
2866
|
+
Cannot find model in ${this.options.getTitle()} models with name "${defaultModelName}" which should be used as default.
|
|
2867
|
+
|
|
2868
|
+
Available models:
|
|
2869
|
+
${block(this.options.getHardcodedModels().map(({ modelName }) => `- "${modelName}"`).join('\n'))}
|
|
2870
|
+
|
|
2871
|
+
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
2872
|
+
|
|
2873
|
+
`));
|
|
2874
|
+
}
|
|
2875
|
+
return model;
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2817
2879
|
/**
|
|
2818
2880
|
* Simple wrapper `new Date().toISOString()`
|
|
2819
2881
|
*
|
|
@@ -2994,440 +3056,524 @@ function templateParameters(template, parameters) {
|
|
|
2994
3056
|
}
|
|
2995
3057
|
|
|
2996
3058
|
/**
|
|
2997
|
-
*
|
|
3059
|
+
* Parses an OpenAI error message to identify which parameter is unsupported
|
|
2998
3060
|
*
|
|
2999
|
-
* @
|
|
3000
|
-
|
|
3001
|
-
const TOOL_EXECUTION_ENVELOPE_MARKER = '__promptbookToolExecutionEnvelope';
|
|
3002
|
-
/**
|
|
3003
|
-
* Parses one serialized tool-execution envelope when present.
|
|
3061
|
+
* @param errorMessage The error message from OpenAI API
|
|
3062
|
+
* @returns The parameter name that is unsupported, or null if not an unsupported parameter error
|
|
3004
3063
|
*
|
|
3005
|
-
* @private
|
|
3064
|
+
* @private utility of LLM Tools
|
|
3006
3065
|
*/
|
|
3007
|
-
function
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
const parsedValue = JSON.parse(rawValue);
|
|
3013
|
-
if (!parsedValue ||
|
|
3014
|
-
typeof parsedValue !== 'object' ||
|
|
3015
|
-
parsedValue[TOOL_EXECUTION_ENVELOPE_MARKER] !== true ||
|
|
3016
|
-
typeof parsedValue.assistantMessage !== 'string') {
|
|
3017
|
-
return null;
|
|
3018
|
-
}
|
|
3019
|
-
return {
|
|
3020
|
-
assistantMessage: parsedValue.assistantMessage,
|
|
3021
|
-
toolResult: parsedValue.toolResult,
|
|
3022
|
-
};
|
|
3066
|
+
function parseUnsupportedParameterError(errorMessage) {
|
|
3067
|
+
// Pattern to match "Unsupported value: 'parameter' does not support ..."
|
|
3068
|
+
const unsupportedValueMatch = errorMessage.match(/Unsupported value:\s*'([^']+)'\s*does not support/i);
|
|
3069
|
+
if (unsupportedValueMatch === null || unsupportedValueMatch === void 0 ? void 0 : unsupportedValueMatch[1]) {
|
|
3070
|
+
return unsupportedValueMatch[1];
|
|
3023
3071
|
}
|
|
3024
|
-
|
|
3025
|
-
|
|
3072
|
+
// Pattern to match "'parameter' of type ... is not supported with this model"
|
|
3073
|
+
const parameterTypeMatch = errorMessage.match(/'([^']+)'\s*of type.*is not supported with this model/i);
|
|
3074
|
+
if (parameterTypeMatch === null || parameterTypeMatch === void 0 ? void 0 : parameterTypeMatch[1]) {
|
|
3075
|
+
return parameterTypeMatch[1];
|
|
3026
3076
|
}
|
|
3077
|
+
return null;
|
|
3027
3078
|
}
|
|
3028
|
-
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3029
|
-
|
|
3030
|
-
/**
|
|
3031
|
-
* Prompt parameter key used to pass hidden runtime context to tool execution.
|
|
3032
|
-
*
|
|
3033
|
-
* @private internal runtime wiring for commitment tools
|
|
3034
|
-
*/
|
|
3035
|
-
const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
|
|
3036
3079
|
/**
|
|
3037
|
-
*
|
|
3080
|
+
* Creates a copy of model requirements with the specified parameter removed
|
|
3038
3081
|
*
|
|
3039
|
-
* @
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
/**
|
|
3043
|
-
* Prompt parameter key used to pass a hidden tool-progress listener token into script execution.
|
|
3082
|
+
* @param modelRequirements Original model requirements
|
|
3083
|
+
* @param unsupportedParameter The parameter to remove
|
|
3084
|
+
* @returns New model requirements without the unsupported parameter
|
|
3044
3085
|
*
|
|
3045
|
-
* @private
|
|
3086
|
+
* @private utility of LLM Tools
|
|
3046
3087
|
*/
|
|
3047
|
-
|
|
3088
|
+
function removeUnsupportedModelRequirement(modelRequirements, unsupportedParameter) {
|
|
3089
|
+
const newRequirements = { ...modelRequirements };
|
|
3090
|
+
// Map of parameter names that might appear in error messages to ModelRequirements properties
|
|
3091
|
+
const parameterMap = {
|
|
3092
|
+
temperature: 'temperature',
|
|
3093
|
+
max_tokens: 'maxTokens',
|
|
3094
|
+
maxTokens: 'maxTokens',
|
|
3095
|
+
seed: 'seed',
|
|
3096
|
+
};
|
|
3097
|
+
const propertyToRemove = parameterMap[unsupportedParameter];
|
|
3098
|
+
if (propertyToRemove && propertyToRemove in newRequirements) {
|
|
3099
|
+
delete newRequirements[propertyToRemove];
|
|
3100
|
+
}
|
|
3101
|
+
return newRequirements;
|
|
3102
|
+
}
|
|
3048
3103
|
/**
|
|
3049
|
-
*
|
|
3104
|
+
* Checks if an error is an "Unsupported value" error from OpenAI
|
|
3050
3105
|
*
|
|
3051
|
-
* @
|
|
3052
|
-
|
|
3053
|
-
const TOOL_PROGRESS_TOKEN_ARGUMENT = '__promptbookToolProgressToken';
|
|
3054
|
-
/**
|
|
3055
|
-
* Monotonic counter used for hidden progress-listener tokens.
|
|
3106
|
+
* @param error The error to check
|
|
3107
|
+
* @returns true if this is an unsupported parameter error
|
|
3056
3108
|
*
|
|
3057
|
-
* @private
|
|
3109
|
+
* @private utility of LLM Tools
|
|
3058
3110
|
*/
|
|
3059
|
-
|
|
3111
|
+
function isUnsupportedParameterError(error) {
|
|
3112
|
+
const errorMessage = error.message.toLowerCase();
|
|
3113
|
+
return (errorMessage.includes('unsupported value:') ||
|
|
3114
|
+
errorMessage.includes('is not supported with this model') ||
|
|
3115
|
+
errorMessage.includes('does not support'));
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3060
3118
|
/**
|
|
3061
|
-
*
|
|
3062
|
-
*
|
|
3063
|
-
* @private internal runtime wiring for commitment tools
|
|
3119
|
+
* Creates one unsupported-parameter retry record.
|
|
3064
3120
|
*/
|
|
3065
|
-
|
|
3121
|
+
function createUnsupportedParameterAttempt(options) {
|
|
3122
|
+
return {
|
|
3123
|
+
modelName: options.modelName,
|
|
3124
|
+
unsupportedParameter: options.unsupportedParameter,
|
|
3125
|
+
errorMessage: options.errorMessage,
|
|
3126
|
+
stripped: options.stripped,
|
|
3127
|
+
};
|
|
3128
|
+
}
|
|
3066
3129
|
/**
|
|
3067
|
-
*
|
|
3068
|
-
*
|
|
3069
|
-
* The returned token is passed into script execution as a hidden argument so tool implementations
|
|
3070
|
-
* can stream progress without exposing extra parameters to the model.
|
|
3071
|
-
*
|
|
3072
|
-
* @param listener - Listener notified about tool progress.
|
|
3073
|
-
* @returns Hidden token used to route progress updates.
|
|
3074
|
-
*
|
|
3075
|
-
* @private internal runtime wiring for commitment tools
|
|
3130
|
+
* Formats the retry history exactly as it is reported in thrown errors.
|
|
3076
3131
|
*/
|
|
3077
|
-
function
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3132
|
+
function formatUnsupportedParameterAttemptHistory(attemptStack) {
|
|
3133
|
+
return attemptStack
|
|
3134
|
+
.map((attempt, index) => ` ${index + 1}. Model: ${attempt.modelName}` +
|
|
3135
|
+
(attempt.unsupportedParameter ? `, Stripped: ${attempt.unsupportedParameter}` : '') +
|
|
3136
|
+
`, Error: ${attempt.errorMessage}` +
|
|
3137
|
+
(attempt.stripped ? ' (stripped and retried)' : ''))
|
|
3138
|
+
.join('\n');
|
|
3082
3139
|
}
|
|
3083
3140
|
/**
|
|
3084
|
-
*
|
|
3085
|
-
*
|
|
3086
|
-
* @param token - Token previously created by `registerToolCallProgressListener`.
|
|
3141
|
+
* Tracks unsupported-parameter retries for one OpenAI-compatible model call.
|
|
3087
3142
|
*
|
|
3088
|
-
* @private
|
|
3143
|
+
* @private helper of `OpenAiCompatibleExecutionTools`
|
|
3089
3144
|
*/
|
|
3090
|
-
|
|
3091
|
-
|
|
3145
|
+
class OpenAiCompatibleUnsupportedParameterRetrier {
|
|
3146
|
+
constructor(isVerbose) {
|
|
3147
|
+
this.isVerbose = isVerbose;
|
|
3148
|
+
this.attemptStack = [];
|
|
3149
|
+
this.retriedUnsupportedParameters = new Set();
|
|
3150
|
+
}
|
|
3151
|
+
/**
|
|
3152
|
+
* Resolves the next retry attempt after an unsupported-parameter failure or rethrows the final error.
|
|
3153
|
+
*/
|
|
3154
|
+
resolveRetryOrThrow(options) {
|
|
3155
|
+
if (!isUnsupportedParameterError(options.error)) {
|
|
3156
|
+
this.throwWithAttemptHistory(options.error);
|
|
3157
|
+
}
|
|
3158
|
+
const unsupportedParameter = parseUnsupportedParameterError(options.error.message);
|
|
3159
|
+
if (!unsupportedParameter) {
|
|
3160
|
+
if (this.isVerbose) {
|
|
3161
|
+
console.warn(colors.bgYellow('Warning'), 'Could not parse unsupported parameter from error:', options.error.message);
|
|
3162
|
+
}
|
|
3163
|
+
throw options.error;
|
|
3164
|
+
}
|
|
3165
|
+
const retryKey = `${options.modelName}-${unsupportedParameter}`;
|
|
3166
|
+
const attempt = createUnsupportedParameterAttempt({
|
|
3167
|
+
modelName: options.modelName,
|
|
3168
|
+
unsupportedParameter,
|
|
3169
|
+
errorMessage: options.error.message,
|
|
3170
|
+
stripped: true,
|
|
3171
|
+
});
|
|
3172
|
+
if (this.retriedUnsupportedParameters.has(retryKey)) {
|
|
3173
|
+
this.attemptStack.push(attempt);
|
|
3174
|
+
throw this.createAttemptHistoryError(options.error.message);
|
|
3175
|
+
}
|
|
3176
|
+
this.retriedUnsupportedParameters.add(retryKey);
|
|
3177
|
+
if (this.isVerbose) {
|
|
3178
|
+
console.warn(colors.bgYellow('Warning'), `Removing unsupported parameter '${unsupportedParameter}' for model '${options.modelName}' and retrying request`);
|
|
3179
|
+
}
|
|
3180
|
+
this.attemptStack.push(attempt);
|
|
3181
|
+
return removeUnsupportedModelRequirement(options.currentModelRequirements, unsupportedParameter);
|
|
3182
|
+
}
|
|
3183
|
+
/**
|
|
3184
|
+
* Rethrows the original error or wraps it with the collected retry history.
|
|
3185
|
+
*/
|
|
3186
|
+
throwWithAttemptHistory(error) {
|
|
3187
|
+
if (this.attemptStack.length > 0) {
|
|
3188
|
+
throw this.createAttemptHistoryError(error.message);
|
|
3189
|
+
}
|
|
3190
|
+
throw error;
|
|
3191
|
+
}
|
|
3192
|
+
/**
|
|
3193
|
+
* Creates the retry-history error message shared by all OpenAI-compatible model variants.
|
|
3194
|
+
*/
|
|
3195
|
+
createAttemptHistoryError(finalErrorMessage) {
|
|
3196
|
+
return new PipelineExecutionError(spaceTrim$1((block) => `
|
|
3197
|
+
All attempts failed. Attempt history:
|
|
3198
|
+
${block(formatUnsupportedParameterAttemptHistory(this.attemptStack))}
|
|
3199
|
+
Final error: ${finalErrorMessage}
|
|
3200
|
+
`));
|
|
3201
|
+
}
|
|
3092
3202
|
}
|
|
3093
|
-
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3094
3203
|
|
|
3095
3204
|
/**
|
|
3096
|
-
*
|
|
3097
|
-
*
|
|
3098
|
-
* For example, when the format value is not a valid JSON or CSV
|
|
3099
|
-
* This is not thrown directly but in extended classes
|
|
3100
|
-
*
|
|
3101
|
-
* @public exported from `@promptbook/core`
|
|
3205
|
+
* Creates a deep clone of JSON-serializable prompt payloads.
|
|
3102
3206
|
*/
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
// public readonly name = 'AbstractFormatError';
|
|
3106
|
-
constructor(message) {
|
|
3107
|
-
super(message);
|
|
3108
|
-
Object.setPrototypeOf(this, AbstractFormatError.prototype);
|
|
3109
|
-
}
|
|
3207
|
+
function cloneSerializableValue(value) {
|
|
3208
|
+
return JSON.parse(JSON.stringify(value));
|
|
3110
3209
|
}
|
|
3111
|
-
|
|
3112
3210
|
/**
|
|
3113
|
-
*
|
|
3211
|
+
* Executes completion, embedding, and image-generation prompts for OpenAI-compatible providers.
|
|
3114
3212
|
*
|
|
3115
|
-
* @
|
|
3213
|
+
* @private helper of `OpenAiCompatibleExecutionTools`
|
|
3116
3214
|
*/
|
|
3117
|
-
class
|
|
3118
|
-
constructor(
|
|
3119
|
-
|
|
3120
|
-
this.name = 'CsvFormatError';
|
|
3121
|
-
Object.setPrototypeOf(this, CsvFormatError.prototype);
|
|
3122
|
-
}
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3125
|
-
/**
|
|
3126
|
-
* AuthenticationError is thrown from login function which is dependency of remote server
|
|
3127
|
-
*
|
|
3128
|
-
* @public exported from `@promptbook/core`
|
|
3129
|
-
*/
|
|
3130
|
-
class AuthenticationError extends Error {
|
|
3131
|
-
constructor(message) {
|
|
3132
|
-
super(message);
|
|
3133
|
-
this.name = 'AuthenticationError';
|
|
3134
|
-
Object.setPrototypeOf(this, AuthenticationError.prototype);
|
|
3135
|
-
}
|
|
3136
|
-
}
|
|
3137
|
-
|
|
3138
|
-
/**
|
|
3139
|
-
* This error indicates that the pipeline collection cannot be properly loaded
|
|
3140
|
-
*
|
|
3141
|
-
* @public exported from `@promptbook/core`
|
|
3142
|
-
*/
|
|
3143
|
-
class CollectionError extends Error {
|
|
3144
|
-
constructor(message) {
|
|
3145
|
-
super(message);
|
|
3146
|
-
this.name = 'CollectionError';
|
|
3147
|
-
Object.setPrototypeOf(this, CollectionError.prototype);
|
|
3148
|
-
}
|
|
3149
|
-
}
|
|
3150
|
-
|
|
3151
|
-
/**
|
|
3152
|
-
* Signals that the requested operation could not be completed because the target already exists.
|
|
3153
|
-
*
|
|
3154
|
-
* @public exported from `@promptbook/core`
|
|
3155
|
-
*/
|
|
3156
|
-
class ConflictError extends Error {
|
|
3157
|
-
constructor(message) {
|
|
3158
|
-
super(message);
|
|
3159
|
-
this.name = 'ConflictError';
|
|
3160
|
-
Object.setPrototypeOf(this, ConflictError.prototype);
|
|
3161
|
-
}
|
|
3162
|
-
}
|
|
3163
|
-
|
|
3164
|
-
/**
|
|
3165
|
-
* This error indicates error from the database
|
|
3166
|
-
*
|
|
3167
|
-
* @public exported from `@promptbook/core`
|
|
3168
|
-
*/
|
|
3169
|
-
class DatabaseError extends Error {
|
|
3170
|
-
constructor(message) {
|
|
3171
|
-
super(message);
|
|
3172
|
-
this.name = 'DatabaseError';
|
|
3173
|
-
Object.setPrototypeOf(this, DatabaseError.prototype);
|
|
3174
|
-
}
|
|
3175
|
-
}
|
|
3176
|
-
// TODO: [🐱🚀] Explain that NotFoundError ([🐱🚀] and other specific errors) has priority over DatabaseError in some contexts
|
|
3177
|
-
|
|
3178
|
-
/**
|
|
3179
|
-
* This error type indicates that you try to use a feature that is not available in the current environment
|
|
3180
|
-
*
|
|
3181
|
-
* @public exported from `@promptbook/core`
|
|
3182
|
-
*/
|
|
3183
|
-
class EnvironmentMismatchError extends Error {
|
|
3184
|
-
constructor(message) {
|
|
3185
|
-
super(message);
|
|
3186
|
-
this.name = 'EnvironmentMismatchError';
|
|
3187
|
-
Object.setPrototypeOf(this, EnvironmentMismatchError.prototype);
|
|
3188
|
-
}
|
|
3189
|
-
}
|
|
3190
|
-
|
|
3191
|
-
/**
|
|
3192
|
-
* This error occurs when some expectation is not met in the execution of the pipeline
|
|
3193
|
-
*
|
|
3194
|
-
* Note: Do not throw this error, its reserved for `checkExpectations` and `createPipelineExecutor` and public ONLY to be serializable through remote server
|
|
3195
|
-
* Note: Always thrown in `checkExpectations` and catched in `createPipelineExecutor` and rethrown as `PipelineExecutionError`
|
|
3196
|
-
* Note: This is a kindof subtype of PipelineExecutionError
|
|
3197
|
-
*
|
|
3198
|
-
* @public exported from `@promptbook/core`
|
|
3199
|
-
*/
|
|
3200
|
-
class ExpectError extends Error {
|
|
3201
|
-
constructor(message) {
|
|
3202
|
-
super(message);
|
|
3203
|
-
this.name = 'ExpectError';
|
|
3204
|
-
Object.setPrototypeOf(this, ExpectError.prototype);
|
|
3205
|
-
}
|
|
3206
|
-
}
|
|
3207
|
-
|
|
3208
|
-
/**
|
|
3209
|
-
* This error indicates that the promptbook can not retrieve knowledge from external sources
|
|
3210
|
-
*
|
|
3211
|
-
* @public exported from `@promptbook/core`
|
|
3212
|
-
*/
|
|
3213
|
-
class KnowledgeScrapeError extends Error {
|
|
3214
|
-
constructor(message) {
|
|
3215
|
-
super(message);
|
|
3216
|
-
this.name = 'KnowledgeScrapeError';
|
|
3217
|
-
Object.setPrototypeOf(this, KnowledgeScrapeError.prototype);
|
|
3218
|
-
}
|
|
3219
|
-
}
|
|
3220
|
-
|
|
3221
|
-
/**
|
|
3222
|
-
* This error type indicates that some tools are missing for pipeline execution or preparation
|
|
3223
|
-
*
|
|
3224
|
-
* @public exported from `@promptbook/core`
|
|
3225
|
-
*/
|
|
3226
|
-
class MissingToolsError extends Error {
|
|
3227
|
-
constructor(message) {
|
|
3228
|
-
super(spaceTrim$1((block) => `
|
|
3229
|
-
${block(message)}
|
|
3230
|
-
|
|
3231
|
-
Note: You have probably forgot to provide some tools for pipeline execution or preparation
|
|
3232
|
-
|
|
3233
|
-
`));
|
|
3234
|
-
this.name = 'MissingToolsError';
|
|
3235
|
-
Object.setPrototypeOf(this, MissingToolsError.prototype);
|
|
3236
|
-
}
|
|
3237
|
-
}
|
|
3238
|
-
|
|
3239
|
-
/**
|
|
3240
|
-
* This error indicates that promptbook operation is not allowed
|
|
3241
|
-
*
|
|
3242
|
-
* @public exported from `@promptbook/core`
|
|
3243
|
-
*/
|
|
3244
|
-
class NotAllowed extends Error {
|
|
3245
|
-
constructor(message) {
|
|
3246
|
-
super(message);
|
|
3247
|
-
this.name = 'NotAllowed';
|
|
3248
|
-
Object.setPrototypeOf(this, NotAllowed.prototype);
|
|
3215
|
+
class OpenAiCompatibleNonChatPromptCaller {
|
|
3216
|
+
constructor(options) {
|
|
3217
|
+
this.options = options;
|
|
3249
3218
|
}
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
*/
|
|
3257
|
-
class NotFoundError extends Error {
|
|
3258
|
-
constructor(message) {
|
|
3259
|
-
super(message);
|
|
3260
|
-
this.name = 'NotFoundError';
|
|
3261
|
-
Object.setPrototypeOf(this, NotFoundError.prototype);
|
|
3219
|
+
/**
|
|
3220
|
+
* Calls one OpenAI-compatible completion model.
|
|
3221
|
+
*/
|
|
3222
|
+
async callCompletionModel(prompt) {
|
|
3223
|
+
const clonedPrompt = cloneSerializableValue(prompt);
|
|
3224
|
+
return this.callCompletionModelWithRetry(clonedPrompt, clonedPrompt.modelRequirements, new OpenAiCompatibleUnsupportedParameterRetrier(this.options.isVerbose));
|
|
3262
3225
|
}
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
*/
|
|
3270
|
-
class NotYetImplementedError extends Error {
|
|
3271
|
-
constructor(message) {
|
|
3272
|
-
super(spaceTrim$1((block) => `
|
|
3273
|
-
${block(message)}
|
|
3274
|
-
|
|
3275
|
-
Note: This feature is not implemented yet but it will be soon.
|
|
3276
|
-
|
|
3277
|
-
If you want speed up the implementation or just read more, look here:
|
|
3278
|
-
https://github.com/webgptorg/promptbook
|
|
3279
|
-
|
|
3280
|
-
Or contact us on pavol@ptbk.io
|
|
3281
|
-
|
|
3282
|
-
`));
|
|
3283
|
-
this.name = 'NotYetImplementedError';
|
|
3284
|
-
Object.setPrototypeOf(this, NotYetImplementedError.prototype);
|
|
3226
|
+
/**
|
|
3227
|
+
* Calls one OpenAI-compatible embedding model.
|
|
3228
|
+
*/
|
|
3229
|
+
async callEmbeddingModel(prompt) {
|
|
3230
|
+
const clonedPrompt = cloneSerializableValue(prompt);
|
|
3231
|
+
return this.callEmbeddingModelWithRetry(clonedPrompt, clonedPrompt.modelRequirements, new OpenAiCompatibleUnsupportedParameterRetrier(this.options.isVerbose));
|
|
3285
3232
|
}
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
*/
|
|
3293
|
-
class ParseError extends Error {
|
|
3294
|
-
constructor(message) {
|
|
3295
|
-
super(message);
|
|
3296
|
-
this.name = 'ParseError';
|
|
3297
|
-
Object.setPrototypeOf(this, ParseError.prototype);
|
|
3233
|
+
/**
|
|
3234
|
+
* Calls one OpenAI-compatible image-generation model.
|
|
3235
|
+
*/
|
|
3236
|
+
async callImageGenerationModel(prompt) {
|
|
3237
|
+
const clonedPrompt = cloneSerializableValue(prompt);
|
|
3238
|
+
return this.callImageGenerationModelWithRetry(clonedPrompt, clonedPrompt.modelRequirements, new OpenAiCompatibleUnsupportedParameterRetrier(this.options.isVerbose));
|
|
3298
3239
|
}
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3240
|
+
/**
|
|
3241
|
+
* Retries completion requests while stripping unsupported model parameters.
|
|
3242
|
+
*/
|
|
3243
|
+
async callCompletionModelWithRetry(prompt, currentModelRequirements, unsupportedParameterRetrier) {
|
|
3244
|
+
var _a;
|
|
3245
|
+
const title = this.options.getTitle();
|
|
3246
|
+
if (this.options.isVerbose) {
|
|
3247
|
+
console.info(`🖋 ${title} callCompletionModel call`, { prompt, currentModelRequirements });
|
|
3248
|
+
}
|
|
3249
|
+
const { content, parameters } = prompt;
|
|
3250
|
+
const client = await this.options.getClient();
|
|
3251
|
+
if (currentModelRequirements.modelVariant !== 'COMPLETION') {
|
|
3252
|
+
throw new PipelineExecutionError('Use callCompletionModel only for COMPLETION variant');
|
|
3253
|
+
}
|
|
3254
|
+
const modelName = currentModelRequirements.modelName || this.options.getDefaultCompletionModel().modelName;
|
|
3255
|
+
const modelSettings = {
|
|
3256
|
+
model: modelName,
|
|
3257
|
+
max_tokens: currentModelRequirements.maxTokens,
|
|
3258
|
+
temperature: currentModelRequirements.temperature,
|
|
3259
|
+
};
|
|
3260
|
+
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
3261
|
+
const rawRequest = {
|
|
3262
|
+
...modelSettings,
|
|
3263
|
+
model: modelName,
|
|
3264
|
+
prompt: rawPromptContent,
|
|
3265
|
+
user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
3266
|
+
};
|
|
3267
|
+
const start = $getCurrentDate();
|
|
3268
|
+
if (this.options.isVerbose) {
|
|
3269
|
+
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
3270
|
+
}
|
|
3271
|
+
try {
|
|
3272
|
+
const turnStart = $getCurrentDate();
|
|
3273
|
+
const rawResponse = await this.options.executeRateLimitedRequest(() => client.completions.create(rawRequest));
|
|
3274
|
+
const turnComplete = $getCurrentDate();
|
|
3275
|
+
if (this.options.isVerbose) {
|
|
3276
|
+
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
3277
|
+
}
|
|
3278
|
+
if (!rawResponse.choices[0]) {
|
|
3279
|
+
throw new PipelineExecutionError(`No choises from ${title}`);
|
|
3280
|
+
}
|
|
3281
|
+
if (rawResponse.choices.length > 1) {
|
|
3282
|
+
throw new PipelineExecutionError(`More than one choise from ${title}`);
|
|
3283
|
+
}
|
|
3284
|
+
const resultContent = rawResponse.choices[0].text;
|
|
3285
|
+
const duration = uncertainNumber((new Date(turnComplete).getTime() - new Date(turnStart).getTime()) / 1000);
|
|
3286
|
+
const usage = this.options.computeUsage(content || '', resultContent || '', rawResponse, duration);
|
|
3287
|
+
return exportJson({
|
|
3288
|
+
name: 'promptResult',
|
|
3289
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callCompletionModel\``,
|
|
3290
|
+
order: [],
|
|
3291
|
+
value: {
|
|
3292
|
+
content: resultContent,
|
|
3293
|
+
modelName: rawResponse.model || modelName,
|
|
3294
|
+
timing: {
|
|
3295
|
+
start,
|
|
3296
|
+
complete: turnComplete,
|
|
3297
|
+
},
|
|
3298
|
+
usage,
|
|
3299
|
+
rawPromptContent,
|
|
3300
|
+
rawRequest,
|
|
3301
|
+
rawResponse,
|
|
3302
|
+
},
|
|
3303
|
+
});
|
|
3304
|
+
}
|
|
3305
|
+
catch (error) {
|
|
3306
|
+
assertsError(error);
|
|
3307
|
+
const modifiedModelRequirements = unsupportedParameterRetrier.resolveRetryOrThrow({
|
|
3308
|
+
error,
|
|
3309
|
+
modelName,
|
|
3310
|
+
currentModelRequirements,
|
|
3311
|
+
});
|
|
3312
|
+
return this.callCompletionModelWithRetry(prompt, modifiedModelRequirements, unsupportedParameterRetrier);
|
|
3313
|
+
}
|
|
3312
3314
|
}
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3315
|
+
/**
|
|
3316
|
+
* Retries embedding requests while stripping unsupported model parameters.
|
|
3317
|
+
*/
|
|
3318
|
+
async callEmbeddingModelWithRetry(prompt, currentModelRequirements, unsupportedParameterRetrier) {
|
|
3319
|
+
const title = this.options.getTitle();
|
|
3320
|
+
if (this.options.isVerbose) {
|
|
3321
|
+
console.info(`🖋 ${title} embedding call`, { prompt, currentModelRequirements });
|
|
3322
|
+
}
|
|
3323
|
+
const { content, parameters } = prompt;
|
|
3324
|
+
const client = await this.options.getClient();
|
|
3325
|
+
if (currentModelRequirements.modelVariant !== 'EMBEDDING') {
|
|
3326
|
+
throw new PipelineExecutionError('Use embed only for EMBEDDING variant');
|
|
3327
|
+
}
|
|
3328
|
+
const modelName = currentModelRequirements.modelName || this.options.getDefaultEmbeddingModel().modelName;
|
|
3329
|
+
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
3330
|
+
const rawRequest = {
|
|
3331
|
+
input: rawPromptContent,
|
|
3332
|
+
model: modelName,
|
|
3333
|
+
};
|
|
3334
|
+
const start = $getCurrentDate();
|
|
3335
|
+
if (this.options.isVerbose) {
|
|
3336
|
+
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
3337
|
+
}
|
|
3338
|
+
try {
|
|
3339
|
+
const turnStart = $getCurrentDate();
|
|
3340
|
+
const rawResponse = await this.options.executeRateLimitedRequest(() => client.embeddings.create(rawRequest));
|
|
3341
|
+
const turnComplete = $getCurrentDate();
|
|
3342
|
+
if (this.options.isVerbose) {
|
|
3343
|
+
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
3344
|
+
}
|
|
3345
|
+
if (rawResponse.data.length !== 1) {
|
|
3346
|
+
throw new PipelineExecutionError(`Expected exactly 1 data item in response, got ${rawResponse.data.length}`);
|
|
3347
|
+
}
|
|
3348
|
+
const resultContent = rawResponse.data[0].embedding;
|
|
3349
|
+
const duration = uncertainNumber((new Date(turnComplete).getTime() - new Date(turnStart).getTime()) / 1000);
|
|
3350
|
+
const usage = this.options.computeUsage(content || '', '', rawResponse, duration);
|
|
3351
|
+
return exportJson({
|
|
3352
|
+
name: 'promptResult',
|
|
3353
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callEmbeddingModel\``,
|
|
3354
|
+
order: [],
|
|
3355
|
+
value: {
|
|
3356
|
+
content: resultContent,
|
|
3357
|
+
modelName: rawResponse.model || modelName,
|
|
3358
|
+
timing: {
|
|
3359
|
+
start,
|
|
3360
|
+
complete: turnComplete,
|
|
3361
|
+
},
|
|
3362
|
+
usage,
|
|
3363
|
+
rawPromptContent,
|
|
3364
|
+
rawRequest,
|
|
3365
|
+
rawResponse,
|
|
3366
|
+
},
|
|
3367
|
+
});
|
|
3368
|
+
}
|
|
3369
|
+
catch (error) {
|
|
3370
|
+
assertsError(error);
|
|
3371
|
+
const modifiedModelRequirements = unsupportedParameterRetrier.resolveRetryOrThrow({
|
|
3372
|
+
error,
|
|
3373
|
+
modelName,
|
|
3374
|
+
currentModelRequirements,
|
|
3375
|
+
});
|
|
3376
|
+
return this.callEmbeddingModelWithRetry(prompt, modifiedModelRequirements, unsupportedParameterRetrier);
|
|
3377
|
+
}
|
|
3325
3378
|
}
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3379
|
+
/**
|
|
3380
|
+
* Retries image-generation requests while stripping unsupported model parameters.
|
|
3381
|
+
*/
|
|
3382
|
+
async callImageGenerationModelWithRetry(prompt, currentModelRequirements, unsupportedParameterRetrier) {
|
|
3383
|
+
var _a, _b;
|
|
3384
|
+
const title = this.options.getTitle();
|
|
3385
|
+
if (this.options.isVerbose) {
|
|
3386
|
+
console.info(`🎨 ${title} callImageGenerationModel call`, { prompt, currentModelRequirements });
|
|
3387
|
+
}
|
|
3388
|
+
const { content, parameters } = prompt;
|
|
3389
|
+
const client = await this.options.getClient();
|
|
3390
|
+
if (currentModelRequirements.modelVariant !== 'IMAGE_GENERATION') {
|
|
3391
|
+
throw new PipelineExecutionError('Use callImageGenerationModel only for IMAGE_GENERATION variant');
|
|
3392
|
+
}
|
|
3393
|
+
const modelName = currentModelRequirements.modelName || this.options.getDefaultImageGenerationModel().modelName;
|
|
3394
|
+
const modelSettings = {
|
|
3395
|
+
model: modelName,
|
|
3396
|
+
size: currentModelRequirements.size,
|
|
3397
|
+
quality: currentModelRequirements.quality,
|
|
3398
|
+
style: currentModelRequirements.style,
|
|
3399
|
+
};
|
|
3400
|
+
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
3401
|
+
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
3402
|
+
rawPromptContent += '\n\n' + prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
3403
|
+
}
|
|
3404
|
+
const rawRequest = {
|
|
3405
|
+
...modelSettings,
|
|
3406
|
+
prompt: rawPromptContent,
|
|
3407
|
+
size: modelSettings.size || '1024x1024',
|
|
3408
|
+
user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
3409
|
+
response_format: 'url',
|
|
3410
|
+
};
|
|
3411
|
+
const start = $getCurrentDate();
|
|
3412
|
+
if (this.options.isVerbose) {
|
|
3413
|
+
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
3414
|
+
}
|
|
3415
|
+
try {
|
|
3416
|
+
const turnStart = $getCurrentDate();
|
|
3417
|
+
const rawResponse = await this.options.executeRateLimitedRequest(() => client.images.generate(rawRequest));
|
|
3418
|
+
const turnComplete = $getCurrentDate();
|
|
3419
|
+
if (this.options.isVerbose) {
|
|
3420
|
+
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
3421
|
+
}
|
|
3422
|
+
if (!rawResponse.data[0]) {
|
|
3423
|
+
throw new PipelineExecutionError(`No choises from ${title}`);
|
|
3424
|
+
}
|
|
3425
|
+
if (rawResponse.data.length > 1) {
|
|
3426
|
+
throw new PipelineExecutionError(`More than one choise from ${title}`);
|
|
3427
|
+
}
|
|
3428
|
+
const resultContent = rawResponse.data[0].url;
|
|
3429
|
+
const modelInfo = this.options.getHardcodedModels().find((model) => model.modelName === modelName);
|
|
3430
|
+
const price = ((_b = modelInfo === null || modelInfo === void 0 ? void 0 : modelInfo.pricing) === null || _b === void 0 ? void 0 : _b.output) ? uncertainNumber(modelInfo.pricing.output) : uncertainNumber();
|
|
3431
|
+
const duration = uncertainNumber((new Date(turnComplete).getTime() - new Date(turnStart).getTime()) / 1000);
|
|
3432
|
+
return exportJson({
|
|
3433
|
+
name: 'promptResult',
|
|
3434
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callImageGenerationModel\``,
|
|
3435
|
+
order: [],
|
|
3436
|
+
value: {
|
|
3437
|
+
content: resultContent,
|
|
3438
|
+
modelName: modelName,
|
|
3439
|
+
timing: {
|
|
3440
|
+
start,
|
|
3441
|
+
complete: turnComplete,
|
|
3442
|
+
},
|
|
3443
|
+
usage: {
|
|
3444
|
+
price,
|
|
3445
|
+
duration,
|
|
3446
|
+
input: {
|
|
3447
|
+
tokensCount: uncertainNumber(0),
|
|
3448
|
+
...computeUsageCounts(rawPromptContent),
|
|
3449
|
+
},
|
|
3450
|
+
output: {
|
|
3451
|
+
tokensCount: uncertainNumber(0),
|
|
3452
|
+
...computeUsageCounts(''),
|
|
3453
|
+
},
|
|
3454
|
+
},
|
|
3455
|
+
rawPromptContent,
|
|
3456
|
+
rawRequest,
|
|
3457
|
+
rawResponse,
|
|
3458
|
+
},
|
|
3459
|
+
});
|
|
3460
|
+
}
|
|
3461
|
+
catch (error) {
|
|
3462
|
+
assertsError(error);
|
|
3463
|
+
const modifiedModelRequirements = unsupportedParameterRetrier.resolveRetryOrThrow({
|
|
3464
|
+
error,
|
|
3465
|
+
modelName,
|
|
3466
|
+
currentModelRequirements,
|
|
3467
|
+
});
|
|
3468
|
+
return this.callImageGenerationModelWithRetry(prompt, modifiedModelRequirements, unsupportedParameterRetrier);
|
|
3469
|
+
}
|
|
3338
3470
|
}
|
|
3339
3471
|
}
|
|
3340
3472
|
|
|
3341
3473
|
/**
|
|
3342
|
-
*
|
|
3343
|
-
*
|
|
3344
|
-
* @public exported from `@promptbook/core`
|
|
3345
|
-
*/
|
|
3346
|
-
const PROMPTBOOK_ERRORS = {
|
|
3347
|
-
AbstractFormatError,
|
|
3348
|
-
CsvFormatError,
|
|
3349
|
-
CollectionError,
|
|
3350
|
-
EnvironmentMismatchError,
|
|
3351
|
-
ExpectError,
|
|
3352
|
-
KnowledgeScrapeError,
|
|
3353
|
-
LimitReachedError,
|
|
3354
|
-
MissingToolsError,
|
|
3355
|
-
NotFoundError,
|
|
3356
|
-
NotYetImplementedError,
|
|
3357
|
-
ParseError,
|
|
3358
|
-
PipelineExecutionError,
|
|
3359
|
-
PipelineLogicError,
|
|
3360
|
-
PipelineUrlError,
|
|
3361
|
-
AuthenticationError,
|
|
3362
|
-
PromptbookFetchError,
|
|
3363
|
-
UnexpectedError,
|
|
3364
|
-
WrappedError,
|
|
3365
|
-
NotAllowed,
|
|
3366
|
-
DatabaseError,
|
|
3367
|
-
ConflictError,
|
|
3368
|
-
// TODO: [🪑]> VersionMismatchError,
|
|
3369
|
-
};
|
|
3370
|
-
/**
|
|
3371
|
-
* Index of all javascript errors
|
|
3372
|
-
*
|
|
3373
|
-
* @private for internal usage
|
|
3374
|
-
*/
|
|
3375
|
-
const COMMON_JAVASCRIPT_ERRORS = {
|
|
3376
|
-
Error,
|
|
3377
|
-
EvalError,
|
|
3378
|
-
RangeError,
|
|
3379
|
-
ReferenceError,
|
|
3380
|
-
SyntaxError,
|
|
3381
|
-
TypeError,
|
|
3382
|
-
URIError,
|
|
3383
|
-
AggregateError,
|
|
3384
|
-
/*
|
|
3385
|
-
Note: Not widely supported
|
|
3386
|
-
> InternalError,
|
|
3387
|
-
> ModuleError,
|
|
3388
|
-
> HeapError,
|
|
3389
|
-
> WebAssemblyCompileError,
|
|
3390
|
-
> WebAssemblyRuntimeError,
|
|
3391
|
-
*/
|
|
3392
|
-
};
|
|
3393
|
-
/**
|
|
3394
|
-
* Index of all errors
|
|
3395
|
-
*
|
|
3396
|
-
* @private for internal usage
|
|
3397
|
-
*/
|
|
3398
|
-
const ALL_ERRORS = {
|
|
3399
|
-
...PROMPTBOOK_ERRORS,
|
|
3400
|
-
...COMMON_JAVASCRIPT_ERRORS,
|
|
3401
|
-
};
|
|
3402
|
-
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3403
|
-
|
|
3404
|
-
/**
|
|
3405
|
-
* Serializes an error into a [🚉] JSON-serializable object
|
|
3474
|
+
* Manages OpenAI-compatible client creation plus shared retry and rate-limit behavior.
|
|
3406
3475
|
*
|
|
3407
|
-
* @
|
|
3476
|
+
* @private helper of `OpenAiCompatibleExecutionTools`
|
|
3408
3477
|
*/
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3478
|
+
class OpenAiCompatibleRequestManager {
|
|
3479
|
+
constructor(options) {
|
|
3480
|
+
this.options = options;
|
|
3481
|
+
this.client = null;
|
|
3482
|
+
this.limiter = new Bottleneck({
|
|
3483
|
+
minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
|
|
3484
|
+
});
|
|
3485
|
+
}
|
|
3486
|
+
/**
|
|
3487
|
+
* Returns the lazily initialized OpenAI client configured from execution-tool options.
|
|
3488
|
+
*/
|
|
3489
|
+
async getClient() {
|
|
3490
|
+
if (this.client === null) {
|
|
3491
|
+
const openAiOptions = { ...this.options };
|
|
3492
|
+
delete openAiOptions.isVerbose;
|
|
3493
|
+
delete openAiOptions.userId;
|
|
3494
|
+
const enhancedOptions = {
|
|
3495
|
+
...openAiOptions,
|
|
3496
|
+
timeout: API_REQUEST_TIMEOUT,
|
|
3497
|
+
maxRetries: CONNECTION_RETRIES_LIMIT,
|
|
3498
|
+
};
|
|
3499
|
+
this.client = new OpenAI(enhancedOptions);
|
|
3500
|
+
}
|
|
3501
|
+
return this.client;
|
|
3502
|
+
}
|
|
3503
|
+
/**
|
|
3504
|
+
* Schedules one request through the shared limiter and retry policy.
|
|
3505
|
+
*/
|
|
3506
|
+
async executeRateLimitedRequest(requestFn) {
|
|
3507
|
+
return this.limiter.schedule(() => this.makeRequestWithNetworkRetry(requestFn)).catch((error) => {
|
|
3508
|
+
assertsError(error);
|
|
3509
|
+
if (this.options.isVerbose) {
|
|
3510
|
+
console.info(colors.bgRed('error'), error);
|
|
3511
|
+
}
|
|
3512
|
+
throw error;
|
|
3513
|
+
});
|
|
3514
|
+
}
|
|
3515
|
+
/**
|
|
3516
|
+
* Retries transient transport errors with exponential backoff.
|
|
3517
|
+
*/
|
|
3518
|
+
async makeRequestWithNetworkRetry(requestFn) {
|
|
3519
|
+
let lastError;
|
|
3520
|
+
for (let attempt = 1; attempt <= CONNECTION_RETRIES_LIMIT; attempt++) {
|
|
3521
|
+
try {
|
|
3522
|
+
return await requestFn();
|
|
3523
|
+
}
|
|
3524
|
+
catch (error) {
|
|
3525
|
+
assertsError(error);
|
|
3526
|
+
lastError = error;
|
|
3527
|
+
const isRetryableError = this.isRetryableNetworkError(error);
|
|
3528
|
+
if (!isRetryableError || attempt === CONNECTION_RETRIES_LIMIT) {
|
|
3529
|
+
if (this.options.isVerbose && this.isRetryableNetworkError(error)) {
|
|
3530
|
+
console.info(colors.bgRed('Final network error after retries'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}:`, error);
|
|
3531
|
+
}
|
|
3532
|
+
throw error;
|
|
3533
|
+
}
|
|
3534
|
+
const baseDelay = 1000;
|
|
3535
|
+
const backoffDelay = baseDelay * Math.pow(2, attempt - 1);
|
|
3536
|
+
const jitterDelay = Math.random() * 500;
|
|
3537
|
+
const totalDelay = backoffDelay + jitterDelay;
|
|
3538
|
+
if (this.options.isVerbose) {
|
|
3539
|
+
console.info(colors.bgYellow('Retrying network request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
|
|
3540
|
+
}
|
|
3541
|
+
await new Promise((resolve) => setTimeout(resolve, totalDelay));
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
throw lastError;
|
|
3545
|
+
}
|
|
3546
|
+
/**
|
|
3547
|
+
* Determines whether the thrown error should be retried as a transient network failure.
|
|
3548
|
+
*/
|
|
3549
|
+
isRetryableNetworkError(error) {
|
|
3550
|
+
const errorMessage = error.message.toLowerCase();
|
|
3551
|
+
const errorCode = error.code;
|
|
3552
|
+
const retryableErrors = [
|
|
3553
|
+
'econnreset',
|
|
3554
|
+
'enotfound',
|
|
3555
|
+
'econnrefused',
|
|
3556
|
+
'etimedout',
|
|
3557
|
+
'socket hang up',
|
|
3558
|
+
'network error',
|
|
3559
|
+
'fetch failed',
|
|
3560
|
+
'connection reset',
|
|
3561
|
+
'connection refused',
|
|
3562
|
+
'timeout',
|
|
3563
|
+
];
|
|
3564
|
+
if (retryableErrors.some((retryableError) => errorMessage.includes(retryableError))) {
|
|
3565
|
+
return true;
|
|
3566
|
+
}
|
|
3567
|
+
if (errorCode && retryableErrors.includes(errorCode.toLowerCase())) {
|
|
3568
|
+
return true;
|
|
3569
|
+
}
|
|
3570
|
+
const errorWithStatus = error;
|
|
3571
|
+
const httpStatus = errorWithStatus.status || errorWithStatus.statusCode;
|
|
3572
|
+
if (httpStatus && [429, 500, 502, 503, 504].includes(httpStatus)) {
|
|
3573
|
+
return true;
|
|
3574
|
+
}
|
|
3575
|
+
return false;
|
|
3424
3576
|
}
|
|
3425
|
-
return {
|
|
3426
|
-
name: name,
|
|
3427
|
-
message,
|
|
3428
|
-
stack,
|
|
3429
|
-
id, // Include id in the serialized object
|
|
3430
|
-
};
|
|
3431
3577
|
}
|
|
3432
3578
|
|
|
3433
3579
|
/**
|
|
@@ -3485,1261 +3631,1246 @@ function addUsage(...usageItems) {
|
|
|
3485
3631
|
}
|
|
3486
3632
|
|
|
3487
3633
|
/**
|
|
3488
|
-
*
|
|
3489
|
-
*
|
|
3490
|
-
* @param array - Array to iterate over
|
|
3491
|
-
* @param options - Options for the function
|
|
3492
|
-
* @param callbackfunction - Function to call for each item
|
|
3493
|
-
* @deprecated [🪂] Use queues instead
|
|
3634
|
+
* Builds incremental chat progress updates, tool-call snapshots, and the final prompt result.
|
|
3494
3635
|
*
|
|
3495
|
-
* @
|
|
3636
|
+
* @private helper of `callOpenAiCompatibleChatModel`
|
|
3496
3637
|
*/
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3638
|
+
class OpenAiCompatibleChatProgressReporter {
|
|
3639
|
+
/**
|
|
3640
|
+
* Creates an empty usage accumulator for multi-turn chat requests.
|
|
3641
|
+
*/
|
|
3642
|
+
createEmptyUsage() {
|
|
3643
|
+
return {
|
|
3644
|
+
price: uncertainNumber(0),
|
|
3645
|
+
duration: uncertainNumber(0),
|
|
3646
|
+
input: {
|
|
3647
|
+
tokensCount: uncertainNumber(0),
|
|
3648
|
+
charactersCount: uncertainNumber(0),
|
|
3649
|
+
wordsCount: uncertainNumber(0),
|
|
3650
|
+
sentencesCount: uncertainNumber(0),
|
|
3651
|
+
linesCount: uncertainNumber(0),
|
|
3652
|
+
paragraphsCount: uncertainNumber(0),
|
|
3653
|
+
pagesCount: uncertainNumber(0),
|
|
3654
|
+
},
|
|
3655
|
+
output: {
|
|
3656
|
+
tokensCount: uncertainNumber(0),
|
|
3657
|
+
charactersCount: uncertainNumber(0),
|
|
3658
|
+
wordsCount: uncertainNumber(0),
|
|
3659
|
+
sentencesCount: uncertainNumber(0),
|
|
3660
|
+
linesCount: uncertainNumber(0),
|
|
3661
|
+
paragraphsCount: uncertainNumber(0),
|
|
3662
|
+
pagesCount: uncertainNumber(0),
|
|
3663
|
+
},
|
|
3664
|
+
};
|
|
3665
|
+
}
|
|
3666
|
+
/**
|
|
3667
|
+
* Creates the initial pending snapshot for one chat tool call.
|
|
3668
|
+
*/
|
|
3669
|
+
createPendingToolCall(options) {
|
|
3670
|
+
return {
|
|
3671
|
+
name: options.functionName,
|
|
3672
|
+
arguments: options.functionArguments,
|
|
3673
|
+
result: '',
|
|
3674
|
+
rawToolCall: options.toolCall,
|
|
3675
|
+
createdAt: options.calledAt,
|
|
3676
|
+
state: 'PENDING',
|
|
3677
|
+
logs: [
|
|
3678
|
+
this.createToolCallLogEntry({
|
|
3679
|
+
kind: 'request',
|
|
3680
|
+
title: 'Request prepared',
|
|
3681
|
+
message: `Prepared ${options.functionName} request.`,
|
|
3682
|
+
payload: {
|
|
3683
|
+
arguments: options.functionArguments,
|
|
3684
|
+
},
|
|
3685
|
+
}),
|
|
3686
|
+
],
|
|
3687
|
+
};
|
|
3688
|
+
}
|
|
3689
|
+
/**
|
|
3690
|
+
* Appends one incremental progress update to the currently tracked tool-call snapshot.
|
|
3691
|
+
*/
|
|
3692
|
+
applyToolCallProgressUpdate(toolCall, update) {
|
|
3693
|
+
var _a;
|
|
3694
|
+
return {
|
|
3695
|
+
...toolCall,
|
|
3696
|
+
state: (_a = update.state) !== null && _a !== void 0 ? _a : 'PARTIAL',
|
|
3697
|
+
logs: update.log ? [...(toolCall.logs || []), update.log] : toolCall.logs,
|
|
3698
|
+
};
|
|
3699
|
+
}
|
|
3700
|
+
/**
|
|
3701
|
+
* Finalizes one chat tool-call snapshot after execution ends.
|
|
3702
|
+
*/
|
|
3703
|
+
createCompletedToolCall(options) {
|
|
3704
|
+
const hasErrors = options.errors !== undefined && options.errors.length > 0;
|
|
3705
|
+
return {
|
|
3706
|
+
...options.currentToolCallSnapshot,
|
|
3707
|
+
result: options.toolResult,
|
|
3708
|
+
rawToolCall: options.toolCall,
|
|
3709
|
+
createdAt: options.calledAt,
|
|
3710
|
+
errors: options.errors,
|
|
3711
|
+
state: this.resolveFinalToolCallState({
|
|
3712
|
+
currentState: options.currentToolCallSnapshot.state,
|
|
3713
|
+
errors: options.errors,
|
|
3714
|
+
}),
|
|
3715
|
+
logs: [
|
|
3716
|
+
...(options.currentToolCallSnapshot.logs || []),
|
|
3717
|
+
this.createToolCallLogEntry({
|
|
3718
|
+
kind: hasErrors ? 'error' : 'result',
|
|
3719
|
+
level: hasErrors ? 'error' : 'info',
|
|
3720
|
+
title: hasErrors ? 'Execution failed' : 'Execution finished',
|
|
3721
|
+
message: hasErrors
|
|
3722
|
+
? `${options.functionName} failed before returning a final result.`
|
|
3723
|
+
: `${options.functionName} returned a result.`,
|
|
3724
|
+
}),
|
|
3725
|
+
],
|
|
3726
|
+
};
|
|
3727
|
+
}
|
|
3728
|
+
/**
|
|
3729
|
+
* Emits one chat progress chunk with shared timing, request metadata, and tool-call snapshots.
|
|
3730
|
+
*/
|
|
3731
|
+
emitProgress(options) {
|
|
3732
|
+
options.onProgress({
|
|
3733
|
+
content: options.content,
|
|
3734
|
+
modelName: options.modelName,
|
|
3735
|
+
timing: {
|
|
3736
|
+
start: options.start,
|
|
3737
|
+
complete: options.complete || $getCurrentDate(),
|
|
3738
|
+
},
|
|
3739
|
+
usage: options.usage,
|
|
3740
|
+
toolCalls: options.toolCalls,
|
|
3741
|
+
rawPromptContent: options.rawPromptContent,
|
|
3742
|
+
rawRequest: options.rawRequest,
|
|
3743
|
+
rawResponse: options.rawResponse,
|
|
3509
3744
|
});
|
|
3510
|
-
if (maxParallelCount < runningTasks.length) {
|
|
3511
|
-
await Promise.race(runningTasks);
|
|
3512
|
-
}
|
|
3513
3745
|
}
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
*/
|
|
3522
|
-
function buildToolInvocationScript(options) {
|
|
3523
|
-
const { functionName, functionArgsExpression } = options;
|
|
3524
|
-
return `
|
|
3525
|
-
const args = ${functionArgsExpression};
|
|
3526
|
-
const runtimeContextRaw =
|
|
3527
|
-
typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
|
|
3528
|
-
? undefined
|
|
3529
|
-
: ${TOOL_RUNTIME_CONTEXT_PARAMETER};
|
|
3530
|
-
|
|
3531
|
-
if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
3532
|
-
args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
|
|
3533
|
-
}
|
|
3534
|
-
|
|
3535
|
-
const toolProgressTokenRaw =
|
|
3536
|
-
typeof ${TOOL_PROGRESS_TOKEN_PARAMETER} === 'undefined'
|
|
3537
|
-
? undefined
|
|
3538
|
-
: ${TOOL_PROGRESS_TOKEN_PARAMETER};
|
|
3539
|
-
|
|
3540
|
-
if (toolProgressTokenRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
3541
|
-
args.${TOOL_PROGRESS_TOKEN_ARGUMENT} = toolProgressTokenRaw;
|
|
3746
|
+
/**
|
|
3747
|
+
* Creates the final chat prompt result after the tool loop has finished.
|
|
3748
|
+
*/
|
|
3749
|
+
createChatPromptResult(options) {
|
|
3750
|
+
const resultContent = options.responseMessage.content;
|
|
3751
|
+
if (resultContent === null) {
|
|
3752
|
+
throw new PipelineExecutionError(`No response message from ${options.title}`);
|
|
3542
3753
|
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
}
|
|
3561
|
-
}));
|
|
3562
|
-
}
|
|
3563
|
-
|
|
3564
|
-
/**
|
|
3565
|
-
* Parses an OpenAI error message to identify which parameter is unsupported
|
|
3566
|
-
*
|
|
3567
|
-
* @param errorMessage The error message from OpenAI API
|
|
3568
|
-
* @returns The parameter name that is unsupported, or null if not an unsupported parameter error
|
|
3569
|
-
*
|
|
3570
|
-
* @private utility of LLM Tools
|
|
3571
|
-
*/
|
|
3572
|
-
function parseUnsupportedParameterError(errorMessage) {
|
|
3573
|
-
// Pattern to match "Unsupported value: 'parameter' does not support ..."
|
|
3574
|
-
const unsupportedValueMatch = errorMessage.match(/Unsupported value:\s*'([^']+)'\s*does not support/i);
|
|
3575
|
-
if (unsupportedValueMatch === null || unsupportedValueMatch === void 0 ? void 0 : unsupportedValueMatch[1]) {
|
|
3576
|
-
return unsupportedValueMatch[1];
|
|
3754
|
+
return exportJson({
|
|
3755
|
+
name: 'promptResult',
|
|
3756
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
|
|
3757
|
+
order: [],
|
|
3758
|
+
value: {
|
|
3759
|
+
content: resultContent,
|
|
3760
|
+
modelName: options.rawResponse.model || options.modelName,
|
|
3761
|
+
timing: {
|
|
3762
|
+
start: options.start,
|
|
3763
|
+
complete: options.complete,
|
|
3764
|
+
},
|
|
3765
|
+
usage: options.usage,
|
|
3766
|
+
toolCalls: options.toolCalls,
|
|
3767
|
+
rawPromptContent: options.rawPromptContent,
|
|
3768
|
+
rawRequest: options.rawRequest,
|
|
3769
|
+
rawResponse: options.rawResponse,
|
|
3770
|
+
},
|
|
3771
|
+
});
|
|
3577
3772
|
}
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3773
|
+
/**
|
|
3774
|
+
* Creates one structured log entry for streamed tool-call updates.
|
|
3775
|
+
*/
|
|
3776
|
+
createToolCallLogEntry(options) {
|
|
3777
|
+
return {
|
|
3778
|
+
createdAt: $getCurrentDate(),
|
|
3779
|
+
kind: options.kind,
|
|
3780
|
+
level: options.level,
|
|
3781
|
+
title: options.title,
|
|
3782
|
+
message: options.message,
|
|
3783
|
+
payload: options.payload,
|
|
3784
|
+
};
|
|
3582
3785
|
}
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
function removeUnsupportedModelRequirement(modelRequirements, unsupportedParameter) {
|
|
3595
|
-
const newRequirements = { ...modelRequirements };
|
|
3596
|
-
// Map of parameter names that might appear in error messages to ModelRequirements properties
|
|
3597
|
-
const parameterMap = {
|
|
3598
|
-
temperature: 'temperature',
|
|
3599
|
-
max_tokens: 'maxTokens',
|
|
3600
|
-
maxTokens: 'maxTokens',
|
|
3601
|
-
seed: 'seed',
|
|
3602
|
-
};
|
|
3603
|
-
const propertyToRemove = parameterMap[unsupportedParameter];
|
|
3604
|
-
if (propertyToRemove && propertyToRemove in newRequirements) {
|
|
3605
|
-
delete newRequirements[propertyToRemove];
|
|
3786
|
+
/**
|
|
3787
|
+
* Resolves the final lifecycle state for one tool call after execution ends.
|
|
3788
|
+
*/
|
|
3789
|
+
resolveFinalToolCallState(options) {
|
|
3790
|
+
if (options.errors && options.errors.length > 0) {
|
|
3791
|
+
return 'ERROR';
|
|
3792
|
+
}
|
|
3793
|
+
if (options.currentState === 'ERROR') {
|
|
3794
|
+
return 'ERROR';
|
|
3795
|
+
}
|
|
3796
|
+
return 'COMPLETE';
|
|
3606
3797
|
}
|
|
3607
|
-
return newRequirements;
|
|
3608
3798
|
}
|
|
3799
|
+
|
|
3609
3800
|
/**
|
|
3610
|
-
*
|
|
3611
|
-
*
|
|
3612
|
-
* @param error The error to check
|
|
3613
|
-
* @returns true if this is an unsupported parameter error
|
|
3801
|
+
* Maps Promptbook tools to OpenAI tools.
|
|
3614
3802
|
*
|
|
3615
|
-
* @private
|
|
3803
|
+
* @private
|
|
3616
3804
|
*/
|
|
3617
|
-
function
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3805
|
+
function mapToolsToOpenAi(tools) {
|
|
3806
|
+
return tools.map((tool) => ({
|
|
3807
|
+
type: 'function',
|
|
3808
|
+
function: {
|
|
3809
|
+
name: tool.name,
|
|
3810
|
+
description: tool.description,
|
|
3811
|
+
parameters: tool.parameters,
|
|
3812
|
+
},
|
|
3813
|
+
}));
|
|
3622
3814
|
}
|
|
3623
3815
|
|
|
3624
3816
|
/**
|
|
3625
|
-
*
|
|
3626
|
-
*/
|
|
3627
|
-
function createUnsupportedParameterAttempt(options) {
|
|
3628
|
-
return {
|
|
3629
|
-
modelName: options.modelName,
|
|
3630
|
-
unsupportedParameter: options.unsupportedParameter,
|
|
3631
|
-
errorMessage: options.errorMessage,
|
|
3632
|
-
stripped: options.stripped,
|
|
3633
|
-
};
|
|
3634
|
-
}
|
|
3635
|
-
/**
|
|
3636
|
-
* Formats the retry history exactly as it is reported in thrown errors.
|
|
3637
|
-
*/
|
|
3638
|
-
function formatUnsupportedParameterAttemptHistory(attemptStack) {
|
|
3639
|
-
return attemptStack
|
|
3640
|
-
.map((attempt, index) => ` ${index + 1}. Model: ${attempt.modelName}` +
|
|
3641
|
-
(attempt.unsupportedParameter ? `, Stripped: ${attempt.unsupportedParameter}` : '') +
|
|
3642
|
-
`, Error: ${attempt.errorMessage}` +
|
|
3643
|
-
(attempt.stripped ? ' (stripped and retried)' : ''))
|
|
3644
|
-
.join('\n');
|
|
3645
|
-
}
|
|
3646
|
-
/**
|
|
3647
|
-
* Tracks unsupported-parameter retries for one OpenAI-compatible model call.
|
|
3817
|
+
* Builds cloned prompt payloads, OpenAI messages, and raw chat requests.
|
|
3648
3818
|
*
|
|
3649
|
-
* @private helper of `
|
|
3819
|
+
* @private helper of `callOpenAiCompatibleChatModel`
|
|
3650
3820
|
*/
|
|
3651
|
-
class
|
|
3652
|
-
constructor(isVerbose) {
|
|
3653
|
-
this.isVerbose = isVerbose;
|
|
3654
|
-
this.attemptStack = [];
|
|
3655
|
-
this.retriedUnsupportedParameters = new Set();
|
|
3656
|
-
}
|
|
3821
|
+
class OpenAiCompatibleChatPromptBuilder {
|
|
3657
3822
|
/**
|
|
3658
|
-
*
|
|
3823
|
+
* Creates a deep copy of the prompt while keeping attached files intact when structured clone is not available.
|
|
3659
3824
|
*/
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3825
|
+
clonePromptPreservingFiles(prompt) {
|
|
3826
|
+
const structuredCloneFn = this.getStructuredCloneFunction();
|
|
3827
|
+
if (typeof structuredCloneFn === 'function') {
|
|
3828
|
+
return structuredCloneFn(prompt);
|
|
3663
3829
|
}
|
|
3664
|
-
const
|
|
3665
|
-
if (
|
|
3666
|
-
|
|
3667
|
-
console.warn(colors.bgYellow('Warning'), 'Could not parse unsupported parameter from error:', options.error.message);
|
|
3668
|
-
}
|
|
3669
|
-
throw options.error;
|
|
3830
|
+
const clonedPrompt = JSON.parse(JSON.stringify(prompt));
|
|
3831
|
+
if (this.hasChatPromptFiles(prompt)) {
|
|
3832
|
+
clonedPrompt.files = prompt.files;
|
|
3670
3833
|
}
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3834
|
+
return clonedPrompt;
|
|
3835
|
+
}
|
|
3836
|
+
/**
|
|
3837
|
+
* Resolves OpenAI chat creation settings from model requirements and prompt format.
|
|
3838
|
+
*/
|
|
3839
|
+
createModelSettings(options) {
|
|
3840
|
+
const modelSettings = {
|
|
3841
|
+
model: options.modelName,
|
|
3842
|
+
max_tokens: options.currentModelRequirements.maxTokens,
|
|
3843
|
+
temperature: options.currentModelRequirements.temperature,
|
|
3844
|
+
};
|
|
3845
|
+
if (options.currentModelRequirements.responseFormat !== undefined) {
|
|
3846
|
+
modelSettings.response_format = options.currentModelRequirements.responseFormat;
|
|
3681
3847
|
}
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3848
|
+
else if (options.format === 'JSON') {
|
|
3849
|
+
modelSettings.response_format = {
|
|
3850
|
+
type: 'json_object',
|
|
3851
|
+
};
|
|
3685
3852
|
}
|
|
3686
|
-
|
|
3687
|
-
return removeUnsupportedModelRequirement(options.currentModelRequirements, unsupportedParameter);
|
|
3853
|
+
return modelSettings;
|
|
3688
3854
|
}
|
|
3689
3855
|
/**
|
|
3690
|
-
*
|
|
3856
|
+
* Creates the full OpenAI chat message list, including system, thread, and user content.
|
|
3691
3857
|
*/
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3858
|
+
async createMessages(options) {
|
|
3859
|
+
return [
|
|
3860
|
+
...(options.currentModelRequirements.systemMessage === undefined
|
|
3861
|
+
? []
|
|
3862
|
+
: [
|
|
3863
|
+
{
|
|
3864
|
+
role: 'system',
|
|
3865
|
+
content: options.currentModelRequirements.systemMessage,
|
|
3866
|
+
},
|
|
3867
|
+
]),
|
|
3868
|
+
...this.createThreadMessages(options.prompt),
|
|
3869
|
+
await this.createPromptUserMessage({
|
|
3870
|
+
prompt: options.prompt,
|
|
3871
|
+
rawPromptContent: options.rawPromptContent,
|
|
3872
|
+
}),
|
|
3873
|
+
];
|
|
3874
|
+
}
|
|
3875
|
+
/**
|
|
3876
|
+
* Creates one raw OpenAI chat request from the current conversation state.
|
|
3877
|
+
*/
|
|
3878
|
+
createRawRequest(options) {
|
|
3879
|
+
var _a;
|
|
3880
|
+
return {
|
|
3881
|
+
...options.modelSettings,
|
|
3882
|
+
messages: options.messages,
|
|
3883
|
+
user: (_a = options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
3884
|
+
tools: options.tools === undefined ? undefined : mapToolsToOpenAi(options.tools),
|
|
3885
|
+
};
|
|
3886
|
+
}
|
|
3887
|
+
/**
|
|
3888
|
+
* Provides access to the structured clone implementation when available.
|
|
3889
|
+
*/
|
|
3890
|
+
getStructuredCloneFunction() {
|
|
3891
|
+
return globalThis.structuredClone;
|
|
3892
|
+
}
|
|
3893
|
+
/**
|
|
3894
|
+
* Checks whether the prompt is a chat prompt that carries file attachments.
|
|
3895
|
+
*/
|
|
3896
|
+
hasChatPromptFiles(prompt) {
|
|
3897
|
+
return 'files' in prompt && Array.isArray(prompt.files);
|
|
3898
|
+
}
|
|
3899
|
+
/**
|
|
3900
|
+
* Converts the existing prompt thread into OpenAI chat messages.
|
|
3901
|
+
*/
|
|
3902
|
+
createThreadMessages(prompt) {
|
|
3903
|
+
if (!('thread' in prompt) || !Array.isArray(prompt.thread)) {
|
|
3904
|
+
return [];
|
|
3695
3905
|
}
|
|
3696
|
-
|
|
3906
|
+
return prompt.thread.map((message) => ({
|
|
3907
|
+
role: message.sender === 'assistant' ? 'assistant' : 'user',
|
|
3908
|
+
content: message.content,
|
|
3909
|
+
}));
|
|
3697
3910
|
}
|
|
3698
3911
|
/**
|
|
3699
|
-
*
|
|
3912
|
+
* Builds the final user message, including inline image attachments when present.
|
|
3700
3913
|
*/
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3914
|
+
async createPromptUserMessage(options) {
|
|
3915
|
+
if (!('files' in options.prompt) || !Array.isArray(options.prompt.files) || options.prompt.files.length === 0) {
|
|
3916
|
+
return {
|
|
3917
|
+
role: 'user',
|
|
3918
|
+
content: options.rawPromptContent,
|
|
3919
|
+
};
|
|
3920
|
+
}
|
|
3921
|
+
const filesContent = await Promise.all(options.prompt.files.map(async (file) => {
|
|
3922
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
3923
|
+
const base64 = Buffer.from(arrayBuffer).toString('base64');
|
|
3924
|
+
return {
|
|
3925
|
+
type: 'image_url',
|
|
3926
|
+
image_url: {
|
|
3927
|
+
url: `data:${file.type};base64,${base64}`,
|
|
3928
|
+
},
|
|
3929
|
+
};
|
|
3930
|
+
}));
|
|
3931
|
+
return {
|
|
3932
|
+
role: 'user',
|
|
3933
|
+
content: [
|
|
3934
|
+
{
|
|
3935
|
+
type: 'text',
|
|
3936
|
+
text: options.rawPromptContent,
|
|
3937
|
+
},
|
|
3938
|
+
...filesContent,
|
|
3939
|
+
],
|
|
3940
|
+
};
|
|
3941
|
+
}
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
/**
|
|
3945
|
+
* Marker property stored inside serialized tool-execution envelopes.
|
|
3946
|
+
*
|
|
3947
|
+
* @private internal tool-execution transport
|
|
3948
|
+
*/
|
|
3949
|
+
const TOOL_EXECUTION_ENVELOPE_MARKER = '__promptbookToolExecutionEnvelope';
|
|
3950
|
+
/**
|
|
3951
|
+
* Parses one serialized tool-execution envelope when present.
|
|
3952
|
+
*
|
|
3953
|
+
* @private internal tool-execution transport
|
|
3954
|
+
*/
|
|
3955
|
+
function parseToolExecutionEnvelope(rawValue) {
|
|
3956
|
+
if (typeof rawValue !== 'string') {
|
|
3957
|
+
return null;
|
|
3958
|
+
}
|
|
3959
|
+
try {
|
|
3960
|
+
const parsedValue = JSON.parse(rawValue);
|
|
3961
|
+
if (!parsedValue ||
|
|
3962
|
+
typeof parsedValue !== 'object' ||
|
|
3963
|
+
parsedValue[TOOL_EXECUTION_ENVELOPE_MARKER] !== true ||
|
|
3964
|
+
typeof parsedValue.assistantMessage !== 'string') {
|
|
3965
|
+
return null;
|
|
3966
|
+
}
|
|
3967
|
+
return {
|
|
3968
|
+
assistantMessage: parsedValue.assistantMessage,
|
|
3969
|
+
toolResult: parsedValue.toolResult,
|
|
3970
|
+
};
|
|
3971
|
+
}
|
|
3972
|
+
catch (_a) {
|
|
3973
|
+
return null;
|
|
3707
3974
|
}
|
|
3708
3975
|
}
|
|
3976
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3709
3977
|
|
|
3710
3978
|
/**
|
|
3711
|
-
*
|
|
3979
|
+
* Prompt parameter key used to pass hidden runtime context to tool execution.
|
|
3980
|
+
*
|
|
3981
|
+
* @private internal runtime wiring for commitment tools
|
|
3982
|
+
*/
|
|
3983
|
+
const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
|
|
3984
|
+
/**
|
|
3985
|
+
* Hidden argument key used to pass runtime context into individual tool calls.
|
|
3986
|
+
*
|
|
3987
|
+
* @private internal runtime wiring for commitment tools
|
|
3988
|
+
*/
|
|
3989
|
+
const TOOL_RUNTIME_CONTEXT_ARGUMENT = '__promptbookToolRuntimeContext';
|
|
3990
|
+
/**
|
|
3991
|
+
* Prompt parameter key used to pass a hidden tool-progress listener token into script execution.
|
|
3992
|
+
*
|
|
3993
|
+
* @private internal runtime wiring for commitment tools
|
|
3994
|
+
*/
|
|
3995
|
+
const TOOL_PROGRESS_TOKEN_PARAMETER = 'promptbookToolProgressToken';
|
|
3996
|
+
/**
|
|
3997
|
+
* Hidden argument key used to pass a tool-progress listener token into individual tool calls.
|
|
3998
|
+
*
|
|
3999
|
+
* @private internal runtime wiring for commitment tools
|
|
4000
|
+
*/
|
|
4001
|
+
const TOOL_PROGRESS_TOKEN_ARGUMENT = '__promptbookToolProgressToken';
|
|
4002
|
+
/**
|
|
4003
|
+
* Monotonic counter used for hidden progress-listener tokens.
|
|
4004
|
+
*
|
|
4005
|
+
* @private internal runtime wiring for commitment tools
|
|
4006
|
+
*/
|
|
4007
|
+
let toolCallProgressListenerCounter = 0;
|
|
4008
|
+
/**
|
|
4009
|
+
* Active tool-progress listeners keyed by hidden execution token.
|
|
4010
|
+
*
|
|
4011
|
+
* @private internal runtime wiring for commitment tools
|
|
4012
|
+
*/
|
|
4013
|
+
const toolCallProgressListeners = new Map();
|
|
4014
|
+
/**
|
|
4015
|
+
* Registers one in-memory listener that receives progress updates emitted by a running tool.
|
|
4016
|
+
*
|
|
4017
|
+
* The returned token is passed into script execution as a hidden argument so tool implementations
|
|
4018
|
+
* can stream progress without exposing extra parameters to the model.
|
|
4019
|
+
*
|
|
4020
|
+
* @param listener - Listener notified about tool progress.
|
|
4021
|
+
* @returns Hidden token used to route progress updates.
|
|
4022
|
+
*
|
|
4023
|
+
* @private internal runtime wiring for commitment tools
|
|
3712
4024
|
*/
|
|
3713
|
-
function
|
|
3714
|
-
|
|
4025
|
+
function registerToolCallProgressListener(listener) {
|
|
4026
|
+
toolCallProgressListenerCounter += 1;
|
|
4027
|
+
const token = `tool-progress:${Date.now()}:${toolCallProgressListenerCounter}`;
|
|
4028
|
+
toolCallProgressListeners.set(token, listener);
|
|
4029
|
+
return token;
|
|
3715
4030
|
}
|
|
3716
4031
|
/**
|
|
3717
|
-
*
|
|
4032
|
+
* Unregisters one in-memory progress listener.
|
|
4033
|
+
*
|
|
4034
|
+
* @param token - Token previously created by `registerToolCallProgressListener`.
|
|
4035
|
+
*
|
|
4036
|
+
* @private internal runtime wiring for commitment tools
|
|
3718
4037
|
*/
|
|
3719
|
-
function
|
|
3720
|
-
|
|
4038
|
+
function unregisterToolCallProgressListener(token) {
|
|
4039
|
+
toolCallProgressListeners.delete(token);
|
|
3721
4040
|
}
|
|
4041
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
4042
|
+
|
|
3722
4043
|
/**
|
|
3723
|
-
*
|
|
4044
|
+
* This error indicates problems parsing the format value
|
|
4045
|
+
*
|
|
4046
|
+
* For example, when the format value is not a valid JSON or CSV
|
|
4047
|
+
* This is not thrown directly but in extended classes
|
|
4048
|
+
*
|
|
4049
|
+
* @public exported from `@promptbook/core`
|
|
3724
4050
|
*/
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
if (hasChatPromptFiles(prompt)) {
|
|
3732
|
-
clonedPrompt.files = prompt.files;
|
|
4051
|
+
class AbstractFormatError extends Error {
|
|
4052
|
+
// Note: To allow instanceof do not put here error `name`
|
|
4053
|
+
// public readonly name = 'AbstractFormatError';
|
|
4054
|
+
constructor(message) {
|
|
4055
|
+
super(message);
|
|
4056
|
+
Object.setPrototypeOf(this, AbstractFormatError.prototype);
|
|
3733
4057
|
}
|
|
3734
|
-
return clonedPrompt;
|
|
3735
4058
|
}
|
|
4059
|
+
|
|
3736
4060
|
/**
|
|
3737
|
-
*
|
|
4061
|
+
* This error indicates problem with parsing of CSV
|
|
4062
|
+
*
|
|
4063
|
+
* @public exported from `@promptbook/core`
|
|
3738
4064
|
*/
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
message: options.message,
|
|
3746
|
-
payload: options.payload,
|
|
3747
|
-
};
|
|
4065
|
+
class CsvFormatError extends AbstractFormatError {
|
|
4066
|
+
constructor(message) {
|
|
4067
|
+
super(message);
|
|
4068
|
+
this.name = 'CsvFormatError';
|
|
4069
|
+
Object.setPrototypeOf(this, CsvFormatError.prototype);
|
|
4070
|
+
}
|
|
3748
4071
|
}
|
|
4072
|
+
|
|
3749
4073
|
/**
|
|
3750
|
-
*
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
4074
|
+
* AuthenticationError is thrown from login function which is dependency of remote server
|
|
4075
|
+
*
|
|
4076
|
+
* @public exported from `@promptbook/core`
|
|
4077
|
+
*/
|
|
4078
|
+
class AuthenticationError extends Error {
|
|
4079
|
+
constructor(message) {
|
|
4080
|
+
super(message);
|
|
4081
|
+
this.name = 'AuthenticationError';
|
|
4082
|
+
Object.setPrototypeOf(this, AuthenticationError.prototype);
|
|
4083
|
+
}
|
|
3759
4084
|
}
|
|
4085
|
+
|
|
3760
4086
|
/**
|
|
3761
|
-
*
|
|
4087
|
+
* This error indicates that the pipeline collection cannot be properly loaded
|
|
4088
|
+
*
|
|
4089
|
+
* @public exported from `@promptbook/core`
|
|
3762
4090
|
*/
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
return 'ERROR';
|
|
4091
|
+
class CollectionError extends Error {
|
|
4092
|
+
constructor(message) {
|
|
4093
|
+
super(message);
|
|
4094
|
+
this.name = 'CollectionError';
|
|
4095
|
+
Object.setPrototypeOf(this, CollectionError.prototype);
|
|
3769
4096
|
}
|
|
3770
|
-
return 'COMPLETE';
|
|
3771
4097
|
}
|
|
4098
|
+
|
|
3772
4099
|
/**
|
|
3773
|
-
*
|
|
4100
|
+
* Signals that the requested operation could not be completed because the target already exists.
|
|
4101
|
+
*
|
|
4102
|
+
* @public exported from `@promptbook/core`
|
|
3774
4103
|
*/
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
charactersCount: uncertainNumber(0),
|
|
3782
|
-
wordsCount: uncertainNumber(0),
|
|
3783
|
-
sentencesCount: uncertainNumber(0),
|
|
3784
|
-
linesCount: uncertainNumber(0),
|
|
3785
|
-
paragraphsCount: uncertainNumber(0),
|
|
3786
|
-
pagesCount: uncertainNumber(0),
|
|
3787
|
-
},
|
|
3788
|
-
output: {
|
|
3789
|
-
tokensCount: uncertainNumber(0),
|
|
3790
|
-
charactersCount: uncertainNumber(0),
|
|
3791
|
-
wordsCount: uncertainNumber(0),
|
|
3792
|
-
sentencesCount: uncertainNumber(0),
|
|
3793
|
-
linesCount: uncertainNumber(0),
|
|
3794
|
-
paragraphsCount: uncertainNumber(0),
|
|
3795
|
-
pagesCount: uncertainNumber(0),
|
|
3796
|
-
},
|
|
3797
|
-
};
|
|
4104
|
+
class ConflictError extends Error {
|
|
4105
|
+
constructor(message) {
|
|
4106
|
+
super(message);
|
|
4107
|
+
this.name = 'ConflictError';
|
|
4108
|
+
Object.setPrototypeOf(this, ConflictError.prototype);
|
|
4109
|
+
}
|
|
3798
4110
|
}
|
|
4111
|
+
|
|
3799
4112
|
/**
|
|
3800
|
-
*
|
|
4113
|
+
* This error indicates error from the database
|
|
3801
4114
|
*
|
|
3802
|
-
* @
|
|
4115
|
+
* @public exported from `@promptbook/core`
|
|
3803
4116
|
*/
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
4117
|
+
class DatabaseError extends Error {
|
|
4118
|
+
constructor(message) {
|
|
4119
|
+
super(message);
|
|
4120
|
+
this.name = 'DatabaseError';
|
|
4121
|
+
Object.setPrototypeOf(this, DatabaseError.prototype);
|
|
4122
|
+
}
|
|
3808
4123
|
}
|
|
4124
|
+
// TODO: [🐱🚀] Explain that NotFoundError ([🐱🚀] and other specific errors) has priority over DatabaseError in some contexts
|
|
4125
|
+
|
|
3809
4126
|
/**
|
|
3810
|
-
*
|
|
4127
|
+
* This error type indicates that you try to use a feature that is not available in the current environment
|
|
4128
|
+
*
|
|
4129
|
+
* @public exported from `@promptbook/core`
|
|
3811
4130
|
*/
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
if (currentModelRequirements.modelVariant !== 'CHAT') {
|
|
3818
|
-
throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
|
|
3819
|
-
}
|
|
3820
|
-
const modelName = currentModelRequirements.modelName || options.getDefaultChatModel().modelName;
|
|
3821
|
-
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
3822
|
-
const modelSettings = createChatModelSettings({
|
|
3823
|
-
currentModelRequirements,
|
|
3824
|
-
format,
|
|
3825
|
-
modelName,
|
|
3826
|
-
});
|
|
3827
|
-
const messages = await createChatMessages({
|
|
3828
|
-
prompt,
|
|
3829
|
-
currentModelRequirements,
|
|
3830
|
-
rawPromptContent,
|
|
3831
|
-
});
|
|
3832
|
-
const client = await options.getClient();
|
|
3833
|
-
let totalUsage = createEmptyUsage();
|
|
3834
|
-
const toolCalls = [];
|
|
3835
|
-
const start = $getCurrentDate();
|
|
3836
|
-
const tools = 'tools' in prompt && Array.isArray(prompt.tools) ? prompt.tools : currentModelRequirements.tools;
|
|
3837
|
-
let isToolCallingLoopActive = true;
|
|
3838
|
-
while (isToolCallingLoopActive) {
|
|
3839
|
-
const rawRequest = createChatRawRequest(options, {
|
|
3840
|
-
modelSettings,
|
|
3841
|
-
messages,
|
|
3842
|
-
tools,
|
|
3843
|
-
});
|
|
3844
|
-
try {
|
|
3845
|
-
const turnResult = await executeChatTurn(options, {
|
|
3846
|
-
client,
|
|
3847
|
-
rawRequest,
|
|
3848
|
-
promptContent: content || '',
|
|
3849
|
-
});
|
|
3850
|
-
messages.push(turnResult.responseMessage);
|
|
3851
|
-
totalUsage = addUsage(totalUsage, turnResult.usage);
|
|
3852
|
-
if (turnResult.responseMessage.tool_calls && turnResult.responseMessage.tool_calls.length > 0) {
|
|
3853
|
-
await handleChatToolCalls(options, {
|
|
3854
|
-
prompt,
|
|
3855
|
-
start,
|
|
3856
|
-
turnComplete: turnResult.turnComplete,
|
|
3857
|
-
rawPromptContent,
|
|
3858
|
-
responseMessage: turnResult.responseMessage,
|
|
3859
|
-
rawRequest,
|
|
3860
|
-
rawResponse: turnResult.rawResponse,
|
|
3861
|
-
modelName,
|
|
3862
|
-
usage: totalUsage,
|
|
3863
|
-
toolCalls,
|
|
3864
|
-
messages,
|
|
3865
|
-
onProgress: options.onProgress,
|
|
3866
|
-
});
|
|
3867
|
-
continue;
|
|
3868
|
-
}
|
|
3869
|
-
isToolCallingLoopActive = false;
|
|
3870
|
-
return createChatPromptResult(options, {
|
|
3871
|
-
responseMessage: turnResult.responseMessage,
|
|
3872
|
-
rawPromptContent,
|
|
3873
|
-
rawRequest,
|
|
3874
|
-
rawResponse: turnResult.rawResponse,
|
|
3875
|
-
modelName,
|
|
3876
|
-
start,
|
|
3877
|
-
complete: $getCurrentDate(),
|
|
3878
|
-
usage: totalUsage,
|
|
3879
|
-
toolCalls,
|
|
3880
|
-
});
|
|
3881
|
-
}
|
|
3882
|
-
catch (error) {
|
|
3883
|
-
isToolCallingLoopActive = false;
|
|
3884
|
-
assertsError(error);
|
|
3885
|
-
return callChatModelWithRetry(options, prompt, unsupportedParameterRetrier.resolveRetryOrThrow({
|
|
3886
|
-
error,
|
|
3887
|
-
modelName,
|
|
3888
|
-
currentModelRequirements,
|
|
3889
|
-
}), unsupportedParameterRetrier);
|
|
3890
|
-
}
|
|
4131
|
+
class EnvironmentMismatchError extends Error {
|
|
4132
|
+
constructor(message) {
|
|
4133
|
+
super(message);
|
|
4134
|
+
this.name = 'EnvironmentMismatchError';
|
|
4135
|
+
Object.setPrototypeOf(this, EnvironmentMismatchError.prototype);
|
|
3891
4136
|
}
|
|
3892
|
-
throw new PipelineExecutionError(`Tool calling loop did not return a result from ${options.title}`);
|
|
3893
4137
|
}
|
|
4138
|
+
|
|
3894
4139
|
/**
|
|
3895
|
-
*
|
|
4140
|
+
* This error occurs when some expectation is not met in the execution of the pipeline
|
|
4141
|
+
*
|
|
4142
|
+
* Note: Do not throw this error, its reserved for `checkExpectations` and `createPipelineExecutor` and public ONLY to be serializable through remote server
|
|
4143
|
+
* Note: Always thrown in `checkExpectations` and catched in `createPipelineExecutor` and rethrown as `PipelineExecutionError`
|
|
4144
|
+
* Note: This is a kindof subtype of PipelineExecutionError
|
|
4145
|
+
*
|
|
4146
|
+
* @public exported from `@promptbook/core`
|
|
3896
4147
|
*/
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
};
|
|
3903
|
-
if (options.currentModelRequirements.responseFormat !== undefined) {
|
|
3904
|
-
modelSettings.response_format = options.currentModelRequirements.responseFormat;
|
|
3905
|
-
}
|
|
3906
|
-
else if (options.format === 'JSON') {
|
|
3907
|
-
modelSettings.response_format = {
|
|
3908
|
-
type: 'json_object',
|
|
3909
|
-
};
|
|
4148
|
+
class ExpectError extends Error {
|
|
4149
|
+
constructor(message) {
|
|
4150
|
+
super(message);
|
|
4151
|
+
this.name = 'ExpectError';
|
|
4152
|
+
Object.setPrototypeOf(this, ExpectError.prototype);
|
|
3910
4153
|
}
|
|
3911
|
-
return modelSettings;
|
|
3912
4154
|
}
|
|
4155
|
+
|
|
3913
4156
|
/**
|
|
3914
|
-
*
|
|
4157
|
+
* This error indicates that the promptbook can not retrieve knowledge from external sources
|
|
4158
|
+
*
|
|
4159
|
+
* @public exported from `@promptbook/core`
|
|
3915
4160
|
*/
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
role: 'system',
|
|
3923
|
-
content: options.currentModelRequirements.systemMessage,
|
|
3924
|
-
},
|
|
3925
|
-
]),
|
|
3926
|
-
...createChatThreadMessages(options.prompt),
|
|
3927
|
-
await createChatPromptUserMessage({
|
|
3928
|
-
prompt: options.prompt,
|
|
3929
|
-
rawPromptContent: options.rawPromptContent,
|
|
3930
|
-
}),
|
|
3931
|
-
];
|
|
4161
|
+
class KnowledgeScrapeError extends Error {
|
|
4162
|
+
constructor(message) {
|
|
4163
|
+
super(message);
|
|
4164
|
+
this.name = 'KnowledgeScrapeError';
|
|
4165
|
+
Object.setPrototypeOf(this, KnowledgeScrapeError.prototype);
|
|
4166
|
+
}
|
|
3932
4167
|
}
|
|
4168
|
+
|
|
3933
4169
|
/**
|
|
3934
|
-
*
|
|
4170
|
+
* This error type indicates that some tools are missing for pipeline execution or preparation
|
|
4171
|
+
*
|
|
4172
|
+
* @public exported from `@promptbook/core`
|
|
3935
4173
|
*/
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
4174
|
+
class MissingToolsError extends Error {
|
|
4175
|
+
constructor(message) {
|
|
4176
|
+
super(spaceTrim$1((block) => `
|
|
4177
|
+
${block(message)}
|
|
4178
|
+
|
|
4179
|
+
Note: You have probably forgot to provide some tools for pipeline execution or preparation
|
|
4180
|
+
|
|
4181
|
+
`));
|
|
4182
|
+
this.name = 'MissingToolsError';
|
|
4183
|
+
Object.setPrototypeOf(this, MissingToolsError.prototype);
|
|
3939
4184
|
}
|
|
3940
|
-
return prompt.thread.map((message) => ({
|
|
3941
|
-
role: message.sender === 'assistant' ? 'assistant' : 'user',
|
|
3942
|
-
content: message.content,
|
|
3943
|
-
}));
|
|
3944
4185
|
}
|
|
4186
|
+
|
|
3945
4187
|
/**
|
|
3946
|
-
*
|
|
4188
|
+
* This error indicates that promptbook operation is not allowed
|
|
4189
|
+
*
|
|
4190
|
+
* @public exported from `@promptbook/core`
|
|
3947
4191
|
*/
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
};
|
|
4192
|
+
class NotAllowed extends Error {
|
|
4193
|
+
constructor(message) {
|
|
4194
|
+
super(message);
|
|
4195
|
+
this.name = 'NotAllowed';
|
|
4196
|
+
Object.setPrototypeOf(this, NotAllowed.prototype);
|
|
3954
4197
|
}
|
|
3955
|
-
const filesContent = await Promise.all(options.prompt.files.map(async (file) => {
|
|
3956
|
-
const arrayBuffer = await file.arrayBuffer();
|
|
3957
|
-
const base64 = Buffer.from(arrayBuffer).toString('base64');
|
|
3958
|
-
return {
|
|
3959
|
-
type: 'image_url',
|
|
3960
|
-
image_url: {
|
|
3961
|
-
url: `data:${file.type};base64,${base64}`,
|
|
3962
|
-
},
|
|
3963
|
-
};
|
|
3964
|
-
}));
|
|
3965
|
-
return {
|
|
3966
|
-
role: 'user',
|
|
3967
|
-
content: [
|
|
3968
|
-
{
|
|
3969
|
-
type: 'text',
|
|
3970
|
-
text: options.rawPromptContent,
|
|
3971
|
-
},
|
|
3972
|
-
...filesContent,
|
|
3973
|
-
],
|
|
3974
|
-
};
|
|
3975
4198
|
}
|
|
4199
|
+
|
|
3976
4200
|
/**
|
|
3977
|
-
*
|
|
4201
|
+
* This error indicates that promptbook not found in the collection
|
|
4202
|
+
*
|
|
4203
|
+
* @public exported from `@promptbook/core`
|
|
3978
4204
|
*/
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
tools: options.tools === undefined ? undefined : mapToolsToOpenAi(options.tools),
|
|
3986
|
-
};
|
|
4205
|
+
class NotFoundError extends Error {
|
|
4206
|
+
constructor(message) {
|
|
4207
|
+
super(message);
|
|
4208
|
+
this.name = 'NotFoundError';
|
|
4209
|
+
Object.setPrototypeOf(this, NotFoundError.prototype);
|
|
4210
|
+
}
|
|
3987
4211
|
}
|
|
4212
|
+
|
|
3988
4213
|
/**
|
|
3989
|
-
*
|
|
4214
|
+
* This error type indicates that some part of the code is not implemented yet
|
|
4215
|
+
*
|
|
4216
|
+
* @public exported from `@promptbook/core`
|
|
3990
4217
|
*/
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4218
|
+
class NotYetImplementedError extends Error {
|
|
4219
|
+
constructor(message) {
|
|
4220
|
+
super(spaceTrim$1((block) => `
|
|
4221
|
+
${block(message)}
|
|
4222
|
+
|
|
4223
|
+
Note: This feature is not implemented yet but it will be soon.
|
|
4224
|
+
|
|
4225
|
+
If you want speed up the implementation or just read more, look here:
|
|
4226
|
+
https://github.com/webgptorg/promptbook
|
|
4227
|
+
|
|
4228
|
+
Or contact us on pavol@ptbk.io
|
|
4229
|
+
|
|
4230
|
+
`));
|
|
4231
|
+
this.name = 'NotYetImplementedError';
|
|
4232
|
+
Object.setPrototypeOf(this, NotYetImplementedError.prototype);
|
|
4003
4233
|
}
|
|
4004
|
-
const responseMessage = rawResponse.choices[0].message;
|
|
4005
|
-
const duration = uncertainNumber((new Date(turnComplete).getTime() - new Date(turnStart).getTime()) / 1000);
|
|
4006
|
-
const usage = openAiOptions.computeUsage(options.promptContent, responseMessage.content || '', rawResponse, duration);
|
|
4007
|
-
return {
|
|
4008
|
-
rawResponse,
|
|
4009
|
-
responseMessage,
|
|
4010
|
-
turnComplete,
|
|
4011
|
-
usage,
|
|
4012
|
-
};
|
|
4013
4234
|
}
|
|
4235
|
+
|
|
4014
4236
|
/**
|
|
4015
|
-
*
|
|
4237
|
+
* This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
|
|
4238
|
+
*
|
|
4239
|
+
* @public exported from `@promptbook/core`
|
|
4016
4240
|
*/
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
toolCallStartedAt.set(toolCall.id, calledAt);
|
|
4024
|
-
}
|
|
4025
|
-
return createPendingChatToolCall({
|
|
4026
|
-
toolCall,
|
|
4027
|
-
functionName: String(toolCall.function.name),
|
|
4028
|
-
functionArguments: toolCall.function.arguments,
|
|
4029
|
-
calledAt,
|
|
4030
|
-
});
|
|
4031
|
-
});
|
|
4032
|
-
emitChatProgress({
|
|
4033
|
-
start: options.start,
|
|
4034
|
-
complete: options.turnComplete,
|
|
4035
|
-
rawPromptContent: options.rawPromptContent,
|
|
4036
|
-
onProgress: options.onProgress,
|
|
4037
|
-
content: options.responseMessage.content || '',
|
|
4038
|
-
modelName: options.rawResponse.model || options.modelName,
|
|
4039
|
-
usage: options.usage,
|
|
4040
|
-
rawRequest: options.rawRequest,
|
|
4041
|
-
rawResponse: options.rawResponse,
|
|
4042
|
-
toolCalls: pendingToolCalls,
|
|
4043
|
-
});
|
|
4044
|
-
await forEachAsync(requestedToolCalls, {}, async (toolCall) => {
|
|
4045
|
-
const completedToolCall = await executeChatToolCall(openAiOptions, {
|
|
4046
|
-
prompt: options.prompt,
|
|
4047
|
-
toolCall,
|
|
4048
|
-
toolCallStartedAt,
|
|
4049
|
-
responseContent: options.responseMessage.content || '',
|
|
4050
|
-
start: options.start,
|
|
4051
|
-
rawPromptContent: options.rawPromptContent,
|
|
4052
|
-
rawRequest: options.rawRequest,
|
|
4053
|
-
rawResponse: options.rawResponse,
|
|
4054
|
-
modelName: options.rawResponse.model || options.modelName,
|
|
4055
|
-
usage: options.usage,
|
|
4056
|
-
messages: options.messages,
|
|
4057
|
-
onProgress: options.onProgress,
|
|
4058
|
-
});
|
|
4059
|
-
options.toolCalls.push(completedToolCall);
|
|
4060
|
-
});
|
|
4241
|
+
class ParseError extends Error {
|
|
4242
|
+
constructor(message) {
|
|
4243
|
+
super(message);
|
|
4244
|
+
this.name = 'ParseError';
|
|
4245
|
+
Object.setPrototypeOf(this, ParseError.prototype);
|
|
4246
|
+
}
|
|
4061
4247
|
}
|
|
4248
|
+
// TODO: Maybe split `ParseError` and `ApplyError`
|
|
4249
|
+
|
|
4062
4250
|
/**
|
|
4063
|
-
*
|
|
4251
|
+
* This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
|
|
4252
|
+
*
|
|
4253
|
+
* @public exported from `@promptbook/core`
|
|
4064
4254
|
*/
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
createdAt: options.calledAt,
|
|
4072
|
-
state: 'PENDING',
|
|
4073
|
-
logs: [
|
|
4074
|
-
createToolCallLogEntry({
|
|
4075
|
-
kind: 'request',
|
|
4076
|
-
title: 'Request prepared',
|
|
4077
|
-
message: `Prepared ${options.functionName} request.`,
|
|
4078
|
-
payload: {
|
|
4079
|
-
arguments: options.functionArguments,
|
|
4080
|
-
},
|
|
4081
|
-
}),
|
|
4082
|
-
],
|
|
4083
|
-
};
|
|
4084
|
-
}
|
|
4085
|
-
/**
|
|
4086
|
-
* Executes one tool call requested by the chat response and appends the tool message.
|
|
4087
|
-
*/
|
|
4088
|
-
async function executeChatToolCall(openAiOptions, options) {
|
|
4089
|
-
const functionName = String(options.toolCall.function.name);
|
|
4090
|
-
const functionArguments = options.toolCall.function.arguments;
|
|
4091
|
-
const calledAt = options.toolCall.id
|
|
4092
|
-
? options.toolCallStartedAt.get(options.toolCall.id) || $getCurrentDate()
|
|
4093
|
-
: $getCurrentDate();
|
|
4094
|
-
const pendingToolCall = createPendingChatToolCall({
|
|
4095
|
-
toolCall: options.toolCall,
|
|
4096
|
-
functionName,
|
|
4097
|
-
functionArguments,
|
|
4098
|
-
calledAt,
|
|
4099
|
-
});
|
|
4100
|
-
const executionResult = await executeChatFunctionTool(openAiOptions, {
|
|
4101
|
-
prompt: options.prompt,
|
|
4102
|
-
start: options.start,
|
|
4103
|
-
rawPromptContent: options.rawPromptContent,
|
|
4104
|
-
onProgress: options.onProgress,
|
|
4105
|
-
content: options.responseContent,
|
|
4106
|
-
rawRequest: options.rawRequest,
|
|
4107
|
-
rawResponse: options.rawResponse,
|
|
4108
|
-
modelName: options.modelName,
|
|
4109
|
-
usage: options.usage,
|
|
4110
|
-
functionName,
|
|
4111
|
-
functionArguments,
|
|
4112
|
-
pendingToolCall,
|
|
4113
|
-
});
|
|
4114
|
-
options.messages.push({
|
|
4115
|
-
role: 'tool',
|
|
4116
|
-
tool_call_id: options.toolCall.id,
|
|
4117
|
-
content: executionResult.assistantVisibleFunctionResponse,
|
|
4118
|
-
});
|
|
4119
|
-
const completedToolCall = createCompletedChatToolCall({
|
|
4120
|
-
toolCall: options.toolCall,
|
|
4121
|
-
functionName,
|
|
4122
|
-
calledAt,
|
|
4123
|
-
currentToolCallSnapshot: executionResult.currentToolCallSnapshot,
|
|
4124
|
-
toolResult: executionResult.toolResult,
|
|
4125
|
-
errors: executionResult.errors,
|
|
4126
|
-
});
|
|
4127
|
-
emitChatProgress({
|
|
4128
|
-
start: options.start,
|
|
4129
|
-
rawPromptContent: options.rawPromptContent,
|
|
4130
|
-
onProgress: options.onProgress,
|
|
4131
|
-
content: options.responseContent,
|
|
4132
|
-
modelName: options.modelName,
|
|
4133
|
-
usage: options.usage,
|
|
4134
|
-
rawRequest: options.rawRequest,
|
|
4135
|
-
rawResponse: options.rawResponse,
|
|
4136
|
-
toolCalls: [completedToolCall],
|
|
4137
|
-
});
|
|
4138
|
-
return completedToolCall;
|
|
4255
|
+
class PipelineLogicError extends Error {
|
|
4256
|
+
constructor(message) {
|
|
4257
|
+
super(message);
|
|
4258
|
+
this.name = 'PipelineLogicError';
|
|
4259
|
+
Object.setPrototypeOf(this, PipelineLogicError.prototype);
|
|
4260
|
+
}
|
|
4139
4261
|
}
|
|
4262
|
+
|
|
4140
4263
|
/**
|
|
4141
|
-
*
|
|
4264
|
+
* This error indicates errors in referencing promptbooks between each other
|
|
4265
|
+
*
|
|
4266
|
+
* @public exported from `@promptbook/core`
|
|
4142
4267
|
*/
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4268
|
+
class PipelineUrlError extends Error {
|
|
4269
|
+
constructor(message) {
|
|
4270
|
+
super(message);
|
|
4271
|
+
this.name = 'PipelineUrlError';
|
|
4272
|
+
Object.setPrototypeOf(this, PipelineUrlError.prototype);
|
|
4147
4273
|
}
|
|
4148
|
-
return Array.isArray(executionTools.script) ? executionTools.script : [executionTools.script];
|
|
4149
4274
|
}
|
|
4275
|
+
|
|
4150
4276
|
/**
|
|
4151
|
-
*
|
|
4277
|
+
* Error thrown when a fetch request fails
|
|
4278
|
+
*
|
|
4279
|
+
* @public exported from `@promptbook/core`
|
|
4152
4280
|
*/
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
let errors;
|
|
4159
|
-
let currentToolCallSnapshot = options.pendingToolCall;
|
|
4160
|
-
try {
|
|
4161
|
-
const scriptTool = scriptTools[0];
|
|
4162
|
-
const progressListenerToken = registerToolCallProgressListener((update) => {
|
|
4163
|
-
currentToolCallSnapshot = applyToolCallProgressUpdate(currentToolCallSnapshot, update);
|
|
4164
|
-
emitChatProgress({
|
|
4165
|
-
start: options.start,
|
|
4166
|
-
rawPromptContent: options.rawPromptContent,
|
|
4167
|
-
onProgress: options.onProgress,
|
|
4168
|
-
content: options.content,
|
|
4169
|
-
modelName: options.modelName,
|
|
4170
|
-
usage: options.usage,
|
|
4171
|
-
rawRequest: options.rawRequest,
|
|
4172
|
-
rawResponse: options.rawResponse,
|
|
4173
|
-
toolCalls: [currentToolCallSnapshot],
|
|
4174
|
-
});
|
|
4175
|
-
});
|
|
4176
|
-
try {
|
|
4177
|
-
functionResponse = await scriptTool.execute({
|
|
4178
|
-
scriptLanguage: 'javascript',
|
|
4179
|
-
script: buildToolInvocationScript({
|
|
4180
|
-
functionName: options.functionName,
|
|
4181
|
-
functionArgsExpression: options.functionArguments,
|
|
4182
|
-
}),
|
|
4183
|
-
parameters: {
|
|
4184
|
-
...options.prompt.parameters,
|
|
4185
|
-
[TOOL_PROGRESS_TOKEN_PARAMETER]: progressListenerToken,
|
|
4186
|
-
},
|
|
4187
|
-
});
|
|
4188
|
-
}
|
|
4189
|
-
finally {
|
|
4190
|
-
unregisterToolCallProgressListener(progressListenerToken);
|
|
4191
|
-
}
|
|
4192
|
-
const toolExecutionEnvelope = parseToolExecutionEnvelope(functionResponse);
|
|
4193
|
-
assistantVisibleFunctionResponse = (toolExecutionEnvelope === null || toolExecutionEnvelope === void 0 ? void 0 : toolExecutionEnvelope.assistantMessage) || functionResponse;
|
|
4194
|
-
toolResult =
|
|
4195
|
-
toolExecutionEnvelope !== null && toolExecutionEnvelope !== undefined
|
|
4196
|
-
? toolExecutionEnvelope.toolResult
|
|
4197
|
-
: functionResponse;
|
|
4198
|
-
}
|
|
4199
|
-
catch (error) {
|
|
4200
|
-
assertsError(error);
|
|
4201
|
-
functionResponse = `Error: ${error.message}`;
|
|
4202
|
-
assistantVisibleFunctionResponse = functionResponse;
|
|
4203
|
-
toolResult = functionResponse;
|
|
4204
|
-
errors = [serializeError(error)];
|
|
4281
|
+
class PromptbookFetchError extends Error {
|
|
4282
|
+
constructor(message) {
|
|
4283
|
+
super(message);
|
|
4284
|
+
this.name = 'PromptbookFetchError';
|
|
4285
|
+
Object.setPrototypeOf(this, PromptbookFetchError.prototype);
|
|
4205
4286
|
}
|
|
4206
|
-
return {
|
|
4207
|
-
assistantVisibleFunctionResponse,
|
|
4208
|
-
currentToolCallSnapshot,
|
|
4209
|
-
errors,
|
|
4210
|
-
toolResult,
|
|
4211
|
-
};
|
|
4212
4287
|
}
|
|
4288
|
+
|
|
4213
4289
|
/**
|
|
4214
|
-
*
|
|
4290
|
+
* Index of all custom errors
|
|
4291
|
+
*
|
|
4292
|
+
* @public exported from `@promptbook/core`
|
|
4215
4293
|
*/
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
}
|
|
4294
|
+
const PROMPTBOOK_ERRORS = {
|
|
4295
|
+
AbstractFormatError,
|
|
4296
|
+
CsvFormatError,
|
|
4297
|
+
CollectionError,
|
|
4298
|
+
EnvironmentMismatchError,
|
|
4299
|
+
ExpectError,
|
|
4300
|
+
KnowledgeScrapeError,
|
|
4301
|
+
LimitReachedError,
|
|
4302
|
+
MissingToolsError,
|
|
4303
|
+
NotFoundError,
|
|
4304
|
+
NotYetImplementedError,
|
|
4305
|
+
ParseError,
|
|
4306
|
+
PipelineExecutionError,
|
|
4307
|
+
PipelineLogicError,
|
|
4308
|
+
PipelineUrlError,
|
|
4309
|
+
AuthenticationError,
|
|
4310
|
+
PromptbookFetchError,
|
|
4311
|
+
UnexpectedError,
|
|
4312
|
+
WrappedError,
|
|
4313
|
+
NotAllowed,
|
|
4314
|
+
DatabaseError,
|
|
4315
|
+
ConflictError,
|
|
4316
|
+
// TODO: [🪑]> VersionMismatchError,
|
|
4317
|
+
};
|
|
4241
4318
|
/**
|
|
4242
|
-
*
|
|
4319
|
+
* Index of all javascript errors
|
|
4320
|
+
*
|
|
4321
|
+
* @private for internal usage
|
|
4243
4322
|
*/
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4323
|
+
const COMMON_JAVASCRIPT_ERRORS = {
|
|
4324
|
+
Error,
|
|
4325
|
+
EvalError,
|
|
4326
|
+
RangeError,
|
|
4327
|
+
ReferenceError,
|
|
4328
|
+
SyntaxError,
|
|
4329
|
+
TypeError,
|
|
4330
|
+
URIError,
|
|
4331
|
+
AggregateError,
|
|
4332
|
+
/*
|
|
4333
|
+
Note: Not widely supported
|
|
4334
|
+
> InternalError,
|
|
4335
|
+
> ModuleError,
|
|
4336
|
+
> HeapError,
|
|
4337
|
+
> WebAssemblyCompileError,
|
|
4338
|
+
> WebAssemblyRuntimeError,
|
|
4339
|
+
*/
|
|
4340
|
+
};
|
|
4259
4341
|
/**
|
|
4260
|
-
*
|
|
4342
|
+
* Index of all errors
|
|
4343
|
+
*
|
|
4344
|
+
* @private for internal usage
|
|
4261
4345
|
*/
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
return exportJson({
|
|
4268
|
-
name: 'promptResult',
|
|
4269
|
-
message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
|
|
4270
|
-
order: [],
|
|
4271
|
-
value: {
|
|
4272
|
-
content: resultContent,
|
|
4273
|
-
modelName: options.rawResponse.model || options.modelName,
|
|
4274
|
-
timing: {
|
|
4275
|
-
start: options.start,
|
|
4276
|
-
complete: options.complete,
|
|
4277
|
-
},
|
|
4278
|
-
usage: options.usage,
|
|
4279
|
-
toolCalls: options.toolCalls,
|
|
4280
|
-
rawPromptContent: options.rawPromptContent,
|
|
4281
|
-
rawRequest: options.rawRequest,
|
|
4282
|
-
rawResponse: options.rawResponse,
|
|
4283
|
-
},
|
|
4284
|
-
});
|
|
4285
|
-
}
|
|
4346
|
+
const ALL_ERRORS = {
|
|
4347
|
+
...PROMPTBOOK_ERRORS,
|
|
4348
|
+
...COMMON_JAVASCRIPT_ERRORS,
|
|
4349
|
+
};
|
|
4350
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
4286
4351
|
|
|
4287
4352
|
/**
|
|
4288
|
-
*
|
|
4353
|
+
* Serializes an error into a [🚉] JSON-serializable object
|
|
4354
|
+
*
|
|
4355
|
+
* @public exported from `@promptbook/utils`
|
|
4289
4356
|
*/
|
|
4290
|
-
function
|
|
4291
|
-
|
|
4357
|
+
function serializeError(error) {
|
|
4358
|
+
const { name, message, stack } = error;
|
|
4359
|
+
const { id } = error;
|
|
4360
|
+
if (!Object.keys(ALL_ERRORS).includes(name)) {
|
|
4361
|
+
console.error(spaceTrim$1((block) => `
|
|
4362
|
+
|
|
4363
|
+
Cannot serialize error with name "${name}"
|
|
4364
|
+
|
|
4365
|
+
Authors of Promptbook probably forgot to add this error into the list of errors:
|
|
4366
|
+
https://github.com/webgptorg/promptbook/blob/main/src/errors/0-index.ts
|
|
4367
|
+
|
|
4368
|
+
|
|
4369
|
+
${block(stack || message)}
|
|
4370
|
+
|
|
4371
|
+
`));
|
|
4372
|
+
}
|
|
4373
|
+
return {
|
|
4374
|
+
name: name,
|
|
4375
|
+
message,
|
|
4376
|
+
stack,
|
|
4377
|
+
id, // Include id in the serialized object
|
|
4378
|
+
};
|
|
4292
4379
|
}
|
|
4380
|
+
|
|
4293
4381
|
/**
|
|
4294
|
-
*
|
|
4382
|
+
* Async version of Array.forEach
|
|
4295
4383
|
*
|
|
4296
|
-
* @
|
|
4384
|
+
* @param array - Array to iterate over
|
|
4385
|
+
* @param options - Options for the function
|
|
4386
|
+
* @param callbackfunction - Function to call for each item
|
|
4387
|
+
* @deprecated [🪂] Use queues instead
|
|
4388
|
+
*
|
|
4389
|
+
* @public exported from `@promptbook/utils`
|
|
4297
4390
|
*/
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
this.client = null;
|
|
4311
|
-
// TODO: Allow configuring rate limits via options
|
|
4312
|
-
this.limiter = new Bottleneck({
|
|
4313
|
-
minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
|
|
4391
|
+
async function forEachAsync(array, options, callbackfunction) {
|
|
4392
|
+
const { maxParallelCount = Infinity } = options;
|
|
4393
|
+
let index = 0;
|
|
4394
|
+
let runningTasks = [];
|
|
4395
|
+
const tasks = [];
|
|
4396
|
+
for (const item of array) {
|
|
4397
|
+
const currentIndex = index++;
|
|
4398
|
+
const task = callbackfunction(item, currentIndex, array);
|
|
4399
|
+
tasks.push(task);
|
|
4400
|
+
runningTasks.push(task);
|
|
4401
|
+
/* not await */ Promise.resolve(task).then(() => {
|
|
4402
|
+
runningTasks = runningTasks.filter((runningTask) => runningTask !== task);
|
|
4314
4403
|
});
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
if (this.client === null) {
|
|
4318
|
-
// Note: Passing only OpenAI relevant options to OpenAI constructor
|
|
4319
|
-
const openAiOptions = { ...this.options };
|
|
4320
|
-
delete openAiOptions.isVerbose;
|
|
4321
|
-
delete openAiOptions.userId;
|
|
4322
|
-
// Enhanced configuration with retries and timeouts.
|
|
4323
|
-
const enhancedOptions = {
|
|
4324
|
-
...openAiOptions,
|
|
4325
|
-
timeout: API_REQUEST_TIMEOUT,
|
|
4326
|
-
maxRetries: CONNECTION_RETRIES_LIMIT,
|
|
4327
|
-
};
|
|
4328
|
-
this.client = new OpenAI(enhancedOptions);
|
|
4404
|
+
if (maxParallelCount < runningTasks.length) {
|
|
4405
|
+
await Promise.race(runningTasks);
|
|
4329
4406
|
}
|
|
4330
|
-
return this.client;
|
|
4331
4407
|
}
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4408
|
+
await Promise.all(tasks);
|
|
4409
|
+
}
|
|
4410
|
+
|
|
4411
|
+
/**
|
|
4412
|
+
* Builds a tool invocation script that injects hidden runtime context into tool args.
|
|
4413
|
+
*
|
|
4414
|
+
* @private utility of OpenAI tool execution wrappers
|
|
4415
|
+
*/
|
|
4416
|
+
function buildToolInvocationScript(options) {
|
|
4417
|
+
const { functionName, functionArgsExpression } = options;
|
|
4418
|
+
return `
|
|
4419
|
+
const args = ${functionArgsExpression};
|
|
4420
|
+
const runtimeContextRaw =
|
|
4421
|
+
typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
|
|
4422
|
+
? undefined
|
|
4423
|
+
: ${TOOL_RUNTIME_CONTEXT_PARAMETER};
|
|
4424
|
+
|
|
4425
|
+
if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
4426
|
+
args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4429
|
+
const toolProgressTokenRaw =
|
|
4430
|
+
typeof ${TOOL_PROGRESS_TOKEN_PARAMETER} === 'undefined'
|
|
4431
|
+
? undefined
|
|
4432
|
+
: ${TOOL_PROGRESS_TOKEN_PARAMETER};
|
|
4433
|
+
|
|
4434
|
+
if (toolProgressTokenRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
|
|
4435
|
+
args.${TOOL_PROGRESS_TOKEN_ARGUMENT} = toolProgressTokenRaw;
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
return await ${functionName}(args);
|
|
4439
|
+
`;
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4442
|
+
/**
|
|
4443
|
+
* Executes chat-requested tools and keeps their progress snapshots in sync with streamed progress updates.
|
|
4444
|
+
*
|
|
4445
|
+
* @private helper of `callOpenAiCompatibleChatModel`
|
|
4446
|
+
*/
|
|
4447
|
+
class OpenAiCompatibleChatToolCaller {
|
|
4448
|
+
constructor(options) {
|
|
4449
|
+
this.options = options;
|
|
4338
4450
|
}
|
|
4339
4451
|
/**
|
|
4340
|
-
*
|
|
4452
|
+
* Executes all tool calls requested in one assistant response and appends their results to the conversation.
|
|
4341
4453
|
*/
|
|
4342
|
-
async
|
|
4343
|
-
const
|
|
4344
|
-
const
|
|
4345
|
-
const
|
|
4346
|
-
|
|
4347
|
-
.
|
|
4348
|
-
|
|
4349
|
-
modelName.startsWith(modelFromApi.id) ||
|
|
4350
|
-
modelFromApi.id.startsWith(modelName));
|
|
4351
|
-
if (modelFromList !== undefined) {
|
|
4352
|
-
return modelFromList;
|
|
4454
|
+
async handleToolCalls(options) {
|
|
4455
|
+
const requestedToolCalls = options.responseMessage.tool_calls || [];
|
|
4456
|
+
const toolCallStartedAt = new Map();
|
|
4457
|
+
const pendingToolCalls = requestedToolCalls.map((toolCall) => {
|
|
4458
|
+
const calledAt = $getCurrentDate();
|
|
4459
|
+
if (toolCall.id) {
|
|
4460
|
+
toolCallStartedAt.set(toolCall.id, calledAt);
|
|
4353
4461
|
}
|
|
4354
|
-
return {
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
};
|
|
4462
|
+
return this.options.progressReporter.createPendingToolCall({
|
|
4463
|
+
toolCall,
|
|
4464
|
+
functionName: String(toolCall.function.name),
|
|
4465
|
+
functionArguments: toolCall.function.arguments,
|
|
4466
|
+
calledAt,
|
|
4467
|
+
});
|
|
4360
4468
|
});
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4469
|
+
this.options.progressReporter.emitProgress({
|
|
4470
|
+
start: options.start,
|
|
4471
|
+
complete: options.turnComplete,
|
|
4472
|
+
rawPromptContent: options.rawPromptContent,
|
|
4473
|
+
onProgress: options.onProgress,
|
|
4474
|
+
content: options.responseMessage.content || '',
|
|
4475
|
+
modelName: options.rawResponse.model || options.modelName,
|
|
4476
|
+
usage: options.usage,
|
|
4477
|
+
rawRequest: options.rawRequest,
|
|
4478
|
+
rawResponse: options.rawResponse,
|
|
4479
|
+
toolCalls: pendingToolCalls,
|
|
4480
|
+
});
|
|
4481
|
+
await forEachAsync(requestedToolCalls, {}, async (toolCall) => {
|
|
4482
|
+
const completedToolCall = await this.executeToolCall({
|
|
4483
|
+
prompt: options.prompt,
|
|
4484
|
+
toolCall,
|
|
4485
|
+
toolCallStartedAt,
|
|
4486
|
+
responseContent: options.responseMessage.content || '',
|
|
4487
|
+
start: options.start,
|
|
4488
|
+
rawPromptContent: options.rawPromptContent,
|
|
4489
|
+
rawRequest: options.rawRequest,
|
|
4490
|
+
rawResponse: options.rawResponse,
|
|
4491
|
+
modelName: options.rawResponse.model || options.modelName,
|
|
4492
|
+
usage: options.usage,
|
|
4493
|
+
messages: options.messages,
|
|
4494
|
+
onProgress: options.onProgress,
|
|
4495
|
+
});
|
|
4496
|
+
options.toolCalls.push(completedToolCall);
|
|
4385
4497
|
});
|
|
4386
4498
|
}
|
|
4387
4499
|
/**
|
|
4388
|
-
* Executes one
|
|
4500
|
+
* Executes one tool call requested by the chat response and appends the tool message.
|
|
4389
4501
|
*/
|
|
4390
|
-
async
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4502
|
+
async executeToolCall(options) {
|
|
4503
|
+
const functionName = String(options.toolCall.function.name);
|
|
4504
|
+
const functionArguments = options.toolCall.function.arguments;
|
|
4505
|
+
const calledAt = options.toolCall.id
|
|
4506
|
+
? options.toolCallStartedAt.get(options.toolCall.id) || $getCurrentDate()
|
|
4507
|
+
: $getCurrentDate();
|
|
4508
|
+
const pendingToolCall = this.options.progressReporter.createPendingToolCall({
|
|
4509
|
+
toolCall: options.toolCall,
|
|
4510
|
+
functionName,
|
|
4511
|
+
functionArguments,
|
|
4512
|
+
calledAt,
|
|
4399
4513
|
});
|
|
4514
|
+
const executionResult = await this.executeFunctionTool({
|
|
4515
|
+
prompt: options.prompt,
|
|
4516
|
+
start: options.start,
|
|
4517
|
+
rawPromptContent: options.rawPromptContent,
|
|
4518
|
+
onProgress: options.onProgress,
|
|
4519
|
+
content: options.responseContent,
|
|
4520
|
+
rawRequest: options.rawRequest,
|
|
4521
|
+
rawResponse: options.rawResponse,
|
|
4522
|
+
modelName: options.modelName,
|
|
4523
|
+
usage: options.usage,
|
|
4524
|
+
functionName,
|
|
4525
|
+
functionArguments,
|
|
4526
|
+
pendingToolCall,
|
|
4527
|
+
});
|
|
4528
|
+
options.messages.push({
|
|
4529
|
+
role: 'tool',
|
|
4530
|
+
tool_call_id: options.toolCall.id,
|
|
4531
|
+
content: executionResult.assistantVisibleFunctionResponse,
|
|
4532
|
+
});
|
|
4533
|
+
const completedToolCall = this.options.progressReporter.createCompletedToolCall({
|
|
4534
|
+
toolCall: options.toolCall,
|
|
4535
|
+
functionName,
|
|
4536
|
+
calledAt,
|
|
4537
|
+
currentToolCallSnapshot: executionResult.currentToolCallSnapshot,
|
|
4538
|
+
toolResult: executionResult.toolResult,
|
|
4539
|
+
errors: executionResult.errors,
|
|
4540
|
+
});
|
|
4541
|
+
this.options.progressReporter.emitProgress({
|
|
4542
|
+
start: options.start,
|
|
4543
|
+
rawPromptContent: options.rawPromptContent,
|
|
4544
|
+
onProgress: options.onProgress,
|
|
4545
|
+
content: options.responseContent,
|
|
4546
|
+
modelName: options.modelName,
|
|
4547
|
+
usage: options.usage,
|
|
4548
|
+
rawRequest: options.rawRequest,
|
|
4549
|
+
rawResponse: options.rawResponse,
|
|
4550
|
+
toolCalls: [completedToolCall],
|
|
4551
|
+
});
|
|
4552
|
+
return completedToolCall;
|
|
4400
4553
|
}
|
|
4401
4554
|
/**
|
|
4402
|
-
*
|
|
4555
|
+
* Resolves the configured script tools for chat tool execution.
|
|
4403
4556
|
*/
|
|
4404
|
-
|
|
4405
|
-
const
|
|
4406
|
-
|
|
4557
|
+
resolveScriptTools(functionName) {
|
|
4558
|
+
const executionTools = this.options.executionToolsOptions.executionTools;
|
|
4559
|
+
if (!executionTools || !executionTools.script) {
|
|
4560
|
+
throw new PipelineExecutionError(`Model requested tool '${functionName}' but no executionTools.script were provided in OpenAiCompatibleExecutionTools options`);
|
|
4561
|
+
}
|
|
4562
|
+
return Array.isArray(executionTools.script) ? executionTools.script : [executionTools.script];
|
|
4407
4563
|
}
|
|
4408
4564
|
/**
|
|
4409
|
-
*
|
|
4565
|
+
* Executes the configured script tool for one chat-requested function call.
|
|
4410
4566
|
*/
|
|
4411
|
-
async
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
// TODO: [☂] Use here more modelRequirements
|
|
4419
|
-
if (currentModelRequirements.modelVariant !== 'COMPLETION') {
|
|
4420
|
-
throw new PipelineExecutionError('Use callCompletionModel only for COMPLETION variant');
|
|
4421
|
-
}
|
|
4422
|
-
const modelName = currentModelRequirements.modelName || this.getDefaultCompletionModel().modelName;
|
|
4423
|
-
const modelSettings = {
|
|
4424
|
-
model: modelName,
|
|
4425
|
-
max_tokens: currentModelRequirements.maxTokens,
|
|
4426
|
-
temperature: currentModelRequirements.temperature,
|
|
4427
|
-
};
|
|
4428
|
-
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
4429
|
-
const rawRequest = {
|
|
4430
|
-
...modelSettings,
|
|
4431
|
-
model: modelName,
|
|
4432
|
-
prompt: rawPromptContent,
|
|
4433
|
-
user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
4434
|
-
};
|
|
4435
|
-
const start = $getCurrentDate();
|
|
4436
|
-
if (this.options.isVerbose) {
|
|
4437
|
-
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
4438
|
-
}
|
|
4567
|
+
async executeFunctionTool(options) {
|
|
4568
|
+
const scriptTools = this.resolveScriptTools(options.functionName);
|
|
4569
|
+
let functionResponse;
|
|
4570
|
+
let assistantVisibleFunctionResponse;
|
|
4571
|
+
let toolResult;
|
|
4572
|
+
let errors;
|
|
4573
|
+
let currentToolCallSnapshot = options.pendingToolCall;
|
|
4439
4574
|
try {
|
|
4440
|
-
const
|
|
4441
|
-
const
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4575
|
+
const scriptTool = scriptTools[0];
|
|
4576
|
+
const progressListenerToken = registerToolCallProgressListener((update) => {
|
|
4577
|
+
currentToolCallSnapshot = this.options.progressReporter.applyToolCallProgressUpdate(currentToolCallSnapshot, update);
|
|
4578
|
+
this.options.progressReporter.emitProgress({
|
|
4579
|
+
start: options.start,
|
|
4580
|
+
rawPromptContent: options.rawPromptContent,
|
|
4581
|
+
onProgress: options.onProgress,
|
|
4582
|
+
content: options.content,
|
|
4583
|
+
modelName: options.modelName,
|
|
4584
|
+
usage: options.usage,
|
|
4585
|
+
rawRequest: options.rawRequest,
|
|
4586
|
+
rawResponse: options.rawResponse,
|
|
4587
|
+
toolCalls: [currentToolCallSnapshot],
|
|
4588
|
+
});
|
|
4589
|
+
});
|
|
4590
|
+
try {
|
|
4591
|
+
functionResponse = await scriptTool.execute({
|
|
4592
|
+
scriptLanguage: 'javascript',
|
|
4593
|
+
script: buildToolInvocationScript({
|
|
4594
|
+
functionName: options.functionName,
|
|
4595
|
+
functionArgsExpression: options.functionArguments,
|
|
4596
|
+
}),
|
|
4597
|
+
parameters: {
|
|
4598
|
+
...options.prompt.parameters,
|
|
4599
|
+
[TOOL_PROGRESS_TOKEN_PARAMETER]: progressListenerToken,
|
|
4600
|
+
},
|
|
4601
|
+
});
|
|
4448
4602
|
}
|
|
4449
|
-
|
|
4450
|
-
|
|
4603
|
+
finally {
|
|
4604
|
+
unregisterToolCallProgressListener(progressListenerToken);
|
|
4451
4605
|
}
|
|
4452
|
-
const
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
order: [],
|
|
4459
|
-
value: {
|
|
4460
|
-
content: resultContent,
|
|
4461
|
-
modelName: rawResponse.model || modelName,
|
|
4462
|
-
timing: {
|
|
4463
|
-
start,
|
|
4464
|
-
complete: turnComplete,
|
|
4465
|
-
},
|
|
4466
|
-
usage,
|
|
4467
|
-
rawPromptContent,
|
|
4468
|
-
rawRequest,
|
|
4469
|
-
rawResponse,
|
|
4470
|
-
},
|
|
4471
|
-
});
|
|
4606
|
+
const toolExecutionEnvelope = parseToolExecutionEnvelope(functionResponse);
|
|
4607
|
+
assistantVisibleFunctionResponse = (toolExecutionEnvelope === null || toolExecutionEnvelope === void 0 ? void 0 : toolExecutionEnvelope.assistantMessage) || functionResponse;
|
|
4608
|
+
toolResult =
|
|
4609
|
+
toolExecutionEnvelope !== null && toolExecutionEnvelope !== undefined
|
|
4610
|
+
? toolExecutionEnvelope.toolResult
|
|
4611
|
+
: functionResponse;
|
|
4472
4612
|
}
|
|
4473
4613
|
catch (error) {
|
|
4474
4614
|
assertsError(error);
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
});
|
|
4480
|
-
return this.callCompletionModelWithRetry(prompt, modifiedModelRequirements, unsupportedParameterRetrier);
|
|
4615
|
+
functionResponse = `Error: ${error.message}`;
|
|
4616
|
+
assistantVisibleFunctionResponse = functionResponse;
|
|
4617
|
+
toolResult = functionResponse;
|
|
4618
|
+
errors = [serializeError(error)];
|
|
4481
4619
|
}
|
|
4620
|
+
return {
|
|
4621
|
+
assistantVisibleFunctionResponse,
|
|
4622
|
+
currentToolCallSnapshot,
|
|
4623
|
+
errors,
|
|
4624
|
+
toolResult,
|
|
4625
|
+
};
|
|
4482
4626
|
}
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4627
|
+
}
|
|
4628
|
+
|
|
4629
|
+
/**
|
|
4630
|
+
* Calls the OpenAI-compatible chat model flow, including tool execution and unsupported-parameter retries.
|
|
4631
|
+
*
|
|
4632
|
+
* @private function of `OpenAiCompatibleExecutionTools`
|
|
4633
|
+
*/
|
|
4634
|
+
async function callOpenAiCompatibleChatModel(options) {
|
|
4635
|
+
const chatPromptBuilder = new OpenAiCompatibleChatPromptBuilder();
|
|
4636
|
+
const chatProgressReporter = new OpenAiCompatibleChatProgressReporter();
|
|
4637
|
+
const chatToolCaller = new OpenAiCompatibleChatToolCaller({
|
|
4638
|
+
executionToolsOptions: options.executionToolsOptions,
|
|
4639
|
+
progressReporter: chatProgressReporter,
|
|
4640
|
+
});
|
|
4641
|
+
const clonedPrompt = chatPromptBuilder.clonePromptPreservingFiles(options.prompt);
|
|
4642
|
+
const unsupportedParameterRetrier = new OpenAiCompatibleUnsupportedParameterRetrier(options.executionToolsOptions.isVerbose);
|
|
4643
|
+
return callChatModelWithRetry({
|
|
4644
|
+
options,
|
|
4645
|
+
prompt: clonedPrompt,
|
|
4646
|
+
currentModelRequirements: clonedPrompt.modelRequirements,
|
|
4647
|
+
unsupportedParameterRetrier,
|
|
4648
|
+
chatPromptBuilder,
|
|
4649
|
+
chatProgressReporter,
|
|
4650
|
+
chatToolCaller,
|
|
4651
|
+
});
|
|
4652
|
+
}
|
|
4653
|
+
/**
|
|
4654
|
+
* Retries the chat flow when OpenAI-compatible providers reject unsupported parameters.
|
|
4655
|
+
*/
|
|
4656
|
+
async function callChatModelWithRetry(options) {
|
|
4657
|
+
if (options.options.executionToolsOptions.isVerbose) {
|
|
4658
|
+
console.info(`💬 ${options.options.title} callChatModel call`, {
|
|
4659
|
+
prompt: options.prompt,
|
|
4660
|
+
currentModelRequirements: options.currentModelRequirements,
|
|
4661
|
+
});
|
|
4489
4662
|
}
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4663
|
+
const { content, parameters, format } = options.prompt;
|
|
4664
|
+
if (options.currentModelRequirements.modelVariant !== 'CHAT') {
|
|
4665
|
+
throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
|
|
4666
|
+
}
|
|
4667
|
+
const modelName = options.currentModelRequirements.modelName || options.options.getDefaultChatModel().modelName;
|
|
4668
|
+
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
4669
|
+
const modelSettings = options.chatPromptBuilder.createModelSettings({
|
|
4670
|
+
currentModelRequirements: options.currentModelRequirements,
|
|
4671
|
+
format,
|
|
4672
|
+
modelName,
|
|
4673
|
+
});
|
|
4674
|
+
const messages = await options.chatPromptBuilder.createMessages({
|
|
4675
|
+
prompt: options.prompt,
|
|
4676
|
+
currentModelRequirements: options.currentModelRequirements,
|
|
4677
|
+
rawPromptContent,
|
|
4678
|
+
});
|
|
4679
|
+
const client = await options.options.getClient();
|
|
4680
|
+
let totalUsage = options.chatProgressReporter.createEmptyUsage();
|
|
4681
|
+
const toolCalls = [];
|
|
4682
|
+
const start = $getCurrentDate();
|
|
4683
|
+
const tools = 'tools' in options.prompt && Array.isArray(options.prompt.tools)
|
|
4684
|
+
? options.prompt.tools
|
|
4685
|
+
: options.currentModelRequirements.tools;
|
|
4686
|
+
let isToolCallingLoopActive = true;
|
|
4687
|
+
while (isToolCallingLoopActive) {
|
|
4688
|
+
const rawRequest = options.chatPromptBuilder.createRawRequest({
|
|
4689
|
+
modelSettings,
|
|
4690
|
+
messages,
|
|
4691
|
+
tools,
|
|
4692
|
+
userId: options.options.executionToolsOptions.userId,
|
|
4693
|
+
});
|
|
4512
4694
|
try {
|
|
4513
|
-
const
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
return exportJson({
|
|
4526
|
-
name: 'promptResult',
|
|
4527
|
-
message: `Result of \`OpenAiCompatibleExecutionTools.callEmbeddingModel\``,
|
|
4528
|
-
order: [],
|
|
4529
|
-
value: {
|
|
4530
|
-
content: resultContent,
|
|
4531
|
-
modelName: rawResponse.model || modelName,
|
|
4532
|
-
timing: {
|
|
4533
|
-
start,
|
|
4534
|
-
complete: turnComplete,
|
|
4535
|
-
},
|
|
4536
|
-
usage,
|
|
4695
|
+
const turnResult = await executeChatTurn(options.options, {
|
|
4696
|
+
client,
|
|
4697
|
+
rawRequest,
|
|
4698
|
+
promptContent: content || '',
|
|
4699
|
+
});
|
|
4700
|
+
messages.push(turnResult.responseMessage);
|
|
4701
|
+
totalUsage = addUsage(totalUsage, turnResult.usage);
|
|
4702
|
+
if (turnResult.responseMessage.tool_calls && turnResult.responseMessage.tool_calls.length > 0) {
|
|
4703
|
+
await options.chatToolCaller.handleToolCalls({
|
|
4704
|
+
prompt: options.prompt,
|
|
4705
|
+
start,
|
|
4706
|
+
turnComplete: turnResult.turnComplete,
|
|
4537
4707
|
rawPromptContent,
|
|
4708
|
+
responseMessage: turnResult.responseMessage,
|
|
4538
4709
|
rawRequest,
|
|
4539
|
-
rawResponse,
|
|
4540
|
-
|
|
4710
|
+
rawResponse: turnResult.rawResponse,
|
|
4711
|
+
modelName,
|
|
4712
|
+
usage: totalUsage,
|
|
4713
|
+
toolCalls,
|
|
4714
|
+
messages,
|
|
4715
|
+
onProgress: options.options.onProgress,
|
|
4716
|
+
});
|
|
4717
|
+
continue;
|
|
4718
|
+
}
|
|
4719
|
+
isToolCallingLoopActive = false;
|
|
4720
|
+
return options.chatProgressReporter.createChatPromptResult({
|
|
4721
|
+
title: options.options.title,
|
|
4722
|
+
responseMessage: turnResult.responseMessage,
|
|
4723
|
+
rawPromptContent,
|
|
4724
|
+
rawRequest,
|
|
4725
|
+
rawResponse: turnResult.rawResponse,
|
|
4726
|
+
modelName,
|
|
4727
|
+
start,
|
|
4728
|
+
complete: $getCurrentDate(),
|
|
4729
|
+
usage: totalUsage,
|
|
4730
|
+
toolCalls,
|
|
4541
4731
|
});
|
|
4542
4732
|
}
|
|
4543
4733
|
catch (error) {
|
|
4734
|
+
isToolCallingLoopActive = false;
|
|
4544
4735
|
assertsError(error);
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4736
|
+
return callChatModelWithRetry({
|
|
4737
|
+
...options,
|
|
4738
|
+
currentModelRequirements: options.unsupportedParameterRetrier.resolveRetryOrThrow({
|
|
4739
|
+
error,
|
|
4740
|
+
modelName,
|
|
4741
|
+
currentModelRequirements: options.currentModelRequirements,
|
|
4742
|
+
}),
|
|
4549
4743
|
});
|
|
4550
|
-
return this.callEmbeddingModelWithRetry(prompt, modifiedModelRequirements, unsupportedParameterRetrier);
|
|
4551
4744
|
}
|
|
4552
4745
|
}
|
|
4746
|
+
throw new PipelineExecutionError(`Tool calling loop did not return a result from ${options.options.title}`);
|
|
4747
|
+
}
|
|
4748
|
+
/**
|
|
4749
|
+
* Executes one chat completion turn and returns the parsed response plus measured usage.
|
|
4750
|
+
*/
|
|
4751
|
+
async function executeChatTurn(openAiOptions, options) {
|
|
4752
|
+
if (openAiOptions.executionToolsOptions.isVerbose) {
|
|
4753
|
+
console.info(colors.bgWhite('rawRequest'), JSON.stringify(options.rawRequest, null, 4));
|
|
4754
|
+
}
|
|
4755
|
+
const turnStart = $getCurrentDate();
|
|
4756
|
+
const rawResponse = await openAiOptions.executeRateLimitedRequest(() => options.client.chat.completions.create(options.rawRequest));
|
|
4757
|
+
const turnComplete = $getCurrentDate();
|
|
4758
|
+
if (openAiOptions.executionToolsOptions.isVerbose) {
|
|
4759
|
+
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
4760
|
+
}
|
|
4761
|
+
if (!rawResponse.choices[0]) {
|
|
4762
|
+
throw new PipelineExecutionError(`No choises from ${openAiOptions.title}`);
|
|
4763
|
+
}
|
|
4764
|
+
const responseMessage = rawResponse.choices[0].message;
|
|
4765
|
+
const duration = uncertainNumber((new Date(turnComplete).getTime() - new Date(turnStart).getTime()) / 1000);
|
|
4766
|
+
const usage = openAiOptions.computeUsage(options.promptContent, responseMessage.content || '', rawResponse, duration);
|
|
4767
|
+
return {
|
|
4768
|
+
rawResponse,
|
|
4769
|
+
responseMessage,
|
|
4770
|
+
turnComplete,
|
|
4771
|
+
usage,
|
|
4772
|
+
};
|
|
4773
|
+
}
|
|
4774
|
+
|
|
4775
|
+
/**
|
|
4776
|
+
* Execution Tools for calling OpenAI API or other OpenAI compatible provider
|
|
4777
|
+
*
|
|
4778
|
+
* @public exported from `@promptbook/openai`
|
|
4779
|
+
*/
|
|
4780
|
+
class OpenAiCompatibleExecutionTools {
|
|
4553
4781
|
/**
|
|
4554
|
-
*
|
|
4782
|
+
* Creates OpenAI compatible Execution Tools.
|
|
4783
|
+
*
|
|
4784
|
+
* @param options which are relevant are directly passed to the OpenAI compatible client
|
|
4555
4785
|
*/
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4786
|
+
constructor(options) {
|
|
4787
|
+
this.options = options;
|
|
4788
|
+
this.requestManager = new OpenAiCompatibleRequestManager(this.options);
|
|
4789
|
+
this.modelCatalog = new OpenAiCompatibleModelCatalog({
|
|
4790
|
+
getTitle: () => this.title,
|
|
4791
|
+
getClient: () => this.getClient(),
|
|
4792
|
+
getHardcodedModels: () => this.HARDCODED_MODELS,
|
|
4793
|
+
});
|
|
4794
|
+
this.nonChatPromptCaller = new OpenAiCompatibleNonChatPromptCaller({
|
|
4795
|
+
getTitle: () => this.title,
|
|
4796
|
+
isVerbose: this.options.isVerbose,
|
|
4797
|
+
userId: this.options.userId,
|
|
4798
|
+
getClient: () => this.getClient(),
|
|
4799
|
+
executeRateLimitedRequest: (requestFn) => this.executeRateLimitedRequest(requestFn),
|
|
4800
|
+
computeUsage: (...usageArguments) => this.computeUsage(...usageArguments),
|
|
4801
|
+
getDefaultCompletionModel: () => this.getDefaultCompletionModel(),
|
|
4802
|
+
getDefaultEmbeddingModel: () => this.getDefaultEmbeddingModel(),
|
|
4803
|
+
getDefaultImageGenerationModel: () => this.getDefaultImageGenerationModel(),
|
|
4804
|
+
getHardcodedModels: () => this.HARDCODED_MODELS,
|
|
4805
|
+
});
|
|
4806
|
+
}
|
|
4807
|
+
async getClient() {
|
|
4808
|
+
return this.requestManager.getClient();
|
|
4559
4809
|
}
|
|
4560
4810
|
/**
|
|
4561
|
-
*
|
|
4811
|
+
* Check the `options` passed to `constructor`
|
|
4562
4812
|
*/
|
|
4563
|
-
async
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
console.info(`🎨 ${this.title} callImageGenerationModel call`, { prompt, currentModelRequirements });
|
|
4567
|
-
}
|
|
4568
|
-
const { content, parameters } = prompt;
|
|
4569
|
-
const client = await this.getClient();
|
|
4570
|
-
// TODO: [☂] Use here more modelRequirements
|
|
4571
|
-
if (currentModelRequirements.modelVariant !== 'IMAGE_GENERATION') {
|
|
4572
|
-
throw new PipelineExecutionError('Use callImageGenerationModel only for IMAGE_GENERATION variant');
|
|
4573
|
-
}
|
|
4574
|
-
const modelName = currentModelRequirements.modelName || this.getDefaultImageGenerationModel().modelName;
|
|
4575
|
-
const modelSettings = {
|
|
4576
|
-
model: modelName,
|
|
4577
|
-
size: currentModelRequirements.size,
|
|
4578
|
-
quality: currentModelRequirements.quality,
|
|
4579
|
-
style: currentModelRequirements.style,
|
|
4580
|
-
};
|
|
4581
|
-
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
4582
|
-
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
4583
|
-
rawPromptContent +=
|
|
4584
|
-
'\n\n' +
|
|
4585
|
-
prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
4586
|
-
}
|
|
4587
|
-
const rawRequest = {
|
|
4588
|
-
...modelSettings,
|
|
4589
|
-
prompt: rawPromptContent,
|
|
4590
|
-
size: modelSettings.size || '1024x1024',
|
|
4591
|
-
user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
4592
|
-
response_format: 'url', // TODO: [🧠] Maybe allow b64_json
|
|
4593
|
-
};
|
|
4594
|
-
const start = $getCurrentDate();
|
|
4595
|
-
if (this.options.isVerbose) {
|
|
4596
|
-
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
4597
|
-
}
|
|
4598
|
-
try {
|
|
4599
|
-
const turnStart = $getCurrentDate();
|
|
4600
|
-
const rawResponse = await this.executeRateLimitedRequest(() => client.images.generate(rawRequest));
|
|
4601
|
-
const turnComplete = $getCurrentDate();
|
|
4602
|
-
if (this.options.isVerbose) {
|
|
4603
|
-
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
4604
|
-
}
|
|
4605
|
-
if (!rawResponse.data[0]) {
|
|
4606
|
-
throw new PipelineExecutionError(`No choises from ${this.title}`);
|
|
4607
|
-
}
|
|
4608
|
-
if (rawResponse.data.length > 1) {
|
|
4609
|
-
throw new PipelineExecutionError(`More than one choise from ${this.title}`);
|
|
4610
|
-
}
|
|
4611
|
-
const resultContent = rawResponse.data[0].url;
|
|
4612
|
-
const modelInfo = this.HARDCODED_MODELS.find((model) => model.modelName === modelName);
|
|
4613
|
-
const price = ((_b = modelInfo === null || modelInfo === void 0 ? void 0 : modelInfo.pricing) === null || _b === void 0 ? void 0 : _b.output) ? uncertainNumber(modelInfo.pricing.output) : uncertainNumber();
|
|
4614
|
-
const duration = uncertainNumber((new Date(turnComplete).getTime() - new Date(turnStart).getTime()) / 1000);
|
|
4615
|
-
return exportJson({
|
|
4616
|
-
name: 'promptResult',
|
|
4617
|
-
message: `Result of \`OpenAiCompatibleExecutionTools.callImageGenerationModel\``,
|
|
4618
|
-
order: [],
|
|
4619
|
-
value: {
|
|
4620
|
-
content: resultContent,
|
|
4621
|
-
modelName: modelName,
|
|
4622
|
-
timing: {
|
|
4623
|
-
start,
|
|
4624
|
-
complete: turnComplete,
|
|
4625
|
-
},
|
|
4626
|
-
usage: {
|
|
4627
|
-
price,
|
|
4628
|
-
duration,
|
|
4629
|
-
input: {
|
|
4630
|
-
tokensCount: uncertainNumber(0),
|
|
4631
|
-
...computeUsageCounts(rawPromptContent),
|
|
4632
|
-
},
|
|
4633
|
-
output: {
|
|
4634
|
-
tokensCount: uncertainNumber(0),
|
|
4635
|
-
...computeUsageCounts(''),
|
|
4636
|
-
},
|
|
4637
|
-
},
|
|
4638
|
-
rawPromptContent,
|
|
4639
|
-
rawRequest,
|
|
4640
|
-
rawResponse,
|
|
4641
|
-
},
|
|
4642
|
-
});
|
|
4643
|
-
}
|
|
4644
|
-
catch (error) {
|
|
4645
|
-
assertsError(error);
|
|
4646
|
-
const modifiedModelRequirements = unsupportedParameterRetrier.resolveRetryOrThrow({
|
|
4647
|
-
error,
|
|
4648
|
-
modelName,
|
|
4649
|
-
currentModelRequirements,
|
|
4650
|
-
});
|
|
4651
|
-
return this.callImageGenerationModelWithRetry(prompt, modifiedModelRequirements, unsupportedParameterRetrier);
|
|
4652
|
-
}
|
|
4813
|
+
async checkConfiguration() {
|
|
4814
|
+
await this.getClient();
|
|
4815
|
+
// TODO: [🎍] Do here a real check that API is online, working and API key is correct
|
|
4653
4816
|
}
|
|
4654
|
-
// <- Note: [🤖] callXxxModel
|
|
4655
4817
|
/**
|
|
4656
|
-
*
|
|
4818
|
+
* List all available OpenAI compatible models that can be used
|
|
4657
4819
|
*/
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
const model = this.HARDCODED_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
|
|
4661
|
-
if (model === undefined) {
|
|
4662
|
-
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
4663
|
-
Cannot find model in ${this.title} models with name "${defaultModelName}" which should be used as default.
|
|
4664
|
-
|
|
4665
|
-
Available models:
|
|
4666
|
-
${block(this.HARDCODED_MODELS.map(({ modelName }) => `- "${modelName}"`).join('\n'))}
|
|
4667
|
-
|
|
4668
|
-
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
4669
|
-
|
|
4670
|
-
`));
|
|
4671
|
-
}
|
|
4672
|
-
return model;
|
|
4820
|
+
async listModels() {
|
|
4821
|
+
return this.modelCatalog.listModels();
|
|
4673
4822
|
}
|
|
4674
|
-
// <- Note: [🤖] getDefaultXxxModel
|
|
4675
4823
|
/**
|
|
4676
|
-
*
|
|
4824
|
+
* Calls OpenAI compatible API to use a chat model.
|
|
4677
4825
|
*/
|
|
4678
|
-
async
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
// Calculate exponential backoff delay
|
|
4696
|
-
const baseDelay = 1000; // 1 second
|
|
4697
|
-
const backoffDelay = baseDelay * Math.pow(2, attempt - 1);
|
|
4698
|
-
const jitterDelay = Math.random() * 500; // Add some randomness
|
|
4699
|
-
const totalDelay = backoffDelay + jitterDelay;
|
|
4700
|
-
if (this.options.isVerbose) {
|
|
4701
|
-
console.info(colors.bgYellow('Retrying network request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
|
|
4702
|
-
}
|
|
4703
|
-
// Wait before retrying
|
|
4704
|
-
await new Promise((resolve) => setTimeout(resolve, totalDelay));
|
|
4705
|
-
}
|
|
4706
|
-
}
|
|
4707
|
-
throw lastError;
|
|
4826
|
+
async callChatModel(prompt) {
|
|
4827
|
+
return this.callChatModelStream(prompt, () => { });
|
|
4828
|
+
}
|
|
4829
|
+
/**
|
|
4830
|
+
* Calls OpenAI compatible API to use a chat model with streaming.
|
|
4831
|
+
*/
|
|
4832
|
+
async callChatModelStream(prompt, onProgress, _options) {
|
|
4833
|
+
return callOpenAiCompatibleChatModel({
|
|
4834
|
+
prompt,
|
|
4835
|
+
onProgress,
|
|
4836
|
+
title: this.title,
|
|
4837
|
+
executionToolsOptions: this.options,
|
|
4838
|
+
getClient: () => this.getClient(),
|
|
4839
|
+
executeRateLimitedRequest: (requestFn) => this.executeRateLimitedRequest(requestFn),
|
|
4840
|
+
computeUsage: (...usageArguments) => this.computeUsage(...usageArguments),
|
|
4841
|
+
getDefaultChatModel: () => this.getDefaultChatModel(),
|
|
4842
|
+
});
|
|
4708
4843
|
}
|
|
4709
4844
|
/**
|
|
4710
|
-
*
|
|
4845
|
+
* Executes one OpenAI request under the shared rate limiter and network retry policy.
|
|
4711
4846
|
*/
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
if (httpStatus && [429, 500, 502, 503, 504].includes(httpStatus)) {
|
|
4740
|
-
return true;
|
|
4741
|
-
}
|
|
4742
|
-
return false;
|
|
4847
|
+
async executeRateLimitedRequest(requestFn) {
|
|
4848
|
+
return this.requestManager.executeRateLimitedRequest(requestFn);
|
|
4849
|
+
}
|
|
4850
|
+
/**
|
|
4851
|
+
* Calls OpenAI API to use a complete model.
|
|
4852
|
+
*/
|
|
4853
|
+
async callCompletionModel(prompt) {
|
|
4854
|
+
return this.nonChatPromptCaller.callCompletionModel(prompt);
|
|
4855
|
+
}
|
|
4856
|
+
/**
|
|
4857
|
+
* Calls OpenAI compatible API to use a embedding model
|
|
4858
|
+
*/
|
|
4859
|
+
async callEmbeddingModel(prompt) {
|
|
4860
|
+
return this.nonChatPromptCaller.callEmbeddingModel(prompt);
|
|
4861
|
+
}
|
|
4862
|
+
/**
|
|
4863
|
+
* Calls OpenAI compatible API to use a image generation model
|
|
4864
|
+
*/
|
|
4865
|
+
async callImageGenerationModel(prompt) {
|
|
4866
|
+
return this.nonChatPromptCaller.callImageGenerationModel(prompt);
|
|
4867
|
+
}
|
|
4868
|
+
// <- Note: [🤖] callXxxModel
|
|
4869
|
+
/**
|
|
4870
|
+
* Get the model that should be used as default
|
|
4871
|
+
*/
|
|
4872
|
+
getDefaultModel(defaultModelName) {
|
|
4873
|
+
return this.modelCatalog.getDefaultModel(defaultModelName);
|
|
4743
4874
|
}
|
|
4744
4875
|
}
|
|
4745
4876
|
// TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
|