1+ import { LDLogger } from '@launchdarkly/js-server-sdk-common' ;
2+
13import { LDAIConfigTracker } from '../config/LDAIConfigTracker' ;
24import { LDAIConversationConfig , LDMessage } from '../config/types' ;
5+ import { Judge } from '../judge/Judge' ;
6+ import { JudgeResponse } from '../judge/types' ;
37import { AIProvider } from '../providers/AIProvider' ;
48import { ChatResponse } from './types' ;
59
@@ -11,13 +15,19 @@ import { ChatResponse } from './types';
1115 */
1216export class TrackedChat {
1317 protected messages : LDMessage [ ] ;
18+ protected judges : Record < string , Judge > ;
19+ private readonly _logger ?: LDLogger ;
1420
1521 constructor (
1622 protected readonly aiConfig : LDAIConversationConfig ,
1723 protected readonly tracker : LDAIConfigTracker ,
1824 protected readonly provider : AIProvider ,
25+ judges ?: Record < string , Judge > ,
26+ logger ?: LDLogger ,
1927 ) {
2028 this . messages = [ ] ;
29+ this . judges = judges || { } ;
30+ this . _logger = logger ;
2131 }
2232
2333 /**
@@ -45,9 +55,63 @@ export class TrackedChat {
4555 // Add the assistant response to the conversation history
4656 this . messages . push ( response . message ) ;
4757
58+ // Start judge evaluations if configured
59+ if (
60+ this . aiConfig . judgeConfiguration ?. judges &&
61+ this . aiConfig . judgeConfiguration . judges . length > 0
62+ ) {
63+ response . evaluations = this . _evaluateWithJudges ( this . messages , response ) ;
64+ }
65+
4866 return response ;
4967 }
5068
69+ /**
70+ * Evaluates the response with all configured judges.
71+ * Returns a promise that resolves to an array of evaluation results.
72+ *
73+ * @param messages Array of messages representing the conversation history
74+ * @param response The AI response to be evaluated
75+ * @returns Promise resolving to array of judge evaluation results
76+ */
77+ private async _evaluateWithJudges (
78+ messages : LDMessage [ ] ,
79+ response : ChatResponse ,
80+ ) : Promise < Array < JudgeResponse | undefined > > {
81+ const judgeConfigs = this . aiConfig . judgeConfiguration ! . judges ;
82+
83+ // Start all judge evaluations in parallel
84+ const evaluationPromises = judgeConfigs . map ( async ( judgeConfig ) => {
85+ const judge = this . judges [ judgeConfig . key ] ;
86+ if ( ! judge ) {
87+ this . _logger ?. warn (
88+ `Judge configuration is not enabled: ${ judgeConfig . key } ` ,
89+ this . tracker . getTrackData ( ) ,
90+ ) ;
91+ return undefined ;
92+ }
93+
94+ const evalResult = await judge . evaluateMessages (
95+ messages ,
96+ response ,
97+ judgeConfig . samplingRate ,
98+ ) ;
99+
100+ // Track scores if evaluation was successful
101+ if ( evalResult && evalResult . success ) {
102+ this . tracker . trackEvalScores ( evalResult . evals ) ;
103+ }
104+
105+ return evalResult ;
106+ } ) ;
107+
108+ // Use Promise.allSettled to ensure all evaluations complete
109+ // even if some fail
110+ const results = await Promise . allSettled ( evaluationPromises ) ;
111+
112+ return results . map ( ( result ) => ( result . status === 'fulfilled' ? result . value : undefined ) ) ;
113+ }
114+
51115 /**
52116 * Get the underlying AI configuration used to initialize this TrackedChat.
53117 */
@@ -70,6 +134,14 @@ export class TrackedChat {
70134 return this . provider ;
71135 }
72136
137+ /**
138+ * Get the judges associated with this TrackedChat.
139+ * Returns a record of judge instances keyed by their configuration keys.
140+ */
141+ getJudges ( ) : Record < string , Judge > {
142+ return this . judges ;
143+ }
144+
73145 /**
74146 * Append messages to the conversation history.
75147 * Adds messages to the conversation history without invoking the model,
0 commit comments