@@ -45,11 +45,12 @@ import {
4545 getChatPayload ,
4646} from '../harness/evaluation-helpers' ;
4747import { createLogger } from '../harness/logger' ;
48- import type { GenerationCollectors } from '../harness/runner' ;
48+ import type { GenerationCollectors , SubgraphMetricsCollector } from '../harness/runner' ;
4949import { TokenUsageTrackingHandler } from '../harness/token-tracking-handler' ;
5050import {
5151 runEvaluation ,
5252 createConsoleLifecycle ,
53+ mergeLifecycles ,
5354 createLLMJudgeEvaluator ,
5455 createProgrammaticEvaluator ,
5556 createPairwiseEvaluator ,
@@ -61,6 +62,7 @@ import {
6162 type GenerationResult ,
6263} from '../index' ;
6364import { generateRunId , isWorkflowStateValues } from '../langsmith/types' ;
65+ import { createIntrospectionAnalysisLifecycle } from '../lifecycles/introspection-analysis' ;
6466import { AGENT_TYPES , EVAL_TYPES , EVAL_USERS } from '../support/constants' ;
6567import { setupTestEnvironment , createAgent , type ResolvedStageLLMs } from '../support/environment' ;
6668
@@ -82,6 +84,28 @@ function hasCoordinationLog(
8284 return Array . isArray ( obj . coordinationLog ) ;
8385}
8486
87+ /**
88+ * Report subgraph metrics from coordination log and workflow.
89+ */
90+ function reportSubgraphMetrics (
91+ collector : SubgraphMetricsCollector ,
92+ stateValues : unknown ,
93+ workflow : SimpleWorkflow ,
94+ ) : void {
95+ const coordinationLog = hasCoordinationLog ( stateValues ) ? stateValues . coordinationLog : undefined ;
96+ const nodeCount = workflow . nodes ?. length ;
97+ const metrics = extractSubgraphMetrics ( coordinationLog , nodeCount ) ;
98+
99+ if (
100+ metrics . discoveryDurationMs !== undefined ||
101+ metrics . builderDurationMs !== undefined ||
102+ metrics . responderDurationMs !== undefined ||
103+ metrics . nodeCount !== undefined
104+ ) {
105+ collector ( metrics ) ;
106+ }
107+ }
108+
85109/**
86110 * Create a workflow generator function for the multi-agent system.
87111 * LangSmith tracing is handled via traceable() in the runner.
@@ -93,6 +117,7 @@ function createWorkflowGenerator(
93117 llms : ResolvedStageLLMs ,
94118 featureFlags ?: BuilderFeatureFlags ,
95119) : ( prompt : string , collectors ?: GenerationCollectors ) => Promise < SimpleWorkflow > {
120+
96121 return async ( prompt : string , collectors ?: GenerationCollectors ) : Promise < SimpleWorkflow > => {
97122 const runId = generateRunId ( ) ;
98123
@@ -138,26 +163,48 @@ function createWorkflowGenerator(
138163
139164 // Extract and report subgraph metrics from coordination log
140165 if ( collectors ?. subgraphMetrics ) {
141- const coordinationLog = hasCoordinationLog ( state . values )
142- ? state . values . coordinationLog
143- : undefined ;
144- const nodeCount = workflow . nodes ?. length ;
145- const metrics = extractSubgraphMetrics ( coordinationLog , nodeCount ) ;
146-
147- if (
148- metrics . discoveryDurationMs !== undefined ||
149- metrics . builderDurationMs !== undefined ||
150- metrics . responderDurationMs !== undefined ||
151- metrics . nodeCount !== undefined
152- ) {
153- collectors . subgraphMetrics ( metrics ) ;
154- }
166+ reportSubgraphMetrics ( collectors . subgraphMetrics , state . values , workflow ) ;
155167 }
156168
169+ // Report introspection events
170+ collectors ?. introspectionEvents ?.( state . values . introspectionEvents ?? [ ] ) ;
171+
157172 return workflow ;
158173 } ;
159174}
160175
176+ /**
177+ * Create evaluators based on suite type.
178+ */
179+ function createEvaluators ( params : {
180+ suite : string ;
181+ judgeLlm : ResolvedStageLLMs [ 'judge' ] ;
182+ parsedNodeTypes : Parameters < typeof createProgrammaticEvaluator > [ 0 ] ;
183+ numJudges : number ;
184+ } ) : Array < Evaluator < EvaluationContext > > {
185+ const { suite, judgeLlm, parsedNodeTypes, numJudges } = params ;
186+ const evaluators : Array < Evaluator < EvaluationContext > > = [ ] ;
187+
188+ switch ( suite ) {
189+ case 'llm-judge' :
190+ evaluators . push ( createLLMJudgeEvaluator ( judgeLlm , parsedNodeTypes ) ) ;
191+ evaluators . push ( createProgrammaticEvaluator ( parsedNodeTypes ) ) ;
192+ break ;
193+ case 'pairwise' :
194+ evaluators . push ( createPairwiseEvaluator ( judgeLlm , { numJudges } ) ) ;
195+ evaluators . push ( createProgrammaticEvaluator ( parsedNodeTypes ) ) ;
196+ break ;
197+ case 'programmatic' :
198+ evaluators . push ( createProgrammaticEvaluator ( parsedNodeTypes ) ) ;
199+ break ;
200+ case 'similarity' :
201+ evaluators . push ( createSimilarityEvaluator ( ) ) ;
202+ break ;
203+ }
204+
205+ return evaluators ;
206+ }
207+
161208/**
162209 * Create a CodeWorkflowBuilder generator function.
163210 * Uses the CodeWorkflowBuilder which coordinates planning and coding agents to generate
@@ -314,7 +361,6 @@ export async function runV2Evaluation(): Promise<void> {
314361
315362 // Setup environment with per-stage model configuration
316363 const logger = createLogger ( args . verbose ) ;
317- const lifecycle = createConsoleLifecycle ( { verbose : args . verbose , logger } ) ;
318364 const stageModels = argsToStageModels ( args ) ;
319365 const env = await setupTestEnvironment ( stageModels , logger ) ;
320366
@@ -324,7 +370,6 @@ export async function runV2Evaluation(): Promise<void> {
324370 }
325371
326372 // Create workflow generator based on agent type
327- // CODE_BUILDER uses CodeWorkflowBuilder
328373 const generateWorkflow =
329374 args . agent === AGENT_TYPES . CODE_BUILDER
330375 ? createCodeWorkflowBuilderGenerator (
@@ -335,43 +380,39 @@ export async function runV2Evaluation(): Promise<void> {
335380 )
336381 : createWorkflowGenerator ( env . parsedNodeTypes , env . llms , args . featureFlags ) ;
337382
338- // Create evaluators based on suite (using judge LLM for evaluation)
339- // The --suite flag is always respected, regardless of agent type
340- const evaluators : Array < Evaluator < EvaluationContext > > = [ ] ;
341-
342- switch ( args . suite ) {
343- case 'llm-judge' :
344- evaluators . push ( createLLMJudgeEvaluator ( env . llms . judge , env . parsedNodeTypes ) ) ;
345- evaluators . push ( createProgrammaticEvaluator ( env . parsedNodeTypes ) ) ;
346- break ;
347- case 'pairwise' :
348- evaluators . push (
349- createPairwiseEvaluator ( env . llms . judge , {
350- numJudges : args . numJudges ,
351- } ) ,
352- ) ;
353- evaluators . push ( createProgrammaticEvaluator ( env . parsedNodeTypes ) ) ;
354- break ;
355- case 'programmatic' :
356- evaluators . push ( createProgrammaticEvaluator ( env . parsedNodeTypes ) ) ;
357- break ;
358- case 'similarity' :
359- evaluators . push ( createSimilarityEvaluator ( ) ) ;
360- break ;
361- }
383+ // Create evaluators based on suite type
384+ const evaluators = createEvaluators ( {
385+ suite : args . suite ,
386+ judgeLlm : env . llms . judge ,
387+ parsedNodeTypes : env . parsedNodeTypes ,
388+ numJudges : args . numJudges ,
389+ } ) ;
362390
363391 const llmCallLimiter = pLimit ( args . concurrency ) ;
364392
393+ // Merge console lifecycle with optional introspection analysis lifecycle
394+ const mergedLifecycle = mergeLifecycles (
395+ createConsoleLifecycle ( { verbose : args . verbose , logger } ) ,
396+ args . suite === 'introspection'
397+ ? createIntrospectionAnalysisLifecycle ( {
398+ judgeLlm : env . llms . judge ,
399+ outputDir : args . outputDir ,
400+ logger,
401+ } )
402+ : undefined ,
403+ ) ;
404+
365405 const baseConfig = {
366406 generateWorkflow,
367407 evaluators,
368- lifecycle,
408+ lifecycle : mergedLifecycle ,
369409 logger,
370410 outputDir : args . outputDir ,
371411 outputCsv : args . outputCsv ,
372412 suite : args . suite ,
373413 timeoutMs : args . timeoutMs ,
374414 context : { llmCallLimiter } ,
415+ passThreshold : args . suite === 'introspection' ? 0 : undefined ,
375416 } ;
376417
377418 const config : RunConfig =
@@ -400,6 +441,7 @@ export async function runV2Evaluation(): Promise<void> {
400441 ...baseConfig ,
401442 mode : 'local' ,
402443 dataset : loadTestCases ( args ) ,
444+ concurrency : args . concurrency ,
403445 } ;
404446
405447 // Run evaluation
0 commit comments