diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index acd3d83bf8..de956aed9b 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -2841,6 +2841,7 @@ DEFAULT_CONFIG = { 'openai.api_base_urls': OPENAI_API_BASE_URLS, 'openai.api_configs': OPENAI_API_CONFIGS, 'models.base_models_cache': ENABLE_BASE_MODELS_CACHE, + 'models.base_models_cache_epoch': '', 'tool_server.connections': TOOL_SERVER_CONNECTIONS, 'oauth.client.timeout': OAUTH_CLIENT_TIMEOUT, 'terminal_server.connections': TERMINAL_SERVER_CONNECTIONS, diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index c84a394b87..914c0620b8 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -587,6 +587,7 @@ app.state.SCIM_TOKEN = SCIM_TOKEN ######################################## app.state.BASE_MODELS = [] +app.state.BASE_MODELS_EPOCH = None ######################################## # diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py index 00f41c01b3..4f719c55e5 100644 --- a/backend/open_webui/routers/ollama.py +++ b/backend/open_webui/routers/ollama.py @@ -9,6 +9,7 @@ import time from datetime import datetime from typing import Optional, Union from urllib.parse import urlparse +from uuid import uuid4 import aiofiles import aiohttp @@ -315,6 +316,7 @@ async def update_config( 'ollama.enable': form_data.ENABLE_OLLAMA_API, 'ollama.base_urls': form_data.OLLAMA_BASE_URLS, 'ollama.api_configs': api_configs, + 'models.base_models_cache_epoch': str(uuid4()), } ) diff --git a/backend/open_webui/routers/openai.py b/backend/open_webui/routers/openai.py index 0f21defdd5..7ea9302d47 100644 --- a/backend/open_webui/routers/openai.py +++ b/backend/open_webui/routers/openai.py @@ -6,6 +6,7 @@ import logging import re from typing import Optional from urllib.parse import quote, urlparse +from uuid import uuid4 import aiofiles import aiohttp @@ -344,6 +345,7 @@ async def get_openai_connection(idx: int) -> tuple[str, str, dict]: async def clear_openai_model_cache(request: Request): + await Config.upsert({'models.base_models_cache_epoch': str(uuid4())}) await get_all_models.cache.clear() request.app.state.BASE_MODELS = [] request.app.state.OPENAI_MODELS = {} @@ -571,14 +573,7 @@ async def update_config(request: Request, form_data: OpenAIConfigForm, user=Depe } ) - await get_all_models.cache.clear() - request.app.state.BASE_MODELS = [] - request.app.state.OPENAI_MODELS = {} - models = getattr(request.app.state, 'MODELS', None) - if hasattr(models, 'clear'): - models.clear() - else: - request.app.state.MODELS = {} + await clear_openai_model_cache(request) await publish_event( request, diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index 1c648b7f38..d55c5b52bc 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -67,22 +67,28 @@ async def get_all_base_models(request: Request, user: UserModel = None): async def get_all_models(request, refresh: bool = False, user: UserModel = None): config = await Config.get_many( 'models.base_models_cache', + 'models.base_models_cache_epoch', 'evaluation.arena.enable', 'evaluation.arena.models', 'models.default_metadata', ) - if refresh: + # A changed epoch means another instance edited a provider, so our cached models are stale. + cache_epoch = config.get('models.base_models_cache_epoch') + stale = request.app.state.BASE_MODELS_EPOCH != cache_epoch + + if refresh or stale: await openai.get_all_models.cache.clear() await ollama.get_all_models.cache.clear() if ( request.app.state.MODELS and request.app.state.BASE_MODELS - and (config.get('models.base_models_cache') and not refresh) + and (config.get('models.base_models_cache') and not (refresh or stale)) ): base_models = request.app.state.BASE_MODELS else: base_models = await get_all_base_models(request, user=user) + request.app.state.BASE_MODELS_EPOCH = cache_epoch if base_models: request.app.state.BASE_MODELS = base_models else: