@launchdarkly/server-sdk-ai 0.19.1 → 0.20.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/CHANGELOG.md +26 -0
- package/README.md +13 -16
- package/dist/index.cjs +586 -351
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +591 -265
- package/dist/index.d.ts +591 -265
- package/dist/index.js +582 -349
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,14 +31,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
AIProvider: () => AIProvider,
|
|
34
|
-
AIProviderFactory: () => AIProviderFactory,
|
|
35
34
|
AgentGraphDefinition: () => AgentGraphDefinition,
|
|
36
35
|
AgentGraphNode: () => AgentGraphNode,
|
|
37
36
|
Judge: () => Judge,
|
|
38
37
|
LDFeedbackKind: () => LDFeedbackKind,
|
|
39
38
|
LDGraphTrackerImpl: () => LDGraphTrackerImpl,
|
|
39
|
+
ManagedAgent: () => ManagedAgent,
|
|
40
|
+
ManagedAgentGraph: () => ManagedAgentGraph,
|
|
41
|
+
ManagedModel: () => ManagedModel,
|
|
42
|
+
RunnerFactory: () => RunnerFactory,
|
|
40
43
|
SUPPORTED_AI_PROVIDERS: () => SUPPORTED_AI_PROVIDERS,
|
|
41
|
-
TrackedChat: () => TrackedChat,
|
|
42
44
|
createBedrockTokenUsage: () => createBedrockTokenUsage,
|
|
43
45
|
createOpenAiUsage: () => createOpenAiUsage,
|
|
44
46
|
createVercelAISDKTokenUsage: () => createVercelAISDKTokenUsage,
|
|
@@ -47,131 +49,112 @@ __export(src_exports, {
|
|
|
47
49
|
module.exports = __toCommonJS(src_exports);
|
|
48
50
|
|
|
49
51
|
// src/LDAIClientImpl.ts
|
|
50
|
-
var
|
|
52
|
+
var import_mustache = __toESM(require("mustache"), 1);
|
|
51
53
|
var import_node_crypto = require("crypto");
|
|
52
54
|
|
|
53
|
-
// src/api/
|
|
54
|
-
var
|
|
55
|
-
constructor(
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
-
this.judges = judges;
|
|
55
|
+
// src/api/ManagedAgent.ts
|
|
56
|
+
var ManagedAgent = class {
|
|
57
|
+
constructor(aiAgentConfig, runner, _logger) {
|
|
58
|
+
this.aiAgentConfig = aiAgentConfig;
|
|
59
|
+
this.runner = runner;
|
|
59
60
|
this._logger = _logger;
|
|
60
|
-
this.messages = [];
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
-
* Invoke the
|
|
64
|
-
*
|
|
63
|
+
* Invoke the agent with a prompt string and return a ManagedResult.
|
|
64
|
+
*
|
|
65
|
+
* `run()` resolves before `ManagedResult.evaluations` resolves. Awaiting
|
|
66
|
+
* `evaluations` guarantees both judge evaluation and tracker.trackJudgeResult()
|
|
67
|
+
* are complete.
|
|
68
|
+
*
|
|
69
|
+
* @param prompt The user input to send to the agent.
|
|
70
|
+
* @returns Promise resolving to ManagedResult (before evaluations settle).
|
|
65
71
|
*/
|
|
66
|
-
async
|
|
67
|
-
const tracker = this.
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
};
|
|
72
|
-
this.messages.push(userMessage);
|
|
73
|
-
const configMessages = this.aiConfig.messages || [];
|
|
74
|
-
const allMessages = [...configMessages, ...this.messages];
|
|
75
|
-
const response = await tracker.trackMetricsOf(
|
|
76
|
-
(result) => result.metrics,
|
|
77
|
-
() => this.provider.invokeModel(allMessages)
|
|
72
|
+
async run(prompt) {
|
|
73
|
+
const tracker = this.aiAgentConfig.createTracker();
|
|
74
|
+
const result = await tracker.trackMetricsOf(
|
|
75
|
+
(r) => r.metrics,
|
|
76
|
+
() => this.runner.run(prompt)
|
|
78
77
|
);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return evaluations;
|
|
78
|
+
const metrics = tracker.getSummary();
|
|
79
|
+
const output = result.content;
|
|
80
|
+
const evaluations = this.aiAgentConfig.evaluator.evaluate(prompt, output).then((results) => {
|
|
81
|
+
results.forEach((judgeResult) => {
|
|
82
|
+
if (!judgeResult.sampled) {
|
|
83
|
+
return;
|
|
86
84
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* Evaluates the response with all configured judges.
|
|
94
|
-
* Returns a promise that resolves to an array of evaluation results.
|
|
95
|
-
*
|
|
96
|
-
* @param messages Array of messages representing the conversation history
|
|
97
|
-
* @param response The AI response to be evaluated
|
|
98
|
-
* @returns Promise resolving to array of judge evaluation results
|
|
99
|
-
*/
|
|
100
|
-
async _evaluateWithJudges(messages, response) {
|
|
101
|
-
const judgeConfigs = this.aiConfig.judgeConfiguration.judges;
|
|
102
|
-
const evaluationPromises = judgeConfigs.map(async (judgeConfig) => {
|
|
103
|
-
const judge = this.judges[judgeConfig.key];
|
|
104
|
-
if (!judge) {
|
|
105
|
-
this._logger?.warn(
|
|
106
|
-
`Judge configuration is not enabled for ${judgeConfig.key} in ${this.aiConfig.key}`
|
|
107
|
-
);
|
|
108
|
-
const result = {
|
|
109
|
-
success: false,
|
|
110
|
-
sampled: true,
|
|
111
|
-
errorMessage: `Judge configuration is not enabled for ${judgeConfig.key}`
|
|
112
|
-
};
|
|
113
|
-
return result;
|
|
114
|
-
}
|
|
115
|
-
return judge.evaluateMessages(messages, response, judgeConfig.samplingRate);
|
|
116
|
-
});
|
|
117
|
-
const results = await Promise.allSettled(evaluationPromises);
|
|
118
|
-
return results.map((settled) => {
|
|
119
|
-
if (settled.status === "fulfilled") {
|
|
120
|
-
return settled.value;
|
|
121
|
-
}
|
|
122
|
-
const result = {
|
|
123
|
-
success: false,
|
|
124
|
-
sampled: true,
|
|
125
|
-
errorMessage: "Judge evaluation failed"
|
|
126
|
-
};
|
|
127
|
-
return result;
|
|
85
|
+
tracker.trackJudgeResult(judgeResult);
|
|
86
|
+
});
|
|
87
|
+
return results;
|
|
88
|
+
}).catch((err) => {
|
|
89
|
+
this._logger?.warn("Judge evaluation failed unexpectedly:", err);
|
|
90
|
+
return [];
|
|
128
91
|
});
|
|
92
|
+
return {
|
|
93
|
+
content: output,
|
|
94
|
+
metrics,
|
|
95
|
+
raw: result.raw,
|
|
96
|
+
parsed: result.parsed,
|
|
97
|
+
evaluations
|
|
98
|
+
};
|
|
129
99
|
}
|
|
130
100
|
/**
|
|
131
|
-
* Get the underlying AI configuration used to initialize this
|
|
101
|
+
* Get the underlying AI agent configuration used to initialize this ManagedAgent.
|
|
132
102
|
*/
|
|
133
103
|
getConfig() {
|
|
134
|
-
return this.
|
|
104
|
+
return this.aiAgentConfig;
|
|
135
105
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
* Get the judges associated with this TrackedChat.
|
|
145
|
-
* Returns a record of judge instances keyed by their configuration keys.
|
|
146
|
-
*/
|
|
147
|
-
getJudges() {
|
|
148
|
-
return this.judges;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/api/ManagedModel.ts
|
|
109
|
+
var ManagedModel = class {
|
|
110
|
+
constructor(aiConfig, runner, _logger) {
|
|
111
|
+
this.aiConfig = aiConfig;
|
|
112
|
+
this.runner = runner;
|
|
113
|
+
this._logger = _logger;
|
|
149
114
|
}
|
|
150
115
|
/**
|
|
151
|
-
*
|
|
152
|
-
* Adds messages to the conversation history without invoking the model,
|
|
153
|
-
* which is useful for managing multi-turn conversations or injecting context.
|
|
116
|
+
* Invoke the model with a prompt string and return a ManagedResult.
|
|
154
117
|
*
|
|
155
|
-
*
|
|
118
|
+
* `run()` resolves before `ManagedResult.evaluations` resolves. Awaiting
|
|
119
|
+
* `evaluations` guarantees both judge evaluation and tracker.trackJudgeResult()
|
|
120
|
+
* are complete.
|
|
121
|
+
*
|
|
122
|
+
* @param prompt The user input to send to the model.
|
|
123
|
+
* @returns Promise resolving to ManagedResult (before evaluations settle).
|
|
156
124
|
*/
|
|
157
|
-
|
|
158
|
-
this.
|
|
125
|
+
async run(prompt) {
|
|
126
|
+
const tracker = this.aiConfig.createTracker();
|
|
127
|
+
const result = await tracker.trackMetricsOf(
|
|
128
|
+
(r) => r.metrics,
|
|
129
|
+
() => this.runner.run(prompt)
|
|
130
|
+
);
|
|
131
|
+
const metrics = tracker.getSummary();
|
|
132
|
+
const output = result.content;
|
|
133
|
+
const evaluations = this.aiConfig.evaluator.evaluate(prompt, output).then((results) => {
|
|
134
|
+
results.forEach((judgeResult) => {
|
|
135
|
+
if (!judgeResult.sampled) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
tracker.trackJudgeResult(judgeResult);
|
|
139
|
+
});
|
|
140
|
+
return results;
|
|
141
|
+
}).catch((err) => {
|
|
142
|
+
this._logger?.warn("Judge evaluation failed unexpectedly:", err);
|
|
143
|
+
return [];
|
|
144
|
+
});
|
|
145
|
+
return {
|
|
146
|
+
content: output,
|
|
147
|
+
metrics,
|
|
148
|
+
raw: result.raw,
|
|
149
|
+
parsed: result.parsed,
|
|
150
|
+
evaluations
|
|
151
|
+
};
|
|
159
152
|
}
|
|
160
153
|
/**
|
|
161
|
-
* Get
|
|
162
|
-
*
|
|
163
|
-
* @param includeConfigMessages Whether to include the config messages from the AIConfig.
|
|
164
|
-
* Defaults to false.
|
|
165
|
-
* @returns Array of messages. When includeConfigMessages is true, returns both config
|
|
166
|
-
* messages and conversation history with config messages prepended. When false,
|
|
167
|
-
* returns only the conversation history messages.
|
|
154
|
+
* Get the underlying AI configuration used to initialize this ManagedModel.
|
|
168
155
|
*/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const configMessages = this.aiConfig.messages || [];
|
|
172
|
-
return [...configMessages, ...this.messages];
|
|
173
|
-
}
|
|
174
|
-
return [...this.messages];
|
|
156
|
+
getConfig() {
|
|
157
|
+
return this.aiConfig;
|
|
175
158
|
}
|
|
176
159
|
};
|
|
177
160
|
|
|
@@ -223,46 +206,52 @@ var LDAIConfigUtils = class {
|
|
|
223
206
|
* @param key The configuration key
|
|
224
207
|
* @param flagValue The flag value from LaunchDarkly
|
|
225
208
|
* @param trackerFactory A factory function that creates a new tracker for each execution
|
|
209
|
+
* @param evaluator The evaluator to attach to completion and agent configs
|
|
226
210
|
* @returns The appropriate AI configuration type
|
|
227
211
|
*/
|
|
228
|
-
static fromFlagValue(key, flagValue, trackerFactory) {
|
|
212
|
+
static fromFlagValue(key, flagValue, trackerFactory, evaluator) {
|
|
229
213
|
const flagValueMode = flagValue._ldMeta?.mode;
|
|
230
214
|
switch (flagValueMode) {
|
|
231
215
|
case "agent":
|
|
232
|
-
return this.toAgentConfig(key, flagValue, trackerFactory);
|
|
216
|
+
return this.toAgentConfig(key, flagValue, trackerFactory, evaluator);
|
|
233
217
|
case "judge":
|
|
234
218
|
return this.toJudgeConfig(key, flagValue, trackerFactory);
|
|
235
219
|
case "completion":
|
|
236
220
|
default:
|
|
237
|
-
return this.toCompletionConfig(key, flagValue, trackerFactory);
|
|
221
|
+
return this.toCompletionConfig(key, flagValue, trackerFactory, evaluator);
|
|
238
222
|
}
|
|
239
223
|
}
|
|
240
224
|
/**
|
|
241
225
|
* Creates a disabled configuration of the specified mode.
|
|
242
226
|
*
|
|
227
|
+
* @param key The configuration key
|
|
243
228
|
* @param mode The mode for the disabled config
|
|
229
|
+
* @param createTracker A factory function that creates a new tracker for each execution
|
|
230
|
+
* @param evaluator The evaluator to attach to completion and agent configs
|
|
244
231
|
* @returns A disabled config of the appropriate type
|
|
245
232
|
*/
|
|
246
|
-
static createDisabledConfig(key, mode) {
|
|
233
|
+
static createDisabledConfig(key, mode, createTracker, evaluator) {
|
|
247
234
|
switch (mode) {
|
|
248
235
|
case "agent":
|
|
249
236
|
return {
|
|
250
237
|
key,
|
|
251
238
|
enabled: false,
|
|
252
|
-
createTracker
|
|
239
|
+
createTracker,
|
|
240
|
+
evaluator
|
|
253
241
|
};
|
|
254
242
|
case "judge":
|
|
255
243
|
return {
|
|
256
244
|
key,
|
|
257
245
|
enabled: false,
|
|
258
|
-
createTracker
|
|
246
|
+
createTracker
|
|
259
247
|
};
|
|
260
248
|
case "completion":
|
|
261
249
|
default:
|
|
262
250
|
return {
|
|
263
251
|
key,
|
|
264
252
|
enabled: false,
|
|
265
|
-
createTracker
|
|
253
|
+
createTracker,
|
|
254
|
+
evaluator
|
|
266
255
|
};
|
|
267
256
|
}
|
|
268
257
|
}
|
|
@@ -304,12 +293,14 @@ var LDAIConfigUtils = class {
|
|
|
304
293
|
* @param key The configuration key
|
|
305
294
|
* @param flagValue The flag value from LaunchDarkly
|
|
306
295
|
* @param trackerFactory A factory function that creates a new tracker for each execution
|
|
296
|
+
* @param evaluator The evaluator for this completion config
|
|
307
297
|
* @returns A completion configuration
|
|
308
298
|
*/
|
|
309
|
-
static toCompletionConfig(key, flagValue, trackerFactory) {
|
|
299
|
+
static toCompletionConfig(key, flagValue, trackerFactory, evaluator) {
|
|
310
300
|
return {
|
|
311
301
|
...this._toBaseConfig(key, flagValue),
|
|
312
302
|
createTracker: trackerFactory,
|
|
303
|
+
evaluator,
|
|
313
304
|
messages: flagValue.messages,
|
|
314
305
|
judgeConfiguration: flagValue.judgeConfiguration,
|
|
315
306
|
tools: this._resolveTools(flagValue)
|
|
@@ -321,12 +312,14 @@ var LDAIConfigUtils = class {
|
|
|
321
312
|
* @param key The configuration key
|
|
322
313
|
* @param flagValue The flag value from LaunchDarkly
|
|
323
314
|
* @param trackerFactory A factory function that creates a new tracker for each execution
|
|
315
|
+
* @param evaluator The evaluator for this agent config
|
|
324
316
|
* @returns An agent configuration
|
|
325
317
|
*/
|
|
326
|
-
static toAgentConfig(key, flagValue, trackerFactory) {
|
|
318
|
+
static toAgentConfig(key, flagValue, trackerFactory, evaluator) {
|
|
327
319
|
return {
|
|
328
320
|
...this._toBaseConfig(key, flagValue),
|
|
329
321
|
createTracker: trackerFactory,
|
|
322
|
+
evaluator,
|
|
330
323
|
instructions: flagValue.instructions,
|
|
331
324
|
judgeConfiguration: flagValue.judgeConfiguration,
|
|
332
325
|
tools: this._resolveTools(flagValue)
|
|
@@ -591,8 +584,98 @@ var AgentGraphDefinition = class _AgentGraphDefinition {
|
|
|
591
584
|
}
|
|
592
585
|
};
|
|
593
586
|
|
|
587
|
+
// src/api/graph/ManagedAgentGraph.ts
|
|
588
|
+
var ManagedAgentGraph = class {
|
|
589
|
+
constructor(_graphDefinition, _logger) {
|
|
590
|
+
this._graphDefinition = _graphDefinition;
|
|
591
|
+
this._logger = _logger;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Runs the agent graph using the provided runner function and returns a ManagedGraphResult.
|
|
595
|
+
*
|
|
596
|
+
* The runner function receives the graph tracker and AgentGraphDefinition,
|
|
597
|
+
* executes the graph, and returns an AgentGraphRunnerResult.
|
|
598
|
+
*
|
|
599
|
+
* run() returns before ManagedGraphResult.evaluations resolves.
|
|
600
|
+
*
|
|
601
|
+
* @param runner Async function that executes the graph and returns AgentGraphRunnerResult.
|
|
602
|
+
* @returns ManagedGraphResult with LDAIGraphMetricSummary and evaluations promise.
|
|
603
|
+
*/
|
|
604
|
+
async run(runner) {
|
|
605
|
+
const graphTracker = this._graphDefinition.createTracker();
|
|
606
|
+
const runnerResult = await runner(this._graphDefinition, graphTracker);
|
|
607
|
+
const metrics = {
|
|
608
|
+
success: runnerResult.metrics.success,
|
|
609
|
+
path: runnerResult.metrics.path,
|
|
610
|
+
durationMs: runnerResult.metrics.durationMs,
|
|
611
|
+
tokens: runnerResult.metrics.tokens,
|
|
612
|
+
nodeMetrics: this._trackNodeMetrics(runnerResult.metrics.nodeMetrics),
|
|
613
|
+
resumptionToken: graphTracker.resumptionToken
|
|
614
|
+
};
|
|
615
|
+
const evaluations = Promise.resolve([]);
|
|
616
|
+
return {
|
|
617
|
+
content: runnerResult.content,
|
|
618
|
+
metrics,
|
|
619
|
+
raw: runnerResult.raw,
|
|
620
|
+
evaluations
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Converts per-node LDAIMetrics from the runner into LDAIMetricSummary by
|
|
625
|
+
* creating a per-node tracker, firing tracking events, and calling getSummary().
|
|
626
|
+
*/
|
|
627
|
+
_trackNodeMetrics(nodeMetrics) {
|
|
628
|
+
const summaries = {};
|
|
629
|
+
for (const [nodeKey, metrics] of Object.entries(nodeMetrics)) {
|
|
630
|
+
const node = this._graphDefinition.getNode(nodeKey);
|
|
631
|
+
if (!node) {
|
|
632
|
+
this._logger?.warn(`ManagedAgentGraph: no node found for key "${nodeKey}", skipping metrics`);
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
const tracker = node.getConfig().createTracker();
|
|
636
|
+
if (metrics.tokens) {
|
|
637
|
+
tracker.trackTokens(metrics.tokens);
|
|
638
|
+
}
|
|
639
|
+
if (metrics.durationMs !== void 0) {
|
|
640
|
+
tracker.trackDuration(metrics.durationMs);
|
|
641
|
+
}
|
|
642
|
+
if (metrics.toolCalls?.length) {
|
|
643
|
+
tracker.trackToolCalls(metrics.toolCalls);
|
|
644
|
+
}
|
|
645
|
+
if (metrics.success) {
|
|
646
|
+
tracker.trackSuccess();
|
|
647
|
+
} else {
|
|
648
|
+
tracker.trackError();
|
|
649
|
+
}
|
|
650
|
+
summaries[nodeKey] = tracker.getSummary();
|
|
651
|
+
}
|
|
652
|
+
return summaries;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Returns the underlying AgentGraphDefinition.
|
|
656
|
+
*/
|
|
657
|
+
getGraphDefinition() {
|
|
658
|
+
return this._graphDefinition;
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
// src/api/judge/Evaluator.ts
|
|
663
|
+
var Evaluator = class _Evaluator {
|
|
664
|
+
constructor(_judges) {
|
|
665
|
+
this._judges = _judges;
|
|
666
|
+
}
|
|
667
|
+
static noop() {
|
|
668
|
+
return new _Evaluator([]);
|
|
669
|
+
}
|
|
670
|
+
async evaluate(input, output) {
|
|
671
|
+
if (this._judges.length === 0) {
|
|
672
|
+
return [];
|
|
673
|
+
}
|
|
674
|
+
return Promise.all(this._judges.map((judge) => judge.evaluate(input, output)));
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
|
|
594
678
|
// src/api/judge/Judge.ts
|
|
595
|
-
var import_mustache = __toESM(require("mustache"), 1);
|
|
596
679
|
var EVALUATION_SCHEMA = {
|
|
597
680
|
type: "object",
|
|
598
681
|
properties: {
|
|
@@ -610,12 +693,25 @@ var EVALUATION_SCHEMA = {
|
|
|
610
693
|
required: ["score", "reasoning"],
|
|
611
694
|
additionalProperties: false
|
|
612
695
|
};
|
|
696
|
+
function stripLegacyJudgeMessages(messages) {
|
|
697
|
+
return messages.filter(
|
|
698
|
+
(msg) => msg.role === "system" || !msg.content.includes("{{message_history}}") && !msg.content.includes("{{response_to_evaluate}}")
|
|
699
|
+
);
|
|
700
|
+
}
|
|
613
701
|
var Judge = class {
|
|
614
|
-
constructor(_aiConfig,
|
|
702
|
+
constructor(_aiConfig, _runner, _sampleRate = 1, logger) {
|
|
615
703
|
this._aiConfig = _aiConfig;
|
|
616
|
-
this.
|
|
704
|
+
this._runner = _runner;
|
|
705
|
+
this._sampleRate = _sampleRate;
|
|
617
706
|
this._logger = logger;
|
|
618
707
|
}
|
|
708
|
+
/**
|
|
709
|
+
* The default sampling rate baked in at construction. Used by `evaluate` /
|
|
710
|
+
* `evaluateMessages` when no per-call rate is supplied.
|
|
711
|
+
*/
|
|
712
|
+
get sampleRate() {
|
|
713
|
+
return this._sampleRate;
|
|
714
|
+
}
|
|
619
715
|
/**
|
|
620
716
|
* Gets the evaluation metric key, prioritizing evaluationMetricKey over evaluationMetricKeys.
|
|
621
717
|
* Falls back to the first valid (non-empty, non-whitespace) value in evaluationMetricKeys if evaluationMetricKey is not provided.
|
|
@@ -639,10 +735,13 @@ var Judge = class {
|
|
|
639
735
|
*
|
|
640
736
|
* @param input The input prompt or question that was provided to the AI
|
|
641
737
|
* @param output The AI-generated response to be evaluated
|
|
642
|
-
* @param samplingRate Sampling rate (0-1) to determine if evaluation should be processed
|
|
738
|
+
* @param samplingRate Sampling rate (0-1) to determine if evaluation should be processed.
|
|
739
|
+
* When omitted, the Judge's constructor-default rate is used. An explicit `0` overrides
|
|
740
|
+
* the default — only `undefined` falls through.
|
|
643
741
|
* @returns Promise that resolves to evaluation results
|
|
644
742
|
*/
|
|
645
|
-
async evaluate(input, output, samplingRate
|
|
743
|
+
async evaluate(input, output, samplingRate) {
|
|
744
|
+
const effectiveRate = samplingRate ?? this._sampleRate;
|
|
646
745
|
const result = {
|
|
647
746
|
success: false,
|
|
648
747
|
sampled: false,
|
|
@@ -660,26 +759,20 @@ var Judge = class {
|
|
|
660
759
|
result.errorMessage = "Judge configuration is missing required evaluation metric key";
|
|
661
760
|
return result;
|
|
662
761
|
}
|
|
663
|
-
if (
|
|
664
|
-
this._logger?.
|
|
665
|
-
result.sampled = true;
|
|
666
|
-
result.errorMessage = "Judge configuration must include messages";
|
|
667
|
-
return result;
|
|
668
|
-
}
|
|
669
|
-
if (Math.random() > samplingRate) {
|
|
670
|
-
this._logger?.debug(`Judge evaluation skipped due to sampling rate: ${samplingRate}`);
|
|
762
|
+
if (Math.random() > effectiveRate) {
|
|
763
|
+
this._logger?.debug(`Judge evaluation skipped due to sampling rate: ${effectiveRate}`);
|
|
671
764
|
return result;
|
|
672
765
|
}
|
|
673
766
|
result.sampled = true;
|
|
674
|
-
const
|
|
767
|
+
const evaluationInput = this._buildEvaluationInput(input, output);
|
|
675
768
|
const response = await tracker.trackMetricsOf(
|
|
676
769
|
(r) => r.metrics,
|
|
677
|
-
() => this.
|
|
770
|
+
() => this._runner.run(evaluationInput, EVALUATION_SCHEMA)
|
|
678
771
|
);
|
|
679
|
-
const evalResult = this._parseEvaluationResponse(response.
|
|
772
|
+
const evalResult = this._parseEvaluationResponse(response.parsed);
|
|
680
773
|
if (!evalResult) {
|
|
681
774
|
this._logger?.warn(
|
|
682
|
-
`Could not parse evaluation response: ${JSON.stringify(response.
|
|
775
|
+
`Could not parse evaluation response: ${JSON.stringify(response.parsed)}`,
|
|
683
776
|
tracker.getTrackData()
|
|
684
777
|
);
|
|
685
778
|
return result;
|
|
@@ -703,10 +796,11 @@ var Judge = class {
|
|
|
703
796
|
*
|
|
704
797
|
* @param messages Array of messages representing the conversation history
|
|
705
798
|
* @param response The AI response to be evaluated
|
|
706
|
-
* @param samplingRatio Sampling ratio (0-1)
|
|
799
|
+
* @param samplingRatio Sampling ratio (0-1). When omitted, the Judge's
|
|
800
|
+
* constructor-default rate is used.
|
|
707
801
|
* @returns Promise that resolves to evaluation results
|
|
708
802
|
*/
|
|
709
|
-
async evaluateMessages(messages, response, samplingRatio
|
|
803
|
+
async evaluateMessages(messages, response, samplingRatio) {
|
|
710
804
|
const input = messages.length === 0 ? "" : messages.map((msg) => msg.content).join("\r\n");
|
|
711
805
|
const output = response.message.content;
|
|
712
806
|
return this.evaluate(input, output, samplingRatio);
|
|
@@ -718,29 +812,23 @@ var Judge = class {
|
|
|
718
812
|
return this._aiConfig;
|
|
719
813
|
}
|
|
720
814
|
/**
|
|
721
|
-
* Returns the
|
|
815
|
+
* Returns the runner used by this judge.
|
|
722
816
|
*/
|
|
723
|
-
|
|
724
|
-
return this.
|
|
725
|
-
}
|
|
726
|
-
/**
|
|
727
|
-
* Constructs evaluation messages by combining judge's config messages with input/output.
|
|
728
|
-
*/
|
|
729
|
-
_constructEvaluationMessages(input, output) {
|
|
730
|
-
const messages = this._aiConfig.messages.map((msg) => ({
|
|
731
|
-
...msg,
|
|
732
|
-
content: this._interpolateMessage(msg.content, {
|
|
733
|
-
message_history: input,
|
|
734
|
-
response_to_evaluate: output
|
|
735
|
-
})
|
|
736
|
-
}));
|
|
737
|
-
return messages;
|
|
817
|
+
getRunner() {
|
|
818
|
+
return this._runner;
|
|
738
819
|
}
|
|
739
820
|
/**
|
|
740
|
-
*
|
|
821
|
+
* Builds the evaluation input string passed to the runner.
|
|
822
|
+
*
|
|
823
|
+
* Combines the original prompt and the response into a single, well-known
|
|
824
|
+
* format the judge model is expected to evaluate.
|
|
741
825
|
*/
|
|
742
|
-
|
|
743
|
-
return
|
|
826
|
+
_buildEvaluationInput(input, output) {
|
|
827
|
+
return `MESSAGE HISTORY:
|
|
828
|
+
${input}
|
|
829
|
+
|
|
830
|
+
RESPONSE TO EVALUATE:
|
|
831
|
+
${output}`;
|
|
744
832
|
}
|
|
745
833
|
/**
|
|
746
834
|
* Parses the structured evaluation response. Expects top-level {score, reasoning}.
|
|
@@ -766,115 +854,101 @@ var Judge = class {
|
|
|
766
854
|
// src/api/providers/AIProvider.ts
|
|
767
855
|
var AIProvider = class {
|
|
768
856
|
constructor(logger) {
|
|
769
|
-
this.
|
|
857
|
+
this._logger = logger;
|
|
770
858
|
}
|
|
771
859
|
/**
|
|
772
|
-
*
|
|
773
|
-
* This method should convert messages to provider format, invoke the model,
|
|
774
|
-
* and return a ChatResponse with the result and metrics.
|
|
860
|
+
* Create a Runner for a completion or judge AI Config.
|
|
775
861
|
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
862
|
+
* Override in provider subclasses to return a configured {@link Runner}.
|
|
863
|
+
* Default implementation returns `undefined`.
|
|
778
864
|
*
|
|
779
|
-
* @param
|
|
780
|
-
* @returns Promise
|
|
865
|
+
* @param config The completion or judge AI configuration.
|
|
866
|
+
* @returns Promise resolving to a {@link Runner}, or `undefined` if this
|
|
867
|
+
* provider does not support model creation.
|
|
781
868
|
*/
|
|
782
|
-
async
|
|
783
|
-
|
|
784
|
-
return {
|
|
785
|
-
message: {
|
|
786
|
-
role: "assistant",
|
|
787
|
-
content: ""
|
|
788
|
-
},
|
|
789
|
-
metrics: {
|
|
790
|
-
success: false,
|
|
791
|
-
usage: {
|
|
792
|
-
total: 0,
|
|
793
|
-
input: 0,
|
|
794
|
-
output: 0
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
};
|
|
869
|
+
async createModel(_config) {
|
|
870
|
+
return void 0;
|
|
798
871
|
}
|
|
799
872
|
/**
|
|
800
|
-
*
|
|
801
|
-
* This method should convert messages to provider format, invoke the model with
|
|
802
|
-
* structured output configuration, and return a structured response.
|
|
873
|
+
* Create a Runner for an agent AI Config.
|
|
803
874
|
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
875
|
+
* Override in provider subclasses to return a configured {@link Runner}.
|
|
876
|
+
* Default implementation returns `undefined`.
|
|
806
877
|
*
|
|
807
|
-
* @param
|
|
808
|
-
* @param
|
|
809
|
-
* @returns Promise
|
|
878
|
+
* @param config The agent AI configuration.
|
|
879
|
+
* @param tools Optional registry of callable tools.
|
|
880
|
+
* @returns Promise resolving to a {@link Runner}, or `undefined` if this
|
|
881
|
+
* provider does not support agent creation.
|
|
810
882
|
*/
|
|
811
|
-
async
|
|
812
|
-
|
|
813
|
-
return {
|
|
814
|
-
data: {},
|
|
815
|
-
rawResponse: "",
|
|
816
|
-
metrics: {
|
|
817
|
-
success: false,
|
|
818
|
-
usage: {
|
|
819
|
-
total: 0,
|
|
820
|
-
input: 0,
|
|
821
|
-
output: 0
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
};
|
|
883
|
+
async createAgent(_config, _tools) {
|
|
884
|
+
return void 0;
|
|
825
885
|
}
|
|
826
886
|
/**
|
|
827
|
-
*
|
|
828
|
-
* Each provider implementation must provide their own static create method
|
|
829
|
-
* that accepts an AIConfig and returns a configured instance.
|
|
887
|
+
* Create an AgentGraphRunner for an agent graph definition.
|
|
830
888
|
*
|
|
831
|
-
*
|
|
832
|
-
*
|
|
833
|
-
*
|
|
889
|
+
* Override in provider subclasses to return a configured {@link AgentGraphRunner}.
|
|
890
|
+
* Default implementation returns `undefined`.
|
|
891
|
+
*
|
|
892
|
+
* @param graphDef The agent graph definition.
|
|
893
|
+
* @param tools Optional registry of callable tools.
|
|
894
|
+
* @returns Promise resolving to an {@link AgentGraphRunner}, or `undefined` if
|
|
895
|
+
* this provider does not support graph execution.
|
|
834
896
|
*/
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
throw new Error("Provider implementations must override the static create method");
|
|
897
|
+
async createAgentGraph(_graphDef, _tools) {
|
|
898
|
+
return void 0;
|
|
838
899
|
}
|
|
839
900
|
};
|
|
840
901
|
|
|
841
|
-
// src/api/providers/
|
|
902
|
+
// src/api/providers/RunnerFactory.ts
|
|
842
903
|
var SUPPORTED_AI_PROVIDERS = [
|
|
843
904
|
"openai",
|
|
844
905
|
// Multi-provider packages should be last in the list
|
|
845
906
|
"langchain",
|
|
846
907
|
"vercel"
|
|
847
908
|
];
|
|
848
|
-
var
|
|
909
|
+
var RunnerFactory = class _RunnerFactory {
|
|
849
910
|
/**
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
911
|
+
* Load and return the AIProvider factory for the given provider type.
|
|
912
|
+
*
|
|
913
|
+
* This is the single place in the codebase that knows provider package names.
|
|
914
|
+
* Each supported provider package exports a `*RunnerFactory` class that
|
|
915
|
+
* extends {@link AIProvider}; this method instantiates it directly.
|
|
853
916
|
*
|
|
854
|
-
* @param
|
|
855
|
-
* @param logger Optional logger
|
|
856
|
-
* @
|
|
917
|
+
* @param providerType One of the {@link SUPPORTED_AI_PROVIDERS} values.
|
|
918
|
+
* @param logger Optional logger forwarded to the provider factory.
|
|
919
|
+
* @returns A configured {@link AIProvider} instance, or `undefined` if the
|
|
920
|
+
* package cannot be loaded.
|
|
857
921
|
*/
|
|
858
|
-
static async
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
922
|
+
static async _getProviderFactory(providerType, logger) {
|
|
923
|
+
try {
|
|
924
|
+
let module2;
|
|
925
|
+
switch (providerType) {
|
|
926
|
+
case "openai": {
|
|
927
|
+
module2 = await import("@launchdarkly/server-sdk-ai-openai");
|
|
928
|
+
return new module2.OpenAIRunnerFactory(logger);
|
|
929
|
+
}
|
|
930
|
+
case "langchain": {
|
|
931
|
+
module2 = await import("@launchdarkly/server-sdk-ai-langchain");
|
|
932
|
+
return new module2.LangChainRunnerFactory(logger);
|
|
933
|
+
}
|
|
934
|
+
case "vercel": {
|
|
935
|
+
module2 = await import("@launchdarkly/server-sdk-ai-vercel");
|
|
936
|
+
return new module2.VercelRunnerFactory(logger);
|
|
937
|
+
}
|
|
938
|
+
default:
|
|
939
|
+
return void 0;
|
|
869
940
|
}
|
|
941
|
+
} catch (error) {
|
|
942
|
+
logger?.warn(
|
|
943
|
+
`Unable to load provider package. Check that you have installed the correct package. ${error.message}`
|
|
944
|
+
);
|
|
945
|
+
return void 0;
|
|
870
946
|
}
|
|
871
|
-
logger?.warn(
|
|
872
|
-
`Provider is not supported or failed to initialize: ${aiConfig.provider?.name ?? "unknown"}`
|
|
873
|
-
);
|
|
874
|
-
return void 0;
|
|
875
947
|
}
|
|
876
948
|
/**
|
|
877
949
|
* Determine which providers to try based on defaultAiProvider and providerName.
|
|
950
|
+
*
|
|
951
|
+
* Mirrors Python's `_get_providers_to_try` helper.
|
|
878
952
|
*/
|
|
879
953
|
static _getProvidersToTry(defaultAiProvider, providerName) {
|
|
880
954
|
if (defaultAiProvider) {
|
|
@@ -891,36 +965,111 @@ var AIProviderFactory = class {
|
|
|
891
965
|
return Array.from(providerSet);
|
|
892
966
|
}
|
|
893
967
|
/**
|
|
894
|
-
* Try
|
|
968
|
+
* Try each provider in order and return the first non-undefined result.
|
|
969
|
+
*
|
|
970
|
+
* Mirrors Python's `_with_fallback` helper. Loads each provider factory via
|
|
971
|
+
* {@link _getProviderFactory} and calls `fn` with it. Returns the first
|
|
972
|
+
* truthy result, or `undefined` if no provider succeeds.
|
|
973
|
+
*
|
|
974
|
+
* @param providers Ordered list of provider types to try.
|
|
975
|
+
* @param fn Callback that calls the appropriate factory method on the provider.
|
|
976
|
+
* @param logger Optional logger forwarded to each provider factory.
|
|
895
977
|
*/
|
|
896
|
-
static async
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
case "langchain": {
|
|
906
|
-
module2 = await import("@launchdarkly/server-sdk-ai-langchain");
|
|
907
|
-
const provider = await module2.LangChainProvider.create(aiConfig, logger);
|
|
908
|
-
return provider;
|
|
909
|
-
}
|
|
910
|
-
case "vercel": {
|
|
911
|
-
module2 = await import("@launchdarkly/server-sdk-ai-vercel");
|
|
912
|
-
const provider = await module2.VercelProvider.create(aiConfig, logger);
|
|
913
|
-
return provider;
|
|
978
|
+
static async _withFallback(providers, fn, logger) {
|
|
979
|
+
for (const providerType of providers) {
|
|
980
|
+
logger?.debug(`Attempting to create runner with provider: ${providerType}`);
|
|
981
|
+
const factory = await _RunnerFactory._getProviderFactory(providerType, logger);
|
|
982
|
+
if (factory) {
|
|
983
|
+
const result = await fn(factory);
|
|
984
|
+
if (result) {
|
|
985
|
+
logger?.debug(`Successfully created runner with provider: ${providerType}`);
|
|
986
|
+
return result;
|
|
914
987
|
}
|
|
915
|
-
default:
|
|
916
|
-
return void 0;
|
|
917
988
|
}
|
|
918
|
-
}
|
|
989
|
+
}
|
|
990
|
+
return void 0;
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Create a Runner for the given AI configuration.
|
|
994
|
+
*
|
|
995
|
+
* Suitable for completion, judge, and agent config modes. Dynamically
|
|
996
|
+
* loads the matching provider package via {@link _getProviderFactory} and
|
|
997
|
+
* delegates to its {@link AIProvider.createModel} method.
|
|
998
|
+
*
|
|
999
|
+
* @param config The AI configuration (completion, agent, or judge).
|
|
1000
|
+
* @param logger Optional logger forwarded to the underlying provider.
|
|
1001
|
+
* @param defaultAiProvider Optional provider override
|
|
1002
|
+
* ('openai', 'langchain', 'vercel', …). When set, only that provider is
|
|
1003
|
+
* tried. When omitted, providers are tried in priority order based on the
|
|
1004
|
+
* provider name in the config.
|
|
1005
|
+
* @returns A configured {@link Runner} ready to invoke the model, or
|
|
1006
|
+
* `undefined` if no suitable provider could be loaded.
|
|
1007
|
+
*/
|
|
1008
|
+
static async createModel(config, logger, defaultAiProvider) {
|
|
1009
|
+
const providerName = config.provider?.name?.toLowerCase();
|
|
1010
|
+
const providers = _RunnerFactory._getProvidersToTry(defaultAiProvider, providerName);
|
|
1011
|
+
const runner = await _RunnerFactory._withFallback(
|
|
1012
|
+
providers,
|
|
1013
|
+
(factory) => factory.createModel(config),
|
|
1014
|
+
logger
|
|
1015
|
+
);
|
|
1016
|
+
if (!runner) {
|
|
919
1017
|
logger?.warn(
|
|
920
|
-
`
|
|
1018
|
+
`Provider is not supported or failed to initialize: ${config.provider?.name ?? "unknown"}`
|
|
921
1019
|
);
|
|
922
|
-
return void 0;
|
|
923
1020
|
}
|
|
1021
|
+
return runner;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Create a Runner for an agent AI Config.
|
|
1025
|
+
*
|
|
1026
|
+
* Delegates to the provider factory's {@link AIProvider.createAgent} method.
|
|
1027
|
+
*
|
|
1028
|
+
* @param config The agent AI configuration.
|
|
1029
|
+
* @param tools Optional registry of callable tools.
|
|
1030
|
+
* @param logger Optional logger forwarded to the underlying provider.
|
|
1031
|
+
* @param defaultAiProvider Optional provider override.
|
|
1032
|
+
* @returns A configured {@link Runner}, or `undefined` if no suitable
|
|
1033
|
+
* provider could be loaded.
|
|
1034
|
+
*/
|
|
1035
|
+
static async createAgent(config, tools, logger, defaultAiProvider) {
|
|
1036
|
+
const providerName = config.provider?.name?.toLowerCase();
|
|
1037
|
+
const providers = _RunnerFactory._getProvidersToTry(defaultAiProvider, providerName);
|
|
1038
|
+
const runner = await _RunnerFactory._withFallback(
|
|
1039
|
+
providers,
|
|
1040
|
+
(factory) => factory.createAgent(config, tools),
|
|
1041
|
+
logger
|
|
1042
|
+
);
|
|
1043
|
+
if (!runner) {
|
|
1044
|
+
logger?.warn(
|
|
1045
|
+
`Provider is not supported or failed to initialize: ${config.provider?.name ?? "unknown"}`
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
return runner;
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Create an AgentGraphRunner for the given agent graph definition.
|
|
1052
|
+
*
|
|
1053
|
+
* Delegates to the provider factory's {@link AIProvider.createAgentGraph} method.
|
|
1054
|
+
*
|
|
1055
|
+
* @param graphDef The agent graph definition.
|
|
1056
|
+
* @param tools Optional registry of callable tools.
|
|
1057
|
+
* @param logger Optional logger forwarded to the underlying provider.
|
|
1058
|
+
* @param defaultAiProvider Optional provider override.
|
|
1059
|
+
* @returns A configured {@link AgentGraphRunner}, or `undefined` if no
|
|
1060
|
+
* suitable provider could be loaded.
|
|
1061
|
+
*/
|
|
1062
|
+
static async createAgentGraph(graphDef, tools, logger, defaultAiProvider) {
|
|
1063
|
+
const providers = _RunnerFactory._getProvidersToTry(defaultAiProvider);
|
|
1064
|
+
const runner = await _RunnerFactory._withFallback(
|
|
1065
|
+
providers,
|
|
1066
|
+
(factory) => factory.createAgentGraph(graphDef, tools),
|
|
1067
|
+
logger
|
|
1068
|
+
);
|
|
1069
|
+
if (!runner) {
|
|
1070
|
+
logger?.warn(`No provider could create an AgentGraphRunner for the given graph definition.`);
|
|
1071
|
+
}
|
|
1072
|
+
return runner;
|
|
924
1073
|
}
|
|
925
1074
|
};
|
|
926
1075
|
|
|
@@ -971,6 +1120,7 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
|
|
|
971
1120
|
this._context = _context;
|
|
972
1121
|
this._graphKey = _graphKey;
|
|
973
1122
|
this._trackedMetrics = {};
|
|
1123
|
+
this._trackedMetrics.resumptionToken = this.resumptionToken;
|
|
974
1124
|
}
|
|
975
1125
|
getTrackData() {
|
|
976
1126
|
return {
|
|
@@ -1054,6 +1204,10 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
|
|
|
1054
1204
|
}
|
|
1055
1205
|
}
|
|
1056
1206
|
trackToolCall(toolKey) {
|
|
1207
|
+
if (!this._trackedMetrics.toolCalls) {
|
|
1208
|
+
this._trackedMetrics.toolCalls = [];
|
|
1209
|
+
}
|
|
1210
|
+
this._trackedMetrics.toolCalls.push(toolKey);
|
|
1057
1211
|
this._ldClient.track("$ld:ai:tool_call", this._context, { ...this.getTrackData(), toolKey }, 1);
|
|
1058
1212
|
}
|
|
1059
1213
|
trackToolCalls(toolKeys) {
|
|
@@ -1109,8 +1263,11 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
|
|
|
1109
1263
|
} else {
|
|
1110
1264
|
this.trackError();
|
|
1111
1265
|
}
|
|
1112
|
-
if (metrics.
|
|
1113
|
-
this.trackTokens(metrics.
|
|
1266
|
+
if (metrics.tokens) {
|
|
1267
|
+
this.trackTokens(metrics.tokens);
|
|
1268
|
+
}
|
|
1269
|
+
if (metrics.toolCalls?.length) {
|
|
1270
|
+
this.trackToolCalls(metrics.toolCalls);
|
|
1114
1271
|
}
|
|
1115
1272
|
return result;
|
|
1116
1273
|
}
|
|
@@ -1134,8 +1291,11 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
|
|
|
1134
1291
|
} else {
|
|
1135
1292
|
this.trackError();
|
|
1136
1293
|
}
|
|
1137
|
-
if (metrics.
|
|
1138
|
-
this.trackTokens(metrics.
|
|
1294
|
+
if (metrics.tokens) {
|
|
1295
|
+
this.trackTokens(metrics.tokens);
|
|
1296
|
+
}
|
|
1297
|
+
if (metrics.toolCalls?.length) {
|
|
1298
|
+
this.trackToolCalls(metrics.toolCalls);
|
|
1139
1299
|
}
|
|
1140
1300
|
} catch (error) {
|
|
1141
1301
|
this.trackError();
|
|
@@ -1220,6 +1380,7 @@ var LDGraphTrackerImpl = class _LDGraphTrackerImpl {
|
|
|
1220
1380
|
this._version = _version;
|
|
1221
1381
|
this._context = _context;
|
|
1222
1382
|
this._summary = {};
|
|
1383
|
+
this._summary.resumptionToken = this.resumptionToken;
|
|
1223
1384
|
}
|
|
1224
1385
|
/**
|
|
1225
1386
|
* Reconstructs an {@link LDGraphTrackerImpl} from a resumption token, preserving
|
|
@@ -1245,15 +1406,12 @@ var LDGraphTrackerImpl = class _LDGraphTrackerImpl {
|
|
|
1245
1406
|
);
|
|
1246
1407
|
}
|
|
1247
1408
|
getTrackData() {
|
|
1248
|
-
|
|
1409
|
+
return {
|
|
1249
1410
|
runId: this._runId,
|
|
1250
1411
|
graphKey: this._graphKey,
|
|
1251
|
-
version: this._version
|
|
1412
|
+
version: this._version,
|
|
1413
|
+
...this._variationKey !== void 0 ? { variationKey: this._variationKey } : {}
|
|
1252
1414
|
};
|
|
1253
|
-
if (this._variationKey !== void 0) {
|
|
1254
|
-
data.variationKey = this._variationKey;
|
|
1255
|
-
}
|
|
1256
|
-
return data;
|
|
1257
1415
|
}
|
|
1258
1416
|
getSummary() {
|
|
1259
1417
|
return { ...this._summary };
|
|
@@ -1358,13 +1516,14 @@ var LDGraphTrackerImpl = class _LDGraphTrackerImpl {
|
|
|
1358
1516
|
|
|
1359
1517
|
// src/sdkInfo.ts
|
|
1360
1518
|
var aiSdkName = "@launchdarkly/server-sdk-ai";
|
|
1361
|
-
var aiSdkVersion = "0.
|
|
1519
|
+
var aiSdkVersion = "0.20.0";
|
|
1362
1520
|
var aiSdkLanguage = "javascript";
|
|
1363
1521
|
|
|
1364
1522
|
// src/LDAIClientImpl.ts
|
|
1365
1523
|
var TRACK_SDK_INFO = "$ld:ai:sdk:info";
|
|
1366
1524
|
var TRACK_USAGE_COMPLETION_CONFIG = "$ld:ai:usage:completion-config";
|
|
1367
1525
|
var TRACK_USAGE_CREATE_CHAT = "$ld:ai:usage:create-chat";
|
|
1526
|
+
var TRACK_USAGE_CREATE_AGENT = "$ld:ai:usage:create-agent";
|
|
1368
1527
|
var TRACK_USAGE_JUDGE_CONFIG = "$ld:ai:usage:judge-config";
|
|
1369
1528
|
var TRACK_USAGE_CREATE_JUDGE = "$ld:ai:usage:create-judge";
|
|
1370
1529
|
var TRACK_USAGE_AGENT_CONFIG = "$ld:ai:usage:agent-config";
|
|
@@ -1392,18 +1551,11 @@ var LDAIClientImpl = class {
|
|
|
1392
1551
|
);
|
|
1393
1552
|
}
|
|
1394
1553
|
_interpolateTemplate(template, variables) {
|
|
1395
|
-
return
|
|
1554
|
+
return import_mustache.default.render(template, variables, void 0, { escape: (item) => item });
|
|
1396
1555
|
}
|
|
1397
|
-
async _evaluate(key, context, defaultValue, mode, variables, graphKey) {
|
|
1556
|
+
async _evaluate(key, context, defaultValue, mode, variables, graphKey, defaultAiProvider) {
|
|
1398
1557
|
const ldFlagValue = LDAIConfigUtils.toFlagValue(defaultValue, mode);
|
|
1399
1558
|
const value = await this._ldClient.variation(key, context, ldFlagValue);
|
|
1400
|
-
const flagMode = value._ldMeta?.mode ?? "completion";
|
|
1401
|
-
if (flagMode !== mode) {
|
|
1402
|
-
this._logger?.warn(
|
|
1403
|
-
`AI Config mode mismatch for ${key}: expected ${mode}, got ${flagMode}. Returning disabled config.`
|
|
1404
|
-
);
|
|
1405
|
-
return LDAIConfigUtils.createDisabledConfig(key, mode);
|
|
1406
|
-
}
|
|
1407
1559
|
const trackerFactory = () => new LDAIConfigTrackerImpl(
|
|
1408
1560
|
this._ldClient,
|
|
1409
1561
|
(0, import_node_crypto.randomUUID)(),
|
|
@@ -1417,7 +1569,23 @@ var LDAIClientImpl = class {
|
|
|
1417
1569
|
context,
|
|
1418
1570
|
graphKey
|
|
1419
1571
|
);
|
|
1420
|
-
const
|
|
1572
|
+
const flagMode = value._ldMeta?.mode ?? "completion";
|
|
1573
|
+
let evaluator = Evaluator.noop();
|
|
1574
|
+
if (flagMode !== mode) {
|
|
1575
|
+
this._logger?.warn(
|
|
1576
|
+
`AI Config mode mismatch for ${key}: expected ${mode}, got ${flagMode}. Returning disabled config.`
|
|
1577
|
+
);
|
|
1578
|
+
return LDAIConfigUtils.createDisabledConfig(key, mode, trackerFactory, evaluator);
|
|
1579
|
+
}
|
|
1580
|
+
if (flagMode !== "judge") {
|
|
1581
|
+
evaluator = await this._buildEvaluator(
|
|
1582
|
+
value.judgeConfiguration?.judges ?? [],
|
|
1583
|
+
context,
|
|
1584
|
+
variables,
|
|
1585
|
+
defaultAiProvider
|
|
1586
|
+
);
|
|
1587
|
+
}
|
|
1588
|
+
const config = LDAIConfigUtils.fromFlagValue(key, value, trackerFactory, evaluator);
|
|
1421
1589
|
return this._applyInterpolation(config, context, variables);
|
|
1422
1590
|
}
|
|
1423
1591
|
_applyInterpolation(config, context, variables) {
|
|
@@ -1439,33 +1607,44 @@ var LDAIClientImpl = class {
|
|
|
1439
1607
|
}
|
|
1440
1608
|
return config;
|
|
1441
1609
|
}
|
|
1442
|
-
async
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1610
|
+
async _buildEvaluator(judgeConfigs, context, variables, defaultAiProvider) {
|
|
1611
|
+
if (judgeConfigs.length === 0) {
|
|
1612
|
+
return Evaluator.noop();
|
|
1613
|
+
}
|
|
1614
|
+
const judgeInstances = (await Promise.all(
|
|
1615
|
+
judgeConfigs.map(
|
|
1616
|
+
(jc) => this._createJudgeInstance(
|
|
1617
|
+
jc.key,
|
|
1618
|
+
context,
|
|
1619
|
+
void 0,
|
|
1620
|
+
variables,
|
|
1621
|
+
defaultAiProvider,
|
|
1622
|
+
jc.samplingRate
|
|
1623
|
+
)
|
|
1624
|
+
)
|
|
1625
|
+
)).filter((j) => j !== void 0);
|
|
1626
|
+
return new Evaluator(judgeInstances);
|
|
1627
|
+
}
|
|
1628
|
+
async _completionConfig(key, context, defaultValue, variables, defaultAiProvider) {
|
|
1629
|
+
return await this._evaluate(
|
|
1630
|
+
key,
|
|
1631
|
+
context,
|
|
1632
|
+
defaultValue,
|
|
1633
|
+
"completion",
|
|
1634
|
+
variables,
|
|
1635
|
+
void 0,
|
|
1636
|
+
defaultAiProvider
|
|
1637
|
+
);
|
|
1465
1638
|
}
|
|
1466
|
-
async completionConfig(key, context, defaultValue, variables) {
|
|
1639
|
+
async completionConfig(key, context, defaultValue, variables, defaultAiProvider) {
|
|
1467
1640
|
this._ldClient.track(TRACK_USAGE_COMPLETION_CONFIG, context, key, 1);
|
|
1468
|
-
return this._completionConfig(
|
|
1641
|
+
return this._completionConfig(
|
|
1642
|
+
key,
|
|
1643
|
+
context,
|
|
1644
|
+
defaultValue ?? disabledAIConfig,
|
|
1645
|
+
variables,
|
|
1646
|
+
defaultAiProvider
|
|
1647
|
+
);
|
|
1469
1648
|
}
|
|
1470
1649
|
/**
|
|
1471
1650
|
* @deprecated Use `completionConfig` instead. This method will be removed in a future version.
|
|
@@ -1474,20 +1653,58 @@ var LDAIClientImpl = class {
|
|
|
1474
1653
|
return this.completionConfig(key, context, defaultValue, variables);
|
|
1475
1654
|
}
|
|
1476
1655
|
async _judgeConfig(key, context, defaultValue, variables) {
|
|
1477
|
-
|
|
1656
|
+
if (variables?.message_history !== void 0) {
|
|
1657
|
+
this._logger?.warn(
|
|
1658
|
+
"The variable 'message_history' is reserved by the judge and will be ignored."
|
|
1659
|
+
);
|
|
1660
|
+
}
|
|
1661
|
+
if (variables?.response_to_evaluate !== void 0) {
|
|
1662
|
+
this._logger?.warn(
|
|
1663
|
+
"The variable 'response_to_evaluate' is reserved by the judge and will be ignored."
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
const extendedVariables = {
|
|
1667
|
+
...variables,
|
|
1668
|
+
message_history: "{{message_history}}",
|
|
1669
|
+
response_to_evaluate: "{{response_to_evaluate}}"
|
|
1670
|
+
};
|
|
1671
|
+
const config = await this._evaluate(
|
|
1672
|
+
key,
|
|
1673
|
+
context,
|
|
1674
|
+
defaultValue,
|
|
1675
|
+
"judge",
|
|
1676
|
+
extendedVariables
|
|
1677
|
+
);
|
|
1678
|
+
if (config.messages) {
|
|
1679
|
+
return { ...config, messages: stripLegacyJudgeMessages(config.messages) };
|
|
1680
|
+
}
|
|
1478
1681
|
return config;
|
|
1479
1682
|
}
|
|
1480
1683
|
async judgeConfig(key, context, defaultValue, variables) {
|
|
1481
1684
|
this._ldClient.track(TRACK_USAGE_JUDGE_CONFIG, context, key, 1);
|
|
1482
1685
|
return this._judgeConfig(key, context, defaultValue ?? disabledAIConfig, variables);
|
|
1483
1686
|
}
|
|
1484
|
-
async _agentConfig(key, context, defaultValue, variables, graphKey) {
|
|
1485
|
-
|
|
1486
|
-
|
|
1687
|
+
async _agentConfig(key, context, defaultValue, variables, graphKey, defaultAiProvider) {
|
|
1688
|
+
return await this._evaluate(
|
|
1689
|
+
key,
|
|
1690
|
+
context,
|
|
1691
|
+
defaultValue,
|
|
1692
|
+
"agent",
|
|
1693
|
+
variables,
|
|
1694
|
+
graphKey,
|
|
1695
|
+
defaultAiProvider
|
|
1696
|
+
);
|
|
1487
1697
|
}
|
|
1488
|
-
async agentConfig(key, context, defaultValue, variables) {
|
|
1698
|
+
async agentConfig(key, context, defaultValue, variables, defaultAiProvider) {
|
|
1489
1699
|
this._ldClient.track(TRACK_USAGE_AGENT_CONFIG, context, key, 1);
|
|
1490
|
-
return this._agentConfig(
|
|
1700
|
+
return this._agentConfig(
|
|
1701
|
+
key,
|
|
1702
|
+
context,
|
|
1703
|
+
defaultValue ?? disabledAIConfig,
|
|
1704
|
+
variables,
|
|
1705
|
+
void 0,
|
|
1706
|
+
defaultAiProvider
|
|
1707
|
+
);
|
|
1491
1708
|
}
|
|
1492
1709
|
/**
|
|
1493
1710
|
* @deprecated Use `agentConfig` instead. This method will be removed in a future version.
|
|
@@ -1522,73 +1739,89 @@ var LDAIClientImpl = class {
|
|
|
1522
1739
|
async agents(agentConfigs, context) {
|
|
1523
1740
|
return this.agentConfigs(agentConfigs, context);
|
|
1524
1741
|
}
|
|
1525
|
-
async
|
|
1526
|
-
this._ldClient.track(
|
|
1527
|
-
|
|
1742
|
+
async createJudge(key, context, defaultValue, variables, defaultAiProvider, sampleRate = 1) {
|
|
1743
|
+
this._ldClient.track(TRACK_USAGE_CREATE_JUDGE, context, key, 1);
|
|
1744
|
+
return this._createJudgeInstance(
|
|
1528
1745
|
key,
|
|
1529
1746
|
context,
|
|
1530
|
-
defaultValue
|
|
1531
|
-
variables
|
|
1532
|
-
);
|
|
1533
|
-
if (!config.enabled) {
|
|
1534
|
-
this._logger?.info(`Chat configuration is disabled: ${key}`);
|
|
1535
|
-
return void 0;
|
|
1536
|
-
}
|
|
1537
|
-
const provider = await AIProviderFactory.create(config, this._logger, defaultAiProvider);
|
|
1538
|
-
if (!provider) {
|
|
1539
|
-
return void 0;
|
|
1540
|
-
}
|
|
1541
|
-
const judges = await this._initializeJudges(
|
|
1542
|
-
config.judgeConfiguration?.judges ?? [],
|
|
1543
|
-
context,
|
|
1747
|
+
defaultValue,
|
|
1544
1748
|
variables,
|
|
1545
|
-
defaultAiProvider
|
|
1749
|
+
defaultAiProvider,
|
|
1750
|
+
sampleRate
|
|
1546
1751
|
);
|
|
1547
|
-
return new TrackedChat(config, provider, judges, this._logger);
|
|
1548
1752
|
}
|
|
1549
|
-
async
|
|
1550
|
-
this._ldClient.track(TRACK_USAGE_CREATE_JUDGE, context, key, 1);
|
|
1753
|
+
async _createJudgeInstance(key, context, defaultValue, variables, defaultAiProvider, sampleRate = 1) {
|
|
1551
1754
|
try {
|
|
1552
|
-
if (variables?.message_history !== void 0) {
|
|
1553
|
-
this._logger?.warn(
|
|
1554
|
-
"The variable 'message_history' is reserved by the judge and will be ignored."
|
|
1555
|
-
);
|
|
1556
|
-
}
|
|
1557
|
-
if (variables?.response_to_evaluate !== void 0) {
|
|
1558
|
-
this._logger?.warn(
|
|
1559
|
-
"The variable 'response_to_evaluate' is reserved by the judge and will be ignored."
|
|
1560
|
-
);
|
|
1561
|
-
}
|
|
1562
|
-
const extendedVariables = {
|
|
1563
|
-
...variables,
|
|
1564
|
-
message_history: "{{message_history}}",
|
|
1565
|
-
response_to_evaluate: "{{response_to_evaluate}}"
|
|
1566
|
-
};
|
|
1567
1755
|
const judgeConfig = await this._judgeConfig(
|
|
1568
1756
|
key,
|
|
1569
1757
|
context,
|
|
1570
1758
|
defaultValue ?? disabledAIConfig,
|
|
1571
|
-
|
|
1759
|
+
variables
|
|
1572
1760
|
);
|
|
1573
1761
|
if (!judgeConfig.enabled) {
|
|
1574
1762
|
this._logger?.info(`Judge configuration is disabled: ${key}`);
|
|
1575
1763
|
return void 0;
|
|
1576
1764
|
}
|
|
1577
|
-
const
|
|
1578
|
-
if (!
|
|
1765
|
+
const runner = await RunnerFactory.createModel(judgeConfig, this._logger, defaultAiProvider);
|
|
1766
|
+
if (!runner) {
|
|
1579
1767
|
return void 0;
|
|
1580
1768
|
}
|
|
1581
|
-
return new Judge(judgeConfig,
|
|
1769
|
+
return new Judge(judgeConfig, runner, sampleRate, this._logger);
|
|
1582
1770
|
} catch (error) {
|
|
1583
1771
|
this._logger?.error(`Failed to initialize judge ${key}:`, error);
|
|
1584
1772
|
return void 0;
|
|
1585
1773
|
}
|
|
1586
1774
|
}
|
|
1775
|
+
async createModel(key, context, defaultValue, variables, defaultAiProvider) {
|
|
1776
|
+
this._ldClient.track(TRACK_USAGE_CREATE_CHAT, context, key, 1);
|
|
1777
|
+
const config = await this._completionConfig(
|
|
1778
|
+
key,
|
|
1779
|
+
context,
|
|
1780
|
+
defaultValue ?? disabledAIConfig,
|
|
1781
|
+
variables,
|
|
1782
|
+
defaultAiProvider
|
|
1783
|
+
);
|
|
1784
|
+
if (!config.enabled) {
|
|
1785
|
+
this._logger?.info(`Completion configuration is disabled: ${key}`);
|
|
1786
|
+
return void 0;
|
|
1787
|
+
}
|
|
1788
|
+
const runner = await RunnerFactory.createModel(config, this._logger, defaultAiProvider);
|
|
1789
|
+
if (!runner) {
|
|
1790
|
+
return void 0;
|
|
1791
|
+
}
|
|
1792
|
+
return new ManagedModel(config, runner, this._logger);
|
|
1793
|
+
}
|
|
1794
|
+
async createAgent(key, context, defaultValue, variables, defaultAiProvider) {
|
|
1795
|
+
this._ldClient.track(TRACK_USAGE_CREATE_AGENT, context, key, 1);
|
|
1796
|
+
const config = await this._agentConfig(
|
|
1797
|
+
key,
|
|
1798
|
+
context,
|
|
1799
|
+
defaultValue ?? disabledAIConfig,
|
|
1800
|
+
variables,
|
|
1801
|
+
void 0,
|
|
1802
|
+
defaultAiProvider
|
|
1803
|
+
);
|
|
1804
|
+
if (!config.enabled) {
|
|
1805
|
+
this._logger?.info(`Agent configuration is disabled: ${key}`);
|
|
1806
|
+
return void 0;
|
|
1807
|
+
}
|
|
1808
|
+
const runner = await RunnerFactory.createAgent(config, void 0, this._logger, defaultAiProvider);
|
|
1809
|
+
if (!runner) {
|
|
1810
|
+
return void 0;
|
|
1811
|
+
}
|
|
1812
|
+
return new ManagedAgent(config, runner, this._logger);
|
|
1813
|
+
}
|
|
1814
|
+
/**
|
|
1815
|
+
* @deprecated Use `createModel` instead. This method will be removed in a future version.
|
|
1816
|
+
*/
|
|
1817
|
+
async createChat(key, context, defaultValue, variables, defaultAiProvider) {
|
|
1818
|
+
return this.createModel(key, context, defaultValue, variables, defaultAiProvider);
|
|
1819
|
+
}
|
|
1587
1820
|
/**
|
|
1588
|
-
* @deprecated Use `
|
|
1821
|
+
* @deprecated Use `createModel` instead. This method will be removed in a future version.
|
|
1589
1822
|
*/
|
|
1590
1823
|
async initChat(key, context, defaultValue, variables, defaultAiProvider) {
|
|
1591
|
-
return this.
|
|
1824
|
+
return this.createModel(key, context, defaultValue, variables, defaultAiProvider);
|
|
1592
1825
|
}
|
|
1593
1826
|
createTracker(token, context) {
|
|
1594
1827
|
return LDAIConfigTrackerImpl.fromResumptionToken(token, this._ldClient, context);
|
|
@@ -1674,14 +1907,16 @@ function initAi(ldClient) {
|
|
|
1674
1907
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1675
1908
|
0 && (module.exports = {
|
|
1676
1909
|
AIProvider,
|
|
1677
|
-
AIProviderFactory,
|
|
1678
1910
|
AgentGraphDefinition,
|
|
1679
1911
|
AgentGraphNode,
|
|
1680
1912
|
Judge,
|
|
1681
1913
|
LDFeedbackKind,
|
|
1682
1914
|
LDGraphTrackerImpl,
|
|
1915
|
+
ManagedAgent,
|
|
1916
|
+
ManagedAgentGraph,
|
|
1917
|
+
ManagedModel,
|
|
1918
|
+
RunnerFactory,
|
|
1683
1919
|
SUPPORTED_AI_PROVIDERS,
|
|
1684
|
-
TrackedChat,
|
|
1685
1920
|
createBedrockTokenUsage,
|
|
1686
1921
|
createOpenAiUsage,
|
|
1687
1922
|
createVercelAISDKTokenUsage,
|