@promptbook/wizard 0.101.0-14 → 0.101.0-15
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 +237 -95
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirements.d.ts +3 -5
- package/esm/typings/src/llm-providers/_common/utils/removeUnsupportedModelRequirements.d.ts +25 -0
- package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +15 -8
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +237 -95
- package/umd/index.umd.js.map +1 -1
@@ -1,4 +1,5 @@
|
|
1
1
|
import type { AvailableModel } from '../../execution/AvailableModel';
|
2
|
+
import { LlmExecutionTools } from '../../execution/LlmExecutionTools';
|
2
3
|
import type { string_model_name } from '../../types/typeAliases';
|
3
4
|
import type { AgentModelRequirements } from './AgentModelRequirements';
|
4
5
|
import type { string_book } from './string_book';
|
@@ -8,11 +9,11 @@ import type { string_book } from './string_book';
|
|
8
9
|
*
|
9
10
|
* There are 2 similar functions:
|
10
11
|
* - `parseAgentSource` which is a lightweight parser for agent source, it parses basic information and its purpose is to be quick and synchronous. The commitments there are hardcoded.
|
11
|
-
* - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works
|
12
|
+
* - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works asynchronous.
|
12
13
|
*
|
13
14
|
* @public exported from `@promptbook/core`
|
14
15
|
*/
|
15
|
-
export declare function createAgentModelRequirements(agentSource: string_book, modelName?: string_model_name, availableModels?: readonly AvailableModel[]): Promise<AgentModelRequirements>;
|
16
|
+
export declare function createAgentModelRequirements(agentSource: string_book, modelName?: string_model_name, availableModels?: readonly AvailableModel[], llmTools?: LlmExecutionTools): Promise<AgentModelRequirements>;
|
16
17
|
/**
|
17
18
|
* Clears the cache for createAgentModelRequirements
|
18
19
|
* Useful when agent sources are updated and cached results should be invalidated
|
@@ -61,6 +62,3 @@ export declare function extractAgentName(agentSource: string_book): string;
|
|
61
62
|
* @private
|
62
63
|
*/
|
63
64
|
export declare function extractAgentProfileImage(agentSource: string_book): string;
|
64
|
-
/**
|
65
|
-
* TODO: [😩] DRY `preparePersona` and `selectBestModelFromAvailable`
|
66
|
-
*/
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import type { ModelRequirements } from '../../../types/ModelRequirements';
|
2
|
+
/**
|
3
|
+
* Parses an OpenAI error message to identify which parameter is unsupported
|
4
|
+
*
|
5
|
+
* @param errorMessage The error message from OpenAI API
|
6
|
+
* @returns The parameter name that is unsupported, or null if not an unsupported parameter error
|
7
|
+
* @private utility of LLM Tools
|
8
|
+
*/
|
9
|
+
export declare function parseUnsupportedParameterError(errorMessage: string): string | null;
|
10
|
+
/**
|
11
|
+
* Creates a copy of model requirements with the specified parameter removed
|
12
|
+
*
|
13
|
+
* @param modelRequirements Original model requirements
|
14
|
+
* @param unsupportedParameter The parameter to remove
|
15
|
+
* @returns New model requirements without the unsupported parameter
|
16
|
+
* @private utility of LLM Tools
|
17
|
+
*/
|
18
|
+
export declare function removeUnsupportedModelRequirement(modelRequirements: ModelRequirements, unsupportedParameter: string): ModelRequirements;
|
19
|
+
/**
|
20
|
+
* Checks if an error is an "Unsupported value" error from OpenAI
|
21
|
+
* @param error The error to check
|
22
|
+
* @returns true if this is an unsupported parameter error
|
23
|
+
* @private utility of LLM Tools
|
24
|
+
*/
|
25
|
+
export declare function isUnsupportedParameterError(error: Error): boolean;
|
@@ -1,15 +1,10 @@
|
|
1
1
|
import OpenAI from 'openai';
|
2
2
|
import type { AvailableModel } from '../../execution/AvailableModel';
|
3
3
|
import type { LlmExecutionTools } from '../../execution/LlmExecutionTools';
|
4
|
-
import type { ChatPromptResult } from '../../execution/PromptResult';
|
5
|
-
import type { CompletionPromptResult } from '../../execution/PromptResult';
|
6
|
-
import type { EmbeddingPromptResult } from '../../execution/PromptResult';
|
4
|
+
import type { ChatPromptResult, CompletionPromptResult, EmbeddingPromptResult } from '../../execution/PromptResult';
|
7
5
|
import type { Usage } from '../../execution/Usage';
|
8
6
|
import type { Prompt } from '../../types/Prompt';
|
9
|
-
import type { string_markdown } from '../../types/typeAliases';
|
10
|
-
import type { string_markdown_text } from '../../types/typeAliases';
|
11
|
-
import type { string_model_name } from '../../types/typeAliases';
|
12
|
-
import type { string_title } from '../../types/typeAliases';
|
7
|
+
import type { string_markdown, string_markdown_text, string_model_name, string_title } from '../../types/typeAliases';
|
13
8
|
import { computeOpenAiUsage } from './computeOpenAiUsage';
|
14
9
|
import type { OpenAiCompatibleExecutionToolsNonProxiedOptions } from './OpenAiCompatibleExecutionToolsOptions';
|
15
10
|
/**
|
@@ -27,6 +22,10 @@ export declare abstract class OpenAiCompatibleExecutionTools implements LlmExecu
|
|
27
22
|
* Rate limiter instance
|
28
23
|
*/
|
29
24
|
private limiter;
|
25
|
+
/**
|
26
|
+
* Tracks models and parameters that have already been retried to prevent infinite loops
|
27
|
+
*/
|
28
|
+
private retriedUnsupportedParameters;
|
30
29
|
/**
|
31
30
|
* Creates OpenAI compatible Execution Tools.
|
32
31
|
*
|
@@ -48,10 +47,18 @@ export declare abstract class OpenAiCompatibleExecutionTools implements LlmExecu
|
|
48
47
|
* Calls OpenAI compatible API to use a chat model.
|
49
48
|
*/
|
50
49
|
callChatModel(prompt: Pick<Prompt, 'content' | 'parameters' | 'modelRequirements' | 'format'>): Promise<ChatPromptResult>;
|
50
|
+
/**
|
51
|
+
* Internal method that handles parameter retry for chat model calls
|
52
|
+
*/
|
53
|
+
private callChatModelWithRetry;
|
51
54
|
/**
|
52
55
|
* Calls OpenAI API to use a complete model.
|
53
56
|
*/
|
54
57
|
callCompletionModel(prompt: Pick<Prompt, 'content' | 'parameters' | 'modelRequirements'>): Promise<CompletionPromptResult>;
|
58
|
+
/**
|
59
|
+
* Internal method that handles parameter retry for completion model calls
|
60
|
+
*/
|
61
|
+
private callCompletionModelWithRetry;
|
55
62
|
/**
|
56
63
|
* Calls OpenAI compatible API to use a embedding model
|
57
64
|
*/
|
@@ -85,7 +92,7 @@ export declare abstract class OpenAiCompatibleExecutionTools implements LlmExecu
|
|
85
92
|
/**
|
86
93
|
* Makes a request with retry logic for network errors like ECONNRESET
|
87
94
|
*/
|
88
|
-
private
|
95
|
+
private makeRequestWithNetworkRetry;
|
89
96
|
/**
|
90
97
|
* Determines if an error is retryable (network-related errors)
|
91
98
|
*/
|
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
|
|
15
15
|
export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
|
16
16
|
/**
|
17
17
|
* Represents the version string of the Promptbook engine.
|
18
|
-
* It follows semantic versioning (e.g., `0.101.0-
|
18
|
+
* It follows semantic versioning (e.g., `0.101.0-14`).
|
19
19
|
*
|
20
20
|
* @generated
|
21
21
|
*/
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@promptbook/wizard",
|
3
|
-
"version": "0.101.0-
|
3
|
+
"version": "0.101.0-15",
|
4
4
|
"description": "Promptbook: Run AI apps in plain human language across multiple models and platforms",
|
5
5
|
"private": false,
|
6
6
|
"sideEffects": false,
|
@@ -95,7 +95,7 @@
|
|
95
95
|
"module": "./esm/index.es.js",
|
96
96
|
"typings": "./esm/typings/src/_packages/wizard.index.d.ts",
|
97
97
|
"peerDependencies": {
|
98
|
-
"@promptbook/core": "0.101.0-
|
98
|
+
"@promptbook/core": "0.101.0-15"
|
99
99
|
},
|
100
100
|
"dependencies": {
|
101
101
|
"@ai-sdk/deepseek": "0.1.6",
|
package/umd/index.umd.js
CHANGED
@@ -48,7 +48,7 @@
|
|
48
48
|
* @generated
|
49
49
|
* @see https://github.com/webgptorg/promptbook
|
50
50
|
*/
|
51
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.101.0-
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.101.0-15';
|
52
52
|
/**
|
53
53
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
54
54
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
@@ -4634,6 +4634,62 @@
|
|
4634
4634
|
* TODO: [🤝] DRY Maybe some common abstraction between `computeOpenAiUsage` and `computeAnthropicClaudeUsage`
|
4635
4635
|
*/
|
4636
4636
|
|
4637
|
+
/**
|
4638
|
+
* Parses an OpenAI error message to identify which parameter is unsupported
|
4639
|
+
*
|
4640
|
+
* @param errorMessage The error message from OpenAI API
|
4641
|
+
* @returns The parameter name that is unsupported, or null if not an unsupported parameter error
|
4642
|
+
* @private utility of LLM Tools
|
4643
|
+
*/
|
4644
|
+
function parseUnsupportedParameterError(errorMessage) {
|
4645
|
+
// Pattern to match "Unsupported value: 'parameter' does not support ..."
|
4646
|
+
const unsupportedValueMatch = errorMessage.match(/Unsupported value:\s*'([^']+)'\s*does not support/i);
|
4647
|
+
if (unsupportedValueMatch === null || unsupportedValueMatch === void 0 ? void 0 : unsupportedValueMatch[1]) {
|
4648
|
+
return unsupportedValueMatch[1];
|
4649
|
+
}
|
4650
|
+
// Pattern to match "'parameter' of type ... is not supported with this model"
|
4651
|
+
const parameterTypeMatch = errorMessage.match(/'([^']+)'\s*of type.*is not supported with this model/i);
|
4652
|
+
if (parameterTypeMatch === null || parameterTypeMatch === void 0 ? void 0 : parameterTypeMatch[1]) {
|
4653
|
+
return parameterTypeMatch[1];
|
4654
|
+
}
|
4655
|
+
return null;
|
4656
|
+
}
|
4657
|
+
/**
|
4658
|
+
* Creates a copy of model requirements with the specified parameter removed
|
4659
|
+
*
|
4660
|
+
* @param modelRequirements Original model requirements
|
4661
|
+
* @param unsupportedParameter The parameter to remove
|
4662
|
+
* @returns New model requirements without the unsupported parameter
|
4663
|
+
* @private utility of LLM Tools
|
4664
|
+
*/
|
4665
|
+
function removeUnsupportedModelRequirement(modelRequirements, unsupportedParameter) {
|
4666
|
+
const newRequirements = { ...modelRequirements };
|
4667
|
+
// Map of parameter names that might appear in error messages to ModelRequirements properties
|
4668
|
+
const parameterMap = {
|
4669
|
+
'temperature': 'temperature',
|
4670
|
+
'max_tokens': 'maxTokens',
|
4671
|
+
'maxTokens': 'maxTokens',
|
4672
|
+
'seed': 'seed',
|
4673
|
+
};
|
4674
|
+
const propertyToRemove = parameterMap[unsupportedParameter];
|
4675
|
+
if (propertyToRemove && propertyToRemove in newRequirements) {
|
4676
|
+
delete newRequirements[propertyToRemove];
|
4677
|
+
}
|
4678
|
+
return newRequirements;
|
4679
|
+
}
|
4680
|
+
/**
|
4681
|
+
* Checks if an error is an "Unsupported value" error from OpenAI
|
4682
|
+
* @param error The error to check
|
4683
|
+
* @returns true if this is an unsupported parameter error
|
4684
|
+
* @private utility of LLM Tools
|
4685
|
+
*/
|
4686
|
+
function isUnsupportedParameterError(error) {
|
4687
|
+
const errorMessage = error.message.toLowerCase();
|
4688
|
+
return errorMessage.includes('unsupported value:') ||
|
4689
|
+
errorMessage.includes('is not supported with this model') ||
|
4690
|
+
errorMessage.includes('does not support');
|
4691
|
+
}
|
4692
|
+
|
4637
4693
|
/**
|
4638
4694
|
* Execution Tools for calling OpenAI API or other OpenAI compatible provider
|
4639
4695
|
*
|
@@ -4651,6 +4707,10 @@
|
|
4651
4707
|
* OpenAI API client.
|
4652
4708
|
*/
|
4653
4709
|
this.client = null;
|
4710
|
+
/**
|
4711
|
+
* Tracks models and parameters that have already been retried to prevent infinite loops
|
4712
|
+
*/
|
4713
|
+
this.retriedUnsupportedParameters = new Set();
|
4654
4714
|
// TODO: Allow configuring rate limits via options
|
4655
4715
|
this.limiter = new Bottleneck__default["default"]({
|
4656
4716
|
minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
|
@@ -4712,21 +4772,27 @@
|
|
4712
4772
|
* Calls OpenAI compatible API to use a chat model.
|
4713
4773
|
*/
|
4714
4774
|
async callChatModel(prompt) {
|
4775
|
+
return this.callChatModelWithRetry(prompt, prompt.modelRequirements);
|
4776
|
+
}
|
4777
|
+
/**
|
4778
|
+
* Internal method that handles parameter retry for chat model calls
|
4779
|
+
*/
|
4780
|
+
async callChatModelWithRetry(prompt, currentModelRequirements) {
|
4715
4781
|
var _a;
|
4716
4782
|
if (this.options.isVerbose) {
|
4717
|
-
console.info(`💬 ${this.title} callChatModel call`, { prompt });
|
4783
|
+
console.info(`💬 ${this.title} callChatModel call`, { prompt, currentModelRequirements });
|
4718
4784
|
}
|
4719
|
-
const { content, parameters,
|
4785
|
+
const { content, parameters, format } = prompt;
|
4720
4786
|
const client = await this.getClient();
|
4721
4787
|
// TODO: [☂] Use here more modelRequirements
|
4722
|
-
if (
|
4788
|
+
if (currentModelRequirements.modelVariant !== 'CHAT') {
|
4723
4789
|
throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
|
4724
4790
|
}
|
4725
|
-
const modelName =
|
4791
|
+
const modelName = currentModelRequirements.modelName || this.getDefaultChatModel().modelName;
|
4726
4792
|
const modelSettings = {
|
4727
4793
|
model: modelName,
|
4728
|
-
max_tokens:
|
4729
|
-
temperature:
|
4794
|
+
max_tokens: currentModelRequirements.maxTokens,
|
4795
|
+
temperature: currentModelRequirements.temperature,
|
4730
4796
|
// <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
|
4731
4797
|
// <- Note: [🧆]
|
4732
4798
|
}; // <- TODO: [💩] Guard here types better
|
@@ -4741,12 +4807,12 @@
|
|
4741
4807
|
const rawRequest = {
|
4742
4808
|
...modelSettings,
|
4743
4809
|
messages: [
|
4744
|
-
...(
|
4810
|
+
...(currentModelRequirements.systemMessage === undefined
|
4745
4811
|
? []
|
4746
4812
|
: [
|
4747
4813
|
{
|
4748
4814
|
role: 'system',
|
4749
|
-
content:
|
4815
|
+
content: currentModelRequirements.systemMessage,
|
4750
4816
|
},
|
4751
4817
|
]),
|
4752
4818
|
{
|
@@ -4760,69 +4826,110 @@
|
|
4760
4826
|
if (this.options.isVerbose) {
|
4761
4827
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
4762
4828
|
}
|
4763
|
-
|
4764
|
-
|
4765
|
-
|
4766
|
-
|
4829
|
+
try {
|
4830
|
+
const rawResponse = await this.limiter
|
4831
|
+
.schedule(() => this.makeRequestWithNetworkRetry(() => client.chat.completions.create(rawRequest)))
|
4832
|
+
.catch((error) => {
|
4833
|
+
assertsError(error);
|
4834
|
+
if (this.options.isVerbose) {
|
4835
|
+
console.info(colors__default["default"].bgRed('error'), error);
|
4836
|
+
}
|
4837
|
+
throw error;
|
4838
|
+
});
|
4767
4839
|
if (this.options.isVerbose) {
|
4768
|
-
console.info(colors__default["default"].
|
4840
|
+
console.info(colors__default["default"].bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
4769
4841
|
}
|
4770
|
-
|
4771
|
-
|
4772
|
-
|
4773
|
-
|
4774
|
-
|
4775
|
-
|
4776
|
-
|
4777
|
-
|
4778
|
-
|
4779
|
-
|
4780
|
-
|
4781
|
-
|
4842
|
+
const complete = $getCurrentDate();
|
4843
|
+
if (!rawResponse.choices[0]) {
|
4844
|
+
throw new PipelineExecutionError(`No choises from ${this.title}`);
|
4845
|
+
}
|
4846
|
+
if (rawResponse.choices.length > 1) {
|
4847
|
+
// TODO: This should be maybe only warning
|
4848
|
+
throw new PipelineExecutionError(`More than one choise from ${this.title}`);
|
4849
|
+
}
|
4850
|
+
const resultContent = rawResponse.choices[0].message.content;
|
4851
|
+
const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
|
4852
|
+
if (resultContent === null) {
|
4853
|
+
throw new PipelineExecutionError(`No response message from ${this.title}`);
|
4854
|
+
}
|
4855
|
+
return exportJson({
|
4856
|
+
name: 'promptResult',
|
4857
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
|
4858
|
+
order: [],
|
4859
|
+
value: {
|
4860
|
+
content: resultContent,
|
4861
|
+
modelName: rawResponse.model || modelName,
|
4862
|
+
timing: {
|
4863
|
+
start,
|
4864
|
+
complete,
|
4865
|
+
},
|
4866
|
+
usage,
|
4867
|
+
rawPromptContent,
|
4868
|
+
rawRequest,
|
4869
|
+
rawResponse,
|
4870
|
+
// <- [🗯]
|
4871
|
+
},
|
4872
|
+
});
|
4782
4873
|
}
|
4783
|
-
|
4784
|
-
|
4785
|
-
|
4786
|
-
|
4874
|
+
catch (error) {
|
4875
|
+
assertsError(error);
|
4876
|
+
// Check if this is an unsupported parameter error
|
4877
|
+
if (!isUnsupportedParameterError(error)) {
|
4878
|
+
throw error;
|
4879
|
+
}
|
4880
|
+
// Parse which parameter is unsupported
|
4881
|
+
const unsupportedParameter = parseUnsupportedParameterError(error.message);
|
4882
|
+
if (!unsupportedParameter) {
|
4883
|
+
if (this.options.isVerbose) {
|
4884
|
+
console.warn(colors__default["default"].bgYellow('Warning'), 'Could not parse unsupported parameter from error:', error.message);
|
4885
|
+
}
|
4886
|
+
throw error;
|
4887
|
+
}
|
4888
|
+
// Create a unique key for this model + parameter combination to prevent infinite loops
|
4889
|
+
const retryKey = `${modelName}-${unsupportedParameter}`;
|
4890
|
+
if (this.retriedUnsupportedParameters.has(retryKey)) {
|
4891
|
+
// Already retried this parameter, throw the error
|
4892
|
+
if (this.options.isVerbose) {
|
4893
|
+
console.warn(colors__default["default"].bgRed('Error'), `Parameter '${unsupportedParameter}' for model '${modelName}' already retried once, throwing error:`, error.message);
|
4894
|
+
}
|
4895
|
+
throw error;
|
4896
|
+
}
|
4897
|
+
// Mark this parameter as retried
|
4898
|
+
this.retriedUnsupportedParameters.add(retryKey);
|
4899
|
+
// Log warning in verbose mode
|
4900
|
+
if (this.options.isVerbose) {
|
4901
|
+
console.warn(colors__default["default"].bgYellow('Warning'), `Removing unsupported parameter '${unsupportedParameter}' for model '${modelName}' and retrying request`);
|
4902
|
+
}
|
4903
|
+
// Remove the unsupported parameter and retry
|
4904
|
+
const modifiedModelRequirements = removeUnsupportedModelRequirement(currentModelRequirements, unsupportedParameter);
|
4905
|
+
return this.callChatModelWithRetry(prompt, modifiedModelRequirements);
|
4787
4906
|
}
|
4788
|
-
return exportJson({
|
4789
|
-
name: 'promptResult',
|
4790
|
-
message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
|
4791
|
-
order: [],
|
4792
|
-
value: {
|
4793
|
-
content: resultContent,
|
4794
|
-
modelName: rawResponse.model || modelName,
|
4795
|
-
timing: {
|
4796
|
-
start,
|
4797
|
-
complete,
|
4798
|
-
},
|
4799
|
-
usage,
|
4800
|
-
rawPromptContent,
|
4801
|
-
rawRequest,
|
4802
|
-
rawResponse,
|
4803
|
-
// <- [🗯]
|
4804
|
-
},
|
4805
|
-
});
|
4806
4907
|
}
|
4807
4908
|
/**
|
4808
4909
|
* Calls OpenAI API to use a complete model.
|
4809
4910
|
*/
|
4810
4911
|
async callCompletionModel(prompt) {
|
4912
|
+
return this.callCompletionModelWithRetry(prompt, prompt.modelRequirements);
|
4913
|
+
}
|
4914
|
+
/**
|
4915
|
+
* Internal method that handles parameter retry for completion model calls
|
4916
|
+
*/
|
4917
|
+
async callCompletionModelWithRetry(prompt, currentModelRequirements) {
|
4811
4918
|
var _a;
|
4812
4919
|
if (this.options.isVerbose) {
|
4813
|
-
console.info(`🖋 ${this.title} callCompletionModel call`, { prompt });
|
4920
|
+
console.info(`🖋 ${this.title} callCompletionModel call`, { prompt, currentModelRequirements });
|
4814
4921
|
}
|
4815
|
-
const { content, parameters
|
4922
|
+
const { content, parameters } = prompt;
|
4816
4923
|
const client = await this.getClient();
|
4817
4924
|
// TODO: [☂] Use here more modelRequirements
|
4818
|
-
if (
|
4925
|
+
if (currentModelRequirements.modelVariant !== 'COMPLETION') {
|
4819
4926
|
throw new PipelineExecutionError('Use callCompletionModel only for COMPLETION variant');
|
4820
4927
|
}
|
4821
|
-
const modelName =
|
4928
|
+
const modelName = currentModelRequirements.modelName || this.getDefaultCompletionModel().modelName;
|
4822
4929
|
const modelSettings = {
|
4823
4930
|
model: modelName,
|
4824
|
-
max_tokens:
|
4825
|
-
temperature:
|
4931
|
+
max_tokens: currentModelRequirements.maxTokens,
|
4932
|
+
temperature: currentModelRequirements.temperature,
|
4826
4933
|
// <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
|
4827
4934
|
// <- Note: [🧆]
|
4828
4935
|
};
|
@@ -4836,46 +4943,81 @@
|
|
4836
4943
|
if (this.options.isVerbose) {
|
4837
4944
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
4838
4945
|
}
|
4839
|
-
|
4840
|
-
|
4841
|
-
|
4842
|
-
|
4946
|
+
try {
|
4947
|
+
const rawResponse = await this.limiter
|
4948
|
+
.schedule(() => this.makeRequestWithNetworkRetry(() => client.completions.create(rawRequest)))
|
4949
|
+
.catch((error) => {
|
4950
|
+
assertsError(error);
|
4951
|
+
if (this.options.isVerbose) {
|
4952
|
+
console.info(colors__default["default"].bgRed('error'), error);
|
4953
|
+
}
|
4954
|
+
throw error;
|
4955
|
+
});
|
4843
4956
|
if (this.options.isVerbose) {
|
4844
|
-
console.info(colors__default["default"].
|
4957
|
+
console.info(colors__default["default"].bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
4845
4958
|
}
|
4846
|
-
|
4847
|
-
|
4848
|
-
|
4849
|
-
|
4850
|
-
|
4851
|
-
|
4852
|
-
|
4853
|
-
|
4959
|
+
const complete = $getCurrentDate();
|
4960
|
+
if (!rawResponse.choices[0]) {
|
4961
|
+
throw new PipelineExecutionError(`No choises from ${this.title}`);
|
4962
|
+
}
|
4963
|
+
if (rawResponse.choices.length > 1) {
|
4964
|
+
// TODO: This should be maybe only warning
|
4965
|
+
throw new PipelineExecutionError(`More than one choise from ${this.title}`);
|
4966
|
+
}
|
4967
|
+
const resultContent = rawResponse.choices[0].text;
|
4968
|
+
const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
|
4969
|
+
return exportJson({
|
4970
|
+
name: 'promptResult',
|
4971
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callCompletionModel\``,
|
4972
|
+
order: [],
|
4973
|
+
value: {
|
4974
|
+
content: resultContent,
|
4975
|
+
modelName: rawResponse.model || modelName,
|
4976
|
+
timing: {
|
4977
|
+
start,
|
4978
|
+
complete,
|
4979
|
+
},
|
4980
|
+
usage,
|
4981
|
+
rawPromptContent,
|
4982
|
+
rawRequest,
|
4983
|
+
rawResponse,
|
4984
|
+
// <- [🗯]
|
4985
|
+
},
|
4986
|
+
});
|
4854
4987
|
}
|
4855
|
-
|
4856
|
-
|
4857
|
-
|
4988
|
+
catch (error) {
|
4989
|
+
assertsError(error);
|
4990
|
+
// Check if this is an unsupported parameter error
|
4991
|
+
if (!isUnsupportedParameterError(error)) {
|
4992
|
+
throw error;
|
4993
|
+
}
|
4994
|
+
// Parse which parameter is unsupported
|
4995
|
+
const unsupportedParameter = parseUnsupportedParameterError(error.message);
|
4996
|
+
if (!unsupportedParameter) {
|
4997
|
+
if (this.options.isVerbose) {
|
4998
|
+
console.warn(colors__default["default"].bgYellow('Warning'), 'Could not parse unsupported parameter from error:', error.message);
|
4999
|
+
}
|
5000
|
+
throw error;
|
5001
|
+
}
|
5002
|
+
// Create a unique key for this model + parameter combination to prevent infinite loops
|
5003
|
+
const retryKey = `${modelName}-${unsupportedParameter}`;
|
5004
|
+
if (this.retriedUnsupportedParameters.has(retryKey)) {
|
5005
|
+
// Already retried this parameter, throw the error
|
5006
|
+
if (this.options.isVerbose) {
|
5007
|
+
console.warn(colors__default["default"].bgRed('Error'), `Parameter '${unsupportedParameter}' for model '${modelName}' already retried once, throwing error:`, error.message);
|
5008
|
+
}
|
5009
|
+
throw error;
|
5010
|
+
}
|
5011
|
+
// Mark this parameter as retried
|
5012
|
+
this.retriedUnsupportedParameters.add(retryKey);
|
5013
|
+
// Log warning in verbose mode
|
5014
|
+
if (this.options.isVerbose) {
|
5015
|
+
console.warn(colors__default["default"].bgYellow('Warning'), `Removing unsupported parameter '${unsupportedParameter}' for model '${modelName}' and retrying request`);
|
5016
|
+
}
|
5017
|
+
// Remove the unsupported parameter and retry
|
5018
|
+
const modifiedModelRequirements = removeUnsupportedModelRequirement(currentModelRequirements, unsupportedParameter);
|
5019
|
+
return this.callCompletionModelWithRetry(prompt, modifiedModelRequirements);
|
4858
5020
|
}
|
4859
|
-
const resultContent = rawResponse.choices[0].text;
|
4860
|
-
const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
|
4861
|
-
return exportJson({
|
4862
|
-
name: 'promptResult',
|
4863
|
-
message: `Result of \`OpenAiCompatibleExecutionTools.callCompletionModel\``,
|
4864
|
-
order: [],
|
4865
|
-
value: {
|
4866
|
-
content: resultContent,
|
4867
|
-
modelName: rawResponse.model || modelName,
|
4868
|
-
timing: {
|
4869
|
-
start,
|
4870
|
-
complete,
|
4871
|
-
},
|
4872
|
-
usage,
|
4873
|
-
rawPromptContent,
|
4874
|
-
rawRequest,
|
4875
|
-
rawResponse,
|
4876
|
-
// <- [🗯]
|
4877
|
-
},
|
4878
|
-
});
|
4879
5021
|
}
|
4880
5022
|
/**
|
4881
5023
|
* Calls OpenAI compatible API to use a embedding model
|
@@ -4901,7 +5043,7 @@
|
|
4901
5043
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
4902
5044
|
}
|
4903
5045
|
const rawResponse = await this.limiter
|
4904
|
-
.schedule(() => this.
|
5046
|
+
.schedule(() => this.makeRequestWithNetworkRetry(() => client.embeddings.create(rawRequest)))
|
4905
5047
|
.catch((error) => {
|
4906
5048
|
assertsError(error);
|
4907
5049
|
if (this.options.isVerbose) {
|
@@ -4963,7 +5105,7 @@
|
|
4963
5105
|
/**
|
4964
5106
|
* Makes a request with retry logic for network errors like ECONNRESET
|
4965
5107
|
*/
|
4966
|
-
async
|
5108
|
+
async makeRequestWithNetworkRetry(requestFn) {
|
4967
5109
|
let lastError;
|
4968
5110
|
for (let attempt = 1; attempt <= CONNECTION_RETRIES_LIMIT; attempt++) {
|
4969
5111
|
try {
|
@@ -4975,8 +5117,8 @@
|
|
4975
5117
|
// Check if this is a retryable network error
|
4976
5118
|
const isRetryableError = this.isRetryableNetworkError(error);
|
4977
5119
|
if (!isRetryableError || attempt === CONNECTION_RETRIES_LIMIT) {
|
4978
|
-
if (this.options.isVerbose) {
|
4979
|
-
console.info(colors__default["default"].bgRed('Final error after retries'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}:`, error);
|
5120
|
+
if (this.options.isVerbose && this.isRetryableNetworkError(error)) {
|
5121
|
+
console.info(colors__default["default"].bgRed('Final network error after retries'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}:`, error);
|
4980
5122
|
}
|
4981
5123
|
throw error;
|
4982
5124
|
}
|
@@ -4986,7 +5128,7 @@
|
|
4986
5128
|
const jitterDelay = Math.random() * 500; // Add some randomness
|
4987
5129
|
const totalDelay = backoffDelay + jitterDelay;
|
4988
5130
|
if (this.options.isVerbose) {
|
4989
|
-
console.info(colors__default["default"].bgYellow('Retrying request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
|
5131
|
+
console.info(colors__default["default"].bgYellow('Retrying network request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
|
4990
5132
|
}
|
4991
5133
|
// Wait before retrying
|
4992
5134
|
await new Promise((resolve) => setTimeout(resolve, totalDelay));
|