@@ -81,6 +81,14 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
81
81
const [ modelDialogOpen , setModelDialogOpen ] = useState < boolean > ( false ) ;
82
82
const [ showKeys , setShowKeys ] = useState < boolean > ( false ) ;
83
83
const [ tempSelectedModelId , setTempSelectedModeId ] = useState < string | undefined > ( selectedModelId ) ;
84
+ const [ providerModelOptions , setProviderModelOptions ] = useState < { [ key : string ] : string [ ] } > ( {
85
+ 'openai' : [ ] ,
86
+ 'azure' : [ ] ,
87
+ 'anthropic' : [ ] ,
88
+ 'gemini' : [ ] ,
89
+ 'ollama' : [ ]
90
+ } ) ;
91
+ const [ isLoadingModelOptions , setIsLoadingModelOptions ] = useState < boolean > ( false ) ;
84
92
const [ appConfig , setAppConfig ] = useState < AppConfig > ( { SHOW_KEYS_ENABLED : true } ) ;
85
93
86
94
// Fetch app configuration
@@ -108,23 +116,60 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
108
116
const [ newApiBase , setNewApiBase ] = useState < string | undefined > ( undefined ) ;
109
117
const [ newApiVersion , setNewApiVersion ] = useState < string | undefined > ( undefined ) ;
110
118
119
+ // Fetch available models from the API
120
+ useEffect ( ( ) => {
121
+ const fetchModelOptions = async ( ) => {
122
+ setIsLoadingModelOptions ( true ) ;
123
+ try {
124
+ const response = await fetch ( getUrls ( ) . CHECK_AVAILABLE_MODELS ) ;
125
+ const data = await response . json ( ) ;
126
+
127
+ // Group models by provider
128
+ const modelsByProvider : { [ key : string ] : string [ ] } = {
129
+ 'openai' : [ ] ,
130
+ 'azure' : [ ] ,
131
+ 'anthropic' : [ ] ,
132
+ 'gemini' : [ ] ,
133
+ 'ollama' : [ ]
134
+ } ;
135
+
136
+ data . forEach ( ( modelConfig : any ) => {
137
+ const provider = modelConfig . endpoint ;
138
+ const model = modelConfig . model ;
139
+
140
+ if ( provider && model && ! modelsByProvider [ provider ] . includes ( model ) ) {
141
+ modelsByProvider [ provider ] . push ( model ) ;
142
+ }
143
+ } ) ;
144
+
145
+ setProviderModelOptions ( modelsByProvider ) ;
146
+ } catch ( error ) {
147
+ console . error ( "Failed to fetch model options:" , error ) ;
148
+ } finally {
149
+ setIsLoadingModelOptions ( false ) ;
150
+ }
151
+ } ;
152
+
153
+ fetchModelOptions ( ) ;
154
+ } , [ ] ) ;
155
+
111
156
useEffect ( ( ) => {
112
157
if ( newEndpoint == 'ollama' ) {
113
158
if ( ! newApiBase ) {
114
159
setNewApiBase ( 'http://localhost:11434' ) ;
115
160
}
116
161
}
117
162
if ( newEndpoint == "openai" ) {
118
- if ( ! newModel ) {
119
- setNewModel ( 'gpt-4o' ) ;
163
+ if ( ! newModel && providerModelOptions . openai . length > 0 ) {
164
+ setNewModel ( providerModelOptions . openai [ 0 ] ) ;
120
165
}
121
166
}
122
167
if ( newEndpoint == "anthropic" ) {
123
- if ( ! newModel ) {
124
- setNewModel ( 'claude-3-5-sonnet-20241022' ) ;
168
+ if ( ! newModel && providerModelOptions . anthropic . length > 0 ) {
169
+ setNewModel ( providerModelOptions . anthropic [ 0 ] ) ;
125
170
}
126
171
}
127
- } , [ newEndpoint ] ) ;
172
+ } , [ newEndpoint , providerModelOptions ] ) ;
128
173
129
174
let modelExists = models . some ( m =>
130
175
m . endpoint == newEndpoint && m . model == newModel && m . api_base == newApiBase
@@ -168,8 +213,8 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
168
213
value = { newEndpoint }
169
214
onChange = { ( event : any , newValue : string | null ) => {
170
215
setNewEndpoint ( newValue || "" ) ;
171
- if ( newModel == "" && newValue == "openai" ) {
172
- setNewModel ( "gpt-4o" ) ;
216
+ if ( newModel == "" && newValue == "openai" && providerModelOptions . openai . length > 0 ) {
217
+ setNewModel ( providerModelOptions . openai [ 0 ] ) ;
173
218
}
174
219
if ( ! newApiVersion && newValue == "azure" ) {
175
220
setNewApiVersion ( "2024-02-15" ) ;
@@ -220,7 +265,8 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
220
265
freeSolo
221
266
onChange = { ( event : any , newValue : string | null ) => { setNewModel ( newValue || "" ) ; } }
222
267
value = { newModel }
223
- options = { [ 'gpt-4o-mini' , 'gpt-4o' , 'claude-3-5-sonnet-20241022' ] }
268
+ options = { newEndpoint && providerModelOptions [ newEndpoint ] ? providerModelOptions [ newEndpoint ] : [ ] }
269
+ loading = { isLoadingModelOptions }
224
270
renderOption = { ( props , option ) => {
225
271
return < Typography { ...props } onClick = { ( ) => { setNewModel ( option ) ; } } sx = { { fontSize : "small" } } > { option } </ Typography >
226
272
} }
@@ -229,7 +275,16 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
229
275
error = { newEndpoint != "" && ! newModel }
230
276
{ ...params }
231
277
placeholder = "model name"
232
- InputProps = { { ...params . InputProps , style : { fontSize : "0.875rem" } } }
278
+ InputProps = { {
279
+ ...params . InputProps ,
280
+ style : { fontSize : "0.875rem" } ,
281
+ endAdornment : (
282
+ < >
283
+ { isLoadingModelOptions ? < CircularProgress color = "inherit" size = { 20 } /> : null }
284
+ { params . InputProps . endAdornment }
285
+ </ >
286
+ ) ,
287
+ } }
233
288
inputProps = { {
234
289
...params . inputProps ,
235
290
'aria-label' : 'Select or enter a model' ,
@@ -244,7 +299,7 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
244
299
PaperComponent = { ( { children } ) => (
245
300
< Paper >
246
301
< Typography sx = { { p : 1 , color : 'gray' , fontStyle : 'italic' , fontSize : 'small' } } >
247
- examples
302
+ { isLoadingModelOptions ? 'Loading models...' : ' examples' }
248
303
</ Typography >
249
304
{ children }
250
305
</ Paper >
0 commit comments