Co-Authored-By: Classic298 <27028174+Classic298@users.noreply.github.com>
This commit is contained in:
Timothy Jaeryang Baek 2026-08-25 14:35:22 -04:00
parent 92a1502126
commit 8be4c5fa6a
5 changed files with 46 additions and 25 deletions

View file

@ -140,7 +140,7 @@ from open_webui.models.chats import ChatForm, Chats
from open_webui.models.config import Config
from open_webui.models.functions import Functions
from open_webui.models.messages import Messages
from open_webui.models.models import Models
from open_webui.models.models import Models, normalize_model_tags
from open_webui.models.users import Users
from open_webui.routers import (
analytics,
@ -890,19 +890,17 @@ async def get_models(request: Request, refresh: bool = False, user=Depends(get_v
models = await get_filtered_models(models, user)
for model in models:
info = model.get('info') if isinstance(model.get('info'), dict) else {}
meta = info.get('meta') if isinstance(info.get('meta'), dict) else {}
# Remove profile image URL to reduce payload size
if model.get('info', {}).get('meta', {}).get('profile_image_url'):
model['info']['meta'].pop('profile_image_url', None)
meta.pop('profile_image_url', None)
try:
model_tags = [tag.get('name') for tag in model.get('info', {}).get('meta', {}).get('tags', [])]
tags = [tag.get('name') for tag in model.get('tags', [])]
if 'tags' in meta:
meta['tags'] = normalize_model_tags(meta['tags'])
tags = list(set(model_tags + tags))
model['tags'] = [{'name': tag} for tag in tags]
except Exception as e:
log.debug('Error processing model tags: %s', e)
model['tags'] = []
tags = normalize_model_tags(meta.get('tags')) + normalize_model_tags(model.get('tags'))
model['tags'] = list({tag['name']: tag for tag in tags}.values())
model_order_list = await Config.get('ui.model_order_list')
if model_order_list:
@ -1857,6 +1855,7 @@ async def chat_completion(
generate_chat_completions = chat_completion
generate_chat_completion = chat_completion
@app.post('/api/v1/chats/{id}/messages/{message_id}/resolve')
async def resolve_chat_message_tool_call(
request: Request,

View file

@ -3,7 +3,7 @@ from __future__ import annotations
import logging
import time
from copy import deepcopy
from typing import Any, Optional
from typing import Any
from open_webui.internal.db import Base, JSONField, get_async_db_context
from open_webui.models.access_grants import AccessGrantModel, AccessGrants
@ -13,7 +13,6 @@ from open_webui.utils.misc import json_text_variants
from open_webui.utils.validate import validate_profile_image_url
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
from sqlalchemy import BigInteger, Boolean, Column, String, Text, cast, delete, func, or_, select, update
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.ext.asyncio import AsyncSession
log = logging.getLogger(__name__)
@ -23,6 +22,18 @@ log = logging.getLogger(__name__)
_warned_profile_urls: set[str] = set()
def normalize_model_tags(tags: Any) -> list[dict[str, str]]:
if not isinstance(tags, list):
return []
normalized = []
for tag in tags:
name = tag.get('name') if isinstance(tag, dict) else tag
if isinstance(name, str) and name.strip():
normalized.append({'name': name.strip()})
return normalized
def strip_extracted_content_from_model_knowledge(knowledge: Any) -> Any:
"""Drop duplicated extracted text from ModelMeta.knowledge."""
if not isinstance(knowledge, list):
@ -99,15 +110,7 @@ class ModelMeta(BaseModel):
@classmethod
def normalize_tags(cls, data):
if isinstance(data, dict) and 'tags' in data:
raw_tags = data['tags']
if isinstance(raw_tags, list):
normalized = []
for tag in raw_tags:
if isinstance(tag, str):
normalized.append({'name': tag})
elif isinstance(tag, dict) and 'name' in tag:
normalized.append(tag)
data['tags'] = normalized
data['tags'] = normalize_model_tags(data['tags'])
return data

View file

@ -1,5 +1,6 @@
import { WEBUI_BASE_URL } from '$lib/constants';
import { convertOpenApiToToolPayload } from '$lib/utils';
import { normalizeTags } from '$lib/utils/tags';
import { getOpenAIModelsDirect } from './openai';
const TOOL_SERVER_FETCH_TIMEOUT = 10000;
@ -141,8 +142,8 @@ export const getModels = async (
}
}
const tags = apiConfig.tags;
if (tags) {
const tags = normalizeTags(apiConfig.tags);
if (tags.length > 0) {
for (const model of models) {
model.tags = tags;
}

View file

@ -18,6 +18,7 @@
import Spinner from '$lib/components/common/Spinner.svelte';
import XMark from '$lib/components/icons/XMark.svelte';
import Textarea from './common/Textarea.svelte';
import { normalizeTags } from '$lib/utils/tags';
export let onSubmit: Function = () => {};
export let onDelete: Function = () => {};
@ -249,7 +250,7 @@
: '';
enable = connection.config?.enable ?? true;
tags = connection.config?.tags ?? [];
tags = normalizeTags(connection.config?.tags);
prefixId = connection.config?.prefix_id ?? '';
passthroughParams = Array.isArray(connection.config?.passthrough_params)
? connection.config.passthrough_params.join(', ')

17
src/lib/utils/tags.ts Normal file
View file

@ -0,0 +1,17 @@
export type Tag = { name: string };
const getTagName = (tag: unknown) => {
if (typeof tag === 'string') {
return tag;
}
if (typeof tag === 'object' && tag !== null && 'name' in tag) {
return (tag as { name?: unknown }).name;
}
};
export const normalizeTags = (tags: unknown): Tag[] =>
(Array.isArray(tags) ? tags : [])
.map(getTagName)
.filter((name): name is string => typeof name === 'string' && name.trim() !== '')
.map((name) => ({ name: name.trim() }));