Skip to content

Commit

Permalink
Merge pull request #16 from Visionatrix/ci-models-check
Browse files Browse the repository at this point in the history
added Action to check for missing models
  • Loading branch information
bigcat88 authored Aug 7, 2024
2 parents 59e9569 + d00073d commit fed45a6
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 18 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/check-models-catalog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Models Catalog

on:
workflow_dispatch:
pull_request:
schedule:
- cron: '0 0 * * *' # This will run once a day at midnight UTC

jobs:
urls_hashes:
name: urls & hashes
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install dependencies
run: python3 -m pip install -r requirements.txt

- name: Check models
run: python3 scripts/ci/models_check.py
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending

- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
files: scripts/

- repo: https://github.com/psf/black
rev: 24.8.0
hooks:
- id: black
files: scripts/
4 changes: 2 additions & 2 deletions flows/flux1_dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
},
"10": {
"inputs": {
"vae_name": "ae.sft"
"vae_name": "ae.safetensors"
},
"class_type": "VAELoader",
"_meta": {
Expand Down Expand Up @@ -217,7 +217,7 @@
"documentation": "https://comfyanonymous.github.io/ComfyUI_examples/flux/#simple-to-use-fp8-checkpoint-version",
"license": "",
"tags": "[\"general\", \"simple\"]",
"version": "1.0.0",
"version": "1.0.1",
"requires": "[]"
},
"class_type": "VixUiWorkflowMetadata",
Expand Down
4 changes: 2 additions & 2 deletions flows/flux1_dev_8bit.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
},
"10": {
"inputs": {
"vae_name": "ae.sft"
"vae_name": "ae.safetensors"
},
"class_type": "VAELoader",
"_meta": {
Expand Down Expand Up @@ -217,7 +217,7 @@
"documentation": "https://comfyanonymous.github.io/ComfyUI_examples/flux/#simple-to-use-fp8-checkpoint-version",
"license": "",
"tags": "[\"general\", \"simple\"]",
"version": "1.0.0",
"version": "1.0.1",
"requires": "[]"
},
"class_type": "VixUiWorkflowMetadata",
Expand Down
6 changes: 3 additions & 3 deletions flows/flux1_schnell.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
},
"10": {
"inputs": {
"vae_name": "ae.sft"
"vae_name": "ae.safetensors"
},
"class_type": "VAELoader",
"_meta": {
Expand All @@ -83,7 +83,7 @@
},
"12": {
"inputs": {
"unet_name": "flux1-schnell.sft",
"unet_name": "flux1-schnell.safetensors",
"weight_dtype": "default"
},
"class_type": "UNETLoader",
Expand Down Expand Up @@ -201,7 +201,7 @@
"documentation": "https://huggingface.co/black-forest-labs/FLUX.1-dev",
"license": "",
"tags": "[\"general\", \"lighting\", \"simple\"]",
"version": "1.0.0",
"version": "1.0.1",
"requires": "[]"
},
"class_type": "VixUiWorkflowMetadata",
Expand Down
4 changes: 2 additions & 2 deletions flows/flux1_schnell_8bit.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
},
"10": {
"inputs": {
"vae_name": "ae.sft"
"vae_name": "ae.safetensors"
},
"class_type": "VAELoader",
"_meta": {
Expand Down Expand Up @@ -201,7 +201,7 @@
"documentation": "https://huggingface.co/black-forest-labs/FLUX.1-dev",
"license": "",
"tags": "[\"general\", \"lighting\", \"simple\"]",
"version": "1.0.0",
"version": "1.0.1",
"requires": "[]"
},
"class_type": "VixUiWorkflowMetadata",
Expand Down
18 changes: 9 additions & 9 deletions models_catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@
}
],
"save_path": "loras/sliders/smiling.pt",
"url": "https://huggingface.co/spaces/baulab/ConceptSliders/resolve/main/models/smiling.pt",
"url": "https://huggingface.co/andrey18106/visionatrix_models/resolve/main/loras/smiling.pt",
"homepage": "https://baulab.info/",
"hash": "6430ab47393ba15222ea0988c3479f547c8b59f93a41024bcddd7121ef7147d1"
},
Expand All @@ -583,19 +583,19 @@
}
],
"save_path": "loras/sliders/cartoon_style.pt",
"url": "https://huggingface.co/spaces/baulab/ConceptSliders/resolve/main/models/cartoon_style.pt",
"url": "https://huggingface.co/andrey18106/visionatrix_models/resolve/main/loras/cartoon_style.pt",
"homepage": "https://baulab.info/",
"hash": "e07c30e4f82f709a474ae11dc5108ac48f81b6996b937757c8dd198920ea9b4d"
},
"FLUX-VAE": {
"regexes": [
{
"input_value": "^(?i:ae\\.sft)$",
"input_value": "^(?i:ae\\.safetensors)$",
"input_name": "(?i)vae"
}
],
"save_path": "vae/ae.sft",
"url": "https://huggingface.co/black-forest-labs/FLUX.1-schnell/resolve/main/ae.sft",
"save_path": "vae/ae.safetensors",
"url": "https://huggingface.co/black-forest-labs/FLUX.1-schnell/resolve/main/ae.safetensors",
"homepage": "https://huggingface.co/black-forest-labs/FLUX.1-schnell",
"hash": "afc8e28272cd15db3919bacdb6918ce9c1ed22e96cb12c4d5ed0fba823529e38"
},
Expand Down Expand Up @@ -638,12 +638,12 @@
"FLUX-1-Schnell": {
"regexes": [
{
"input_value": "^(?=.*(?i:flux1))(?=.*(?i:schnell))(?=.*(?i:sft)).*",
"input_value": "^(?!.*(?i:fp8))(?=.*(?i:flux1))(?=.*(?i:schnell))(?=.*(?i:safetensors)).*",
"input_name": "^(?!.*(?i:lora)).*"
}
],
"save_path": "unet/flux1-schnell.sft",
"url": "https://huggingface.co/black-forest-labs/FLUX.1-schnell/resolve/main/flux1-schnell.sft",
"save_path": "unet/flux1-schnell.safetensors",
"url": "https://huggingface.co/black-forest-labs/FLUX.1-schnell/resolve/main/flux1-schnell.safetensors",
"homepage": "https://huggingface.co/black-forest-labs/FLUX.1-schnell",
"hash": "9403429e0052277ac2a87ad800adece5481eecefd9ed334e1f348723621d2a0a"
},
Expand All @@ -662,7 +662,7 @@
"FLUX-1-Dev": {
"regexes": [
{
"input_value": "^(?=.*(?i:flux1))(?=.*(?i:dev))(?=.*(?i:sft)).*",
"input_value": "^(?!.*(?i:fp8))(?=.*(?i:flux1))(?=.*(?i:dev))(?=.*(?i:sft)).*",
"input_name": "^(?!.*(?i:lora)).*"
}
],
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ sphinx-inline-tabs
sphinx-issues>=3.0.1
sphinx-rtd-theme>=1
requests
huggingface_hub
80 changes: 80 additions & 0 deletions scripts/ci/models_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import builtins
import contextlib
import json
import re
import sys
from pathlib import Path

import requests
from huggingface_hub import HfApi

ERRORS_LIST = []


def parse_huggingface_url(url: str):
parts = url.split("/")
repo_id = "/".join(parts[3:5])
revision = parts[6:7][0]
filename = "/".join(parts[7:])
return repo_id, filename, revision


def get_huggingface_model_hash(model_url: str) -> str | None:
with contextlib.suppress(Exception):
repo_id, filename, revision = parse_huggingface_url(model_url)
repo_info = HfApi().model_info(repo_id, revision=revision, files_metadata=True)
for file in repo_info.siblings:
if file.rfilename == filename:
return file.lfs.sha256
return None


def get_civitai_model_hash(model_url: str) -> str | None:
m = re.search(r"api/download/models/(\d+)", model_url)
if not m:
return None
model_id = m.group(1)
response = requests.get(f"https://civitai.com/api/v1/model-versions/{model_id}")
if response.status_code != 200:
return None
model_info = json.loads(response.text)
for i in model_info["files"]:
if model_url.startswith(i["downloadUrl"]):
return i["hashes"]["SHA256"]
return None


def check_model(model_name: str, model: dict) -> bool:
url = model["url"]
if "huggingface.co" in url:
model_hash = get_huggingface_model_hash(url)
elif "civitai.com" in url:
model_hash = get_civitai_model_hash(url)
else:
ERRORS_LIST.append(f"{model_name}: FAILED. Unknown host for URL: {url}")
return False

if not model_hash:
ERRORS_LIST.append(f"{model_name}: FAILED. {url} --> can't get the hash")
return False
if model_hash == model["hash"]:
print(f"{model_name}: OK.")
return True
ERRORS_LIST.append(
f"{model_name}: FAILED. {url} --> the expected hash({model['hash']}) does not match({model_hash})"
)
return False


if __name__ == "__main__":
with builtins.open(
Path(__file__).parent.parent.parent.joinpath("models_catalog.json"), "r"
) as f:
models = json.load(f)
for name, info in models.items():
check_model(name, info)
print()
print(f"ERRORS: {len(ERRORS_LIST)}")
for i in ERRORS_LIST:
print(i)
sys.exit(0 if not ERRORS_LIST else 2)

0 comments on commit fed45a6

Please sign in to comment.