@@ -173,11 +173,13 @@ const uploadViewStyle = css`
173173` ;
174174
175175const JUDGE_MODELS = [
176- 'gemini-2.5-flash' ,
177- 'gemini-2.0-flash' ,
178- 'claude-3.5-sonnet' ,
179- 'gpt-4o' ,
180- ] ;
176+ { value : 'gemini-2.5-flash' , provider : 'google' } ,
177+ { value : 'gemini-2.0-flash' , provider : 'google' } ,
178+ { value : 'anthropic/claude-3.5-sonnet' , provider : 'anthropic' } ,
179+ { value : 'openai/gpt-4o' , provider : 'openai' } ,
180+ ] as const ;
181+
182+ type JudgeModelProvider = typeof JUDGE_MODELS [ number ] [ 'provider' ] ;
181183
182184export const UploadView : React . FC = ( ) => {
183185 const { state, actions } = useTraceContext ( ) ;
@@ -430,13 +432,40 @@ export const UploadView: React.FC = () => {
430432 < Select
431433 value = { state . judgeModel }
432434 onChange = { actions . setJudgeModel }
433- options = { JUDGE_MODELS . map ( ( model ) => ( { label : model , value : model } ) ) }
435+ options = { JUDGE_MODELS . map ( ( { value } ) => ( { label : value , value } ) ) }
434436 style = { { width : '100%' } }
435437 size = "small"
436438 />
437- < span className = "setting-hint" >
438- LLM for judge-based metrics
439- </ span >
439+ { state . apiKeyStatus && (
440+ < div style = { { display : 'flex' , gap : 10 , marginTop : 4 , flexWrap : 'wrap' } } >
441+ { ( [
442+ { label : 'GOOGLE_API_KEY' , provider : 'google' as const } ,
443+ { label : 'ANTHROPIC_API_KEY' , provider : 'anthropic' as const } ,
444+ { label : 'OPENAI_API_KEY' , provider : 'openai' as const } ,
445+ ] as const ) . map ( ( { label, provider } ) => {
446+ const ok = state . apiKeyStatus ! [ provider ] ;
447+ return (
448+ < span key = { provider } style = { { display : 'flex' , alignItems : 'center' , gap : 4 , fontSize : 10 , color : ok ? 'var(--status-success)' : 'var(--status-failure)' } } >
449+ < span style = { { width : 6 , height : 6 , borderRadius : '50%' , backgroundColor : ok ? 'var(--status-success)' : 'var(--status-failure)' , flexShrink : 0 } } />
450+ { label }
451+ </ span >
452+ ) ;
453+ } ) }
454+ </ div >
455+ ) }
456+ { ( ( ) => {
457+ const selected = JUDGE_MODELS . find ( ( m ) => m . value === state . judgeModel ) ;
458+ const provider = selected ?. provider as JudgeModelProvider | undefined ;
459+ if ( ! provider || ! state . apiKeyStatus || state . apiKeyStatus [ provider ] ) return null ;
460+ const keyName = provider === 'google' ? 'GOOGLE_API_KEY / GEMINI_API_KEY'
461+ : provider === 'anthropic' ? 'ANTHROPIC_API_KEY'
462+ : 'OPENAI_API_KEY' ;
463+ return (
464+ < span style = { { fontSize : '11px' , color : 'var(--status-failure)' , marginTop : 2 } } >
465+ { keyName } is not set — this model will fail
466+ </ span >
467+ ) ;
468+ } ) ( ) }
440469 </ div >
441470
442471 < div className = "setting-item" style = { { marginTop : 10 } } >
0 commit comments