@@ -269,44 +269,44 @@ export function parseBestGenerationIndex(
269269}
270270
271271/**
272- * Evaluates multiple generations and selects the best one
272+ * Handles the case when there's only one successful generation
273273 */
274- export async function evaluateGenerations (
274+ function handleSingleGeneration (
275+ successfulResults : GenerationResult [ ] ,
275276 generationResults : GenerationResult [ ] ,
277+ ) : { bestIndex : number ; evaluationReason : string } {
278+ const originalIndex = generationResults . indexOf ( successfulResults [ 0 ] ) ;
279+ return {
280+ bestIndex : originalIndex ,
281+ evaluationReason : "Only one successful generation available" ,
282+ } ;
283+ }
284+
285+ /**
286+ * Attempts to evaluate generations with a specific model
287+ */
288+ async function attemptEvaluationWithModel (
289+ model : string ,
290+ modelIndex : number ,
291+ models : string [ ] ,
276292 providerName : string ,
277- visionModel : string | string [ ] ,
293+ imageContents : (
294+ | { type : "text" ; text : string }
295+ | { type : "image" ; image : Buffer }
296+ ) [ ] ,
278297 maxRetries : number ,
298+ successfulResults : GenerationResult [ ] ,
299+ generationResults : GenerationResult [ ] ,
279300 verbose : boolean ,
280- ) : Promise < { bestIndex : number ; evaluationReason : string } > {
281- // Filter out failed generations
282- const successfulResults = generationResults . filter (
283- ( result ) => result . success ,
284- ) ;
285-
286- if ( successfulResults . length === 0 ) {
287- throw new Error ( "No successful generations to evaluate" ) ;
288- }
289-
290- if ( successfulResults . length === 1 ) {
291- // Find the index of this successful result in the original array
292- const originalIndex = generationResults . indexOf ( successfulResults [ 0 ] ) ;
293- return {
294- bestIndex : originalIndex ,
295- evaluationReason : "Only one successful generation available" ,
296- } ;
297- }
298-
299- const aiProvider = handleProviderSetup ( providerName , visionModel ) ;
300- // Only pass successful generations to prepareImageContents
301- const imageContents = await prepareImageContents ( successfulResults , verbose ) ;
302-
303- if ( verbose ) {
301+ ) : Promise < { bestIndex : number ; evaluationReason : string } | null > {
302+ if ( verbose && models . length > 1 ) {
304303 console . log (
305- `Evaluating ${ String ( successfulResults . length ) } successful generations with AI ...` ,
304+ `Attempting evaluation with model ${ model } ( ${ String ( modelIndex + 1 ) } / ${ String ( models . length ) } ) ...` ,
306305 ) ;
307306 }
308307
309308 try {
309+ const aiProvider = handleProviderSetup ( providerName , model ) ;
310310 const response = await generateText ( {
311311 model : aiProvider ,
312312 messages : [
@@ -343,18 +343,110 @@ export async function evaluateGenerations(
343343 bestIndex : finalIndex ,
344344 evaluationReason : responseText ,
345345 } ;
346- } catch ( error ) {
347- if ( verbose ) {
348- console . warn ( "AI evaluation failed, using first generation:" , error ) ;
349- }
350- // Find the index of the first successful generation in the original array
351- const firstSuccessfulIndex = generationResults . findIndex (
352- ( result ) => result . success ,
346+ } catch {
347+ // Handle error in the calling function
348+ return null ;
349+ }
350+ }
351+
352+ /**
353+ * Handles the fallback case when all models fail
354+ */
355+ function handleAllModelsFailed (
356+ generationResults : GenerationResult [ ] ,
357+ lastError : unknown ,
358+ verbose : boolean ,
359+ ) : { bestIndex : number ; evaluationReason : string } {
360+ if ( verbose ) {
361+ console . warn (
362+ "All AI evaluation models failed, using first generation as fallback:" ,
363+ lastError ,
353364 ) ;
365+ }
354366
355- return {
356- bestIndex : Math . max ( firstSuccessfulIndex , 0 ) ,
357- evaluationReason : `AI evaluation failed: ${ error instanceof Error ? error . message : "Unknown error" } . Using first successful generation as fallback.` ,
358- } ;
367+ // Find the index of the first successful generation in the original array
368+ const firstSuccessfulIndex = generationResults . findIndex (
369+ ( result ) => result . success ,
370+ ) ;
371+
372+ return {
373+ bestIndex : Math . max ( firstSuccessfulIndex , 0 ) ,
374+ evaluationReason : `AI evaluation failed: ${ lastError instanceof Error ? lastError . message : "Unknown error" } . Using first successful generation as fallback.` ,
375+ } ;
376+ }
377+
378+ /**
379+ * Evaluates multiple generations and selects the best one
380+ * If multiple models are specified, it will try each one sequentially until successful
381+ */
382+ export async function evaluateGenerations (
383+ generationResults : GenerationResult [ ] ,
384+ providerName : string ,
385+ visionModel : string | string [ ] ,
386+ maxRetries : number ,
387+ verbose : boolean ,
388+ ) : Promise < { bestIndex : number ; evaluationReason : string } > {
389+ // Filter out failed generations
390+ const successfulResults = generationResults . filter (
391+ ( result ) => result . success ,
392+ ) ;
393+
394+ if ( successfulResults . length === 0 ) {
395+ throw new Error ( "No successful generations to evaluate" ) ;
396+ }
397+
398+ if ( successfulResults . length === 1 ) {
399+ return handleSingleGeneration ( successfulResults , generationResults ) ;
359400 }
401+
402+ // Only pass successful generations to prepareImageContents
403+ const imageContents = await prepareImageContents ( successfulResults , verbose ) ;
404+
405+ if ( verbose ) {
406+ console . log (
407+ `Evaluating ${ String ( successfulResults . length ) } successful generations with AI...` ,
408+ ) ;
409+ }
410+
411+ // Convert visionModel to array for sequential attempts
412+ const models = Array . isArray ( visionModel ) ? visionModel : [ visionModel ] ;
413+ let lastError : unknown = null ;
414+
415+ // Try each model sequentially until one succeeds
416+ for ( let modelIndex = 0 ; modelIndex < models . length ; modelIndex ++ ) {
417+ const currentModel = models [ modelIndex ] ;
418+
419+ const result = await attemptEvaluationWithModel (
420+ currentModel ,
421+ modelIndex ,
422+ models ,
423+ providerName ,
424+ imageContents ,
425+ maxRetries ,
426+ successfulResults ,
427+ generationResults ,
428+ verbose ,
429+ ) ;
430+
431+ if ( result ) {
432+ return result ;
433+ } else {
434+ // Handle error and try next model if available
435+ const error = new Error ( `Evaluation with model ${ currentModel } failed` ) ;
436+ lastError = error ;
437+
438+ if ( verbose ) {
439+ console . warn (
440+ `AI evaluation with model ${ currentModel } failed: ${ error . message } ` ,
441+ ) ;
442+ }
443+
444+ if ( modelIndex < models . length - 1 && verbose ) {
445+ console . log ( `Trying next model: ${ models [ modelIndex + 1 ] } ...` ) ;
446+ }
447+ }
448+ }
449+
450+ // If we get here, all models failed
451+ return handleAllModelsFailed ( generationResults , lastError , verbose ) ;
360452}
0 commit comments