@memberjunction/ai-prompts 2.48.0 → 2.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +369 -24
- package/dist/AIPromptCategoryExtended.d.ts.map +1 -1
- package/dist/AIPromptCategoryExtended.js +2 -2
- package/dist/AIPromptCategoryExtended.js.map +1 -1
- package/dist/AIPromptRunner.d.ts +4 -94
- package/dist/AIPromptRunner.d.ts.map +1 -1
- package/dist/AIPromptRunner.js +175 -143
- package/dist/AIPromptRunner.js.map +1 -1
- package/dist/SystemPlaceholders.d.ts +18 -0
- package/dist/SystemPlaceholders.d.ts.map +1 -0
- package/dist/SystemPlaceholders.js +239 -0
- package/dist/SystemPlaceholders.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +101 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +10 -7
package/dist/AIPromptRunner.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.LoadAIPromptRunner = exports.AIPromptRunner = exports.
|
|
6
|
+
exports.LoadAIPromptRunner = exports.AIPromptRunner = exports.AIPromptParams = void 0;
|
|
7
7
|
const ai_1 = require("@memberjunction/ai");
|
|
8
8
|
const core_1 = require("@memberjunction/core");
|
|
9
9
|
const global_1 = require("@memberjunction/global");
|
|
@@ -12,19 +12,9 @@ const ExecutionPlanner_1 = require("./ExecutionPlanner");
|
|
|
12
12
|
const ParallelExecutionCoordinator_1 = require("./ParallelExecutionCoordinator");
|
|
13
13
|
const aiengine_1 = require("@memberjunction/aiengine");
|
|
14
14
|
const ajv_1 = __importDefault(require("ajv"));
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this.parentPlaceholder = parentPlaceholder;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
exports.ChildPromptParam = ChildPromptParam;
|
|
22
|
-
class AIPromptParams {
|
|
23
|
-
}
|
|
24
|
-
exports.AIPromptParams = AIPromptParams;
|
|
25
|
-
class AIPromptRunResult {
|
|
26
|
-
}
|
|
27
|
-
exports.AIPromptRunResult = AIPromptRunResult;
|
|
15
|
+
const SystemPlaceholders_1 = require("./SystemPlaceholders");
|
|
16
|
+
var types_1 = require("./types");
|
|
17
|
+
Object.defineProperty(exports, "AIPromptParams", { enumerable: true, get: function () { return types_1.AIPromptParams; } });
|
|
28
18
|
class AIPromptRunner {
|
|
29
19
|
constructor() {
|
|
30
20
|
this._metadata = new core_1.Metadata();
|
|
@@ -50,7 +40,7 @@ class AIPromptRunner {
|
|
|
50
40
|
const startTime = new Date();
|
|
51
41
|
const promptRun = null;
|
|
52
42
|
if (params.cancellationToken?.aborted) {
|
|
53
|
-
|
|
43
|
+
const result = {
|
|
54
44
|
success: false,
|
|
55
45
|
status: 'cancelled',
|
|
56
46
|
cancelled: true,
|
|
@@ -58,7 +48,10 @@ class AIPromptRunner {
|
|
|
58
48
|
errorMessage: 'Prompt execution was cancelled before starting',
|
|
59
49
|
executionTimeMS: 0,
|
|
60
50
|
chatResult: { success: false, errorMessage: 'Prompt execution was cancelled before starting' },
|
|
51
|
+
tokensUsed: 0,
|
|
52
|
+
combinedTokensUsed: 0
|
|
61
53
|
};
|
|
54
|
+
return result;
|
|
62
55
|
}
|
|
63
56
|
try {
|
|
64
57
|
const prompt = params.prompt;
|
|
@@ -69,11 +62,20 @@ class AIPromptRunner {
|
|
|
69
62
|
throw new Error(`Prompt ${prompt.Name} is not active (Status: ${prompt.Status})`);
|
|
70
63
|
}
|
|
71
64
|
let renderedPromptText = '';
|
|
65
|
+
let parentPromptRun;
|
|
66
|
+
let selectedModel;
|
|
67
|
+
let childTemplateRenderingResult;
|
|
72
68
|
if (params.childPrompts && params.childPrompts.length > 0) {
|
|
73
|
-
(0, core_1.LogStatus)(`🌳
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
(0, core_1.LogStatus)(`🌳 Composing prompt with ${params.childPrompts.length} child templates in hierarchical mode`);
|
|
70
|
+
selectedModel = await this.selectModel(prompt, params.modelId, params.contextUser, params.configurationId, params.vendorId);
|
|
71
|
+
if (!selectedModel) {
|
|
72
|
+
throw new Error(`No suitable model found for prompt ${prompt.Name}`);
|
|
73
|
+
}
|
|
74
|
+
parentPromptRun = await this.createPromptRun(prompt, selectedModel, params, startTime, params.vendorId);
|
|
75
|
+
(0, core_1.LogStatus)(`📝 Created prompt run ${parentPromptRun.ID} for hierarchical template composition`);
|
|
76
|
+
childTemplateRenderingResult = await this.renderChildPromptTemplates(params.childPrompts, params, params.cancellationToken);
|
|
77
|
+
renderedPromptText = await this.renderPromptWithChildTemplates(prompt, params, childTemplateRenderingResult.renderedTemplates);
|
|
78
|
+
(0, core_1.LogStatus)(`✅ Hierarchical template composition completed with ${Object.keys(childTemplateRenderingResult.renderedTemplates).length} child templates embedded`);
|
|
77
79
|
}
|
|
78
80
|
else if (prompt.TemplateID && (!params.conversationMessages || params.templateMessageRole !== 'none')) {
|
|
79
81
|
await this._templateEngine.Config(false, params.contextUser);
|
|
@@ -81,7 +83,7 @@ class AIPromptRunner {
|
|
|
81
83
|
if (!template) {
|
|
82
84
|
throw new Error(`Template with ID ${prompt.TemplateID} not found for prompt ${prompt.Name}`);
|
|
83
85
|
}
|
|
84
|
-
const renderedPrompt = await this.renderPromptTemplate(template, params
|
|
86
|
+
const renderedPrompt = await this.renderPromptTemplate(template, params);
|
|
85
87
|
if (!renderedPrompt.Success) {
|
|
86
88
|
throw new Error(`Failed to render template for prompt ${prompt.Name}: ${renderedPrompt.Message}`);
|
|
87
89
|
}
|
|
@@ -91,12 +93,14 @@ class AIPromptRunner {
|
|
|
91
93
|
throw new Error('Prompt execution was cancelled during template rendering');
|
|
92
94
|
}
|
|
93
95
|
const shouldUseParallelExecution = prompt.ParallelizationMode && prompt.ParallelizationMode !== 'None';
|
|
96
|
+
let result;
|
|
94
97
|
if (shouldUseParallelExecution) {
|
|
95
|
-
|
|
98
|
+
result = await this.executePromptInParallel(prompt, renderedPromptText, params, startTime, parentPromptRun);
|
|
96
99
|
}
|
|
97
100
|
else {
|
|
98
|
-
|
|
101
|
+
result = await this.executeSinglePrompt(prompt, renderedPromptText, params, startTime, parentPromptRun, selectedModel);
|
|
99
102
|
}
|
|
103
|
+
return result;
|
|
100
104
|
}
|
|
101
105
|
catch (error) {
|
|
102
106
|
(0, core_1.LogError)(error);
|
|
@@ -111,27 +115,30 @@ class AIPromptRunner {
|
|
|
111
115
|
(0, core_1.LogError)(`Failed to save error to AIPromptRun: ${promptRun.LatestResult?.Message || 'Unknown error'}`);
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
|
-
|
|
118
|
+
const errorResult = {
|
|
115
119
|
success: false,
|
|
116
120
|
errorMessage: error.message,
|
|
117
121
|
promptRun,
|
|
118
122
|
executionTimeMS,
|
|
119
123
|
chatResult: { success: false, errorMessage: error.message },
|
|
124
|
+
tokensUsed: 0,
|
|
125
|
+
combinedTokensUsed: 0
|
|
120
126
|
};
|
|
127
|
+
return errorResult;
|
|
121
128
|
}
|
|
122
129
|
}
|
|
123
|
-
async executeSinglePrompt(prompt, renderedPromptText, params, startTime) {
|
|
130
|
+
async executeSinglePrompt(prompt, renderedPromptText, params, startTime, existingPromptRun, existingModel) {
|
|
124
131
|
if (params.cancellationToken?.aborted) {
|
|
125
132
|
throw new Error('Prompt execution was cancelled before model selection');
|
|
126
133
|
}
|
|
127
|
-
const selectedModel = await this.selectModel(prompt, params.modelId, params.contextUser, params.configurationId, params.vendorId);
|
|
134
|
+
const selectedModel = existingModel || await this.selectModel(prompt, params.modelId, params.contextUser, params.configurationId, params.vendorId);
|
|
128
135
|
if (!selectedModel) {
|
|
129
136
|
throw new Error(`No suitable model found for prompt ${prompt.Name}`);
|
|
130
137
|
}
|
|
131
138
|
if (params.cancellationToken?.aborted) {
|
|
132
139
|
throw new Error('Prompt execution was cancelled after model selection');
|
|
133
140
|
}
|
|
134
|
-
const promptRun = await this.createPromptRun(prompt, selectedModel, params, startTime, params.vendorId);
|
|
141
|
+
const promptRun = existingPromptRun || await this.createPromptRun(prompt, selectedModel, params, startTime, params.vendorId);
|
|
135
142
|
if (params.cancellationToken?.aborted) {
|
|
136
143
|
throw new Error('Prompt execution was cancelled before model execution');
|
|
137
144
|
}
|
|
@@ -140,6 +147,7 @@ class AIPromptRunner {
|
|
|
140
147
|
const executionTimeMS = endTime.getTime() - startTime.getTime();
|
|
141
148
|
await this.updatePromptRun(promptRun, modelResult, parsedResult, endTime, executionTimeMS, validationAttempts);
|
|
142
149
|
const chatResult = modelResult;
|
|
150
|
+
const usage = chatResult.data?.usage;
|
|
143
151
|
return {
|
|
144
152
|
success: true,
|
|
145
153
|
rawResult: chatResult.data?.choices?.[0]?.message?.content,
|
|
@@ -147,12 +155,17 @@ class AIPromptRunner {
|
|
|
147
155
|
chatResult,
|
|
148
156
|
promptRun,
|
|
149
157
|
executionTimeMS,
|
|
150
|
-
|
|
158
|
+
promptTokens: usage?.promptTokens,
|
|
159
|
+
completionTokens: usage?.completionTokens,
|
|
160
|
+
tokensUsed: (usage?.promptTokens || 0) + (usage?.completionTokens || 0),
|
|
161
|
+
cost: usage?.cost,
|
|
162
|
+
costCurrency: usage?.costCurrency,
|
|
151
163
|
validationResult: parsedResult.validationResult,
|
|
152
164
|
validationAttempts,
|
|
165
|
+
combinedTokensUsed: (usage?.promptTokens || 0) + (usage?.completionTokens || 0)
|
|
153
166
|
};
|
|
154
167
|
}
|
|
155
|
-
async executePromptInParallel(prompt, renderedPromptText, params, startTime) {
|
|
168
|
+
async executePromptInParallel(prompt, renderedPromptText, params, startTime, existingPromptRun) {
|
|
156
169
|
if (params.cancellationToken?.aborted) {
|
|
157
170
|
throw new Error('Parallel execution was cancelled before starting');
|
|
158
171
|
}
|
|
@@ -186,12 +199,38 @@ class AIPromptRunner {
|
|
|
186
199
|
selectedResult = aiSelectedResult;
|
|
187
200
|
}
|
|
188
201
|
}
|
|
189
|
-
|
|
202
|
+
let totalPromptTokens = 0;
|
|
203
|
+
let totalCompletionTokens = 0;
|
|
204
|
+
let totalCost = 0;
|
|
205
|
+
let hasCost = false;
|
|
206
|
+
for (const result of successfulResults) {
|
|
207
|
+
const usage = result.modelResult?.data?.usage;
|
|
208
|
+
if (usage) {
|
|
209
|
+
totalPromptTokens += usage.promptTokens || 0;
|
|
210
|
+
totalCompletionTokens += usage.completionTokens || 0;
|
|
211
|
+
if (usage.cost !== undefined) {
|
|
212
|
+
totalCost += usage.cost;
|
|
213
|
+
hasCost = true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const consolidatedPromptRun = existingPromptRun || await this.createPromptRun(prompt, selectedResult.task.model, params, startTime, params.vendorId);
|
|
190
218
|
const endTime = new Date();
|
|
191
219
|
consolidatedPromptRun.CompletedAt = endTime;
|
|
192
220
|
consolidatedPromptRun.ExecutionTimeMS = parallelResult.totalExecutionTimeMS;
|
|
193
221
|
consolidatedPromptRun.Result = selectedResult.rawResult || '';
|
|
194
222
|
consolidatedPromptRun.TokensUsed = parallelResult.totalTokensUsed;
|
|
223
|
+
const selectedResultUsage = selectedResult.modelResult?.data?.usage;
|
|
224
|
+
if (selectedResultUsage) {
|
|
225
|
+
consolidatedPromptRun.TokensPrompt = selectedResultUsage.promptTokens;
|
|
226
|
+
consolidatedPromptRun.TokensCompletion = selectedResultUsage.completionTokens;
|
|
227
|
+
if (selectedResultUsage.cost !== undefined) {
|
|
228
|
+
consolidatedPromptRun.Cost = selectedResultUsage.cost;
|
|
229
|
+
}
|
|
230
|
+
if (selectedResultUsage.costCurrency !== undefined) {
|
|
231
|
+
consolidatedPromptRun.CostCurrency = selectedResultUsage.costCurrency;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
195
234
|
const parallelMetadata = {
|
|
196
235
|
parallelizationMode: prompt.ParallelizationMode,
|
|
197
236
|
totalTasks: executionTasks.length,
|
|
@@ -207,6 +246,12 @@ class AIPromptRunner {
|
|
|
207
246
|
parallelExecution: parallelMetadata,
|
|
208
247
|
});
|
|
209
248
|
}
|
|
249
|
+
consolidatedPromptRun.TokensPromptRollup = totalPromptTokens;
|
|
250
|
+
consolidatedPromptRun.TokensCompletionRollup = totalCompletionTokens;
|
|
251
|
+
consolidatedPromptRun.TokensUsedRollup = totalPromptTokens + totalCompletionTokens;
|
|
252
|
+
if (hasCost) {
|
|
253
|
+
consolidatedPromptRun.TotalCost = totalCost;
|
|
254
|
+
}
|
|
210
255
|
const saveResult = await consolidatedPromptRun.Save();
|
|
211
256
|
if (!saveResult) {
|
|
212
257
|
(0, core_1.LogError)(`Failed to save consolidated AIPromptRun: ${consolidatedPromptRun.LatestResult?.Message || 'Unknown error'}`);
|
|
@@ -222,13 +267,18 @@ class AIPromptRunner {
|
|
|
222
267
|
if (result.task.taskId !== selectedResult.task.taskId) {
|
|
223
268
|
const { result: parsedResultData, validationResult, validationErrors } = await this.parseAndValidateResultEnhanced(result.modelResult, prompt, params.skipValidation);
|
|
224
269
|
const parsedResult = { result: parsedResultData, validationResult };
|
|
270
|
+
const resultUsage = result.modelResult?.data?.usage;
|
|
225
271
|
additionalResults.push({
|
|
226
272
|
success: result.success,
|
|
227
273
|
rawResult: result.rawResult,
|
|
228
274
|
result: parsedResult.result,
|
|
229
275
|
chatResult: result.modelResult,
|
|
230
276
|
executionTimeMS: result.executionTimeMS,
|
|
231
|
-
|
|
277
|
+
promptTokens: resultUsage?.promptTokens,
|
|
278
|
+
completionTokens: resultUsage?.completionTokens,
|
|
279
|
+
tokensUsed: (resultUsage?.promptTokens || 0) + (resultUsage?.completionTokens || 0),
|
|
280
|
+
cost: resultUsage?.cost,
|
|
281
|
+
costCurrency: resultUsage?.costCurrency,
|
|
232
282
|
validationResult: parsedResult.validationResult,
|
|
233
283
|
ranking: result.ranking,
|
|
234
284
|
judgeRationale: result.judgeRationale,
|
|
@@ -238,11 +288,13 @@ class AIPromptRunner {
|
|
|
238
288
|
vendorId: undefined,
|
|
239
289
|
vendorName: result.task.model.Vendor,
|
|
240
290
|
},
|
|
291
|
+
combinedTokensUsed: (resultUsage?.promptTokens || 0) + (resultUsage?.completionTokens || 0)
|
|
241
292
|
});
|
|
242
293
|
}
|
|
243
294
|
}
|
|
244
295
|
const { result: selectedResultData, validationResult: selectedValidationResult } = await this.parseAndValidateResultEnhanced(selectedResult.modelResult, prompt, params.skipValidation);
|
|
245
296
|
const selectedParsedResult = { result: selectedResultData, validationResult: selectedValidationResult };
|
|
297
|
+
const selectedUsage = selectedResult.modelResult?.data?.usage;
|
|
246
298
|
return {
|
|
247
299
|
success: true,
|
|
248
300
|
rawResult: selectedResult.rawResult,
|
|
@@ -250,7 +302,15 @@ class AIPromptRunner {
|
|
|
250
302
|
chatResult: selectedResult.modelResult,
|
|
251
303
|
promptRun: consolidatedPromptRun,
|
|
252
304
|
executionTimeMS: parallelResult.totalExecutionTimeMS,
|
|
253
|
-
|
|
305
|
+
promptTokens: selectedUsage?.promptTokens,
|
|
306
|
+
completionTokens: selectedUsage?.completionTokens,
|
|
307
|
+
tokensUsed: (selectedUsage?.promptTokens || 0) + (selectedUsage?.completionTokens || 0),
|
|
308
|
+
cost: selectedUsage?.cost,
|
|
309
|
+
costCurrency: selectedUsage?.costCurrency,
|
|
310
|
+
combinedPromptTokens: totalPromptTokens,
|
|
311
|
+
combinedCompletionTokens: totalCompletionTokens,
|
|
312
|
+
combinedTokensUsed: totalPromptTokens + totalCompletionTokens,
|
|
313
|
+
combinedCost: hasCost ? totalCost : undefined,
|
|
254
314
|
validationResult: selectedParsedResult.validationResult,
|
|
255
315
|
additionalResults: additionalResults.length > 0 ? additionalResults : undefined,
|
|
256
316
|
ranking: selectedResult.ranking || 1,
|
|
@@ -274,61 +334,83 @@ class AIPromptRunner {
|
|
|
274
334
|
return null;
|
|
275
335
|
}
|
|
276
336
|
}
|
|
277
|
-
async
|
|
337
|
+
async renderChildPromptTemplates(childPrompts, params, cancellationToken) {
|
|
278
338
|
if (!childPrompts || childPrompts.length === 0) {
|
|
279
|
-
return {
|
|
339
|
+
return {
|
|
340
|
+
renderedTemplates: {}
|
|
341
|
+
};
|
|
280
342
|
}
|
|
281
343
|
if (cancellationToken?.aborted) {
|
|
282
344
|
throw new Error('Child prompt execution was cancelled');
|
|
283
345
|
}
|
|
284
|
-
(0, core_1.LogStatus)(`🔄
|
|
285
|
-
const
|
|
346
|
+
(0, core_1.LogStatus)(`🔄 Rendering ${childPrompts.length} child prompt templates in parallel`);
|
|
347
|
+
const childRenderingPromises = childPrompts.map(async (childParam) => {
|
|
286
348
|
try {
|
|
287
349
|
if (cancellationToken?.aborted) {
|
|
288
|
-
throw new Error('Child prompt
|
|
350
|
+
throw new Error('Child prompt template rendering was cancelled');
|
|
289
351
|
}
|
|
290
352
|
let childData = { ...childParam.childPrompt.data };
|
|
291
353
|
if (childParam.childPrompt.childPrompts && childParam.childPrompt.childPrompts.length > 0) {
|
|
292
|
-
const grandchildResults = await this.
|
|
293
|
-
childData = { ...childData, ...grandchildResults };
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
354
|
+
const grandchildResults = await this.renderChildPromptTemplates(childParam.childPrompt.childPrompts, params, cancellationToken);
|
|
355
|
+
childData = { ...childData, ...grandchildResults.renderedTemplates };
|
|
356
|
+
}
|
|
357
|
+
(0, core_1.LogStatus)(` 🔹 Rendering child prompt template: ${childParam.childPrompt.prompt.Name} -> ${childParam.parentPlaceholder}`);
|
|
358
|
+
const childPrompt = childParam.childPrompt.prompt;
|
|
359
|
+
let renderedChildTemplate = '';
|
|
360
|
+
if (childPrompt.TemplateID) {
|
|
361
|
+
await this._templateEngine.Config(false, params.contextUser);
|
|
362
|
+
const template = await this.loadTemplate(childPrompt.TemplateID, params.contextUser);
|
|
363
|
+
if (!template) {
|
|
364
|
+
throw new Error(`Template with ID ${childPrompt.TemplateID} not found for child prompt ${childPrompt.Name}`);
|
|
365
|
+
}
|
|
366
|
+
const mergedChildData = {
|
|
367
|
+
...params.data,
|
|
368
|
+
...childData,
|
|
369
|
+
...childParam.childPrompt.templateData
|
|
370
|
+
};
|
|
371
|
+
const childRenderResult = await this.renderPromptTemplate(template, {
|
|
372
|
+
...params,
|
|
373
|
+
data: mergedChildData,
|
|
374
|
+
templateData: childParam.childPrompt.templateData
|
|
375
|
+
});
|
|
376
|
+
if (!childRenderResult.Success) {
|
|
377
|
+
throw new Error(`Failed to render child template for prompt ${childPrompt.Name}: ${childRenderResult.Message}`);
|
|
378
|
+
}
|
|
379
|
+
renderedChildTemplate = childRenderResult.Output;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
renderedChildTemplate = '';
|
|
303
383
|
}
|
|
304
384
|
return {
|
|
305
385
|
placeholder: childParam.parentPlaceholder,
|
|
306
|
-
|
|
386
|
+
renderedTemplate: renderedChildTemplate,
|
|
307
387
|
success: true
|
|
308
388
|
};
|
|
309
389
|
}
|
|
310
390
|
catch (error) {
|
|
311
|
-
(0, core_1.LogError)(`Error
|
|
391
|
+
(0, core_1.LogError)(`Error rendering child prompt template for placeholder ${childParam.parentPlaceholder}: ${error.message}`);
|
|
312
392
|
return {
|
|
313
393
|
placeholder: childParam.parentPlaceholder,
|
|
314
|
-
|
|
394
|
+
renderedTemplate: `ERROR: ${error.message}`,
|
|
315
395
|
success: false
|
|
316
396
|
};
|
|
317
397
|
}
|
|
318
398
|
});
|
|
319
|
-
const childResults = await Promise.all(
|
|
399
|
+
const childResults = await Promise.all(childRenderingPromises);
|
|
320
400
|
const failedChildren = childResults.filter(r => !r.success);
|
|
321
401
|
if (failedChildren.length > 0) {
|
|
322
|
-
(0, core_1.LogError)(`${failedChildren.length} out of ${childResults.length} child
|
|
402
|
+
(0, core_1.LogError)(`${failedChildren.length} out of ${childResults.length} child prompt templates failed to render`);
|
|
323
403
|
}
|
|
324
|
-
const
|
|
404
|
+
const renderedTemplatesMap = {};
|
|
325
405
|
for (const childResult of childResults) {
|
|
326
|
-
|
|
406
|
+
renderedTemplatesMap[childResult.placeholder] = childResult.renderedTemplate;
|
|
327
407
|
}
|
|
328
|
-
(0, core_1.LogStatus)(`✅ Completed
|
|
329
|
-
return
|
|
408
|
+
(0, core_1.LogStatus)(`✅ Completed rendering of ${childResults.length} child prompt templates`);
|
|
409
|
+
return {
|
|
410
|
+
renderedTemplates: renderedTemplatesMap
|
|
411
|
+
};
|
|
330
412
|
}
|
|
331
|
-
async
|
|
413
|
+
async renderPromptWithChildTemplates(prompt, params, childTemplates) {
|
|
332
414
|
if (!prompt.TemplateID) {
|
|
333
415
|
return '';
|
|
334
416
|
}
|
|
@@ -338,24 +420,26 @@ class AIPromptRunner {
|
|
|
338
420
|
if (!template) {
|
|
339
421
|
throw new Error(`Template with ID ${prompt.TemplateID} not found for prompt ${prompt.Name}`);
|
|
340
422
|
}
|
|
423
|
+
const systemPlaceholders = await SystemPlaceholders_1.SystemPlaceholderManager.resolveAllPlaceholders(params);
|
|
341
424
|
const mergedData = {
|
|
425
|
+
...systemPlaceholders,
|
|
342
426
|
...params.data,
|
|
343
|
-
...
|
|
427
|
+
...childTemplates,
|
|
344
428
|
...params.templateData
|
|
345
429
|
};
|
|
346
|
-
(0, core_1.LogStatus)(`🔧 Rendering prompt template with ${Object.keys(
|
|
347
|
-
for (const [placeholder,
|
|
348
|
-
const
|
|
349
|
-
(0, core_1.LogStatus)(` 📝 ${placeholder} -> ${
|
|
430
|
+
(0, core_1.LogStatus)(`🔧 Rendering prompt template with ${Object.keys(childTemplates).length} child templates and ${Object.keys(systemPlaceholders).length} system placeholders`);
|
|
431
|
+
for (const [placeholder, template] of Object.entries(childTemplates)) {
|
|
432
|
+
const truncatedTemplate = template.length > 100 ? template.substring(0, 100) + '...' : template;
|
|
433
|
+
(0, core_1.LogStatus)(` 📝 ${placeholder} -> ${truncatedTemplate}`);
|
|
350
434
|
}
|
|
351
|
-
const renderedPrompt = await this.
|
|
435
|
+
const renderedPrompt = await this._templateEngine.RenderTemplate(template, template.GetHighestPriorityContent(), mergedData);
|
|
352
436
|
if (!renderedPrompt.Success) {
|
|
353
437
|
throw new Error(`Failed to render template for prompt ${prompt.Name}: ${renderedPrompt.Message}`);
|
|
354
438
|
}
|
|
355
439
|
return renderedPrompt.Output;
|
|
356
440
|
}
|
|
357
441
|
catch (error) {
|
|
358
|
-
(0, core_1.LogError)(`Error rendering prompt with child
|
|
442
|
+
(0, core_1.LogError)(`Error rendering prompt with child templates: ${error.message}`);
|
|
359
443
|
throw error;
|
|
360
444
|
}
|
|
361
445
|
}
|
|
@@ -434,8 +518,8 @@ class AIPromptRunner {
|
|
|
434
518
|
}
|
|
435
519
|
}
|
|
436
520
|
async createPromptRun(prompt, model, params, startTime, vendorId) {
|
|
521
|
+
const promptRun = await this._metadata.GetEntityObject('MJ: AI Prompt Runs', params.contextUser);
|
|
437
522
|
try {
|
|
438
|
-
const promptRun = await this._metadata.GetEntityObject('MJ: AI Prompt Runs', params.contextUser);
|
|
439
523
|
promptRun.NewRecord();
|
|
440
524
|
promptRun.PromptID = prompt.ID;
|
|
441
525
|
promptRun.ModelID = model.ID;
|
|
@@ -454,6 +538,9 @@ class AIPromptRunner {
|
|
|
454
538
|
if (params.agentRunId) {
|
|
455
539
|
promptRun.AgentRunID = params.agentRunId;
|
|
456
540
|
}
|
|
541
|
+
if (params.parentPromptRunId) {
|
|
542
|
+
promptRun.ParentID = params.parentPromptRunId;
|
|
543
|
+
}
|
|
457
544
|
if (params.data || params.templateData) {
|
|
458
545
|
promptRun.Messages = JSON.stringify({
|
|
459
546
|
data: params.data,
|
|
@@ -469,17 +556,24 @@ class AIPromptRunner {
|
|
|
469
556
|
return promptRun;
|
|
470
557
|
}
|
|
471
558
|
catch (error) {
|
|
472
|
-
|
|
473
|
-
|
|
559
|
+
const msg = `Error creating prompt run record: ${error.message} - ${promptRun?.LatestResult?.Message} - ${promptRun?.LatestResult?.Errors[0]?.Message}`;
|
|
560
|
+
(0, core_1.LogError)(msg);
|
|
561
|
+
throw new Error(msg);
|
|
474
562
|
}
|
|
475
563
|
}
|
|
476
|
-
async renderPromptTemplate(template,
|
|
564
|
+
async renderPromptTemplate(template, params) {
|
|
477
565
|
try {
|
|
478
566
|
const templateContent = template.GetHighestPriorityContent();
|
|
479
567
|
if (!templateContent) {
|
|
480
568
|
throw new Error(`No content found for template ${template.Name}`);
|
|
481
569
|
}
|
|
482
|
-
const
|
|
570
|
+
const systemPlaceholders = await SystemPlaceholders_1.SystemPlaceholderManager.resolveAllPlaceholders(params);
|
|
571
|
+
const mergedData = {
|
|
572
|
+
...systemPlaceholders,
|
|
573
|
+
...params.data,
|
|
574
|
+
...params.templateData
|
|
575
|
+
};
|
|
576
|
+
(0, core_1.LogStatus)(`🔧 Rendering template '${template.Name}' with ${Object.keys(systemPlaceholders).length} system placeholders`);
|
|
483
577
|
return await this._templateEngine.RenderTemplate(template, templateContent, mergedData);
|
|
484
578
|
}
|
|
485
579
|
catch (error) {
|
|
@@ -888,80 +982,6 @@ class AIPromptRunner {
|
|
|
888
982
|
}
|
|
889
983
|
return validationErrors;
|
|
890
984
|
}
|
|
891
|
-
async parseAndValidateResult(modelResult, prompt, skipValidation = false) {
|
|
892
|
-
try {
|
|
893
|
-
if (!modelResult.success) {
|
|
894
|
-
throw new Error(`Model execution failed: ${modelResult.errorMessage}`);
|
|
895
|
-
}
|
|
896
|
-
const rawOutput = modelResult.data?.choices?.[0]?.message?.content;
|
|
897
|
-
if (!rawOutput) {
|
|
898
|
-
throw new Error('No output received from model');
|
|
899
|
-
}
|
|
900
|
-
let parsedResult = rawOutput;
|
|
901
|
-
switch (prompt.OutputType) {
|
|
902
|
-
case 'string':
|
|
903
|
-
parsedResult = rawOutput.toString();
|
|
904
|
-
break;
|
|
905
|
-
case 'number': {
|
|
906
|
-
const numberResult = parseFloat(rawOutput);
|
|
907
|
-
if (isNaN(numberResult)) {
|
|
908
|
-
throw new Error(`Expected number output but got: ${rawOutput}`);
|
|
909
|
-
}
|
|
910
|
-
parsedResult = numberResult;
|
|
911
|
-
break;
|
|
912
|
-
}
|
|
913
|
-
case 'boolean': {
|
|
914
|
-
const lowerOutput = rawOutput.toLowerCase().trim();
|
|
915
|
-
if (['true', 'yes', '1'].includes(lowerOutput)) {
|
|
916
|
-
parsedResult = true;
|
|
917
|
-
}
|
|
918
|
-
else if (['false', 'no', '0'].includes(lowerOutput)) {
|
|
919
|
-
parsedResult = false;
|
|
920
|
-
}
|
|
921
|
-
else {
|
|
922
|
-
throw new Error(`Expected boolean output but got: ${rawOutput}`);
|
|
923
|
-
}
|
|
924
|
-
break;
|
|
925
|
-
}
|
|
926
|
-
case 'date': {
|
|
927
|
-
const dateResult = new Date(rawOutput);
|
|
928
|
-
if (isNaN(dateResult.getTime())) {
|
|
929
|
-
throw new Error(`Expected date output but got: ${rawOutput}`);
|
|
930
|
-
}
|
|
931
|
-
parsedResult = dateResult;
|
|
932
|
-
break;
|
|
933
|
-
}
|
|
934
|
-
case 'object':
|
|
935
|
-
try {
|
|
936
|
-
parsedResult = JSON.parse(rawOutput);
|
|
937
|
-
}
|
|
938
|
-
catch (jsonError) {
|
|
939
|
-
throw new Error(`Expected JSON object but got invalid JSON: ${rawOutput}`);
|
|
940
|
-
}
|
|
941
|
-
break;
|
|
942
|
-
default:
|
|
943
|
-
parsedResult = rawOutput;
|
|
944
|
-
}
|
|
945
|
-
const validationResult = new core_1.ValidationResult();
|
|
946
|
-
validationResult.Success = true;
|
|
947
|
-
if (!skipValidation && prompt.OutputExample && prompt.OutputType === 'object') {
|
|
948
|
-
}
|
|
949
|
-
return { result: parsedResult, validationResult };
|
|
950
|
-
}
|
|
951
|
-
catch (error) {
|
|
952
|
-
(0, core_1.LogError)(`Error parsing/validating result: ${error.message}`);
|
|
953
|
-
switch (prompt.ValidationBehavior) {
|
|
954
|
-
case 'Strict':
|
|
955
|
-
throw error;
|
|
956
|
-
case 'Warn':
|
|
957
|
-
(0, core_1.LogError)(`Validation warning for prompt ${prompt.Name}: ${error.message}`);
|
|
958
|
-
return { result: modelResult.data?.choices?.[0]?.message?.content };
|
|
959
|
-
case 'None':
|
|
960
|
-
default:
|
|
961
|
-
return { result: modelResult.data?.choices?.[0]?.message?.content };
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
985
|
async updatePromptRun(promptRun, modelResult, parsedResult, endTime, executionTimeMS, validationAttempts) {
|
|
966
986
|
try {
|
|
967
987
|
promptRun.CompletedAt = endTime;
|
|
@@ -971,6 +991,12 @@ class AIPromptRunner {
|
|
|
971
991
|
promptRun.TokensUsed = modelResult.data.usage.totalTokens;
|
|
972
992
|
promptRun.TokensPrompt = modelResult.data.usage.promptTokens;
|
|
973
993
|
promptRun.TokensCompletion = modelResult.data.usage.completionTokens;
|
|
994
|
+
if (modelResult.data.usage.cost !== undefined) {
|
|
995
|
+
promptRun.Cost = modelResult.data.usage.cost;
|
|
996
|
+
}
|
|
997
|
+
if (modelResult.data.usage.costCurrency !== undefined) {
|
|
998
|
+
promptRun.CostCurrency = modelResult.data.usage.costCurrency;
|
|
999
|
+
}
|
|
974
1000
|
}
|
|
975
1001
|
if (validationAttempts && validationAttempts.length > 0) {
|
|
976
1002
|
try {
|
|
@@ -1001,6 +1027,12 @@ class AIPromptRunner {
|
|
|
1001
1027
|
}
|
|
1002
1028
|
}
|
|
1003
1029
|
promptRun.Success = modelResult.success && (parsedResult.validationResult?.Success !== false);
|
|
1030
|
+
promptRun.TokensPromptRollup = promptRun.TokensPrompt;
|
|
1031
|
+
promptRun.TokensCompletionRollup = promptRun.TokensCompletion;
|
|
1032
|
+
promptRun.TokensUsedRollup = promptRun.TokensUsed;
|
|
1033
|
+
if (promptRun.Cost !== undefined) {
|
|
1034
|
+
promptRun.TotalCost = promptRun.Cost;
|
|
1035
|
+
}
|
|
1004
1036
|
const saveResult = await promptRun.Save();
|
|
1005
1037
|
if (!saveResult) {
|
|
1006
1038
|
(0, core_1.LogError)(`Failed to update AIPromptRun with results: ${promptRun.LatestResult?.Message || 'Unknown error'}`);
|