refac: models workspace optimization
This commit is contained in:
@@ -6,12 +6,12 @@ from open_webui.internal.db import Base, JSONField, get_db
|
||||
from open_webui.env import SRC_LOG_LEVELS
|
||||
|
||||
from open_webui.models.groups import Groups
|
||||
from open_webui.models.users import Users, UserResponse
|
||||
from open_webui.models.users import User, UserModel, Users, UserResponse
|
||||
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
from sqlalchemy import or_, and_, func
|
||||
from sqlalchemy import String, cast, or_, and_, func
|
||||
from sqlalchemy.dialects import postgresql, sqlite
|
||||
from sqlalchemy import BigInteger, Column, Text, JSON, Boolean
|
||||
|
||||
@@ -133,6 +133,11 @@ class ModelResponse(ModelModel):
|
||||
pass
|
||||
|
||||
|
||||
class ModelListResponse(BaseModel):
|
||||
items: list[ModelUserResponse]
|
||||
total: int
|
||||
|
||||
|
||||
class ModelForm(BaseModel):
|
||||
id: str
|
||||
base_model_id: Optional[str] = None
|
||||
@@ -215,6 +220,84 @@ class ModelsTable:
|
||||
or has_access(user_id, permission, model.access_control, user_group_ids)
|
||||
]
|
||||
|
||||
def search_models(
|
||||
self, user_id: str, filter: dict = {}, skip: int = 0, limit: int = 30
|
||||
) -> ModelListResponse:
|
||||
with get_db() as db:
|
||||
# Join GroupMember so we can order by group_id when requested
|
||||
query = db.query(Model, User).outerjoin(User, User.id == Model.user_id)
|
||||
query = query.filter(Model.base_model_id != None)
|
||||
|
||||
if filter:
|
||||
query_key = filter.get("query")
|
||||
if query_key:
|
||||
query = query.filter(
|
||||
or_(
|
||||
Model.name.ilike(f"%{query_key}%"),
|
||||
Model.base_model_id.ilike(f"%{query_key}%"),
|
||||
)
|
||||
)
|
||||
|
||||
if filter.get("user_id"):
|
||||
query = query.filter(Model.user_id == filter.get("user_id"))
|
||||
|
||||
view_option = filter.get("view_option")
|
||||
|
||||
if view_option == "created":
|
||||
query = query.filter(Model.user_id == user_id)
|
||||
elif view_option == "shared":
|
||||
query = query.filter(Model.user_id != user_id)
|
||||
|
||||
tag = filter.get("tag")
|
||||
if tag:
|
||||
# TODO: This is a simple implementation and should be improved for performance
|
||||
like_pattern = f'%"{tag.lower()}"%' # `"tag"` inside JSON array
|
||||
meta_text = func.lower(cast(Model.meta, String))
|
||||
|
||||
query = query.filter(meta_text.like(like_pattern))
|
||||
|
||||
order_by = filter.get("order_by")
|
||||
direction = filter.get("direction")
|
||||
|
||||
if order_by == "name":
|
||||
if direction == "asc":
|
||||
query = query.order_by(Model.name.asc())
|
||||
else:
|
||||
query = query.order_by(Model.name.desc())
|
||||
elif order_by == "created_at":
|
||||
if direction == "asc":
|
||||
query = query.order_by(Model.created_at.asc())
|
||||
else:
|
||||
query = query.order_by(Model.created_at.desc())
|
||||
elif order_by == "updated_at":
|
||||
if direction == "asc":
|
||||
query = query.order_by(Model.updated_at.asc())
|
||||
else:
|
||||
query = query.order_by(Model.updated_at.desc())
|
||||
|
||||
else:
|
||||
query = query.order_by(Model.created_at.desc())
|
||||
|
||||
# Count BEFORE pagination
|
||||
total = query.count()
|
||||
|
||||
if skip:
|
||||
query = query.offset(skip)
|
||||
if limit:
|
||||
query = query.limit(limit)
|
||||
|
||||
items = query.all()
|
||||
|
||||
models = []
|
||||
for model, user in items:
|
||||
model_model = ModelModel.model_validate(model)
|
||||
user_model = UserResponse(**UserModel.model_validate(user).model_dump())
|
||||
models.append(
|
||||
ModelUserResponse(**model_model.model_dump(), user=user_model)
|
||||
)
|
||||
|
||||
return ModelListResponse(items=models, total=total)
|
||||
|
||||
def get_model_by_id(self, id: str) -> Optional[ModelModel]:
|
||||
try:
|
||||
with get_db() as db:
|
||||
|
||||
@@ -9,7 +9,7 @@ from open_webui.models.models import (
|
||||
ModelForm,
|
||||
ModelModel,
|
||||
ModelResponse,
|
||||
ModelUserResponse,
|
||||
ModelListResponse,
|
||||
Models,
|
||||
)
|
||||
|
||||
@@ -44,14 +44,43 @@ def is_valid_model_id(model_id: str) -> bool:
|
||||
###########################
|
||||
|
||||
|
||||
PAGE_ITEM_COUNT = 30
|
||||
|
||||
|
||||
@router.get(
|
||||
"/list", response_model=list[ModelUserResponse]
|
||||
"/list", response_model=ModelListResponse
|
||||
) # do NOT use "/" as path, conflicts with main.py
|
||||
async def get_models(id: Optional[str] = None, user=Depends(get_verified_user)):
|
||||
if user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL:
|
||||
return Models.get_models()
|
||||
else:
|
||||
return Models.get_models_by_user_id(user.id)
|
||||
async def get_models(
|
||||
query: Optional[str] = None,
|
||||
view_option: Optional[str] = None,
|
||||
tag: Optional[str] = None,
|
||||
order_by: Optional[str] = None,
|
||||
direction: Optional[str] = None,
|
||||
page: Optional[int] = 1,
|
||||
user=Depends(get_verified_user),
|
||||
):
|
||||
|
||||
limit = PAGE_ITEM_COUNT
|
||||
|
||||
page = max(1, page)
|
||||
skip = (page - 1) * limit
|
||||
|
||||
filter = {}
|
||||
if query:
|
||||
filter["query"] = query
|
||||
if view_option:
|
||||
filter["view_option"] = view_option
|
||||
if tag:
|
||||
filter["tag"] = tag
|
||||
if order_by:
|
||||
filter["order_by"] = order_by
|
||||
if direction:
|
||||
filter["direction"] = direction
|
||||
|
||||
if not user.role == "admin" or not BYPASS_ADMIN_ACCESS_CONTROL:
|
||||
filter["user_id"] = user.id
|
||||
|
||||
return Models.search_models(user.id, filter=filter, skip=skip, limit=limit)
|
||||
|
||||
|
||||
###########################
|
||||
@@ -64,6 +93,29 @@ async def get_base_models(user=Depends(get_admin_user)):
|
||||
return Models.get_base_models()
|
||||
|
||||
|
||||
###########################
|
||||
# GetModelTags
|
||||
###########################
|
||||
|
||||
|
||||
@router.get("/tags", response_model=list[str])
|
||||
async def get_model_tags(user=Depends(get_verified_user)):
|
||||
if user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL:
|
||||
models = Models.get_models()
|
||||
else:
|
||||
models = Models.get_models_by_user_id(user.id)
|
||||
|
||||
tags_set = set()
|
||||
for model in models:
|
||||
if model.meta and model.meta.tags:
|
||||
for tag in model.meta.tags:
|
||||
tags_set.add((tag.get("name")))
|
||||
|
||||
tags = [tag for tag in tags_set]
|
||||
tags.sort()
|
||||
return tags
|
||||
|
||||
|
||||
############################
|
||||
# CreateNewModel
|
||||
############################
|
||||
|
||||
Reference in New Issue
Block a user