diff --git a/backend/open_webui/apps/webui/main.py b/backend/open_webui/apps/webui/main.py index bedd49ae3..054c6280e 100644 --- a/backend/open_webui/apps/webui/main.py +++ b/backend/open_webui/apps/webui/main.py @@ -31,6 +31,7 @@ from open_webui.config import ( DEFAULT_MODELS, DEFAULT_PROMPT_SUGGESTIONS, DEFAULT_USER_ROLE, + MODEL_ORDER_LIST, ENABLE_COMMUNITY_SHARING, ENABLE_LOGIN_FORM, ENABLE_MESSAGE_RATING, @@ -120,6 +121,7 @@ app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE app.state.config.USER_PERMISSIONS = USER_PERMISSIONS app.state.config.WEBHOOK_URL = WEBHOOK_URL app.state.config.BANNERS = WEBUI_BANNERS +app.state.config.MODEL_ORDER_LIST = MODEL_ORDER_LIST app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING app.state.config.ENABLE_MESSAGE_RATING = ENABLE_MESSAGE_RATING diff --git a/backend/open_webui/apps/webui/routers/configs.py b/backend/open_webui/apps/webui/routers/configs.py index 1c30b0b3b..b19fc1745 100644 --- a/backend/open_webui/apps/webui/routers/configs.py +++ b/backend/open_webui/apps/webui/routers/configs.py @@ -34,8 +34,32 @@ async def export_config(user=Depends(get_admin_user)): return get_config() -class SetDefaultModelsForm(BaseModel): - models: str +############################ +# SetDefaultModels +############################ +class ModelsConfigForm(BaseModel): + DEFAULT_MODELS: str + MODEL_ORDER_LIST: list[str] + + +@router.get("/models", response_model=ModelsConfigForm) +async def get_models_config(request: Request, user=Depends(get_admin_user)): + return { + "DEFAULT_MODELS": request.app.state.config.DEFAULT_MODELS, + "MODEL_ORDER_LIST": request.app.state.config.MODEL_ORDER_LIST, + } + + +@router.post("/models", response_model=ModelsConfigForm) +async def set_models_config( + request: Request, form_data: ModelsConfigForm, user=Depends(get_admin_user) +): + request.app.state.config.DEFAULT_MODELS = form_data.DEFAULT_MODELS + request.app.state.config.MODEL_ORDER_LIST = form_data.MODEL_ORDER_LIST + return { + "DEFAULT_MODELS": request.app.state.config.DEFAULT_MODELS, + "MODEL_ORDER_LIST": request.app.state.config.MODEL_ORDER_LIST, + } class PromptSuggestion(BaseModel): @@ -47,21 +71,8 @@ class SetDefaultSuggestionsForm(BaseModel): suggestions: list[PromptSuggestion] -############################ -# SetDefaultModels -############################ - - -@router.post("/default/models", response_model=str) -async def set_global_default_models( - request: Request, form_data: SetDefaultModelsForm, user=Depends(get_admin_user) -): - request.app.state.config.DEFAULT_MODELS = form_data.models - return request.app.state.config.DEFAULT_MODELS - - -@router.post("/default/suggestions", response_model=list[PromptSuggestion]) -async def set_global_default_suggestions( +@router.post("/suggestions", response_model=list[PromptSuggestion]) +async def set_default_suggestions( request: Request, form_data: SetDefaultSuggestionsForm, user=Depends(get_admin_user), diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index db24403e5..3c1ee798d 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -740,6 +740,12 @@ DEFAULT_PROMPT_SUGGESTIONS = PersistentConfig( ], ) +MODEL_ORDER_LIST = PersistentConfig( + "MODEL_ORDER_LIST", + "ui.model_order_list", + [], +) + DEFAULT_USER_ROLE = PersistentConfig( "DEFAULT_USER_ROLE", "ui.default_user_role", diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 4c52ceb0f..0dca21b08 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -1194,6 +1194,14 @@ async def get_models(user=Depends(get_verified_user)): if "pipeline" not in model or model["pipeline"].get("type", None) != "filter" ] + model_order_list = webui_app.state.config.MODEL_ORDER_LIST + if model_order_list: + model_order_dict = {model_id: i for i, model_id in enumerate(model_order_list)} + # Sort models by order list priority, with fallback for those not in the list + models.sort( + key=lambda x: (model_order_dict.get(x["id"], float("inf")), x["name"]) + ) + # Filter out models that the user does not have access to if user.role == "user": filtered_models = [] diff --git a/src/lib/apis/configs/index.ts b/src/lib/apis/configs/index.ts index 0c4de6ad6..b3b002557 100644 --- a/src/lib/apis/configs/index.ts +++ b/src/lib/apis/configs/index.ts @@ -58,17 +58,46 @@ export const exportConfig = async (token: string) => { return res; }; -export const setDefaultModels = async (token: string, models: string) => { + +export const getModelsConfig = async (token: string) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/configs/default/models`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/models`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.log(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + + +export const setModelsConfig = async (token: string, config: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/models`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, body: JSON.stringify({ - models: models + ...config }) }) .then(async (res) => { @@ -88,10 +117,11 @@ export const setDefaultModels = async (token: string, models: string) => { return res; }; + export const setDefaultPromptSuggestions = async (token: string, promptSuggestions: string) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/configs/default/suggestions`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/suggestions`, { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index 9c726e4d0..a33610c31 100644 --- a/src/lib/apis/index.ts +++ b/src/lib/apis/index.ts @@ -25,26 +25,6 @@ export const getModels = async (token: string = '', base: boolean = false) => { } let models = res?.data ?? []; - models = models - .filter((models) => models) - // Sort the models - .sort((a, b) => { - // Compare case-insensitively by name for models without position property - const lowerA = a.name.toLowerCase(); - const lowerB = b.name.toLowerCase(); - - if (lowerA < lowerB) return -1; - if (lowerA > lowerB) return 1; - - // If same case-insensitively, sort by original strings, - // lowercase will come before uppercase due to ASCII values - if (a.name < b.name) return -1; - if (a.name > b.name) return 1; - - return 0; // They are equal - }); - - console.log(models); return models; }; diff --git a/src/lib/components/admin/Settings/Evaluations/ArenaModelModal.svelte b/src/lib/components/admin/Settings/Evaluations/ArenaModelModal.svelte index 5f64137e4..ac45e7f2c 100644 --- a/src/lib/components/admin/Settings/Evaluations/ArenaModelModal.svelte +++ b/src/lib/components/admin/Settings/Evaluations/ArenaModelModal.svelte @@ -375,7 +375,7 @@