Spaces:
Running
Running
Upload 3 files
Browse files- app.py +17 -10
- civitai_to_hf.py +94 -5
app.py
CHANGED
@@ -3,6 +3,7 @@ from civitai_to_hf import search_civitai, download_civitai, select_civitai_item,
|
|
3 |
|
4 |
css = """
|
5 |
.title { font-size: 3em; align-items: center; text-align: center; }
|
|
|
6 |
.block.result { margin: 1em 0; padding: 1em; box-shadow: 0 0 3px 3px #664422, 0 0 3px 2px #664422 inset; border-radius: 6px; background: #665544; }
|
7 |
"""
|
8 |
|
@@ -21,28 +22,34 @@ with gr.Blocks(theme="NoCrypt/miku@>=1.2.2", fill_width=True, css=css, delete_ca
|
|
21 |
search_civitai_tag = gr.Textbox(label="Tag", lines=1)
|
22 |
search_civitai_submit = gr.Button("Search on Civitai")
|
23 |
with gr.Row():
|
24 |
-
search_civitai_json = gr.JSON(value={}, visible=False)
|
25 |
search_civitai_desc = gr.Markdown(value="", visible=False)
|
|
|
26 |
search_civitai_result = gr.Dropdown(label="Search Results", choices=[("", "")], value="", allow_custom_value=True, visible=False, multiselect=True)
|
27 |
search_civitai_add = gr.Button("Add to download URLs")
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
with gr.Row():
|
34 |
-
newrepo_id = gr.Textbox(label="Upload repo ID", placeholder="yourid/yourrepo", value="", max_lines=1)
|
35 |
newrepo_type = gr.Radio(label="Upload repo type", choices=["model", "dataset"], value="model")
|
36 |
is_private = gr.Checkbox(label="Create private repo", value=True)
|
|
|
|
|
37 |
uploaded_urls = gr.CheckboxGroup(visible=False, choices=[], value=None) # hidden
|
38 |
-
run_button = gr.Button(value="Download and Upload")
|
39 |
urls_md = gr.Markdown("<br><br>", elem_classes="result")
|
40 |
gr.DuplicateButton(value="Duplicate Space")
|
41 |
|
42 |
gr.on(
|
43 |
triggers=[run_button.click],
|
44 |
fn=download_civitai,
|
45 |
-
inputs=[dl_url, civitai_key, hf_token, uploaded_urls, newrepo_id, newrepo_type, is_private],
|
46 |
outputs=[uploaded_urls, urls_md],
|
47 |
)
|
48 |
gr.on(
|
@@ -53,7 +60,7 @@ with gr.Blocks(theme="NoCrypt/miku@>=1.2.2", fill_width=True, css=css, delete_ca
|
|
53 |
queue=True,
|
54 |
show_api=False,
|
55 |
)
|
56 |
-
search_civitai_result.change(select_civitai_item, [search_civitai_result], [search_civitai_desc], queue=False, show_api=False)
|
57 |
search_civitai_add.click(add_civitai_item, [search_civitai_result, dl_url], [dl_url], queue=False, show_api=False)
|
58 |
|
59 |
demo.queue()
|
|
|
3 |
|
4 |
css = """
|
5 |
.title { font-size: 3em; align-items: center; text-align: center; }
|
6 |
+
.info { align-items: center; text-align: center; }
|
7 |
.block.result { margin: 1em 0; padding: 1em; box-shadow: 0 0 3px 3px #664422, 0 0 3px 2px #664422 inset; border-radius: 6px; background: #665544; }
|
8 |
"""
|
9 |
|
|
|
22 |
search_civitai_tag = gr.Textbox(label="Tag", lines=1)
|
23 |
search_civitai_submit = gr.Button("Search on Civitai")
|
24 |
with gr.Row():
|
|
|
25 |
search_civitai_desc = gr.Markdown(value="", visible=False)
|
26 |
+
search_civitai_json = gr.JSON(value={}, visible=False)
|
27 |
search_civitai_result = gr.Dropdown(label="Search Results", choices=[("", "")], value="", allow_custom_value=True, visible=False, multiselect=True)
|
28 |
search_civitai_add = gr.Button("Add to download URLs")
|
29 |
+
with gr.Group():
|
30 |
+
dl_url = gr.Textbox(label="Download URL(s)", placeholder="https://civitai.com/api/download/models/28907\n...", value="", lines=3, max_lines=255)
|
31 |
+
with gr.Column():
|
32 |
+
civitai_key = gr.Textbox(label="Your Civitai Key", value="", max_lines=1)
|
33 |
+
gr.Markdown("Your Civitai API key is available at [https://civitai.com/user/account](https://civitai.com/user/account).", elem_classes="info")
|
34 |
+
with gr.Group():
|
35 |
+
with gr.Row():
|
36 |
+
with gr.Column():
|
37 |
+
hf_token = gr.Textbox(label="Your HF write token", placeholder="hf_...", value="", max_lines=1)
|
38 |
+
gr.Markdown("Your token is available at [hf.co/settings/tokens](https://huggingface.co/settings/tokens).", elem_classes="info")
|
39 |
+
newrepo_id = gr.Textbox(label="Upload repo ID", placeholder="yourid/yourrepo", value="", max_lines=1)
|
40 |
with gr.Row():
|
|
|
41 |
newrepo_type = gr.Radio(label="Upload repo type", choices=["model", "dataset"], value="model")
|
42 |
is_private = gr.Checkbox(label="Create private repo", value=True)
|
43 |
+
is_info = gr.Checkbox(label="Upload Civitai information files", value=False)
|
44 |
+
run_button = gr.Button(value="Download and Upload", variant="primary")
|
45 |
uploaded_urls = gr.CheckboxGroup(visible=False, choices=[], value=None) # hidden
|
|
|
46 |
urls_md = gr.Markdown("<br><br>", elem_classes="result")
|
47 |
gr.DuplicateButton(value="Duplicate Space")
|
48 |
|
49 |
gr.on(
|
50 |
triggers=[run_button.click],
|
51 |
fn=download_civitai,
|
52 |
+
inputs=[dl_url, civitai_key, hf_token, uploaded_urls, newrepo_id, newrepo_type, is_private, is_info],
|
53 |
outputs=[uploaded_urls, urls_md],
|
54 |
)
|
55 |
gr.on(
|
|
|
60 |
queue=True,
|
61 |
show_api=False,
|
62 |
)
|
63 |
+
search_civitai_result.change(select_civitai_item, [search_civitai_result], [search_civitai_desc, search_civitai_json], queue=False, show_api=False)
|
64 |
search_civitai_add.click(add_civitai_item, [search_civitai_result, dl_url], [dl_url], queue=False, show_api=False)
|
65 |
|
66 |
demo.queue()
|
civitai_to_hf.py
CHANGED
@@ -8,6 +8,11 @@ from requests.adapters import HTTPAdapter
|
|
8 |
from urllib3.util import Retry
|
9 |
from utils import get_token, set_token, is_repo_exists, get_user_agent, get_download_file, list_uniq
|
10 |
import re
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
|
13 |
def parse_urls(s):
|
@@ -41,18 +46,61 @@ def upload_safetensors_to_repo(filename, repo_id, repo_type, is_private, progres
|
|
41 |
print(f"Error: Failed to upload to {repo_id}. {e}")
|
42 |
gr.Warning(f"Error: Failed to upload to {repo_id}. {e}")
|
43 |
return None
|
|
|
|
|
44 |
return url
|
45 |
|
46 |
|
47 |
def download_file(dl_url, civitai_key, progress=gr.Progress(track_tqdm=True)):
|
48 |
-
download_dir =
|
49 |
progress(0, desc=f"Start downloading... {dl_url}")
|
50 |
output_filename = get_download_file(download_dir, dl_url, civitai_key)
|
51 |
return output_filename
|
52 |
|
53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
def download_civitai(dl_url, civitai_key, hf_token, urls,
|
55 |
-
newrepo_id, repo_type="model", is_private=True, progress=gr.Progress(track_tqdm=True)):
|
56 |
if hf_token: set_token(hf_token)
|
57 |
else: set_token(os.environ.get("HF_TOKEN")) # default huggingface write token
|
58 |
if not civitai_key: civitai_key = os.environ.get("CIVITAI_API_KEY") # default Civitai API key
|
@@ -64,8 +112,9 @@ def download_civitai(dl_url, civitai_key, hf_token, urls,
|
|
64 |
file = download_file(u, civitai_key)
|
65 |
if not Path(file).exists() or not Path(file).is_file(): continue
|
66 |
url = upload_safetensors_to_repo(file, newrepo_id, repo_type, is_private)
|
67 |
-
if url:
|
68 |
-
|
|
|
69 |
progress(1, desc="Processing...")
|
70 |
md = f'### Your repo: [{newrepo_id}]({"https://huggingface.co/datasets/" if repo_type == "dataset" else "https://huggingface.co/"}{newrepo_id})\n'
|
71 |
for u in urls:
|
@@ -143,11 +192,51 @@ def search_civitai(query, types, base_model=[], sort=CIVITAI_SORT[0], period=CIV
|
|
143 |
gr.update(visible=True), gr.update(visible=True)
|
144 |
|
145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
def select_civitai_item(results: list[str]):
|
147 |
if "http" not in "".join(results): return gr.update(value="None", visible=True)
|
148 |
result = civitai_last_results.get(results[-1], "None")
|
149 |
md = result['md'] if result else ""
|
150 |
-
|
|
|
|
|
151 |
|
152 |
|
153 |
def add_civitai_item(results: list[str], dl_url: str):
|
|
|
8 |
from urllib3.util import Retry
|
9 |
from utils import get_token, set_token, is_repo_exists, get_user_agent, get_download_file, list_uniq
|
10 |
import re
|
11 |
+
from PIL import Image
|
12 |
+
import json
|
13 |
+
|
14 |
+
|
15 |
+
TEMP_DIR = "."
|
16 |
|
17 |
|
18 |
def parse_urls(s):
|
|
|
46 |
print(f"Error: Failed to upload to {repo_id}. {e}")
|
47 |
gr.Warning(f"Error: Failed to upload to {repo_id}. {e}")
|
48 |
return None
|
49 |
+
finally:
|
50 |
+
Path(filename).unlink()
|
51 |
return url
|
52 |
|
53 |
|
54 |
def download_file(dl_url, civitai_key, progress=gr.Progress(track_tqdm=True)):
|
55 |
+
download_dir = TEMP_DIR
|
56 |
progress(0, desc=f"Start downloading... {dl_url}")
|
57 |
output_filename = get_download_file(download_dir, dl_url, civitai_key)
|
58 |
return output_filename
|
59 |
|
60 |
|
61 |
+
def save_civitai_info(dl_url, filename, progress=gr.Progress(track_tqdm=True)):
|
62 |
+
json_str, html_str, image_path = get_civitai_json(dl_url, True, filename)
|
63 |
+
if not json_str: return "", "", ""
|
64 |
+
json_path = str(Path(TEMP_DIR, Path(filename).stem + ".json"))
|
65 |
+
html_path = str(Path(TEMP_DIR, Path(filename).stem + ".html"))
|
66 |
+
try:
|
67 |
+
with open(json_path, 'w') as f:
|
68 |
+
json.dump(json_str, f, indent=2)
|
69 |
+
with open(html_path, mode='w', encoding="utf-8") as f:
|
70 |
+
f.write(html_str)
|
71 |
+
return json_path, html_path, image_path
|
72 |
+
except Exception as e:
|
73 |
+
print(f"Error: Failed to save info file {json_path}, {html_path} {e}")
|
74 |
+
return "", "", ""
|
75 |
+
|
76 |
+
|
77 |
+
def upload_info_to_repo(dl_url, filename, repo_id, repo_type, is_private, progress=gr.Progress(track_tqdm=True)):
|
78 |
+
def upload_file(api, filename, repo_id, repo_type, hf_token):
|
79 |
+
if not Path(filename).exists(): return
|
80 |
+
api.upload_file(path_or_fileobj=filename, path_in_repo=Path(filename).name, repo_type=repo_type, revision="main", token=hf_token, repo_id=repo_id)
|
81 |
+
Path(filename).unlink()
|
82 |
+
|
83 |
+
hf_token = get_token()
|
84 |
+
api = HfApi(token=hf_token)
|
85 |
+
try:
|
86 |
+
if not is_repo_exists(repo_id, repo_type): api.create_repo(repo_id=repo_id, repo_type=repo_type, token=hf_token, private=is_private)
|
87 |
+
progress(0, desc=f"Downloading info... {filename}")
|
88 |
+
json_path, html_path, image_path = save_civitai_info(dl_url, filename)
|
89 |
+
progress(0, desc=f"Start uploading info... {filename} to {repo_id}")
|
90 |
+
if not json_path: return
|
91 |
+
else: upload_file(api, json_path, repo_id, repo_type, hf_token)
|
92 |
+
if html_path: upload_file(api, html_path, repo_id, repo_type, hf_token)
|
93 |
+
if image_path: upload_file(api, image_path, repo_id, repo_type, hf_token)
|
94 |
+
progress(1, desc="Info uploaded.")
|
95 |
+
return
|
96 |
+
except Exception as e:
|
97 |
+
print(f"Error: Failed to upload info to {repo_id}. {e}")
|
98 |
+
gr.Warning(f"Error: Failed to upload info to {repo_id}. {e}")
|
99 |
+
return
|
100 |
+
|
101 |
+
|
102 |
def download_civitai(dl_url, civitai_key, hf_token, urls,
|
103 |
+
newrepo_id, repo_type="model", is_private=True, is_info=False, progress=gr.Progress(track_tqdm=True)):
|
104 |
if hf_token: set_token(hf_token)
|
105 |
else: set_token(os.environ.get("HF_TOKEN")) # default huggingface write token
|
106 |
if not civitai_key: civitai_key = os.environ.get("CIVITAI_API_KEY") # default Civitai API key
|
|
|
112 |
file = download_file(u, civitai_key)
|
113 |
if not Path(file).exists() or not Path(file).is_file(): continue
|
114 |
url = upload_safetensors_to_repo(file, newrepo_id, repo_type, is_private)
|
115 |
+
if url:
|
116 |
+
urls.append(url)
|
117 |
+
if is_info: upload_info_to_repo(u, file, newrepo_id, repo_type, is_private)
|
118 |
progress(1, desc="Processing...")
|
119 |
md = f'### Your repo: [{newrepo_id}]({"https://huggingface.co/datasets/" if repo_type == "dataset" else "https://huggingface.co/"}{newrepo_id})\n'
|
120 |
for u in urls:
|
|
|
192 |
gr.update(visible=True), gr.update(visible=True)
|
193 |
|
194 |
|
195 |
+
def get_civitai_json(dl_url: str, is_html: bool=False, image_baseurl: str=""):
|
196 |
+
if not image_baseurl: image_baseurl = dl_url
|
197 |
+
default = ("", "", "") if is_html else ""
|
198 |
+
if "https://civitai.com/api/download/models/" not in dl_url: return default
|
199 |
+
user_agent = get_user_agent()
|
200 |
+
headers = {'User-Agent': user_agent, 'content-type': 'application/json'}
|
201 |
+
base_url = 'https://civitai.com/api/v1/model-versions/'
|
202 |
+
params = {}
|
203 |
+
session = requests.Session()
|
204 |
+
retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
|
205 |
+
session.mount("https://", HTTPAdapter(max_retries=retries))
|
206 |
+
url = base_url + str(dl_url.split("/")[-1])
|
207 |
+
try:
|
208 |
+
r = session.get(url, params=params, headers=headers, stream=True, timeout=(3.0, 15))
|
209 |
+
if not r.ok: return default
|
210 |
+
json = dict(r.json()).copy()
|
211 |
+
html = ""
|
212 |
+
image = ""
|
213 |
+
if "modelId" in json.keys():
|
214 |
+
url = f"https://civitai.com/models/{json['modelId']}"
|
215 |
+
r = session.get(url, params=params, headers=headers, stream=True, timeout=(3.0, 15))
|
216 |
+
if not r.ok: return json, html, image
|
217 |
+
html = r.text
|
218 |
+
if 'images' in json.keys() and len(json["images"]) != 0:
|
219 |
+
url = json["images"][0]["url"]
|
220 |
+
r = session.get(url, params=params, headers=headers, stream=True, timeout=(3.0, 15))
|
221 |
+
if not r.ok: return json, html, image
|
222 |
+
image_temp = str(Path(TEMP_DIR, "image" + Path(url.split("/")[-1]).suffix))
|
223 |
+
image = str(Path(TEMP_DIR, Path(image_baseurl.split("/")[-1]).stem + ".png"))
|
224 |
+
with open(image_temp, 'wb') as f:
|
225 |
+
f.write(r.content)
|
226 |
+
Image.open(image_temp).convert('RGBA').save(image)
|
227 |
+
return json, html, image
|
228 |
+
except Exception as e:
|
229 |
+
print(e)
|
230 |
+
return default
|
231 |
+
|
232 |
+
|
233 |
def select_civitai_item(results: list[str]):
|
234 |
if "http" not in "".join(results): return gr.update(value="None", visible=True)
|
235 |
result = civitai_last_results.get(results[-1], "None")
|
236 |
md = result['md'] if result else ""
|
237 |
+
json = {}
|
238 |
+
#json, html, image = get_civitai_json(results[-1], True) # for debugging
|
239 |
+
return gr.update(value=md, visible=True), gr.update(value=json, visible=False)
|
240 |
|
241 |
|
242 |
def add_civitai_item(results: list[str], dl_url: str):
|