This commit is contained in:
Jan Kessler 2025-06-26 16:41:05 +08:00 committed by GitHub
commit b3523d6455
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 74 additions and 52 deletions

View File

@ -57,8 +57,8 @@ from open_webui.utils.logger import start_logger
from open_webui.socket.main import (
app as socket_app,
periodic_usage_pool_cleanup,
get_models_in_use,
get_active_user_ids,
get_requests_count_per_model,
get_active_users_count,
)
from open_webui.routers import (
audio,
@ -1663,7 +1663,7 @@ async def get_current_usage(user=Depends(get_verified_user)):
This is an experimental endpoint and subject to change.
"""
try:
return {"model_ids": get_models_in_use(), "user_ids": get_active_user_ids()}
return {"requests_per_model": get_requests_count_per_model(), "users_count": get_active_users_count()}
except Exception as e:
log.error(f"Error getting usage statistics: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")

View File

@ -117,22 +117,22 @@ async def periodic_usage_pool_cleanup():
now = int(time.time())
send_usage = False
for model_id, connections in list(USAGE_POOL.items()):
# Creating a list of sids to remove if they have timed out
expired_sids = [
sid
for sid, details in connections.items()
for model_id, messages in list(USAGE_POOL.items()):
# Creating a list of messages to remove if they have timed out
expired_messages = [
message_id
for message_id, details in messages.items()
if now - details["updated_at"] > TIMEOUT_DURATION
]
for sid in expired_sids:
del connections[sid]
for message_id in expired_messages:
del messages[message_id]
if not connections:
if not messages:
log.debug(f"Cleaning up model {model_id} from usage pool")
del USAGE_POOL[model_id]
else:
USAGE_POOL[model_id] = connections
USAGE_POOL[model_id] = messages
send_usage = True
await asyncio.sleep(TIMEOUT_DURATION)
@ -146,10 +146,18 @@ app = socketio.ASGIApp(
)
def get_models_in_use():
# List models that are currently in use
models_in_use = list(USAGE_POOL.keys())
return models_in_use
def get_requests_count_per_model():
"""Get currently used models and their current request count"""
active_models = list(USAGE_POOL.keys())
requests_count_per_model = {}
for model in active_models:
requests_count_per_model[model] = len(USAGE_POOL[model].keys())
return requests_count_per_model
def get_active_users_count():
"""Get the number of active users."""
return len(USER_POOL)
def get_active_user_ids():
@ -192,14 +200,15 @@ def get_active_status_by_user_id(user_id):
@sio.on("usage")
async def usage(sid, data):
if sid in SESSION_POOL:
model_id = data["model"]
model_id = data["model_id"]
message_id = data["message_id"]
# Record the timestamp for the last update
current_time = int(time.time())
# Store the new usage data and task
USAGE_POOL[model_id] = {
**(USAGE_POOL[model_id] if model_id in USAGE_POOL else {}),
sid: {"updated_at": current_time},
message_id: {"updated_at": current_time},
}

View File

@ -1057,13 +1057,18 @@
}
};
const getChatEventEmitter = async (modelId: string, chatId: string = '') => {
const socketEmitUsage = (modelId: string, messageId: string = '') => {
$socket?.emit('usage', {
action: 'chat',
model_id: modelId,
message_id: messageId
});
};
const getChatEventEmitter = async (modelId: string, messageId: string = '') => {
socketEmitUsage(modelId, messageId);
return setInterval(() => {
$socket?.emit('usage', {
action: 'chat',
model: modelId,
chat_id: chatId
});
socketEmitUsage(modelId, messageId);
}, 1000);
};
@ -1533,7 +1538,7 @@
let responseMessageId =
responseMessageIds[`${modelId}-${modelIdx ? modelIdx : _modelIdx}`];
const chatEventEmitter = await getChatEventEmitter(model.id, _chatId);
const chatEventEmitter = await getChatEventEmitter(model.id, responseMessageId);
scrollToBottom();
await sendPromptSocket(_history, model, responseMessageId, _chatId);

View File

@ -206,40 +206,48 @@
</button>
{#if usage}
{#if usage?.user_ids?.length > 0}
<hr class=" border-gray-100 dark:border-gray-800 my-1 p-0" />
<hr class=" border-gray-100 dark:border-gray-800 my-1 p-0" />
<Tooltip
content={usage?.model_ids && usage?.model_ids.length > 0
? `${$i18n.t('Running')}: ${usage.model_ids.join(', ')} ✨`
: ''}
<Tooltip
content={usage?.requests_per_model && Object.keys(usage?.requests_per_model).length > 0
? `${$i18n.t('Running')}: ${Object.entries(usage?.requests_per_model).reduce((a, b) => a + b[0] + ' (' + b[1] + '), ', '')} ✨`
: ''}
>
<div
class="flex rounded-md py-1 px-3 text-xs gap-2.5 items-center"
on:mouseenter={() => {
getUsageInfo();
}}
>
<div
class="flex rounded-md py-1 px-3 text-xs gap-2.5 items-center"
on:mouseenter={() => {
getUsageInfo();
}}
>
<div class=" flex items-center">
<span class="relative flex size-2">
<span
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"
/>
<span class="relative inline-flex rounded-full size-2 bg-green-500" />
</span>
</div>
<div class=" flex items-center">
<span class="relative flex size-2">
<span
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"
/>
<span class="relative inline-flex rounded-full size-2 bg-green-500" />
</span>
</div>
<div class=" ">
<div class=" ">
{#if usage?.users_count}
<span class="">
{$i18n.t('Active Users')}:
</span>
<span class=" font-semibold">
{usage?.user_ids?.length}
{usage?.users_count}<br>
</span>
</div>
{/if}
{#if usage?.requests_per_model}
<span class="">
{$i18n.t('Running Requests')}:
</span>
<span class=" font-semibold">
{Object.values(usage?.requests_per_model).reduce((a, b) => a + b, 0)}
</span>
{/if}
</div>
</Tooltip>
{/if}
</div>
</Tooltip>
{/if}
<!-- <DropdownMenu.Item class="flex items-center py-1.5 px-3 text-sm ">

View File

@ -1061,6 +1061,7 @@
"RTL": "RTL",
"Run": "Ausführen",
"Running": "Läuft",
"Running Requests": "Laufende Anfragen",
"Save": "Speichern",
"Save & Create": "Erstellen",
"Save & Update": "Aktualisieren",

View File

@ -1061,6 +1061,7 @@
"RTL": "",
"Run": "",
"Running": "",
"Running Requests": "",
"Save": "",
"Save & Create": "",
"Save & Update": "",

View File

@ -22,8 +22,6 @@ export const MODEL_DOWNLOAD_POOL = writable({});
export const mobile = writable(false);
export const socket: Writable<null | Socket> = writable(null);
export const activeUserIds: Writable<null | string[]> = writable(null);
export const USAGE_POOL: Writable<null | string[]> = writable(null);
export const theme = writable('system');