add tag2implicit.json for DINOv3

This commit is contained in:
silveroxides
2026-04-12 07:39:02 +02:00
parent cc454a8e7f
commit 32d92a940d
3 changed files with 30 additions and 50 deletions
+1
View File
@@ -55,6 +55,7 @@
"url": "{HF_ENDPOINT}/lodestones/tagger-experiment/resolve/main/tagger_proto.safetensors",
"vocab_url": "{HF_ENDPOINT}/lodestones/tagger-experiment/resolve/main/tagger_vocab.json",
"cat_vocab_url": "{HF_ENDPOINT}/lodestones/tagger-experiment/resolve/main/tagger_vocab_with_categories_and_alias_updated.json",
"tag2implicit_url": "{HF_ENDPOINT}/spaces/silveroxides/lode-tagger-experiment/resolve/main/tag2implicit.json",
"data_url": "{HF_ENDPOINT}/RedRocket/JTP-3/resolve/main/data",
"data_tag_file": "jtp-3-hydra-tags.csv"
}
+3 -3
View File
@@ -113,7 +113,7 @@ class DINOv3Inference:
if check_updates:
if DINOv3ModelManager.check_for_update(model_name):
# Model updated, clear vocab so it gets re-downloaded
for ext in ["-vocab.json", "-cat-vocab.json", "-tags.csv"]:
for ext in ["-vocab.json", "-cat-vocab.json", "-tag2implicit.json"]:
p = os.path.join(tags_basepath, f"{model_name}{ext}")
if os.path.exists(p):
try:
@@ -188,8 +188,8 @@ class DINOv3Inference:
# Load tag metadata (implications) if needed and available.
# Category exclusion uses tag2category from cat-vocab independently.
if implications_mode != "off" and not DINOv3TagManager.has_metadata(model_name):
csv_path = os.path.join(tags_basepath, f"{model_name}-tags.csv")
if not os.path.exists(csv_path):
json_path = os.path.join(tags_basepath, f"{model_name}-tag2implicit.json")
if not os.path.exists(json_path):
DINOv3TagManager.download_metadata(model_name)
DINOv3TagManager.load_metadata(model_name)
+26 -47
View File
@@ -219,35 +219,31 @@ class DINOv3TagManager(metaclass=Singleton):
@classmethod
def load_metadata(cls, model_name: str) -> bool:
"""Load tag metadata (categories + implications) from a JTP-3-style
CSV. All tag keys and implication references are normalised to use
"""Load tag metadata (implications) from downloaded tag2implicit.json.
All tag keys and implication references are normalised to use
spaces instead of underscores to match DINOv3 output format.
Metadata is stored as {normalized_tag: (-1, [normalized_implied_tag])}.
"""
csv_path = os.path.join(cls().tags_basepath, f"{model_name}-tags.csv")
if not os.path.exists(csv_path):
json_path = os.path.join(cls().tags_basepath, f"{model_name}-tag2implicit.json")
if not os.path.exists(json_path):
ComfyLogger().log(
f"DINOv3 tag metadata CSV not found: {csv_path} "
f"DINOv3 tag metadata JSON not found: {json_path} "
"(implications will be unavailable)",
type="WARNING", always=True,
)
return False
try:
with open(json_path, "r", encoding="utf-8") as f:
data = json.load(f)
tag2implicit = data.get("tag2implicit", {})
metadata: Dict[str, Tuple[int, List[str]]] = {}
with open(csv_path, "r", encoding="utf-8", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
# Normalise tag: underscores -> spaces
tag = row["tag"].replace("_", " ")
category = int(row.get("category", 0))
# Normalise implications the same way
raw_impl = row.get("implications", "")
implications = [
imp.replace("_", " ")
for imp in raw_impl.split()
if imp
]
metadata[tag] = (category, implications)
for tag, implied in tag2implicit.items():
# Normalise tag and implied: underscores -> spaces
normalized_tag = tag.replace("_", " ")
normalized_implied = implied.replace("_", " ")
metadata[normalized_tag] = (-1, [normalized_implied])
ComfyCache.set(f"tags_dino.{model_name}.metadata", metadata)
ComfyLogger().log(
@@ -397,7 +393,7 @@ class DINOv3TagManager(metaclass=Singleton):
@classmethod
def download_metadata(cls, model_name: str) -> bool:
"""Download tag metadata CSV from the configured ``data_url``."""
"""Download tag2implicit.json from the configured URL."""
os.makedirs(cls().tags_basepath, exist_ok=True)
config = ComfyExtensionConfig().get()
@@ -406,38 +402,21 @@ class DINOv3TagManager(metaclass=Singleton):
hf_endpoint = f"https://{hf_endpoint}"
hf_endpoint = hf_endpoint.rstrip("/")
data_url = ComfyExtensionConfig().get(
property=f"models_dino.{model_name}.data_url",
tag2implicit_url = ComfyExtensionConfig().get(
property=f"models_dino.{model_name}.tag2implicit_url",
)
if not data_url:
if not tag2implicit_url:
ComfyLogger().log(
f"No data_url for DINOv3 model {model_name} — "
f"No tag2implicit_url for DINOv3 model {model_name} — "
"implications will not be available",
type="WARNING", always=True,
)
return False
data_url = data_url.replace("{HF_ENDPOINT}", hf_endpoint)
if not data_url.endswith("/"):
data_url += "/"
# The CSV filename follows the convention from the data_url source.
# The config's data_url_tag_file overrides the default if set.
tag_file = ComfyExtensionConfig().get(
property=f"models_dino.{model_name}.data_url_tag_file",
)
if not tag_file or not isinstance(tag_file, str):
# Default: derive from the JTP-3 naming convention
tag_file = ComfyExtensionConfig().get(
property=f"models_dino.{model_name}.data_tag_file",
)
if not tag_file or not isinstance(tag_file, str):
tag_file = "jtp-3-hydra-tags.csv"
url = f"{data_url}{tag_file}"
dest = os.path.join(cls().tags_basepath, f"{model_name}-tags.csv")
url = tag2implicit_url.replace("{HF_ENDPOINT}", hf_endpoint)
dest = os.path.join(cls().tags_basepath, f"{model_name}-tag2implicit.json")
ComfyLogger().log(
f"Downloading DINOv3 tag metadata from {url}",
f"Downloading DINOv3 tag2implicit.json from {url}",
type="INFO", always=True,
)
@@ -445,7 +424,7 @@ class DINOv3TagManager(metaclass=Singleton):
response = requests.get(url, stream=True)
if response.status_code != 200:
ComfyLogger().log(
f"Failed to download tag metadata: HTTP {response.status_code}",
f"Failed to download tag2implicit.json: HTTP {response.status_code}",
type="WARNING", always=True,
)
return False
@@ -455,7 +434,7 @@ class DINOv3TagManager(metaclass=Singleton):
pbar = comfy.utils.ProgressBar(total_size) if total_size > 0 else None
with open(dest, "wb") as f, tqdm(
desc=f"{model_name}-tags.csv",
desc=f"{model_name}-tag2implicit.json",
total=total_size,
unit="iB",
unit_scale=True,
@@ -473,7 +452,7 @@ class DINOv3TagManager(metaclass=Singleton):
except Exception as e:
ComfyLogger().log(
f"Failed to download DINOv3 tag metadata: {e}\n{traceback.format_exc()}",
f"Failed to download DINOv3 tag2implicit.json: {e}\n{traceback.format_exc()}",
type="WARNING", always=True,
)
return False