@launchdarkly/server-sdk-ai 0.12.3 → 0.14.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 +44 -0
- package/README.md +2 -2
- package/__tests__/Judge.test.ts +496 -0
- package/__tests__/LDAIClientImpl.test.ts +530 -323
- package/__tests__/LDAIConfigTrackerImpl.test.ts +50 -290
- package/__tests__/TrackedChat.test.ts +4 -5
- package/dist/package.json +53 -0
- package/dist/src/LDAIClientImpl.d.ts +39 -0
- package/dist/src/LDAIClientImpl.d.ts.map +1 -0
- package/dist/src/LDAIClientImpl.js +164 -0
- package/dist/src/LDAIClientImpl.js.map +1 -0
- package/dist/{LDAIConfigTrackerImpl.d.ts → src/LDAIConfigTrackerImpl.d.ts} +13 -11
- package/dist/src/LDAIConfigTrackerImpl.d.ts.map +1 -0
- package/dist/{LDAIConfigTrackerImpl.js → src/LDAIConfigTrackerImpl.js} +59 -44
- package/dist/src/LDAIConfigTrackerImpl.js.map +1 -0
- package/dist/src/LDClientMin.d.ts.map +1 -0
- package/dist/{LDClientMin.js.map → src/LDClientMin.js.map} +1 -1
- package/dist/src/api/LDAIClient.d.ts +258 -0
- package/dist/src/api/LDAIClient.d.ts.map +1 -0
- package/dist/{api → src/api}/LDAIClient.js.map +1 -1
- package/dist/{api → src/api}/chat/TrackedChat.d.ts +22 -4
- package/dist/src/api/chat/TrackedChat.d.ts.map +1 -0
- package/dist/{api → src/api}/chat/TrackedChat.js +43 -2
- package/dist/src/api/chat/TrackedChat.js.map +1 -0
- package/dist/src/api/chat/index.d.ts.map +1 -0
- package/dist/src/api/chat/index.js.map +1 -0
- package/dist/src/api/chat/types.d.ts +22 -0
- package/dist/src/api/chat/types.d.ts.map +1 -0
- package/dist/{api → src/api}/chat/types.js.map +1 -1
- package/dist/{api → src/api}/config/LDAIConfigTracker.d.ts +41 -22
- package/dist/src/api/config/LDAIConfigTracker.d.ts.map +1 -0
- package/dist/src/api/config/LDAIConfigTracker.js.map +1 -0
- package/dist/src/api/config/LDAIConfigUtils.d.ts +2 -0
- package/dist/src/api/config/LDAIConfigUtils.d.ts.map +1 -0
- package/dist/src/api/config/LDAIConfigUtils.js +141 -0
- package/dist/src/api/config/LDAIConfigUtils.js.map +1 -0
- package/dist/src/api/config/index.d.ts +3 -0
- package/dist/src/api/config/index.d.ts.map +1 -0
- package/dist/{api/agents → src/api/config}/index.js +1 -1
- package/dist/src/api/config/index.js.map +1 -0
- package/dist/src/api/config/types.d.ts +202 -0
- package/dist/src/api/config/types.d.ts.map +1 -0
- package/dist/{api/agents/LDAIAgent.js → src/api/config/types.js} +1 -1
- package/dist/src/api/config/types.js.map +1 -0
- package/dist/{api → src/api}/index.d.ts +1 -1
- package/dist/src/api/index.d.ts.map +1 -0
- package/dist/{api → src/api}/index.js +1 -1
- package/dist/src/api/index.js.map +1 -0
- package/dist/src/api/judge/EvaluationSchemaBuilder.d.ts +11 -0
- package/dist/src/api/judge/EvaluationSchemaBuilder.d.ts.map +1 -0
- package/dist/src/api/judge/EvaluationSchemaBuilder.js +52 -0
- package/dist/src/api/judge/EvaluationSchemaBuilder.js.map +1 -0
- package/dist/src/api/judge/Judge.d.ts +63 -0
- package/dist/src/api/judge/Judge.d.ts.map +1 -0
- package/dist/src/api/judge/Judge.js +149 -0
- package/dist/src/api/judge/Judge.js.map +1 -0
- package/dist/src/api/judge/index.d.ts +3 -0
- package/dist/src/api/judge/index.d.ts.map +1 -0
- package/dist/src/api/judge/index.js +6 -0
- package/dist/src/api/judge/index.js.map +1 -0
- package/dist/src/api/judge/types.d.ts +35 -0
- package/dist/src/api/judge/types.d.ts.map +1 -0
- package/dist/{api/config/LDAIConfig.js → src/api/judge/types.js} +1 -1
- package/dist/src/api/judge/types.js.map +1 -0
- package/dist/src/api/metrics/BedrockTokenUsage.d.ts.map +1 -0
- package/dist/src/api/metrics/BedrockTokenUsage.js.map +1 -0
- package/dist/src/api/metrics/LDAIMetrics.d.ts.map +1 -0
- package/dist/src/api/metrics/LDAIMetrics.js.map +1 -0
- package/dist/src/api/metrics/LDFeedbackKind.d.ts.map +1 -0
- package/dist/src/api/metrics/LDFeedbackKind.js.map +1 -0
- package/dist/src/api/metrics/LDTokenUsage.d.ts.map +1 -0
- package/dist/src/api/metrics/LDTokenUsage.js.map +1 -0
- package/dist/src/api/metrics/OpenAiUsage.d.ts.map +1 -0
- package/dist/src/api/metrics/OpenAiUsage.js.map +1 -0
- package/dist/src/api/metrics/VercelAISDKTokenUsage.d.ts.map +1 -0
- package/dist/src/api/metrics/VercelAISDKTokenUsage.js.map +1 -0
- package/dist/src/api/metrics/index.d.ts.map +1 -0
- package/dist/src/api/metrics/index.js.map +1 -0
- package/dist/{api → src/api}/providers/AIProvider.d.ts +20 -3
- package/dist/src/api/providers/AIProvider.d.ts.map +1 -0
- package/dist/src/api/providers/AIProvider.js +88 -0
- package/dist/src/api/providers/AIProvider.js.map +1 -0
- package/dist/{api → src/api}/providers/AIProviderFactory.d.ts +2 -2
- package/dist/src/api/providers/AIProviderFactory.d.ts.map +1 -0
- package/dist/src/api/providers/AIProviderFactory.js.map +1 -0
- package/dist/src/api/providers/index.d.ts.map +1 -0
- package/dist/src/api/providers/index.js.map +1 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js.map +1 -0
- package/docs/assets/search.js +1 -1
- package/docs/classes/AIProvider.html +55 -20
- package/docs/classes/AIProviderFactory.html +27 -17
- package/docs/classes/Judge.html +322 -0
- package/docs/classes/TrackedChat.html +97 -29
- package/docs/enums/LDFeedbackKind.html +22 -12
- package/docs/functions/createBedrockTokenUsage.html +20 -10
- package/docs/functions/createOpenAiUsage.html +20 -10
- package/docs/functions/createVercelAISDKTokenUsage.html +20 -10
- package/docs/functions/initAi.html +20 -10
- package/docs/index.html +36 -16
- package/docs/interfaces/ChatResponse.html +35 -14
- package/docs/interfaces/EvalScore.html +119 -0
- package/docs/interfaces/JudgeResponse.html +129 -0
- package/docs/interfaces/LDAIAgentConfig.html +81 -33
- package/docs/interfaces/{LDAIAgent.html → LDAIAgentConfigDefault.html} +51 -41
- package/docs/interfaces/LDAIAgentRequestConfig.html +129 -0
- package/docs/interfaces/LDAIClient.html +234 -40
- package/docs/interfaces/{VercelAISDKConfig.html → LDAICompletionConfig.html} +86 -86
- package/docs/interfaces/LDAICompletionConfigDefault.html +155 -0
- package/docs/interfaces/LDAIConfig.html +45 -75
- package/docs/interfaces/LDAIConfigDefault.html +133 -0
- package/docs/interfaces/LDAIConfigTracker.html +140 -59
- package/docs/interfaces/LDAIJudgeConfig.html +167 -0
- package/docs/interfaces/LDAIJudgeConfigDefault.html +155 -0
- package/docs/interfaces/LDAIMetrics.html +22 -12
- package/docs/interfaces/LDJudge.html +119 -0
- package/docs/interfaces/{VercelAISDKMapOptions.html → LDJudgeConfiguration.html} +36 -19
- package/docs/interfaces/LDLogger.html +19 -9
- package/docs/interfaces/LDMessage.html +22 -12
- package/docs/interfaces/LDModelConfig.html +23 -13
- package/docs/interfaces/LDProviderConfig.html +21 -11
- package/docs/interfaces/LDTokenUsage.html +23 -13
- package/docs/interfaces/StructuredResponse.html +129 -0
- package/docs/types/{VercelAISDKProvider.html → LDAIConfigDefaultKind.html} +26 -31
- package/docs/types/{LDAIAgentDefaults.html → LDAIConfigKind.html} +24 -14
- package/docs/types/{LDAIDefaults.html → LDAIConfigMode.html} +24 -24
- package/docs/types/SupportedAIProvider.html +20 -10
- package/docs/variables/SUPPORTED_AI_PROVIDERS.html +20 -10
- package/package.json +3 -3
- package/src/LDAIClientImpl.ts +222 -176
- package/src/LDAIConfigTrackerImpl.ts +73 -54
- package/src/api/LDAIClient.ts +166 -33
- package/src/api/chat/TrackedChat.ts +64 -5
- package/src/api/chat/types.ts +8 -1
- package/src/api/config/LDAIConfigTracker.ts +46 -27
- package/src/api/config/LDAIConfigUtils.ts +201 -0
- package/src/api/config/index.ts +2 -2
- package/src/api/config/types.ts +256 -0
- package/src/api/index.ts +1 -1
- package/src/api/judge/EvaluationSchemaBuilder.ts +54 -0
- package/src/api/judge/Judge.ts +216 -0
- package/src/api/judge/index.ts +2 -0
- package/src/api/judge/types.ts +39 -0
- package/src/api/providers/AIProvider.ts +54 -3
- package/src/api/providers/AIProviderFactory.ts +4 -4
- package/tsconfig.json +3 -3
- package/tsconfig.ref.json +1 -1
- package/__tests__/LDAIConfigMapper.test.ts +0 -159
- package/dist/LDAIClientImpl.d.ts +0 -23
- package/dist/LDAIClientImpl.d.ts.map +0 -1
- package/dist/LDAIClientImpl.js +0 -128
- package/dist/LDAIClientImpl.js.map +0 -1
- package/dist/LDAIConfigMapper.d.ts +0 -10
- package/dist/LDAIConfigMapper.d.ts.map +0 -1
- package/dist/LDAIConfigMapper.js +0 -55
- package/dist/LDAIConfigMapper.js.map +0 -1
- package/dist/LDAIConfigTrackerImpl.d.ts.map +0 -1
- package/dist/LDAIConfigTrackerImpl.js.map +0 -1
- package/dist/LDClientMin.d.ts.map +0 -1
- package/dist/api/LDAIClient.d.ts +0 -169
- package/dist/api/LDAIClient.d.ts.map +0 -1
- package/dist/api/agents/LDAIAgent.d.ts +0 -32
- package/dist/api/agents/LDAIAgent.d.ts.map +0 -1
- package/dist/api/agents/LDAIAgent.js.map +0 -1
- package/dist/api/agents/index.d.ts +0 -2
- package/dist/api/agents/index.d.ts.map +0 -1
- package/dist/api/agents/index.js.map +0 -1
- package/dist/api/chat/TrackedChat.d.ts.map +0 -1
- package/dist/api/chat/TrackedChat.js.map +0 -1
- package/dist/api/chat/index.d.ts.map +0 -1
- package/dist/api/chat/index.js.map +0 -1
- package/dist/api/chat/types.d.ts +0 -16
- package/dist/api/chat/types.d.ts.map +0 -1
- package/dist/api/config/LDAIConfig.d.ts +0 -92
- package/dist/api/config/LDAIConfig.d.ts.map +0 -1
- package/dist/api/config/LDAIConfig.js.map +0 -1
- package/dist/api/config/LDAIConfigTracker.d.ts.map +0 -1
- package/dist/api/config/LDAIConfigTracker.js.map +0 -1
- package/dist/api/config/VercelAISDK.d.ts +0 -19
- package/dist/api/config/VercelAISDK.d.ts.map +0 -1
- package/dist/api/config/VercelAISDK.js +0 -3
- package/dist/api/config/VercelAISDK.js.map +0 -1
- package/dist/api/config/index.d.ts +0 -4
- package/dist/api/config/index.d.ts.map +0 -1
- package/dist/api/config/index.js +0 -19
- package/dist/api/config/index.js.map +0 -1
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js.map +0 -1
- package/dist/api/metrics/BedrockTokenUsage.d.ts.map +0 -1
- package/dist/api/metrics/BedrockTokenUsage.js.map +0 -1
- package/dist/api/metrics/LDAIMetrics.d.ts.map +0 -1
- package/dist/api/metrics/LDAIMetrics.js.map +0 -1
- package/dist/api/metrics/LDFeedbackKind.d.ts.map +0 -1
- package/dist/api/metrics/LDFeedbackKind.js.map +0 -1
- package/dist/api/metrics/LDTokenUsage.d.ts.map +0 -1
- package/dist/api/metrics/LDTokenUsage.js.map +0 -1
- package/dist/api/metrics/OpenAiUsage.d.ts.map +0 -1
- package/dist/api/metrics/OpenAiUsage.js.map +0 -1
- package/dist/api/metrics/VercelAISDKTokenUsage.d.ts.map +0 -1
- package/dist/api/metrics/VercelAISDKTokenUsage.js.map +0 -1
- package/dist/api/metrics/index.d.ts.map +0 -1
- package/dist/api/metrics/index.js.map +0 -1
- package/dist/api/providers/AIProvider.d.ts.map +0 -1
- package/dist/api/providers/AIProvider.js +0 -31
- package/dist/api/providers/AIProvider.js.map +0 -1
- package/dist/api/providers/AIProviderFactory.d.ts.map +0 -1
- package/dist/api/providers/AIProviderFactory.js.map +0 -1
- package/dist/api/providers/index.d.ts.map +0 -1
- package/dist/api/providers/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/src/LDAIConfigMapper.ts +0 -65
- package/src/api/agents/LDAIAgent.ts +0 -36
- package/src/api/agents/index.ts +0 -1
- package/src/api/config/LDAIConfig.ts +0 -101
- package/src/api/config/VercelAISDK.ts +0 -21
- /package/dist/{LDClientMin.d.ts → src/LDClientMin.d.ts} +0 -0
- /package/dist/{LDClientMin.js → src/LDClientMin.js} +0 -0
- /package/dist/{api → src/api}/LDAIClient.js +0 -0
- /package/dist/{api → src/api}/chat/index.d.ts +0 -0
- /package/dist/{api → src/api}/chat/index.js +0 -0
- /package/dist/{api → src/api}/chat/types.js +0 -0
- /package/dist/{api → src/api}/config/LDAIConfigTracker.js +0 -0
- /package/dist/{api → src/api}/metrics/BedrockTokenUsage.d.ts +0 -0
- /package/dist/{api → src/api}/metrics/BedrockTokenUsage.js +0 -0
- /package/dist/{api → src/api}/metrics/LDAIMetrics.d.ts +0 -0
- /package/dist/{api → src/api}/metrics/LDAIMetrics.js +0 -0
- /package/dist/{api → src/api}/metrics/LDFeedbackKind.d.ts +0 -0
- /package/dist/{api → src/api}/metrics/LDFeedbackKind.js +0 -0
- /package/dist/{api → src/api}/metrics/LDTokenUsage.d.ts +0 -0
- /package/dist/{api → src/api}/metrics/LDTokenUsage.js +0 -0
- /package/dist/{api → src/api}/metrics/OpenAiUsage.d.ts +0 -0
- /package/dist/{api → src/api}/metrics/OpenAiUsage.js +0 -0
- /package/dist/{api → src/api}/metrics/VercelAISDKTokenUsage.d.ts +0 -0
- /package/dist/{api → src/api}/metrics/VercelAISDKTokenUsage.js +0 -0
- /package/dist/{api → src/api}/metrics/index.d.ts +0 -0
- /package/dist/{api → src/api}/metrics/index.js +0 -0
- /package/dist/{api → src/api}/providers/AIProviderFactory.js +0 -0
- /package/dist/{api → src/api}/providers/index.d.ts +0 -0
- /package/dist/{api → src/api}/providers/index.js +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { LDContext } from '@launchdarkly/js-server-sdk-common';
|
|
2
2
|
|
|
3
|
+
import { name as aiSdkName, version as aiSdkVersion } from '../package.json';
|
|
3
4
|
import { LDAIConfigTracker } from './api/config';
|
|
4
5
|
import { LDAIMetricSummary } from './api/config/LDAIConfigTracker';
|
|
6
|
+
import { EvalScore } from './api/judge/types';
|
|
5
7
|
import {
|
|
6
8
|
createBedrockTokenUsage,
|
|
7
9
|
createOpenAiUsage,
|
|
@@ -25,12 +27,14 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker {
|
|
|
25
27
|
private _context: LDContext,
|
|
26
28
|
) {}
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
getTrackData(): {
|
|
29
31
|
variationKey: string;
|
|
30
32
|
configKey: string;
|
|
31
33
|
version: number;
|
|
32
34
|
modelName: string;
|
|
33
35
|
providerName: string;
|
|
36
|
+
aiSdkName: string;
|
|
37
|
+
aiSdkVersion: string;
|
|
34
38
|
} {
|
|
35
39
|
return {
|
|
36
40
|
variationKey: this._variationKey,
|
|
@@ -38,12 +42,14 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker {
|
|
|
38
42
|
version: this._version,
|
|
39
43
|
modelName: this._modelName,
|
|
40
44
|
providerName: this._providerName,
|
|
45
|
+
aiSdkName,
|
|
46
|
+
aiSdkVersion,
|
|
41
47
|
};
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
trackDuration(duration: number): void {
|
|
45
51
|
this._trackedMetrics.durationMs = duration;
|
|
46
|
-
this._ldClient.track('$ld:ai:duration:total', this._context, this.
|
|
52
|
+
this._ldClient.track('$ld:ai:duration:total', this._context, this.getTrackData(), duration);
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
async trackDurationOf<TRes>(func: () => Promise<TRes>): Promise<TRes> {
|
|
@@ -64,28 +70,35 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker {
|
|
|
64
70
|
this._ldClient.track(
|
|
65
71
|
'$ld:ai:tokens:ttf',
|
|
66
72
|
this._context,
|
|
67
|
-
this.
|
|
73
|
+
this.getTrackData(),
|
|
68
74
|
timeToFirstTokenMs,
|
|
69
75
|
);
|
|
70
76
|
}
|
|
71
77
|
|
|
78
|
+
trackEvalScores(scores: Record<string, EvalScore>) {
|
|
79
|
+
// Track each evaluation score individually
|
|
80
|
+
Object.entries(scores).forEach(([metricKey, evalScore]) => {
|
|
81
|
+
this._ldClient.track(metricKey, this._context, this.getTrackData(), evalScore.score);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
72
85
|
trackFeedback(feedback: { kind: LDFeedbackKind }): void {
|
|
73
86
|
this._trackedMetrics.feedback = feedback;
|
|
74
87
|
if (feedback.kind === LDFeedbackKind.Positive) {
|
|
75
|
-
this._ldClient.track('$ld:ai:feedback:user:positive', this._context, this.
|
|
88
|
+
this._ldClient.track('$ld:ai:feedback:user:positive', this._context, this.getTrackData(), 1);
|
|
76
89
|
} else if (feedback.kind === LDFeedbackKind.Negative) {
|
|
77
|
-
this._ldClient.track('$ld:ai:feedback:user:negative', this._context, this.
|
|
90
|
+
this._ldClient.track('$ld:ai:feedback:user:negative', this._context, this.getTrackData(), 1);
|
|
78
91
|
}
|
|
79
92
|
}
|
|
80
93
|
|
|
81
94
|
trackSuccess(): void {
|
|
82
95
|
this._trackedMetrics.success = true;
|
|
83
|
-
this._ldClient.track('$ld:ai:generation:success', this._context, this.
|
|
96
|
+
this._ldClient.track('$ld:ai:generation:success', this._context, this.getTrackData(), 1);
|
|
84
97
|
}
|
|
85
98
|
|
|
86
99
|
trackError(): void {
|
|
87
100
|
this._trackedMetrics.success = false;
|
|
88
|
-
this._ldClient.track('$ld:ai:generation:error', this._context, this.
|
|
101
|
+
this._ldClient.track('$ld:ai:generation:error', this._context, this.getTrackData(), 1);
|
|
89
102
|
}
|
|
90
103
|
|
|
91
104
|
async trackMetricsOf<TRes>(
|
|
@@ -119,6 +132,58 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker {
|
|
|
119
132
|
return result;
|
|
120
133
|
}
|
|
121
134
|
|
|
135
|
+
trackStreamMetricsOf<TStream>(
|
|
136
|
+
streamCreator: () => TStream,
|
|
137
|
+
metricsExtractor: (stream: TStream) => Promise<LDAIMetrics>,
|
|
138
|
+
): TStream {
|
|
139
|
+
const startTime = Date.now();
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
// Create the stream synchronously
|
|
143
|
+
const stream = streamCreator();
|
|
144
|
+
|
|
145
|
+
// Start background metrics tracking (fire and forget)
|
|
146
|
+
this._trackStreamMetricsInBackground(stream, metricsExtractor, startTime);
|
|
147
|
+
|
|
148
|
+
// Return stream immediately for consumption
|
|
149
|
+
return stream;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
// Track error if stream creation fails
|
|
152
|
+
this.trackDuration(Date.now() - startTime);
|
|
153
|
+
this.trackError();
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private async _trackStreamMetricsInBackground<TStream>(
|
|
159
|
+
stream: TStream,
|
|
160
|
+
metricsExtractor: (stream: TStream) => Promise<LDAIMetrics>,
|
|
161
|
+
startTime: number,
|
|
162
|
+
): Promise<void> {
|
|
163
|
+
try {
|
|
164
|
+
// Wait for metrics to be available
|
|
165
|
+
const metrics = await metricsExtractor(stream);
|
|
166
|
+
|
|
167
|
+
// Track success/error based on metrics
|
|
168
|
+
if (metrics.success) {
|
|
169
|
+
this.trackSuccess();
|
|
170
|
+
} else {
|
|
171
|
+
this.trackError();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Track token usage if available
|
|
175
|
+
if (metrics.usage) {
|
|
176
|
+
this.trackTokens(metrics.usage);
|
|
177
|
+
}
|
|
178
|
+
} catch (error) {
|
|
179
|
+
// If metrics extraction fails, track error
|
|
180
|
+
this.trackError();
|
|
181
|
+
} finally {
|
|
182
|
+
// Track duration regardless of success/error
|
|
183
|
+
this.trackDuration(Date.now() - startTime);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
122
187
|
async trackOpenAIMetrics<
|
|
123
188
|
TRes extends {
|
|
124
189
|
usage?: {
|
|
@@ -190,55 +255,9 @@ export class LDAIConfigTrackerImpl implements LDAIConfigTracker {
|
|
|
190
255
|
}
|
|
191
256
|
}
|
|
192
257
|
|
|
193
|
-
trackVercelAISDKStreamTextMetrics<
|
|
194
|
-
TRes extends {
|
|
195
|
-
finishReason?: Promise<string>;
|
|
196
|
-
usage?: Promise<{
|
|
197
|
-
totalTokens?: number;
|
|
198
|
-
inputTokens?: number;
|
|
199
|
-
promptTokens?: number;
|
|
200
|
-
outputTokens?: number;
|
|
201
|
-
completionTokens?: number;
|
|
202
|
-
}>;
|
|
203
|
-
},
|
|
204
|
-
>(func: () => TRes): TRes {
|
|
205
|
-
const startTime = Date.now();
|
|
206
|
-
try {
|
|
207
|
-
const result = func();
|
|
208
|
-
result.finishReason
|
|
209
|
-
?.then(async (finishReason) => {
|
|
210
|
-
const endTime = Date.now();
|
|
211
|
-
this.trackDuration(endTime - startTime);
|
|
212
|
-
if (finishReason === 'error') {
|
|
213
|
-
this.trackError();
|
|
214
|
-
} else {
|
|
215
|
-
this.trackSuccess();
|
|
216
|
-
if (result.usage) {
|
|
217
|
-
try {
|
|
218
|
-
this.trackTokens(createVercelAISDKTokenUsage(await result.usage));
|
|
219
|
-
} catch {
|
|
220
|
-
// Intentionally squashing this error
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
})
|
|
225
|
-
.catch(() => {
|
|
226
|
-
const endTime = Date.now();
|
|
227
|
-
this.trackDuration(endTime - startTime);
|
|
228
|
-
this.trackError();
|
|
229
|
-
});
|
|
230
|
-
return result;
|
|
231
|
-
} catch (err) {
|
|
232
|
-
const endTime = Date.now();
|
|
233
|
-
this.trackDuration(endTime - startTime);
|
|
234
|
-
this.trackError();
|
|
235
|
-
throw err;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
258
|
trackTokens(tokens: LDTokenUsage): void {
|
|
240
259
|
this._trackedMetrics.tokens = tokens;
|
|
241
|
-
const trackData = this.
|
|
260
|
+
const trackData = this.getTrackData();
|
|
242
261
|
if (tokens.total > 0) {
|
|
243
262
|
this._ldClient.track('$ld:ai:tokens:total', this._context, trackData, tokens.total);
|
|
244
263
|
}
|
package/src/api/LDAIClient.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { LDContext } from '@launchdarkly/js-server-sdk-common';
|
|
2
2
|
|
|
3
|
-
import { LDAIAgent, LDAIAgentConfig, LDAIAgentDefaults } from './agents';
|
|
4
3
|
import { TrackedChat } from './chat';
|
|
5
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
LDAIAgentConfig,
|
|
6
|
+
LDAIAgentConfigDefault,
|
|
7
|
+
LDAIAgentRequestConfig,
|
|
8
|
+
LDAICompletionConfig,
|
|
9
|
+
LDAICompletionConfigDefault,
|
|
10
|
+
LDAIJudgeConfig,
|
|
11
|
+
LDAIJudgeConfigDefault,
|
|
12
|
+
} from './config';
|
|
13
|
+
import { Judge } from './judge/Judge';
|
|
6
14
|
import { SupportedAIProvider } from './providers';
|
|
7
15
|
|
|
8
16
|
/**
|
|
@@ -10,7 +18,7 @@ import { SupportedAIProvider } from './providers';
|
|
|
10
18
|
*/
|
|
11
19
|
export interface LDAIClient {
|
|
12
20
|
/**
|
|
13
|
-
* Retrieves and processes
|
|
21
|
+
* Retrieves and processes a completion AI Config based on the provided key, LaunchDarkly context,
|
|
14
22
|
* and variables. This includes the model configuration and the customized messages.
|
|
15
23
|
*
|
|
16
24
|
* @param key The key of the AI Config.
|
|
@@ -34,9 +42,11 @@ export interface LDAIClient {
|
|
|
34
42
|
* const variables = {username: 'john'};
|
|
35
43
|
* const defaultValue = {
|
|
36
44
|
* enabled: false,
|
|
45
|
+
* model: { name: 'gpt-4' },
|
|
46
|
+
* provider: { name: 'openai' },
|
|
37
47
|
* };
|
|
38
48
|
*
|
|
39
|
-
* const result =
|
|
49
|
+
* const result = completionConfig(key, context, defaultValue, variables);
|
|
40
50
|
* // Output:
|
|
41
51
|
* {
|
|
42
52
|
* enabled: true,
|
|
@@ -60,12 +70,22 @@ export interface LDAIClient {
|
|
|
60
70
|
* }
|
|
61
71
|
* ```
|
|
62
72
|
*/
|
|
73
|
+
completionConfig(
|
|
74
|
+
key: string,
|
|
75
|
+
context: LDContext,
|
|
76
|
+
defaultValue: LDAICompletionConfigDefault,
|
|
77
|
+
variables?: Record<string, unknown>,
|
|
78
|
+
): Promise<LDAICompletionConfig>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @deprecated Use `completionConfig` instead. This method will be removed in a future version.
|
|
82
|
+
*/
|
|
63
83
|
config(
|
|
64
84
|
key: string,
|
|
65
85
|
context: LDContext,
|
|
66
|
-
defaultValue:
|
|
86
|
+
defaultValue: LDAICompletionConfigDefault,
|
|
67
87
|
variables?: Record<string, unknown>,
|
|
68
|
-
): Promise<
|
|
88
|
+
): Promise<LDAICompletionConfig>;
|
|
69
89
|
|
|
70
90
|
/**
|
|
71
91
|
* Retrieves and processes a single AI Config agent based on the provided key, LaunchDarkly context,
|
|
@@ -89,21 +109,67 @@ export interface LDAIClient {
|
|
|
89
109
|
* const key = "research_agent";
|
|
90
110
|
* const context = {...};
|
|
91
111
|
* const variables = { topic: 'climate change' };
|
|
92
|
-
* const
|
|
112
|
+
* const agentConfig = await client.agentConfig(key, context, {
|
|
93
113
|
* enabled: true,
|
|
114
|
+
* model: { name: 'gpt-4' },
|
|
115
|
+
* provider: { name: 'openai' },
|
|
94
116
|
* instructions: 'You are a research assistant.',
|
|
95
117
|
* }, variables);
|
|
96
118
|
*
|
|
97
|
-
* const researchResult =
|
|
98
|
-
*
|
|
119
|
+
* const researchResult = agentConfig.instructions; // Interpolated instructions
|
|
120
|
+
* agentConfig.tracker.trackSuccess();
|
|
99
121
|
* ```
|
|
100
122
|
*/
|
|
123
|
+
agentConfig(
|
|
124
|
+
key: string,
|
|
125
|
+
context: LDContext,
|
|
126
|
+
defaultValue: LDAIAgentConfigDefault,
|
|
127
|
+
variables?: Record<string, unknown>,
|
|
128
|
+
): Promise<LDAIAgentConfig>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @deprecated Use `agentConfig` instead. This method will be removed in a future version.
|
|
132
|
+
*/
|
|
101
133
|
agent(
|
|
102
134
|
key: string,
|
|
103
135
|
context: LDContext,
|
|
104
|
-
defaultValue:
|
|
136
|
+
defaultValue: LDAIAgentConfigDefault,
|
|
137
|
+
variables?: Record<string, unknown>,
|
|
138
|
+
): Promise<LDAIAgentConfig>;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Retrieves and processes a Judge AI Config based on the provided key, LaunchDarkly context,
|
|
142
|
+
* and variables. This includes the model configuration and the customized messages for evaluation.
|
|
143
|
+
*
|
|
144
|
+
* @param key The key of the Judge AI Config.
|
|
145
|
+
* @param context The LaunchDarkly context object that contains relevant information about the
|
|
146
|
+
* current environment, user, or session. This context may influence how the configuration is
|
|
147
|
+
* processed or personalized.
|
|
148
|
+
* @param defaultValue A fallback value containing model configuration and messages. This will
|
|
149
|
+
* be used if the configuration is not available from LaunchDarkly.
|
|
150
|
+
* @param variables Optional variables for template interpolation in messages and instructions.
|
|
151
|
+
* @returns A promise that resolves to a tracked judge configuration.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const judgeConf = await client.judgeConfig(key, context, {
|
|
156
|
+
* enabled: true,
|
|
157
|
+
* model: { name: 'gpt-4' },
|
|
158
|
+
* provider: { name: 'openai' },
|
|
159
|
+
* evaluationMetricKeys: ['$ld:ai:judge:relevance'],
|
|
160
|
+
* messages: [{ role: 'system', content: 'You are a relevance judge.' }]
|
|
161
|
+
* }, variables);
|
|
162
|
+
*
|
|
163
|
+
* const config = judgeConf.config; // Interpolated configuration
|
|
164
|
+
* judgeConf.tracker.trackSuccess();
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
judgeConfig(
|
|
168
|
+
key: string,
|
|
169
|
+
context: LDContext,
|
|
170
|
+
defaultValue: LDAIJudgeConfigDefault,
|
|
105
171
|
variables?: Record<string, unknown>,
|
|
106
|
-
): Promise<
|
|
172
|
+
): Promise<LDAIJudgeConfig>;
|
|
107
173
|
|
|
108
174
|
/**
|
|
109
175
|
* Retrieves and processes multiple AI Config agents based on the provided agent configurations
|
|
@@ -122,38 +188,59 @@ export interface LDAIClient {
|
|
|
122
188
|
*
|
|
123
189
|
* @example
|
|
124
190
|
* ```
|
|
125
|
-
* const
|
|
191
|
+
* const agentConfigsList = [
|
|
126
192
|
* {
|
|
127
193
|
* key: 'research_agent',
|
|
128
|
-
* defaultValue: {
|
|
194
|
+
* defaultValue: {
|
|
195
|
+
* enabled: true,
|
|
196
|
+
* model: { name: 'gpt-4' },
|
|
197
|
+
* provider: { name: 'openai' },
|
|
198
|
+
* instructions: 'You are a research assistant.'
|
|
199
|
+
* },
|
|
129
200
|
* variables: { topic: 'climate change' }
|
|
130
201
|
* },
|
|
131
202
|
* {
|
|
132
203
|
* key: 'writing_agent',
|
|
133
|
-
* defaultValue: {
|
|
204
|
+
* defaultValue: {
|
|
205
|
+
* enabled: true,
|
|
206
|
+
* model: { name: 'gpt-4' },
|
|
207
|
+
* provider: { name: 'openai' },
|
|
208
|
+
* instructions: 'You are a writing assistant.'
|
|
209
|
+
* },
|
|
134
210
|
* variables: { style: 'academic' }
|
|
135
211
|
* }
|
|
136
212
|
* ] as const;
|
|
137
213
|
* const context = {...};
|
|
138
214
|
*
|
|
139
|
-
* const
|
|
140
|
-
* const researchResult =
|
|
141
|
-
*
|
|
215
|
+
* const configs = await client.agentConfigs(agentConfigsList, context);
|
|
216
|
+
* const researchResult = configs["research_agent"].instructions; // Interpolated instructions
|
|
217
|
+
* configs["research_agent"].tracker.trackSuccess();
|
|
142
218
|
* ```
|
|
143
219
|
*/
|
|
144
|
-
|
|
220
|
+
agentConfigs<const T extends readonly LDAIAgentRequestConfig[]>(
|
|
221
|
+
agentConfigs: T,
|
|
222
|
+
context: LDContext,
|
|
223
|
+
): Promise<Record<T[number]['key'], LDAIAgentConfig>>;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @deprecated Use `agentConfigs` instead. This method will be removed in a future version.
|
|
227
|
+
*/
|
|
228
|
+
agents<const T extends readonly LDAIAgentRequestConfig[]>(
|
|
145
229
|
agentConfigs: T,
|
|
146
230
|
context: LDContext,
|
|
147
|
-
): Promise<Record<T[number]['key'],
|
|
231
|
+
): Promise<Record<T[number]['key'], LDAIAgentConfig>>;
|
|
148
232
|
|
|
149
233
|
/**
|
|
150
|
-
*
|
|
234
|
+
* Returns a TrackedChat instance for chat interactions.
|
|
151
235
|
* This method serves as the primary entry point for creating TrackedChat instances from configuration.
|
|
152
236
|
*
|
|
153
237
|
* @param key The key identifying the AI chat configuration to use.
|
|
154
238
|
* @param context The standard LDContext used when evaluating flags.
|
|
155
239
|
* @param defaultValue A default value representing a standard AI chat config result.
|
|
156
240
|
* @param variables Dictionary of values for instruction interpolation.
|
|
241
|
+
* The variables will also be used for judge evaluation. For the judge only, the variables
|
|
242
|
+
* `message_history` and `response_to_evaluate` are reserved and will be ignored.
|
|
243
|
+
* @param defaultAiProvider Optional default AI provider to use.
|
|
157
244
|
* @returns A promise that resolves to the TrackedChat instance, or null if the configuration is disabled.
|
|
158
245
|
*
|
|
159
246
|
* @example
|
|
@@ -161,32 +248,78 @@ export interface LDAIClient {
|
|
|
161
248
|
* const key = "customer_support_chat";
|
|
162
249
|
* const context = {...};
|
|
163
250
|
* const defaultValue = {
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* }
|
|
251
|
+
* enabled: false,
|
|
252
|
+
* model: { name: "gpt-4" },
|
|
253
|
+
* provider: { name: "openai" },
|
|
254
|
+
* messages: [
|
|
255
|
+
* { role: "system", content: "You are a helpful customer support agent." }
|
|
256
|
+
* ]
|
|
171
257
|
* };
|
|
172
258
|
* const variables = { customerName: 'John' };
|
|
173
259
|
*
|
|
174
|
-
* const chat = await client.
|
|
260
|
+
* const chat = await client.createChat(key, context, defaultValue, variables);
|
|
175
261
|
* if (chat) {
|
|
176
262
|
* const response = await chat.invoke("I need help with my order");
|
|
177
263
|
* console.log(response.message.content);
|
|
178
|
-
*
|
|
179
|
-
* // Access configuration and tracker if needed
|
|
180
|
-
* console.log('Model:', chat.getConfig().model?.name);
|
|
181
|
-
* chat.getTracker().trackSuccess();
|
|
182
264
|
* }
|
|
183
265
|
* ```
|
|
184
266
|
*/
|
|
267
|
+
createChat(
|
|
268
|
+
key: string,
|
|
269
|
+
context: LDContext,
|
|
270
|
+
defaultValue: LDAICompletionConfigDefault,
|
|
271
|
+
variables?: Record<string, unknown>,
|
|
272
|
+
defaultAiProvider?: SupportedAIProvider,
|
|
273
|
+
): Promise<TrackedChat | undefined>;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @deprecated Use `createChat` instead. This method will be removed in a future version.
|
|
277
|
+
*/
|
|
185
278
|
initChat(
|
|
186
279
|
key: string,
|
|
187
280
|
context: LDContext,
|
|
188
|
-
defaultValue:
|
|
281
|
+
defaultValue: LDAICompletionConfigDefault,
|
|
189
282
|
variables?: Record<string, unknown>,
|
|
190
283
|
defaultAiProvider?: SupportedAIProvider,
|
|
191
284
|
): Promise<TrackedChat | undefined>;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Creates and returns a new Judge instance for AI evaluation.
|
|
288
|
+
*
|
|
289
|
+
* @param key The key identifying the AI judge configuration to use
|
|
290
|
+
* @param context Standard LDContext used when evaluating flags
|
|
291
|
+
* @param defaultValue A default value representing a standard AI config result
|
|
292
|
+
* @param variables Dictionary of values for instruction interpolation.
|
|
293
|
+
* The variables `message_history` and `response_to_evaluate` are reserved for the judge and will be ignored.
|
|
294
|
+
* @param defaultAiProvider Optional default AI provider to use.
|
|
295
|
+
* @returns Promise that resolves to a Judge instance or undefined if disabled/unsupported
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```
|
|
299
|
+
* const judge = await client.createJudge(
|
|
300
|
+
* "relevance-judge",
|
|
301
|
+
* context,
|
|
302
|
+
* {
|
|
303
|
+
* enabled: true,
|
|
304
|
+
* model: { name: "gpt-4" },
|
|
305
|
+
* provider: { name: "openai" },
|
|
306
|
+
* evaluationMetricKeys: ['$ld:ai:judge:relevance'],
|
|
307
|
+
* messages: [{ role: 'system', content: 'You are a relevance judge.' }]
|
|
308
|
+
* },
|
|
309
|
+
* { metric: "relevance" }
|
|
310
|
+
* );
|
|
311
|
+
*
|
|
312
|
+
* if (judge) {
|
|
313
|
+
* const result = await judge.evaluate("User question", "AI response");
|
|
314
|
+
* console.log('Relevance score:', result.evals.relevance?.score);
|
|
315
|
+
* }
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
createJudge(
|
|
319
|
+
key: string,
|
|
320
|
+
context: LDContext,
|
|
321
|
+
defaultValue: LDAIJudgeConfigDefault,
|
|
322
|
+
variables?: Record<string, unknown>,
|
|
323
|
+
defaultAiProvider?: SupportedAIProvider,
|
|
324
|
+
): Promise<Judge | undefined>;
|
|
192
325
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LDLogger } from '@launchdarkly/js-server-sdk-common';
|
|
2
|
+
|
|
2
3
|
import { LDAIConfigTracker } from '../config/LDAIConfigTracker';
|
|
4
|
+
import { LDAICompletionConfig, LDMessage } from '../config/types';
|
|
5
|
+
import { Judge } from '../judge/Judge';
|
|
6
|
+
import { JudgeResponse } from '../judge/types';
|
|
3
7
|
import { AIProvider } from '../providers/AIProvider';
|
|
4
8
|
import { ChatResponse } from './types';
|
|
5
9
|
|
|
@@ -13,9 +17,11 @@ export class TrackedChat {
|
|
|
13
17
|
protected messages: LDMessage[];
|
|
14
18
|
|
|
15
19
|
constructor(
|
|
16
|
-
protected readonly aiConfig:
|
|
20
|
+
protected readonly aiConfig: LDAICompletionConfig,
|
|
17
21
|
protected readonly tracker: LDAIConfigTracker,
|
|
18
22
|
protected readonly provider: AIProvider,
|
|
23
|
+
protected readonly judges: Record<string, Judge> = {},
|
|
24
|
+
private readonly _logger?: LDLogger,
|
|
19
25
|
) {
|
|
20
26
|
this.messages = [];
|
|
21
27
|
}
|
|
@@ -42,16 +48,61 @@ export class TrackedChat {
|
|
|
42
48
|
() => this.provider.invokeModel(allMessages),
|
|
43
49
|
);
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
if (
|
|
52
|
+
this.aiConfig.judgeConfiguration?.judges &&
|
|
53
|
+
this.aiConfig.judgeConfiguration.judges.length > 0
|
|
54
|
+
) {
|
|
55
|
+
response.evaluations = this._evaluateWithJudges(this.messages, response);
|
|
56
|
+
}
|
|
47
57
|
|
|
58
|
+
this.messages.push(response.message);
|
|
48
59
|
return response;
|
|
49
60
|
}
|
|
50
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Evaluates the response with all configured judges.
|
|
64
|
+
* Returns a promise that resolves to an array of evaluation results.
|
|
65
|
+
*
|
|
66
|
+
* @param messages Array of messages representing the conversation history
|
|
67
|
+
* @param response The AI response to be evaluated
|
|
68
|
+
* @returns Promise resolving to array of judge evaluation results
|
|
69
|
+
*/
|
|
70
|
+
private async _evaluateWithJudges(
|
|
71
|
+
messages: LDMessage[],
|
|
72
|
+
response: ChatResponse,
|
|
73
|
+
): Promise<Array<JudgeResponse | undefined>> {
|
|
74
|
+
const judgeConfigs = this.aiConfig.judgeConfiguration!.judges;
|
|
75
|
+
|
|
76
|
+
// Start all judge evaluations in parallel
|
|
77
|
+
const evaluationPromises = judgeConfigs.map(async (judgeConfig) => {
|
|
78
|
+
const judge = this.judges[judgeConfig.key];
|
|
79
|
+
if (!judge) {
|
|
80
|
+
this._logger?.warn(
|
|
81
|
+
`Judge configuration is not enabled: ${judgeConfig.key}`,
|
|
82
|
+
this.tracker.getTrackData(),
|
|
83
|
+
);
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const evalResult = await judge.evaluateMessages(messages, response, judgeConfig.samplingRate);
|
|
88
|
+
|
|
89
|
+
if (evalResult && evalResult.success) {
|
|
90
|
+
this.tracker.trackEvalScores(evalResult.evals);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return evalResult;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// ensure all evaluations complete even if some fail
|
|
97
|
+
const results = await Promise.allSettled(evaluationPromises);
|
|
98
|
+
|
|
99
|
+
return results.map((result) => (result.status === 'fulfilled' ? result.value : undefined));
|
|
100
|
+
}
|
|
101
|
+
|
|
51
102
|
/**
|
|
52
103
|
* Get the underlying AI configuration used to initialize this TrackedChat.
|
|
53
104
|
*/
|
|
54
|
-
getConfig():
|
|
105
|
+
getConfig(): LDAICompletionConfig {
|
|
55
106
|
return this.aiConfig;
|
|
56
107
|
}
|
|
57
108
|
|
|
@@ -70,6 +121,14 @@ export class TrackedChat {
|
|
|
70
121
|
return this.provider;
|
|
71
122
|
}
|
|
72
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Get the judges associated with this TrackedChat.
|
|
126
|
+
* Returns a record of judge instances keyed by their configuration keys.
|
|
127
|
+
*/
|
|
128
|
+
getJudges(): Record<string, Judge> {
|
|
129
|
+
return this.judges;
|
|
130
|
+
}
|
|
131
|
+
|
|
73
132
|
/**
|
|
74
133
|
* Append messages to the conversation history.
|
|
75
134
|
* Adds messages to the conversation history without invoking the model,
|
package/src/api/chat/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { LDMessage } from '../config/
|
|
1
|
+
import { LDMessage } from '../config/types';
|
|
2
|
+
import { JudgeResponse } from '../judge/types';
|
|
2
3
|
import { LDAIMetrics } from '../metrics/LDAIMetrics';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -14,4 +15,10 @@ export interface ChatResponse {
|
|
|
14
15
|
* Metrics information including success status and token usage.
|
|
15
16
|
*/
|
|
16
17
|
metrics: LDAIMetrics;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Promise that resolves to judge evaluation results.
|
|
21
|
+
* Only present when judges are configured for evaluation.
|
|
22
|
+
*/
|
|
23
|
+
evaluations?: Promise<Array<JudgeResponse | undefined>>;
|
|
17
24
|
}
|