feat: events when a model goes online or offline

Webhooks and event functions had no way to know when a model appeared or disappeared from a connection, for example when a vLLM server stops answering. Open WebUI now sends a model online event when a model shows up in the model list and a model offline event when it drops out of it. The events are checked whenever the model list is fetched from the connections, so they are not a live health check. Nothing is sent for the first model list after startup.
This commit is contained in:
Classic298 2026-11-04 19:21:08 +01:00
parent aac0e97627
commit a18fa85f76
3 changed files with 36 additions and 0 deletions

View file

@ -490,6 +490,12 @@ class EventDefinitions(BaseModel):
MODEL_DISABLED: EventDefinition = EventDefinition(
name='model.disabled', description='A model was disabled.', message='Model disabled'
)
MODEL_ONLINE: EventDefinition = EventDefinition(
name='model.online', description='A model became available.', message='Model online'
)
MODEL_OFFLINE: EventDefinition = EventDefinition(
name='model.offline', description='A model is no longer available.', message='Model offline'
)
MODEL_ACCESS_UPDATED: EventDefinition = EventDefinition(
name='model.access_updated', description='Model access was updated.', message='Model access updated'
)

View file

@ -625,6 +625,7 @@ app.state.SCIM_TOKEN = SCIM_TOKEN
# Models
app.state.BASE_MODELS = []
app.state.ONLINE_MODELS = None
# WebUI

View file

@ -9,6 +9,7 @@ from open_webui.config import (
DEFAULT_ARENA_MODEL,
)
from open_webui.env import BYPASS_MODEL_ACCESS_CONTROL, ENABLE_FUNCTIONS, GLOBAL_LOG_LEVEL, REDIS_KEY_PREFIX
from open_webui.events import EVENTS, publish_event
from open_webui.functions import get_function_models
from open_webui.models.access_grants import AccessGrants
from open_webui.models.config import Config
@ -90,6 +91,33 @@ async def get_all_base_models(request: Request, user: UserModel = None):
return function_models + openai_models + ollama_models
async def publish_model_status_events(request: Request, base_models: list[dict]):
online_models = {model['id']: model.get('name') for model in base_models}
previous_models = request.app.state.ONLINE_MODELS
request.app.state.ONLINE_MODELS = online_models
if previous_models is None:
return
for model_id in sorted(online_models.keys() - previous_models.keys()):
await publish_event(
request,
EVENTS.MODEL_ONLINE,
subject_id=model_id,
subject_type='model',
source='system',
data={'name': online_models[model_id]},
)
for model_id in sorted(previous_models.keys() - online_models.keys()):
await publish_event(
request,
EVENTS.MODEL_OFFLINE,
subject_id=model_id,
subject_type='model',
source='system',
data={'name': previous_models[model_id]},
)
async def get_all_models(request, refresh: bool = False, user: UserModel = None):
config = await Config.get_many(
'models.base_models_cache',
@ -123,6 +151,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None)
if base_models is None:
base_models = await get_all_base_models(request, user=user)
await publish_model_status_events(request, base_models)
if base_models:
request.app.state.BASE_MODELS = base_models
if config.get('models.base_models_cache') and redis is not None: