From 2c6f9d8602f582752c17af996755add978447089 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 6 Aug 2025 18:32:57 +0800 Subject: [PATCH] feat: add creator search option and update related functionality across models and UI --- py/routes/base_model_routes.py | 1 + py/services/base_model_service.py | 16 ++++++++++++++++ py/utils/constants.py | 3 ++- py/utils/utils.py | 2 +- static/js/api/baseModelApi.js | 3 +++ static/js/managers/SearchManager.js | 2 ++ static/js/state/index.js | 3 +++ templates/components/header.html | 3 +++ 8 files changed, 31 insertions(+), 2 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index f39a47d9..400b10b4 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -177,6 +177,7 @@ class BaseModelRoutes(ABC): 'filename': request.query.get('search_filename', 'true').lower() == 'true', 'modelname': request.query.get('search_modelname', 'true').lower() == 'true', 'tags': request.query.get('search_tags', 'false').lower() == 'true', + 'creator': request.query.get('search_creator', 'false').lower() == 'true', 'recursive': request.query.get('recursive', 'false').lower() == 'true', } diff --git a/py/services/base_model_service.py b/py/services/base_model_service.py index 72242daa..cabcc98b 100644 --- a/py/services/base_model_service.py +++ b/py/services/base_model_service.py @@ -199,6 +199,22 @@ class BaseModelService(ABC): for tag in item['tags']): search_results.append(item) continue + + # Search by creator + civitai = item.get('civitai') + creator_username = '' + if civitai and isinstance(civitai, dict): + creator = civitai.get('creator') + if creator and isinstance(creator, dict): + creator_username = creator.get('username', '') + if search_options.get('creator', False) and creator_username: + if fuzzy_search: + if fuzzy_match(creator_username, search): + search_results.append(item) + continue + elif search.lower() in creator_username.lower(): + search_results.append(item) + continue return search_results diff --git a/py/utils/constants.py b/py/utils/constants.py index c484a2c6..1e7d3db7 100644 --- a/py/utils/constants.py +++ b/py/utils/constants.py @@ -50,7 +50,8 @@ VALID_LORA_TYPES = ['lora', 'locon', 'dora'] # Civitai model tags in priority order for subfolder organization CIVITAI_MODEL_TAGS = [ - 'character', 'style', 'concept', 'clothing', 'base model', + 'character', 'style', 'concept', 'clothing', + # 'base model', # exclude 'base model' 'poses', 'background', 'tool', 'vehicle', 'buildings', 'objects', 'assets', 'animal', 'action' ] \ No newline at end of file diff --git a/py/utils/utils.py b/py/utils/utils.py index 5acec3c9..0a9bd7a4 100644 --- a/py/utils/utils.py +++ b/py/utils/utils.py @@ -47,7 +47,7 @@ def get_lora_info(lora_name): # No event loop is running, we can use asyncio.run() return asyncio.run(_get_lora_info_async()) -def fuzzy_match(text: str, pattern: str, threshold: float = 0.7) -> bool: +def fuzzy_match(text: str, pattern: str, threshold: float = 0.85) -> bool: """ Check if text matches pattern using fuzzy matching. Returns True if similarity ratio is above threshold. diff --git a/static/js/api/baseModelApi.js b/static/js/api/baseModelApi.js index a73b62db..e78ab657 100644 --- a/static/js/api/baseModelApi.js +++ b/static/js/api/baseModelApi.js @@ -628,6 +628,9 @@ export class BaseModelApiClient { if (pageState.searchOptions.tags !== undefined) { params.append('search_tags', pageState.searchOptions.tags.toString()); } + if (pageState.searchOptions.creator !== undefined) { + params.append('search_creator', pageState.searchOptions.creator.toString()); + } params.append('recursive', (pageState.searchOptions?.recursive ?? false).toString()); } } diff --git a/static/js/managers/SearchManager.js b/static/js/managers/SearchManager.js index 6686bb00..d6c43b05 100644 --- a/static/js/managers/SearchManager.js +++ b/static/js/managers/SearchManager.js @@ -318,6 +318,7 @@ export class SearchManager { filename: options.filename || false, modelname: options.modelname || false, tags: options.tags || false, + creator: options.creator || false, recursive: recursive }; } else if (this.currentPage === 'checkpoints') { @@ -325,6 +326,7 @@ export class SearchManager { filename: options.filename || false, modelname: options.modelname || false, tags: options.tags || false, + creator: options.creator || false, recursive: recursive }; } diff --git a/static/js/state/index.js b/static/js/state/index.js index 65aa9bbc..26427c2b 100644 --- a/static/js/state/index.js +++ b/static/js/state/index.js @@ -37,6 +37,7 @@ export const state = { filename: true, modelname: true, tags: false, + creator: false, recursive: false }, filters: { @@ -83,6 +84,7 @@ export const state = { searchOptions: { filename: true, modelname: true, + creator: false, recursive: false }, filters: { @@ -110,6 +112,7 @@ export const state = { filename: true, modelname: true, tags: false, + creator: false, recursive: false }, filters: { diff --git a/templates/components/header.html b/templates/components/header.html index d506f6e6..d2358f5d 100644 --- a/templates/components/header.html +++ b/templates/components/header.html @@ -86,15 +86,18 @@