@promptbook/openai 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
package/esm/index.es.js
CHANGED
|
@@ -19,7 +19,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
19
19
|
* @generated
|
|
20
20
|
* @see https://github.com/webgptorg/promptbook
|
|
21
21
|
*/
|
|
22
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.101.0-
|
|
22
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.101.0-15';
|
|
23
23
|
/**
|
|
24
24
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
25
25
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -2012,6 +2012,62 @@ resultContent, rawResponse) {
|
|
|
2012
2012
|
* TODO: [🤝] DRY Maybe some common abstraction between `computeOpenAiUsage` and `computeAnthropicClaudeUsage`
|
|
2013
2013
|
*/
|
|
2014
2014
|
|
|
2015
|
+
/**
|
|
2016
|
+
* Parses an OpenAI error message to identify which parameter is unsupported
|
|
2017
|
+
*
|
|
2018
|
+
* @param errorMessage The error message from OpenAI API
|
|
2019
|
+
* @returns The parameter name that is unsupported, or null if not an unsupported parameter error
|
|
2020
|
+
* @private utility of LLM Tools
|
|
2021
|
+
*/
|
|
2022
|
+
function parseUnsupportedParameterError(errorMessage) {
|
|
2023
|
+
// Pattern to match "Unsupported value: 'parameter' does not support ..."
|
|
2024
|
+
const unsupportedValueMatch = errorMessage.match(/Unsupported value:\s*'([^']+)'\s*does not support/i);
|
|
2025
|
+
if (unsupportedValueMatch === null || unsupportedValueMatch === void 0 ? void 0 : unsupportedValueMatch[1]) {
|
|
2026
|
+
return unsupportedValueMatch[1];
|
|
2027
|
+
}
|
|
2028
|
+
// Pattern to match "'parameter' of type ... is not supported with this model"
|
|
2029
|
+
const parameterTypeMatch = errorMessage.match(/'([^']+)'\s*of type.*is not supported with this model/i);
|
|
2030
|
+
if (parameterTypeMatch === null || parameterTypeMatch === void 0 ? void 0 : parameterTypeMatch[1]) {
|
|
2031
|
+
return parameterTypeMatch[1];
|
|
2032
|
+
}
|
|
2033
|
+
return null;
|
|
2034
|
+
}
|
|
2035
|
+
/**
|
|
2036
|
+
* Creates a copy of model requirements with the specified parameter removed
|
|
2037
|
+
*
|
|
2038
|
+
* @param modelRequirements Original model requirements
|
|
2039
|
+
* @param unsupportedParameter The parameter to remove
|
|
2040
|
+
* @returns New model requirements without the unsupported parameter
|
|
2041
|
+
* @private utility of LLM Tools
|
|
2042
|
+
*/
|
|
2043
|
+
function removeUnsupportedModelRequirement(modelRequirements, unsupportedParameter) {
|
|
2044
|
+
const newRequirements = { ...modelRequirements };
|
|
2045
|
+
// Map of parameter names that might appear in error messages to ModelRequirements properties
|
|
2046
|
+
const parameterMap = {
|
|
2047
|
+
'temperature': 'temperature',
|
|
2048
|
+
'max_tokens': 'maxTokens',
|
|
2049
|
+
'maxTokens': 'maxTokens',
|
|
2050
|
+
'seed': 'seed',
|
|
2051
|
+
};
|
|
2052
|
+
const propertyToRemove = parameterMap[unsupportedParameter];
|
|
2053
|
+
if (propertyToRemove && propertyToRemove in newRequirements) {
|
|
2054
|
+
delete newRequirements[propertyToRemove];
|
|
2055
|
+
}
|
|
2056
|
+
return newRequirements;
|
|
2057
|
+
}
|
|
2058
|
+
/**
|
|
2059
|
+
* Checks if an error is an "Unsupported value" error from OpenAI
|
|
2060
|
+
* @param error The error to check
|
|
2061
|
+
* @returns true if this is an unsupported parameter error
|
|
2062
|
+
* @private utility of LLM Tools
|
|
2063
|
+
*/
|
|
2064
|
+
function isUnsupportedParameterError(error) {
|
|
2065
|
+
const errorMessage = error.message.toLowerCase();
|
|
2066
|
+
return errorMessage.includes('unsupported value:') ||
|
|
2067
|
+
errorMessage.includes('is not supported with this model') ||
|
|
2068
|
+
errorMessage.includes('does not support');
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2015
2071
|
/**
|
|
2016
2072
|
* Execution Tools for calling OpenAI API or other OpenAI compatible provider
|
|
2017
2073
|
*
|
|
@@ -2029,6 +2085,10 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2029
2085
|
* OpenAI API client.
|
|
2030
2086
|
*/
|
|
2031
2087
|
this.client = null;
|
|
2088
|
+
/**
|
|
2089
|
+
* Tracks models and parameters that have already been retried to prevent infinite loops
|
|
2090
|
+
*/
|
|
2091
|
+
this.retriedUnsupportedParameters = new Set();
|
|
2032
2092
|
// TODO: Allow configuring rate limits via options
|
|
2033
2093
|
this.limiter = new Bottleneck({
|
|
2034
2094
|
minTime: 60000 / (this.options.maxRequestsPerMinute || DEFAULT_MAX_REQUESTS_PER_MINUTE),
|
|
@@ -2090,21 +2150,27 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2090
2150
|
* Calls OpenAI compatible API to use a chat model.
|
|
2091
2151
|
*/
|
|
2092
2152
|
async callChatModel(prompt) {
|
|
2153
|
+
return this.callChatModelWithRetry(prompt, prompt.modelRequirements);
|
|
2154
|
+
}
|
|
2155
|
+
/**
|
|
2156
|
+
* Internal method that handles parameter retry for chat model calls
|
|
2157
|
+
*/
|
|
2158
|
+
async callChatModelWithRetry(prompt, currentModelRequirements) {
|
|
2093
2159
|
var _a;
|
|
2094
2160
|
if (this.options.isVerbose) {
|
|
2095
|
-
console.info(`💬 ${this.title} callChatModel call`, { prompt });
|
|
2161
|
+
console.info(`💬 ${this.title} callChatModel call`, { prompt, currentModelRequirements });
|
|
2096
2162
|
}
|
|
2097
|
-
const { content, parameters,
|
|
2163
|
+
const { content, parameters, format } = prompt;
|
|
2098
2164
|
const client = await this.getClient();
|
|
2099
2165
|
// TODO: [☂] Use here more modelRequirements
|
|
2100
|
-
if (
|
|
2166
|
+
if (currentModelRequirements.modelVariant !== 'CHAT') {
|
|
2101
2167
|
throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
|
|
2102
2168
|
}
|
|
2103
|
-
const modelName =
|
|
2169
|
+
const modelName = currentModelRequirements.modelName || this.getDefaultChatModel().modelName;
|
|
2104
2170
|
const modelSettings = {
|
|
2105
2171
|
model: modelName,
|
|
2106
|
-
max_tokens:
|
|
2107
|
-
temperature:
|
|
2172
|
+
max_tokens: currentModelRequirements.maxTokens,
|
|
2173
|
+
temperature: currentModelRequirements.temperature,
|
|
2108
2174
|
// <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
|
|
2109
2175
|
// <- Note: [🧆]
|
|
2110
2176
|
}; // <- TODO: [💩] Guard here types better
|
|
@@ -2119,12 +2185,12 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2119
2185
|
const rawRequest = {
|
|
2120
2186
|
...modelSettings,
|
|
2121
2187
|
messages: [
|
|
2122
|
-
...(
|
|
2188
|
+
...(currentModelRequirements.systemMessage === undefined
|
|
2123
2189
|
? []
|
|
2124
2190
|
: [
|
|
2125
2191
|
{
|
|
2126
2192
|
role: 'system',
|
|
2127
|
-
content:
|
|
2193
|
+
content: currentModelRequirements.systemMessage,
|
|
2128
2194
|
},
|
|
2129
2195
|
]),
|
|
2130
2196
|
{
|
|
@@ -2138,69 +2204,110 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2138
2204
|
if (this.options.isVerbose) {
|
|
2139
2205
|
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
2140
2206
|
}
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2207
|
+
try {
|
|
2208
|
+
const rawResponse = await this.limiter
|
|
2209
|
+
.schedule(() => this.makeRequestWithNetworkRetry(() => client.chat.completions.create(rawRequest)))
|
|
2210
|
+
.catch((error) => {
|
|
2211
|
+
assertsError(error);
|
|
2212
|
+
if (this.options.isVerbose) {
|
|
2213
|
+
console.info(colors.bgRed('error'), error);
|
|
2214
|
+
}
|
|
2215
|
+
throw error;
|
|
2216
|
+
});
|
|
2145
2217
|
if (this.options.isVerbose) {
|
|
2146
|
-
console.info(colors.
|
|
2218
|
+
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
2147
2219
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2220
|
+
const complete = $getCurrentDate();
|
|
2221
|
+
if (!rawResponse.choices[0]) {
|
|
2222
|
+
throw new PipelineExecutionError(`No choises from ${this.title}`);
|
|
2223
|
+
}
|
|
2224
|
+
if (rawResponse.choices.length > 1) {
|
|
2225
|
+
// TODO: This should be maybe only warning
|
|
2226
|
+
throw new PipelineExecutionError(`More than one choise from ${this.title}`);
|
|
2227
|
+
}
|
|
2228
|
+
const resultContent = rawResponse.choices[0].message.content;
|
|
2229
|
+
const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
|
|
2230
|
+
if (resultContent === null) {
|
|
2231
|
+
throw new PipelineExecutionError(`No response message from ${this.title}`);
|
|
2232
|
+
}
|
|
2233
|
+
return exportJson({
|
|
2234
|
+
name: 'promptResult',
|
|
2235
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
|
|
2236
|
+
order: [],
|
|
2237
|
+
value: {
|
|
2238
|
+
content: resultContent,
|
|
2239
|
+
modelName: rawResponse.model || modelName,
|
|
2240
|
+
timing: {
|
|
2241
|
+
start,
|
|
2242
|
+
complete,
|
|
2243
|
+
},
|
|
2244
|
+
usage,
|
|
2245
|
+
rawPromptContent,
|
|
2246
|
+
rawRequest,
|
|
2247
|
+
rawResponse,
|
|
2248
|
+
// <- [🗯]
|
|
2249
|
+
},
|
|
2250
|
+
});
|
|
2160
2251
|
}
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2252
|
+
catch (error) {
|
|
2253
|
+
assertsError(error);
|
|
2254
|
+
// Check if this is an unsupported parameter error
|
|
2255
|
+
if (!isUnsupportedParameterError(error)) {
|
|
2256
|
+
throw error;
|
|
2257
|
+
}
|
|
2258
|
+
// Parse which parameter is unsupported
|
|
2259
|
+
const unsupportedParameter = parseUnsupportedParameterError(error.message);
|
|
2260
|
+
if (!unsupportedParameter) {
|
|
2261
|
+
if (this.options.isVerbose) {
|
|
2262
|
+
console.warn(colors.bgYellow('Warning'), 'Could not parse unsupported parameter from error:', error.message);
|
|
2263
|
+
}
|
|
2264
|
+
throw error;
|
|
2265
|
+
}
|
|
2266
|
+
// Create a unique key for this model + parameter combination to prevent infinite loops
|
|
2267
|
+
const retryKey = `${modelName}-${unsupportedParameter}`;
|
|
2268
|
+
if (this.retriedUnsupportedParameters.has(retryKey)) {
|
|
2269
|
+
// Already retried this parameter, throw the error
|
|
2270
|
+
if (this.options.isVerbose) {
|
|
2271
|
+
console.warn(colors.bgRed('Error'), `Parameter '${unsupportedParameter}' for model '${modelName}' already retried once, throwing error:`, error.message);
|
|
2272
|
+
}
|
|
2273
|
+
throw error;
|
|
2274
|
+
}
|
|
2275
|
+
// Mark this parameter as retried
|
|
2276
|
+
this.retriedUnsupportedParameters.add(retryKey);
|
|
2277
|
+
// Log warning in verbose mode
|
|
2278
|
+
if (this.options.isVerbose) {
|
|
2279
|
+
console.warn(colors.bgYellow('Warning'), `Removing unsupported parameter '${unsupportedParameter}' for model '${modelName}' and retrying request`);
|
|
2280
|
+
}
|
|
2281
|
+
// Remove the unsupported parameter and retry
|
|
2282
|
+
const modifiedModelRequirements = removeUnsupportedModelRequirement(currentModelRequirements, unsupportedParameter);
|
|
2283
|
+
return this.callChatModelWithRetry(prompt, modifiedModelRequirements);
|
|
2165
2284
|
}
|
|
2166
|
-
return exportJson({
|
|
2167
|
-
name: 'promptResult',
|
|
2168
|
-
message: `Result of \`OpenAiCompatibleExecutionTools.callChatModel\``,
|
|
2169
|
-
order: [],
|
|
2170
|
-
value: {
|
|
2171
|
-
content: resultContent,
|
|
2172
|
-
modelName: rawResponse.model || modelName,
|
|
2173
|
-
timing: {
|
|
2174
|
-
start,
|
|
2175
|
-
complete,
|
|
2176
|
-
},
|
|
2177
|
-
usage,
|
|
2178
|
-
rawPromptContent,
|
|
2179
|
-
rawRequest,
|
|
2180
|
-
rawResponse,
|
|
2181
|
-
// <- [🗯]
|
|
2182
|
-
},
|
|
2183
|
-
});
|
|
2184
2285
|
}
|
|
2185
2286
|
/**
|
|
2186
2287
|
* Calls OpenAI API to use a complete model.
|
|
2187
2288
|
*/
|
|
2188
2289
|
async callCompletionModel(prompt) {
|
|
2290
|
+
return this.callCompletionModelWithRetry(prompt, prompt.modelRequirements);
|
|
2291
|
+
}
|
|
2292
|
+
/**
|
|
2293
|
+
* Internal method that handles parameter retry for completion model calls
|
|
2294
|
+
*/
|
|
2295
|
+
async callCompletionModelWithRetry(prompt, currentModelRequirements) {
|
|
2189
2296
|
var _a;
|
|
2190
2297
|
if (this.options.isVerbose) {
|
|
2191
|
-
console.info(`🖋 ${this.title} callCompletionModel call`, { prompt });
|
|
2298
|
+
console.info(`🖋 ${this.title} callCompletionModel call`, { prompt, currentModelRequirements });
|
|
2192
2299
|
}
|
|
2193
|
-
const { content, parameters
|
|
2300
|
+
const { content, parameters } = prompt;
|
|
2194
2301
|
const client = await this.getClient();
|
|
2195
2302
|
// TODO: [☂] Use here more modelRequirements
|
|
2196
|
-
if (
|
|
2303
|
+
if (currentModelRequirements.modelVariant !== 'COMPLETION') {
|
|
2197
2304
|
throw new PipelineExecutionError('Use callCompletionModel only for COMPLETION variant');
|
|
2198
2305
|
}
|
|
2199
|
-
const modelName =
|
|
2306
|
+
const modelName = currentModelRequirements.modelName || this.getDefaultCompletionModel().modelName;
|
|
2200
2307
|
const modelSettings = {
|
|
2201
2308
|
model: modelName,
|
|
2202
|
-
max_tokens:
|
|
2203
|
-
temperature:
|
|
2309
|
+
max_tokens: currentModelRequirements.maxTokens,
|
|
2310
|
+
temperature: currentModelRequirements.temperature,
|
|
2204
2311
|
// <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
|
|
2205
2312
|
// <- Note: [🧆]
|
|
2206
2313
|
};
|
|
@@ -2214,46 +2321,81 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2214
2321
|
if (this.options.isVerbose) {
|
|
2215
2322
|
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
2216
2323
|
}
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2324
|
+
try {
|
|
2325
|
+
const rawResponse = await this.limiter
|
|
2326
|
+
.schedule(() => this.makeRequestWithNetworkRetry(() => client.completions.create(rawRequest)))
|
|
2327
|
+
.catch((error) => {
|
|
2328
|
+
assertsError(error);
|
|
2329
|
+
if (this.options.isVerbose) {
|
|
2330
|
+
console.info(colors.bgRed('error'), error);
|
|
2331
|
+
}
|
|
2332
|
+
throw error;
|
|
2333
|
+
});
|
|
2221
2334
|
if (this.options.isVerbose) {
|
|
2222
|
-
console.info(colors.
|
|
2335
|
+
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
2223
2336
|
}
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2337
|
+
const complete = $getCurrentDate();
|
|
2338
|
+
if (!rawResponse.choices[0]) {
|
|
2339
|
+
throw new PipelineExecutionError(`No choises from ${this.title}`);
|
|
2340
|
+
}
|
|
2341
|
+
if (rawResponse.choices.length > 1) {
|
|
2342
|
+
// TODO: This should be maybe only warning
|
|
2343
|
+
throw new PipelineExecutionError(`More than one choise from ${this.title}`);
|
|
2344
|
+
}
|
|
2345
|
+
const resultContent = rawResponse.choices[0].text;
|
|
2346
|
+
const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
|
|
2347
|
+
return exportJson({
|
|
2348
|
+
name: 'promptResult',
|
|
2349
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callCompletionModel\``,
|
|
2350
|
+
order: [],
|
|
2351
|
+
value: {
|
|
2352
|
+
content: resultContent,
|
|
2353
|
+
modelName: rawResponse.model || modelName,
|
|
2354
|
+
timing: {
|
|
2355
|
+
start,
|
|
2356
|
+
complete,
|
|
2357
|
+
},
|
|
2358
|
+
usage,
|
|
2359
|
+
rawPromptContent,
|
|
2360
|
+
rawRequest,
|
|
2361
|
+
rawResponse,
|
|
2362
|
+
// <- [🗯]
|
|
2363
|
+
},
|
|
2364
|
+
});
|
|
2232
2365
|
}
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2366
|
+
catch (error) {
|
|
2367
|
+
assertsError(error);
|
|
2368
|
+
// Check if this is an unsupported parameter error
|
|
2369
|
+
if (!isUnsupportedParameterError(error)) {
|
|
2370
|
+
throw error;
|
|
2371
|
+
}
|
|
2372
|
+
// Parse which parameter is unsupported
|
|
2373
|
+
const unsupportedParameter = parseUnsupportedParameterError(error.message);
|
|
2374
|
+
if (!unsupportedParameter) {
|
|
2375
|
+
if (this.options.isVerbose) {
|
|
2376
|
+
console.warn(colors.bgYellow('Warning'), 'Could not parse unsupported parameter from error:', error.message);
|
|
2377
|
+
}
|
|
2378
|
+
throw error;
|
|
2379
|
+
}
|
|
2380
|
+
// Create a unique key for this model + parameter combination to prevent infinite loops
|
|
2381
|
+
const retryKey = `${modelName}-${unsupportedParameter}`;
|
|
2382
|
+
if (this.retriedUnsupportedParameters.has(retryKey)) {
|
|
2383
|
+
// Already retried this parameter, throw the error
|
|
2384
|
+
if (this.options.isVerbose) {
|
|
2385
|
+
console.warn(colors.bgRed('Error'), `Parameter '${unsupportedParameter}' for model '${modelName}' already retried once, throwing error:`, error.message);
|
|
2386
|
+
}
|
|
2387
|
+
throw error;
|
|
2388
|
+
}
|
|
2389
|
+
// Mark this parameter as retried
|
|
2390
|
+
this.retriedUnsupportedParameters.add(retryKey);
|
|
2391
|
+
// Log warning in verbose mode
|
|
2392
|
+
if (this.options.isVerbose) {
|
|
2393
|
+
console.warn(colors.bgYellow('Warning'), `Removing unsupported parameter '${unsupportedParameter}' for model '${modelName}' and retrying request`);
|
|
2394
|
+
}
|
|
2395
|
+
// Remove the unsupported parameter and retry
|
|
2396
|
+
const modifiedModelRequirements = removeUnsupportedModelRequirement(currentModelRequirements, unsupportedParameter);
|
|
2397
|
+
return this.callCompletionModelWithRetry(prompt, modifiedModelRequirements);
|
|
2236
2398
|
}
|
|
2237
|
-
const resultContent = rawResponse.choices[0].text;
|
|
2238
|
-
const usage = this.computeUsage(content || '', resultContent || '', rawResponse);
|
|
2239
|
-
return exportJson({
|
|
2240
|
-
name: 'promptResult',
|
|
2241
|
-
message: `Result of \`OpenAiCompatibleExecutionTools.callCompletionModel\``,
|
|
2242
|
-
order: [],
|
|
2243
|
-
value: {
|
|
2244
|
-
content: resultContent,
|
|
2245
|
-
modelName: rawResponse.model || modelName,
|
|
2246
|
-
timing: {
|
|
2247
|
-
start,
|
|
2248
|
-
complete,
|
|
2249
|
-
},
|
|
2250
|
-
usage,
|
|
2251
|
-
rawPromptContent,
|
|
2252
|
-
rawRequest,
|
|
2253
|
-
rawResponse,
|
|
2254
|
-
// <- [🗯]
|
|
2255
|
-
},
|
|
2256
|
-
});
|
|
2257
2399
|
}
|
|
2258
2400
|
/**
|
|
2259
2401
|
* Calls OpenAI compatible API to use a embedding model
|
|
@@ -2279,7 +2421,7 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2279
2421
|
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
2280
2422
|
}
|
|
2281
2423
|
const rawResponse = await this.limiter
|
|
2282
|
-
.schedule(() => this.
|
|
2424
|
+
.schedule(() => this.makeRequestWithNetworkRetry(() => client.embeddings.create(rawRequest)))
|
|
2283
2425
|
.catch((error) => {
|
|
2284
2426
|
assertsError(error);
|
|
2285
2427
|
if (this.options.isVerbose) {
|
|
@@ -2341,7 +2483,7 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2341
2483
|
/**
|
|
2342
2484
|
* Makes a request with retry logic for network errors like ECONNRESET
|
|
2343
2485
|
*/
|
|
2344
|
-
async
|
|
2486
|
+
async makeRequestWithNetworkRetry(requestFn) {
|
|
2345
2487
|
let lastError;
|
|
2346
2488
|
for (let attempt = 1; attempt <= CONNECTION_RETRIES_LIMIT; attempt++) {
|
|
2347
2489
|
try {
|
|
@@ -2353,8 +2495,8 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2353
2495
|
// Check if this is a retryable network error
|
|
2354
2496
|
const isRetryableError = this.isRetryableNetworkError(error);
|
|
2355
2497
|
if (!isRetryableError || attempt === CONNECTION_RETRIES_LIMIT) {
|
|
2356
|
-
if (this.options.isVerbose) {
|
|
2357
|
-
console.info(colors.bgRed('Final error after retries'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}:`, error);
|
|
2498
|
+
if (this.options.isVerbose && this.isRetryableNetworkError(error)) {
|
|
2499
|
+
console.info(colors.bgRed('Final network error after retries'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}:`, error);
|
|
2358
2500
|
}
|
|
2359
2501
|
throw error;
|
|
2360
2502
|
}
|
|
@@ -2364,7 +2506,7 @@ class OpenAiCompatibleExecutionTools {
|
|
|
2364
2506
|
const jitterDelay = Math.random() * 500; // Add some randomness
|
|
2365
2507
|
const totalDelay = backoffDelay + jitterDelay;
|
|
2366
2508
|
if (this.options.isVerbose) {
|
|
2367
|
-
console.info(colors.bgYellow('Retrying request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
|
|
2509
|
+
console.info(colors.bgYellow('Retrying network request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
|
|
2368
2510
|
}
|
|
2369
2511
|
// Wait before retrying
|
|
2370
2512
|
await new Promise((resolve) => setTimeout(resolve, totalDelay));
|