From 752d636324f6f5b901649fd6776334a9b84687b2 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Sun, 10 Aug 2025 10:53:28 -0400 Subject: [PATCH] add /sdapi/v1/network Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 1 + javascript/civitai.js | 2 +- javascript/extraNetworks.js | 2 +- modules/api/loras.py | 1 + modules/civitai/search_civitai.py | 2 +- modules/lora/lora_overrides.py | 4 +++ modules/ui_extra_networks.py | 34 +++++++++++++------ modules/ui_extra_networks_lora.py | 1 + modules/ui_extra_networks_styles.py | 1 + .../ui_extra_networks_textual_inversion.py | 1 + modules/ui_extra_networks_vae.py | 1 + 11 files changed, 37 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 069619144..21a3b93fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -410,6 +410,7 @@ And (as always) many bugfixes and improvements to existing features! *note*: you need to enable quantization and choose what it applies on, then xyz grid can change quantization mode *note*: you can also enable 'add time info' to compare performance of different quantization modes - **API** + - Add `/sdapi/v1/network?page=&item=` endpoint that returns full network info - Add `/sdapi/v1/lora?lora=` endpoint that returns full lora info and metadata - Add `/sdapi/v1/controlnets?model_type=` endpoints that returns list of available controlnets for specific model type - Set default sampler to `Default` diff --git a/javascript/civitai.js b/javascript/civitai.js index c60909f4a..31f1fc890 100644 --- a/javascript/civitai.js +++ b/javascript/civitai.js @@ -107,7 +107,7 @@ async function modelCardClick(id) { downloads: data.downloads?.toString() || '', creator, desc: data.desc || 'no description available', - image: images.length > 0 ? images[0] : './sd_extra_networks/thumb?filename=html/card-no-preview.png', + image: images.length > 0 ? images[0] : '/sdapi/v1/network/thumb?filename=html/card-no-preview.png', versions: versionsHTML || '', }); el.innerHTML = modelHTML; diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index a2e35f426..c7cfcdeaf 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -102,7 +102,7 @@ function readCardTags(el, tags) { } function readCardDescription(page, item) { - xhrGet('/sd_extra_networks/description', { page, item }, (data) => { + xhrGet('/sdapi/v1/network/desc', { page, item }, (data) => { const tabName = getENActiveTab(); const description = gradioApp().querySelector(`#${tabName}_description > label > textarea`); if (description) { diff --git a/modules/api/loras.py b/modules/api/loras.py index 4fbae29c5..c387bdaa0 100644 --- a/modules/api/loras.py +++ b/modules/api/loras.py @@ -7,6 +7,7 @@ def get_lora(lora: str) -> dict: if lora not in lora_load.available_networks: raise HTTPException(status_code=404, detail=f"Lora '{lora}' not found") obj = lora_load.available_networks[lora] + obj.meta = obj.get_metadata() obj.info = obj.get_info() obj.desc = obj.get_desc() return obj.__dict__ diff --git a/modules/civitai/search_civitai.py b/modules/civitai/search_civitai.py index dda495028..226925bf9 100644 --- a/modules/civitai/search_civitai.py +++ b/modules/civitai/search_civitai.py @@ -200,7 +200,7 @@ def create_model_cards(all_models: list[Model]) -> str: if image.url and len(image.url) > 0 and not image.url.lower().endswith('.mp4'): previews.append(image.url) if len(previews) == 0: - previews = ['./sd_extra_networks/thumb?filename=html/card-no-preview.png'] + previews = ['/sdapi/v1/network/thumb?filename=html/card-no-preview.png'] all_cards += card.format(id=model.id, name=model.name, type=model.type, preview=previews[0]) html = details + cards.format(cards=all_cards) return html diff --git a/modules/lora/lora_overrides.py b/modules/lora/lora_overrides.py index f18dfd9b1..9b51b62e2 100644 --- a/modules/lora/lora_overrides.py +++ b/modules/lora/lora_overrides.py @@ -33,6 +33,10 @@ force_models_diffusers = [ # forced always 'hunyuandit', 'auraflow', 'lumina2', + 'qwen', + 'bria', + 'flite', + 'cosmos', # video models 'hunyuanvideo', 'cogvideo', diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 46b002abe..8e9b5afdc 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -70,7 +70,7 @@ def init_api(): return FileResponse(filename, headers={"Accept-Ranges": "bytes"}) def get_metadata(page: str = "", item: str = ""): - page = next(iter([x for x in shared.extra_networks if x.name == page]), None) + page = next(iter([x for x in shared.extra_networks if x.name.lower() == page.lower()]), None) if page is None: return JSONResponse({ 'metadata': 'none' }) metadata = page.metadata.get(item, 'none') @@ -80,10 +80,10 @@ def init_api(): return JSONResponse({"metadata": metadata}) def get_info(page: str = "", item: str = ""): - page = next(iter([x for x in get_pages() if x.name == page]), None) + page = next(iter([x for x in get_pages() if x.name.lower() == page.lower()]), None) if page is None: return JSONResponse({ 'info': 'none' }) - item = next(iter([x for x in page.items if x['name'] == item]), None) + item = next(iter([x for x in page.items if x['name'].lower() == item.lower()]), None) if item is None: return JSONResponse({ 'info': 'none' }) info = page.find_info(item.get('filename', None) or item.get('name', None)) @@ -93,10 +93,10 @@ def init_api(): return JSONResponse({"info": info}) def get_desc(page: str = "", item: str = ""): - page = next(iter([x for x in get_pages() if x.name == page]), None) + page = next(iter([x for x in get_pages() if x.name.lower() == page.lower()]), None) if page is None: return JSONResponse({ 'description': 'none' }) - item = next(iter([x for x in page.items if x['name'] == item]), None) + item = next(iter([x for x in page.items if x['name'].lower() == item.lower()]), None) if item is None: return JSONResponse({ 'description': 'none' }) desc = page.find_description(item.get('filename', None) or item.get('name', None)) @@ -105,10 +105,21 @@ def init_api(): # shared.log.debug(f"Networks desc: page='{page.name}' item={item['name']} len={len(desc)}") return JSONResponse({"description": desc}) - shared.api.add_api_route("/sd_extra_networks/thumb", fetch_file, methods=["GET"]) - shared.api.add_api_route("/sd_extra_networks/metadata", get_metadata, methods=["GET"]) - shared.api.add_api_route("/sd_extra_networks/info", get_info, methods=["GET"]) - shared.api.add_api_route("/sd_extra_networks/description", get_desc, methods=["GET"]) + def get_network(page: str = "", item: str = ""): + page = next(iter([x for x in get_pages() if x.name.lower() == page.lower()]), None) + if page is None: + return JSONResponse({ 'page': 'none' }) + item = next(iter([x for x in page.items if (x['alias'].lower() == item.lower() or x['name'].lower() == item.lower())]), None) + if item is None: + return JSONResponse({ 'item': 'none' }) + return JSONResponse(item) + + + shared.api.add_api_route("/sdapi/v1/network", get_network, methods=["GET"]) + shared.api.add_api_route("/sdapi/v1/network/thumb", fetch_file, methods=["GET"]) + shared.api.add_api_route("/sdapi/v1/network/metadata", get_metadata, methods=["GET"]) + shared.api.add_api_route("/sdapi/v1/network/info", get_info, methods=["GET"]) + shared.api.add_api_route("/sdapi/v1/network/desc", get_desc, methods=["GET"]) class ExtraNetworksPage: @@ -131,6 +142,9 @@ class ExtraNetworksPage: self.view = shared.opts.extra_networks_view self.card = card_full if shared.opts.extra_networks_view == 'gallery' else card_list + def __str__(self): + return f'Page(title="{self.title}" name="{self.name}" items={len(self.items)})' + def refresh(self): pass @@ -159,7 +173,7 @@ class ExtraNetworksPage: def link_preview(self, filename): quoted_filename = urllib.parse.quote(filename.replace('\\', '/')) mtime = os.path.getmtime(filename) if os.path.exists(filename) else 0 - preview = f"./sd_extra_networks/thumb?filename={quoted_filename}&mtime={mtime}" + preview = f"/sdapi/v1/network/thumb?filename={quoted_filename}&mtime={mtime}" return preview def create_thumb(self): diff --git a/modules/ui_extra_networks_lora.py b/modules/ui_extra_networks_lora.py index 194f16b41..597f32941 100644 --- a/modules/ui_extra_networks_lora.py +++ b/modules/ui_extra_networks_lora.py @@ -88,6 +88,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): item = { "type": 'Lora', "name": name, + "alias": os.path.splitext(os.path.basename(l.filename))[0], "filename": l.filename, "hash": l.shorthash, "prompt": json.dumps(f" "), diff --git a/modules/ui_extra_networks_styles.py b/modules/ui_extra_networks_styles.py index 29ac541a8..3cd17b07a 100644 --- a/modules/ui_extra_networks_styles.py +++ b/modules/ui_extra_networks_styles.py @@ -80,6 +80,7 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage): "type": 'Style', "name": name, "title": k, + "alias": os.path.splitext(os.path.basename(style.filename))[0], "filename": style.filename, "preview": style.preview if getattr(style, 'preview', None) is not None and style.preview.startswith('data:') else None, "description": style.description if getattr(style, 'description', None) is not None and len(style.description) > 0 else txt, diff --git a/modules/ui_extra_networks_textual_inversion.py b/modules/ui_extra_networks_textual_inversion.py index 55b5b01d1..92c8acc92 100644 --- a/modules/ui_extra_networks_textual_inversion.py +++ b/modules/ui_extra_networks_textual_inversion.py @@ -27,6 +27,7 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage): "type": 'Embedding', "name": name, "filename": embedding.filename, + "alias": os.path.splitext(os.path.basename(embedding.filename))[0], "prompt": json.dumps(f" {os.path.splitext(embedding.name)[0]}"), "tags": tags, "mtime": os.path.getmtime(embedding.filename), diff --git a/modules/ui_extra_networks_vae.py b/modules/ui_extra_networks_vae.py index de18b5d26..ed9ddadc3 100644 --- a/modules/ui_extra_networks_vae.py +++ b/modules/ui_extra_networks_vae.py @@ -17,6 +17,7 @@ class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage): record = { "type": 'VAE', "name": name, + "alias": os.path.splitext(os.path.basename(filename))[0], "title": name, "filename": filename, "hash": hashes.sha256_from_cache(filename, f"vae/{filename}"),