|
|
|
|
@ -14,7 +14,7 @@ import gradio as gr
|
|
|
|
|
import yaml
|
|
|
|
|
from fastapi import FastAPI
|
|
|
|
|
from fastapi.responses import FileResponse, JSONResponse, Response
|
|
|
|
|
from modules import hashes, script_callbacks, sd_hijack, sd_models, shared
|
|
|
|
|
from modules import hashes, script_callbacks, sd_models, shared
|
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
|
|
|
|
from scripts.model_keyword_support import (get_lora_simple_hash,
|
|
|
|
|
@ -22,6 +22,11 @@ from scripts.model_keyword_support import (get_lora_simple_hash,
|
|
|
|
|
write_model_keyword_path)
|
|
|
|
|
from scripts.shared_paths import *
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from modules import sd_hijack
|
|
|
|
|
except (ImportError, ModuleNotFoundError):
|
|
|
|
|
sd_hijack = None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
try:
|
|
|
|
|
from scripts import tag_frequency_db as tdb
|
|
|
|
|
@ -98,9 +103,9 @@ def sort_models(model_list, sort_method = None, name_has_subpath = False):
|
|
|
|
|
# During merging on the JS side we need to re-sort anyway, so here only the sort criteria are calculated.
|
|
|
|
|
# The list itself doesn't need to get sorted at this point.
|
|
|
|
|
if len(model_list[0]) > 2:
|
|
|
|
|
results = [f'{name},"{sorter(path, name, name_has_subpath)}",{meta}' for path, name, meta in model_list]
|
|
|
|
|
results = [f'"{name}","{sorter(path, name, name_has_subpath)}",{meta}' for path, name, meta in model_list]
|
|
|
|
|
else:
|
|
|
|
|
results = [f'{name},"{sorter(path, name, name_has_subpath)}"' for path, name in model_list]
|
|
|
|
|
results = [f'"{name}","{sorter(path, name, name_has_subpath)}"' for path, name in model_list]
|
|
|
|
|
return results
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -151,17 +156,21 @@ def parse_umi_format(umi_tags, data):
|
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_dynamic_prompt_format(yaml_wildcards, data, path):
|
|
|
|
|
def parse_dynamic_prompt_format(yaml_wildcards, data, path, root):
|
|
|
|
|
# Recurse subkeys, delete those without string lists as values
|
|
|
|
|
def recurse_dict(d: dict):
|
|
|
|
|
for key, value in d.copy().items():
|
|
|
|
|
if isinstance(value, dict):
|
|
|
|
|
recurse_dict(value)
|
|
|
|
|
elif not (isinstance(value, list) and all(isinstance(v, str) for v in value)):
|
|
|
|
|
elif (not isinstance(value, str) and # a string value is treated as a list of one item
|
|
|
|
|
not (isinstance(value, list) and all(isinstance(v, str) for v in value))):
|
|
|
|
|
del d[key]
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
recurse_dict(data)
|
|
|
|
|
# prepend folder parts
|
|
|
|
|
for part in reversed(path.relative_to(root).parent.parts):
|
|
|
|
|
data = {part: data}
|
|
|
|
|
# Add to yaml_wildcards
|
|
|
|
|
yaml_wildcards[path.name] = data
|
|
|
|
|
except:
|
|
|
|
|
@ -172,14 +181,14 @@ def get_yaml_wildcards():
|
|
|
|
|
"""Returns a list of all tags found in extension YAML files found under a Tags: key."""
|
|
|
|
|
yaml_files = []
|
|
|
|
|
for path in WILDCARD_EXT_PATHS:
|
|
|
|
|
yaml_files.extend(p for p in path.rglob("*.yml") if p.is_file())
|
|
|
|
|
yaml_files.extend(p for p in path.rglob("*.yaml") if p.is_file())
|
|
|
|
|
yaml_files.extend((p, path) for p in path.rglob("*.yml") if p.is_file())
|
|
|
|
|
yaml_files.extend((p, path) for p in path.rglob("*.yaml") if p.is_file())
|
|
|
|
|
|
|
|
|
|
yaml_wildcards = {}
|
|
|
|
|
|
|
|
|
|
umi_tags = {} # { tag: count }
|
|
|
|
|
|
|
|
|
|
for path in yaml_files:
|
|
|
|
|
for path, root in yaml_files:
|
|
|
|
|
try:
|
|
|
|
|
with open(path, encoding="utf8") as file:
|
|
|
|
|
data = yaml.safe_load(file)
|
|
|
|
|
@ -187,7 +196,7 @@ def get_yaml_wildcards():
|
|
|
|
|
if (is_umi_format(data)):
|
|
|
|
|
parse_umi_format(umi_tags, data)
|
|
|
|
|
else:
|
|
|
|
|
parse_dynamic_prompt_format(yaml_wildcards, data, path)
|
|
|
|
|
parse_dynamic_prompt_format(yaml_wildcards, data, path, root)
|
|
|
|
|
else:
|
|
|
|
|
print('No data found in ' + path.name)
|
|
|
|
|
except (yaml.YAMLError, UnicodeDecodeError, AttributeError, TypeError) as e:
|
|
|
|
|
@ -748,7 +757,7 @@ def api_tac(_: gr.Blocks, app: FastAPI):
|
|
|
|
|
return Response(status_code=404)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
json_candidates = glob.glob(base_path.as_posix() + f"/**/{filename}.json", recursive=True)
|
|
|
|
|
json_candidates = glob.glob(base_path.as_posix() + f"/**/{glob.escape(filename)}.json", recursive=True)
|
|
|
|
|
if json_candidates is not None and len(json_candidates) > 0 and Path(json_candidates[0]).is_file():
|
|
|
|
|
return FileResponse(json_candidates[0])
|
|
|
|
|
except Exception as e:
|
|
|
|
|
@ -759,7 +768,7 @@ def api_tac(_: gr.Blocks, app: FastAPI):
|
|
|
|
|
return Response(status_code=404)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
img_glob = glob.glob(base_path.as_posix() + f"/**/{filename}.*", recursive=True)
|
|
|
|
|
img_glob = glob.glob(base_path.as_posix() + f"/**/{glob.escape(filename)}.*", recursive=True)
|
|
|
|
|
img_candidates = [img for img in img_glob if Path(img).suffix in [".png", ".jpg", ".jpeg", ".webp", ".gif"] and Path(img).is_file()]
|
|
|
|
|
if img_candidates is not None and len(img_candidates) > 0:
|
|
|
|
|
if blob:
|
|
|
|
|
@ -788,7 +797,7 @@ def api_tac(_: gr.Blocks, app: FastAPI):
|
|
|
|
|
|
|
|
|
|
@app.get("/tacapi/v1/lora-cached-hash/{lora_name}")
|
|
|
|
|
async def get_lora_cached_hash(lora_name: str):
|
|
|
|
|
path_glob = glob.glob(LORA_PATH.as_posix() + f"/**/{lora_name}.*", recursive=True)
|
|
|
|
|
path_glob = glob.glob(LORA_PATH.as_posix() + f"/**/{glob.escape(lora_name)}.*", recursive=True)
|
|
|
|
|
paths = [lora for lora in path_glob if Path(lora).suffix in [".safetensors", ".ckpt", ".pt"] and Path(lora).is_file()]
|
|
|
|
|
if paths is not None and len(paths) > 0:
|
|
|
|
|
path = paths[0]
|
|
|
|
|
|