Spaces:
Running on Zero
Running on Zero
Upload 5 files
Browse files- README.md +166 -165
- app.py +81 -80
- env.py +2 -0
- modutils.py +119 -35
- requirements.txt +23 -22
README.md
CHANGED
|
@@ -1,165 +1,166 @@
|
|
| 1 |
-
---
|
| 2 |
-
title: 🧩 DiffuseCraft Mod (SDXL/SD1.5 Models Text-to-Image)
|
| 3 |
-
emoji: 🧩🖼️📦
|
| 4 |
-
colorFrom: red
|
| 5 |
-
colorTo: pink
|
| 6 |
-
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
---
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
>
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
-
|
| 29 |
-
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
"
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
print(
|
| 76 |
-
print(
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
"
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
-H "
|
| 131 |
-
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
"
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
0,
|
| 139 |
-
|
| 140 |
-
//
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
-H "
|
| 151 |
-
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
"
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
0,
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: 🧩 DiffuseCraft Mod (SDXL/SD1.5 Models Text-to-Image)
|
| 3 |
+
emoji: 🧩🖼️📦
|
| 4 |
+
colorFrom: red
|
| 5 |
+
colorTo: pink
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 6.17.3
|
| 8 |
+
python_version: "3.12"
|
| 9 |
+
app_file: app.py
|
| 10 |
+
pinned: true
|
| 11 |
+
header: mini
|
| 12 |
+
license: mit
|
| 13 |
+
duplicated_from: r3gm/DiffuseCraft
|
| 14 |
+
short_description: Stunning images using stable diffusion.
|
| 15 |
+
preload_from_hub:
|
| 16 |
+
- madebyollin/sdxl-vae-fp16-fix config.json,diffusion_pytorch_model.safetensors
|
| 17 |
+
---
|
| 18 |
+
|
| 19 |
+
## Using this Space programmatically
|
| 20 |
+
|
| 21 |
+
You can call this Space from Python (via `gradio_client`) or from plain `curl`.
|
| 22 |
+
|
| 23 |
+
> ⚠️ Note: This README may lag behind the actual API definition shown in the Space’s “View API” page.
|
| 24 |
+
> If something does not work, always double-check the latest argument list and endpoint names there.
|
| 25 |
+
|
| 26 |
+
Assumptions:
|
| 27 |
+
|
| 28 |
+
- Space ID: `John6666/DiffuseCraftMod`
|
| 29 |
+
- You have a valid Hugging Face access token: `hf_xxx...` (read access is enough)
|
| 30 |
+
- Replace `hf_xxx...` with your own token
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
|
| 34 |
+
### 1. Python examples (`gradio_client`)
|
| 35 |
+
|
| 36 |
+
Install:
|
| 37 |
+
|
| 38 |
+
```bash
|
| 39 |
+
pip install gradio_client
|
| 40 |
+
````
|
| 41 |
+
|
| 42 |
+
#### 1.1 Synchronous API – `generate_image`
|
| 43 |
+
|
| 44 |
+
```python
|
| 45 |
+
from gradio_client import Client
|
| 46 |
+
|
| 47 |
+
client = Client("John6666/DiffuseCraftMod", hf_token="hf_xxx...")
|
| 48 |
+
|
| 49 |
+
status, images, info = client.predict(
|
| 50 |
+
# Core text controls
|
| 51 |
+
prompt="Hello!!",
|
| 52 |
+
negative_prompt=(
|
| 53 |
+
"lowres, bad anatomy, bad hands, missing fingers, extra digit, "
|
| 54 |
+
"fewer digits, worst quality, low quality"
|
| 55 |
+
),
|
| 56 |
+
|
| 57 |
+
# Basic generation controls
|
| 58 |
+
num_images=1,
|
| 59 |
+
num_inference_steps=28,
|
| 60 |
+
guidance_scale=7.0,
|
| 61 |
+
clip_skip=0,
|
| 62 |
+
seed=-1,
|
| 63 |
+
|
| 64 |
+
# Canvas / model / task (optional, server has defaults)
|
| 65 |
+
height=1024,
|
| 66 |
+
width=1024,
|
| 67 |
+
model_name="votepurchase/animagine-xl-3.1",
|
| 68 |
+
vae_model="None",
|
| 69 |
+
task="txt2img",
|
| 70 |
+
|
| 71 |
+
# All other arguments are optional; defaults match the UI
|
| 72 |
+
api_name="/generate_image",
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
print(status) # e.g. "COMPLETE"
|
| 76 |
+
print(images) # list of image paths / URLs
|
| 77 |
+
print(info) # generation metadata (seed, model, etc.)
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
#### 1.2 Streaming API – `generate_image_stream`
|
| 81 |
+
|
| 82 |
+
```python
|
| 83 |
+
from gradio_client import Client
|
| 84 |
+
|
| 85 |
+
client = Client("John6666/DiffuseCraftMod", hf_token="hf_xxx...")
|
| 86 |
+
|
| 87 |
+
job = client.submit(
|
| 88 |
+
prompt="Hello!!",
|
| 89 |
+
negative_prompt=(
|
| 90 |
+
"lowres, bad anatomy, bad hands, missing fingers, extra digit, "
|
| 91 |
+
"fewer digits, worst quality, low quality"
|
| 92 |
+
),
|
| 93 |
+
num_images=1,
|
| 94 |
+
num_inference_steps=28,
|
| 95 |
+
guidance_scale=7.0,
|
| 96 |
+
clip_skip=0,
|
| 97 |
+
seed=-1,
|
| 98 |
+
height=1024,
|
| 99 |
+
width=1024,
|
| 100 |
+
model_name="votepurchase/animagine-xl-3.1",
|
| 101 |
+
vae_model="None",
|
| 102 |
+
task="txt2img",
|
| 103 |
+
api_name="/generate_image_stream",
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
for status, images, info in job:
|
| 107 |
+
# You will see progress messages, intermediate previews, and the final result.
|
| 108 |
+
print(status, images, info)
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
You can stop iterating once you see a `"COMPLETE"` status if you only care about the final output.
|
| 112 |
+
|
| 113 |
+
---
|
| 114 |
+
|
| 115 |
+
### 2. `curl` examples
|
| 116 |
+
|
| 117 |
+
When calling from `curl`, include your HF token; anonymous calls may be rate-limited or rejected.
|
| 118 |
+
|
| 119 |
+
```bash
|
| 120 |
+
export HF_TOKEN="hf_xxx..." # your Hugging Face access token
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
The `data` field is a positional array. The order must match the function signature.
|
| 124 |
+
For simplicity, the examples below only send the first few arguments and rely on server defaults for the rest.
|
| 125 |
+
|
| 126 |
+
#### 2.1 Synchronous API – `generate_image`
|
| 127 |
+
|
| 128 |
+
```bash
|
| 129 |
+
curl -X POST "https://john6666-diffusecraftmod.hf.space/call/generate_image" \
|
| 130 |
+
-H "Authorization: Bearer $HF_TOKEN" \
|
| 131 |
+
-H "Content-Type: application/json" \
|
| 132 |
+
-d '{
|
| 133 |
+
"data": [
|
| 134 |
+
"Hello!!", // prompt
|
| 135 |
+
"lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, worst quality, low quality", // negative_prompt
|
| 136 |
+
1, // num_images
|
| 137 |
+
28, // num_inference_steps
|
| 138 |
+
7.0, // guidance_scale
|
| 139 |
+
0, // clip_skip
|
| 140 |
+
-1 // seed
|
| 141 |
+
// All subsequent parameters will use their default values
|
| 142 |
+
]
|
| 143 |
+
}'
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
#### 2.2 Streaming API – `generate_image_stream`
|
| 147 |
+
|
| 148 |
+
```bash
|
| 149 |
+
curl -X POST "https://john6666-diffusecraftmod.hf.space/call/generate_image_stream" \
|
| 150 |
+
-H "Authorization: Bearer $HF_TOKEN" \
|
| 151 |
+
-H "Content-Type: application/json" \
|
| 152 |
+
-d '{
|
| 153 |
+
"data": [
|
| 154 |
+
"Hello!!",
|
| 155 |
+
"lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, worst quality, low quality",
|
| 156 |
+
1,
|
| 157 |
+
28,
|
| 158 |
+
7.0,
|
| 159 |
+
0,
|
| 160 |
+
-1
|
| 161 |
+
]
|
| 162 |
+
}'
|
| 163 |
+
```
|
| 164 |
+
|
| 165 |
+
For full parameter coverage (all advanced options such as LoRAs, ControlNet, IP-Adapter, etc.),
|
| 166 |
+
refer to the Space’s “View API” page and adapt the examples above accordingly.
|
app.py
CHANGED
|
@@ -878,7 +878,7 @@ CSS ="""
|
|
| 878 |
.desc [src$='#float'] { float: right; margin: 20px; }
|
| 879 |
"""
|
| 880 |
|
| 881 |
-
with gr.Blocks(
|
| 882 |
gr.Markdown("# 🧩 DiffuseCraft Mod", elem_classes="title")
|
| 883 |
gr.Markdown("This space is a modification of [r3gm's DiffuseCraft](https://huggingface.co/spaces/r3gm/DiffuseCraft).", elem_classes="info")
|
| 884 |
with gr.Column():
|
|
@@ -923,9 +923,9 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 923 |
keep_tags_gui = gr.Radio(label="Remove tags leaving only the following", choices=["body", "dress", "all"], value="all")
|
| 924 |
image_algorithms = gr.CheckboxGroup(["Use WD Tagger"], label="Algorithms", value=["Use WD Tagger"], visible=False)
|
| 925 |
generate_from_image_btn_gui = gr.Button(value="GENERATE TAGS FROM IMAGE")
|
| 926 |
-
prompt_gui = gr.Textbox(lines=6, placeholder="1girl, solo, ...", label="Prompt",
|
| 927 |
with gr.Accordion("Negative prompt, etc.", open=False) as menu_negative:
|
| 928 |
-
neg_prompt_gui = gr.Textbox(lines=3, placeholder="Enter Neg prompt", label="Negative prompt", value="lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, worst quality, low quality, very displeasing, (bad)",
|
| 929 |
translate_prompt_button = gr.Button(value="Translate prompt to English", size="sm", variant="secondary")
|
| 930 |
with gr.Row():
|
| 931 |
insert_prompt_gui = gr.Radio(label="Insert reccomended positive / negative prompt", choices=["None", "Auto", "Animagine", "Pony"], value="Auto", interactive=True)
|
|
@@ -955,7 +955,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 955 |
update_task_options,
|
| 956 |
[model_name_gui, task_gui],
|
| 957 |
[task_gui],
|
| 958 |
-
|
| 959 |
)
|
| 960 |
|
| 961 |
load_model_gui = gr.HTML(elem_id="load_model", elem_classes="contain")
|
|
@@ -972,8 +972,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 972 |
# height="auto",
|
| 973 |
interactive=False,
|
| 974 |
preview=False,
|
| 975 |
-
|
| 976 |
-
show_download_button=True,
|
| 977 |
selected_index=50,
|
| 978 |
format="png",
|
| 979 |
)
|
|
@@ -984,9 +983,9 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 984 |
|
| 985 |
with gr.Accordion("History", open=False):
|
| 986 |
history_files = gr.Files(interactive=False, visible=False)
|
| 987 |
-
history_gallery = gr.Gallery(label="History", columns=6, object_fit="contain", format="png", interactive=False,
|
| 988 |
history_clear_button = gr.Button(value="Clear History", variant="secondary")
|
| 989 |
-
history_clear_button.click(lambda: ([], []), None, [history_gallery, history_files], queue=False,
|
| 990 |
|
| 991 |
with gr.Row(equal_height=False, variant="default"):
|
| 992 |
gpu_duration_gui = gr.Number(minimum=5, maximum=240, value=20, show_label=False, container=False, info="GPU time duration (seconds)")
|
|
@@ -1166,7 +1165,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1166 |
return gr.Slider(minimum=-val_lora, maximum=val_lora, step=0.01, value=1.0, label=label, visible=visible)
|
| 1167 |
|
| 1168 |
def lora_textbox(label):
|
| 1169 |
-
return gr.Textbox(label=label, info="Example of prompt:", value="None",
|
| 1170 |
|
| 1171 |
with gr.Row():
|
| 1172 |
with gr.Column():
|
|
@@ -1237,7 +1236,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1237 |
search_civitai_button_lora = gr.Button("Search on Civitai")
|
| 1238 |
search_civitai_desc_lora = gr.Markdown(value="", visible=False, elem_classes="desc")
|
| 1239 |
with gr.Accordion("Select from Gallery", open=False):
|
| 1240 |
-
search_civitai_gallery_lora = gr.Gallery([], label="Results", allow_preview=False, columns=5,
|
| 1241 |
search_civitai_result_lora = gr.Dropdown(label="Search Results", choices=[("", "")], value="", allow_custom_value=True, visible=False)
|
| 1242 |
with gr.Row():
|
| 1243 |
text_lora = gr.Textbox(label="LoRA's download URL", placeholder="https://civitai.com/api/download/models/28907", info="It has to be .safetensors files, and you can also download them from Hugging Face.", lines=1, scale=4)
|
|
@@ -1321,8 +1320,8 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1321 |
use_textual_inversion_gui = gr.CheckboxGroup(choices=get_embed_list(get_model_pipeline(model_name_gui.value)) if active_textual_inversion_gui.value else [], value=None, label="Use Textual Invertion in prompt")
|
| 1322 |
def update_textual_inversion_gui(active_textual_inversion_gui, model_name_gui):
|
| 1323 |
return gr.update(choices=get_embed_list(get_model_pipeline(model_name_gui)) if active_textual_inversion_gui else [])
|
| 1324 |
-
active_textual_inversion_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui],
|
| 1325 |
-
model_name_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui],
|
| 1326 |
|
| 1327 |
with gr.Accordion("ControlNet / Img2img / Inpaint", open=False, visible=True) as menu_i2i:
|
| 1328 |
with gr.Row():
|
|
@@ -1360,7 +1359,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1360 |
change_preprocessor_choices,
|
| 1361 |
[task_gui],
|
| 1362 |
[preprocessor_name_gui],
|
| 1363 |
-
|
| 1364 |
)
|
| 1365 |
|
| 1366 |
with gr.Row():
|
|
@@ -1420,7 +1419,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1420 |
gr.Info(f"{len(sd_gen.model.STYLE_NAMES)} styles loaded")
|
| 1421 |
return gr.update(value=None, choices=sd_gen.model.STYLE_NAMES)
|
| 1422 |
|
| 1423 |
-
style_button.click(load_json_style_file, [style_json_gui], [style_prompt_gui],
|
| 1424 |
|
| 1425 |
with gr.Accordion("Other settings", open=False, visible=True) as menu_other:
|
| 1426 |
with gr.Row():
|
|
@@ -1542,7 +1541,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1542 |
|
| 1543 |
def change_visibility_canvas():
|
| 1544 |
return gr.update(visible=True, interactive=True), gr.update(visible=False)
|
| 1545 |
-
show_canvas.click(change_visibility_canvas, [], [image_base, show_canvas],
|
| 1546 |
|
| 1547 |
invert_mask = gr.Checkbox(value=False, label="Invert mask")
|
| 1548 |
btn = gr.Button("Create mask")
|
|
@@ -1556,7 +1555,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1556 |
|
| 1557 |
def send_img(img_source, img_result):
|
| 1558 |
return img_source, img_result
|
| 1559 |
-
btn_send.click(send_img, [img_source, img_result], [image_control, image_mask_gui],
|
| 1560 |
|
| 1561 |
with gr.Tab("PNG Info"):
|
| 1562 |
with gr.Row():
|
|
@@ -1564,7 +1563,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1564 |
image_metadata = gr.Image(label="Image with metadata", type="pil", sources=["upload"])
|
| 1565 |
|
| 1566 |
with gr.Column():
|
| 1567 |
-
result_metadata = gr.Textbox(label="Metadata", show_label=True,
|
| 1568 |
|
| 1569 |
image_metadata.change(
|
| 1570 |
fn=extract_exif_data,
|
|
@@ -1602,11 +1601,11 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1602 |
[menu_model, menu_from_image, menu_negative, menu_gen, menu_hires, menu_lora, menu_advanced,
|
| 1603 |
menu_example, task_gui, quick_speed_gui],
|
| 1604 |
queue=False,
|
| 1605 |
-
|
| 1606 |
)
|
| 1607 |
-
model_name_gui.change(get_t2i_model_info, [model_name_gui], [model_info_gui], queue=False,
|
| 1608 |
-
translate_prompt_gui.click(translate_to_en, [prompt_gui], [prompt_gui], queue=False,
|
| 1609 |
-
.then(translate_to_en, [neg_prompt_gui], [neg_prompt_gui], queue=False,
|
| 1610 |
|
| 1611 |
gr.on(
|
| 1612 |
triggers=[quick_model_type_gui.change, quick_genre_gui.change, quick_speed_gui.change, quick_aspect_gui.change],
|
|
@@ -1615,7 +1614,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1615 |
outputs=[quality_selector_gui, style_selector_gui, sampler_selector_gui, optimization_gui, insert_prompt_gui],
|
| 1616 |
queue=False,
|
| 1617 |
trigger_mode="once",
|
| 1618 |
-
|
| 1619 |
)
|
| 1620 |
gr.on(
|
| 1621 |
triggers=[quality_selector_gui.change, style_selector_gui.change, insert_prompt_gui.change],
|
|
@@ -1624,7 +1623,7 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1624 |
outputs=[prompt_gui, neg_prompt_gui, quick_model_type_gui],
|
| 1625 |
queue=False,
|
| 1626 |
trigger_mode="once",
|
| 1627 |
-
|
| 1628 |
)
|
| 1629 |
sampler_selector_gui.change(set_sampler_settings, [sampler_selector_gui], [sampler_gui, steps_gui, cfg_gui, clip_skip_gui, img_width_gui, img_height_gui, optimization_gui], queue=False)
|
| 1630 |
optimization_gui.change(set_optimization, [optimization_gui, steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], [steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], queue=False)
|
|
@@ -1647,15 +1646,15 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1647 |
lora7_gui, lora_scale_7_gui, lora7_info_gui, lora7_copy_gui, lora7_desc_gui],
|
| 1648 |
queue=False,
|
| 1649 |
trigger_mode="once",
|
| 1650 |
-
|
| 1651 |
)
|
| 1652 |
-
lora1_copy_gui.click(apply_lora_prompt, [prompt_gui, lora1_info_gui], [prompt_gui], queue=False,
|
| 1653 |
-
lora2_copy_gui.click(apply_lora_prompt, [prompt_gui, lora2_info_gui], [prompt_gui], queue=False,
|
| 1654 |
-
lora3_copy_gui.click(apply_lora_prompt, [prompt_gui, lora3_info_gui], [prompt_gui], queue=False,
|
| 1655 |
-
lora4_copy_gui.click(apply_lora_prompt, [prompt_gui, lora4_info_gui], [prompt_gui], queue=False,
|
| 1656 |
-
lora5_copy_gui.click(apply_lora_prompt, [prompt_gui, lora5_info_gui], [prompt_gui], queue=False,
|
| 1657 |
-
lora6_copy_gui.click(apply_lora_prompt, [prompt_gui, lora6_info_gui], [prompt_gui], queue=False,
|
| 1658 |
-
lora7_copy_gui.click(apply_lora_prompt, [prompt_gui, lora7_info_gui], [prompt_gui], queue=False,
|
| 1659 |
gr.on(
|
| 1660 |
triggers=[search_civitai_button_lora.click, search_civitai_query_lora.submit],
|
| 1661 |
fn=search_civitai_lora,
|
|
@@ -1664,54 +1663,54 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1664 |
outputs=[search_civitai_result_lora, search_civitai_desc_lora, search_civitai_button_lora, search_civitai_query_lora, search_civitai_gallery_lora],
|
| 1665 |
queue=True,
|
| 1666 |
scroll_to_output=True,
|
| 1667 |
-
|
| 1668 |
)
|
| 1669 |
-
search_civitai_result_lora.change(select_civitai_lora, [search_civitai_result_lora], [text_lora, search_civitai_desc_lora], queue=False, scroll_to_output=True,
|
| 1670 |
-
search_civitai_gallery_lora.select(update_civitai_selection, None, [search_civitai_result_lora], queue=False,
|
| 1671 |
-
button_lora.click(get_my_lora, [text_lora, romanize_text], [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui, lora6_gui, lora7_gui, new_lora_status], scroll_to_output=True,
|
| 1672 |
-
upload_button_lora.upload(upload_file_lora, [upload_button_lora], [file_output_lora, upload_button_lora],
|
| 1673 |
-
move_file_lora, [file_output_lora], [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui, lora6_gui, lora7_gui], scroll_to_output=True,
|
| 1674 |
|
| 1675 |
-
use_textual_inversion_gui.change(set_textual_inversion_prompt, [use_textual_inversion_gui, prompt_gui, neg_prompt_gui, prompt_syntax_gui], [prompt_gui, neg_prompt_gui],
|
| 1676 |
|
| 1677 |
generate_from_image_btn_gui.click(
|
| 1678 |
-
lambda: ("", "", ""), None, [series_dbt, character_dbt, prompt_gui], queue=False,
|
| 1679 |
).success(
|
| 1680 |
predict_tags_wd,
|
| 1681 |
[input_image_gui, prompt_gui, image_algorithms, general_threshold_gui, character_threshold_gui],
|
| 1682 |
[series_dbt, character_dbt, prompt_gui, copy_button_dbt],
|
| 1683 |
-
|
| 1684 |
).success(
|
| 1685 |
-
compose_prompt_to_copy, [character_dbt, series_dbt, prompt_gui], [prompt_gui], queue=False,
|
| 1686 |
).success(
|
| 1687 |
-
remove_specific_prompt, [prompt_gui, keep_tags_gui], [prompt_gui], queue=False,
|
| 1688 |
).success(
|
| 1689 |
-
convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False,
|
| 1690 |
).success(
|
| 1691 |
-
insert_recom_prompt, [prompt_gui, neg_prompt_gui, recom_prompt_gui], [prompt_gui, neg_prompt_gui], queue=False,
|
| 1692 |
)
|
| 1693 |
|
| 1694 |
-
prompt_type_button.click(convert_danbooru_to_e621_prompt, [prompt_gui, prompt_type_gui], [prompt_gui], queue=False,
|
| 1695 |
-
random_character_gui.click(select_random_character, [series_dbt, character_dbt], [series_dbt, character_dbt], queue=False,
|
| 1696 |
generate_db_random_button.click(
|
| 1697 |
v2_random_prompt,
|
| 1698 |
[prompt_gui, series_dbt, character_dbt,
|
| 1699 |
rating_dbt, aspect_ratio_dbt, length_dbt, identity_dbt, ban_tags_dbt, model_name_dbt],
|
| 1700 |
[prompt_gui, series_dbt, character_dbt],
|
| 1701 |
-
|
| 1702 |
).success(
|
| 1703 |
-
convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False,
|
| 1704 |
)
|
| 1705 |
|
| 1706 |
-
translate_prompt_button.click(translate_prompt, [prompt_gui], [prompt_gui], queue=False,
|
| 1707 |
-
translate_prompt_button.click(translate_prompt, [character_dbt], [character_dbt], queue=False,
|
| 1708 |
-
translate_prompt_button.click(translate_prompt, [series_dbt], [series_dbt], queue=False,
|
| 1709 |
|
| 1710 |
generate_button.click(
|
| 1711 |
fn=insert_model_recom_prompt,
|
| 1712 |
inputs=[prompt_gui, neg_prompt_gui, model_name_gui, recom_prompt_gui],
|
| 1713 |
outputs=[prompt_gui, neg_prompt_gui],
|
| 1714 |
-
|
| 1715 |
queue=False,
|
| 1716 |
).success(
|
| 1717 |
fn=sd_gen.load_new_model,
|
|
@@ -1854,8 +1853,8 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1854 |
api_name="sd_gen_generate_pipeline",
|
| 1855 |
queue=True,
|
| 1856 |
show_progress="full",
|
| 1857 |
-
).success(save_gallery_images, [result_images, model_name_gui], [result_images, result_images_files], queue=False,
|
| 1858 |
-
.success(save_gallery_history, [result_images, result_images_files, history_gallery, history_files], [history_gallery, history_files], queue=False,
|
| 1859 |
|
| 1860 |
with gr.Tab("Danbooru Tags Transformer with WD Tagger", render=True):
|
| 1861 |
with gr.Column(scale=2):
|
|
@@ -1894,60 +1893,60 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 1894 |
generate_btn = gr.Button(value="GENERATE TAGS", size="lg", variant="primary")
|
| 1895 |
with gr.Row():
|
| 1896 |
with gr.Group():
|
| 1897 |
-
output_text = gr.TextArea(label="Output tags", interactive=False,
|
| 1898 |
with gr.Row():
|
| 1899 |
copy_btn = gr.Button(value="Copy to clipboard", size="sm", interactive=False)
|
| 1900 |
copy_prompt_btn = gr.Button(value="Copy to primary prompt", size="sm", interactive=False)
|
| 1901 |
with gr.Group():
|
| 1902 |
-
output_text_pony = gr.TextArea(label="Output tags (Pony e621 style)", interactive=False,
|
| 1903 |
with gr.Row():
|
| 1904 |
copy_btn_pony = gr.Button(value="Copy to clipboard", size="sm", interactive=False)
|
| 1905 |
copy_prompt_btn_pony = gr.Button(value="Copy to primary prompt", size="sm", interactive=False)
|
| 1906 |
description_ui()
|
| 1907 |
|
| 1908 |
-
translate_input_prompt_button.click(translate_prompt, inputs=[input_general], outputs=[input_general], queue=False,
|
| 1909 |
-
translate_input_prompt_button.click(translate_prompt, inputs=[input_character], outputs=[input_character], queue=False,
|
| 1910 |
-
translate_input_prompt_button.click(translate_prompt, inputs=[input_copyright], outputs=[input_copyright], queue=False,
|
| 1911 |
|
| 1912 |
generate_from_image_btn.click(
|
| 1913 |
-
lambda: ("", "", ""), None, [input_copyright, input_character, input_general], queue=False,
|
| 1914 |
).success(
|
| 1915 |
predict_tags_wd,
|
| 1916 |
[input_image, input_general, image_algorithms, general_threshold, character_threshold],
|
| 1917 |
[input_copyright, input_character, input_general, copy_input_btn],
|
| 1918 |
-
|
| 1919 |
).success(
|
| 1920 |
-
remove_specific_prompt, inputs=[input_general, keep_tags], outputs=[input_general], queue=False,
|
| 1921 |
).success(
|
| 1922 |
-
convert_danbooru_to_e621_prompt, inputs=[input_general, input_tag_type], outputs=[input_general], queue=False,
|
| 1923 |
).success(
|
| 1924 |
-
insert_recom_prompt, inputs=[input_general, dummy_np, recom_prompt], outputs=[input_general, dummy_np], queue=False,
|
| 1925 |
).success(lambda: gr.update(interactive=True), None, [copy_prompt_btn_input], queue=False)
|
| 1926 |
-
copy_input_btn.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy],
|
| 1927 |
-
.success(gradio_copy_text, inputs=[input_tags_to_copy], js=COPY_ACTION_JS,
|
| 1928 |
-
copy_prompt_btn_input.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy],
|
| 1929 |
-
.success(gradio_copy_prompt, inputs=[input_tags_to_copy], outputs=[prompt_gui],
|
| 1930 |
|
| 1931 |
-
pick_random_character.click(select_random_character, [input_copyright, input_character], [input_copyright, input_character],
|
| 1932 |
|
| 1933 |
generate_btn.click(
|
| 1934 |
v2_upsampling_prompt,
|
| 1935 |
[model_name, input_copyright, input_character, input_general,
|
| 1936 |
input_rating, input_aspect_ratio, input_length, input_identity, input_ban_tags],
|
| 1937 |
[output_text],
|
| 1938 |
-
|
| 1939 |
).success(
|
| 1940 |
-
convert_danbooru_to_e621_prompt, inputs=[output_text, tag_type], outputs=[output_text_pony], queue=False,
|
| 1941 |
).success(
|
| 1942 |
-
insert_recom_prompt, inputs=[output_text, dummy_np, recom_animagine], outputs=[output_text, dummy_np], queue=False,
|
| 1943 |
).success(
|
| 1944 |
-
insert_recom_prompt, inputs=[output_text_pony, dummy_np, recom_pony], outputs=[output_text_pony, dummy_np], queue=False,
|
| 1945 |
).success(lambda: (gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)),
|
| 1946 |
-
None, [copy_btn, copy_btn_pony, copy_prompt_btn, copy_prompt_btn_pony], queue=False,
|
| 1947 |
-
copy_btn.click(gradio_copy_text, inputs=[output_text], js=COPY_ACTION_JS,
|
| 1948 |
-
copy_btn_pony.click(gradio_copy_text, inputs=[output_text_pony], js=COPY_ACTION_JS,
|
| 1949 |
-
copy_prompt_btn.click(gradio_copy_prompt, inputs=[output_text], outputs=[prompt_gui],
|
| 1950 |
-
copy_prompt_btn_pony.click(gradio_copy_prompt, inputs=[output_text_pony], outputs=[prompt_gui],
|
| 1951 |
|
| 1952 |
from typing import Any, Dict, List, Optional, Tuple, Generator
|
| 1953 |
# 1) Helper: model loader (keeps existing behavior)
|
|
@@ -2285,8 +2284,8 @@ with gr.Blocks(theme=args.theme, elem_id="main", fill_width=True, fill_height=Fa
|
|
| 2285 |
yield from _generate_image(argv)
|
| 2286 |
|
| 2287 |
# 5) Register two APIs with explicit signatures
|
| 2288 |
-
gr.api(generate_image, api_name="generate_image",
|
| 2289 |
-
gr.api(generate_image_stream, api_name="generate_image_stream",
|
| 2290 |
|
| 2291 |
gr.DuplicateButton(value="Duplicate Space for private use (This demo does not work on CPU. Requires GPU Space)")
|
| 2292 |
|
|
@@ -2300,5 +2299,7 @@ if __name__ == "__main__":
|
|
| 2300 |
ssr_mode=args.ssr,
|
| 2301 |
mcp_server=False,
|
| 2302 |
allowed_paths=[allowed_path],
|
|
|
|
|
|
|
| 2303 |
)
|
| 2304 |
## END MOD
|
|
|
|
| 878 |
.desc [src$='#float'] { float: right; margin: 20px; }
|
| 879 |
"""
|
| 880 |
|
| 881 |
+
with gr.Blocks(elem_id="main", fill_width=True, fill_height=False) as app:
|
| 882 |
gr.Markdown("# 🧩 DiffuseCraft Mod", elem_classes="title")
|
| 883 |
gr.Markdown("This space is a modification of [r3gm's DiffuseCraft](https://huggingface.co/spaces/r3gm/DiffuseCraft).", elem_classes="info")
|
| 884 |
with gr.Column():
|
|
|
|
| 923 |
keep_tags_gui = gr.Radio(label="Remove tags leaving only the following", choices=["body", "dress", "all"], value="all")
|
| 924 |
image_algorithms = gr.CheckboxGroup(["Use WD Tagger"], label="Algorithms", value=["Use WD Tagger"], visible=False)
|
| 925 |
generate_from_image_btn_gui = gr.Button(value="GENERATE TAGS FROM IMAGE")
|
| 926 |
+
prompt_gui = gr.Textbox(lines=6, placeholder="1girl, solo, ...", label="Prompt", buttons=["copy"])
|
| 927 |
with gr.Accordion("Negative prompt, etc.", open=False) as menu_negative:
|
| 928 |
+
neg_prompt_gui = gr.Textbox(lines=3, placeholder="Enter Neg prompt", label="Negative prompt", value="lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, worst quality, low quality, very displeasing, (bad)", buttons=["copy"])
|
| 929 |
translate_prompt_button = gr.Button(value="Translate prompt to English", size="sm", variant="secondary")
|
| 930 |
with gr.Row():
|
| 931 |
insert_prompt_gui = gr.Radio(label="Insert reccomended positive / negative prompt", choices=["None", "Auto", "Animagine", "Pony"], value="Auto", interactive=True)
|
|
|
|
| 955 |
update_task_options,
|
| 956 |
[model_name_gui, task_gui],
|
| 957 |
[task_gui],
|
| 958 |
+
api_visibility="undocumented",
|
| 959 |
)
|
| 960 |
|
| 961 |
load_model_gui = gr.HTML(elem_id="load_model", elem_classes="contain")
|
|
|
|
| 972 |
# height="auto",
|
| 973 |
interactive=False,
|
| 974 |
preview=False,
|
| 975 |
+
buttons=["download", "fullscreen"],
|
|
|
|
| 976 |
selected_index=50,
|
| 977 |
format="png",
|
| 978 |
)
|
|
|
|
| 983 |
|
| 984 |
with gr.Accordion("History", open=False):
|
| 985 |
history_files = gr.Files(interactive=False, visible=False)
|
| 986 |
+
history_gallery = gr.Gallery(label="History", columns=6, object_fit="contain", format="png", interactive=False, buttons=["download", "fullscreen"])
|
| 987 |
history_clear_button = gr.Button(value="Clear History", variant="secondary")
|
| 988 |
+
history_clear_button.click(lambda: ([], []), None, [history_gallery, history_files], queue=False, api_visibility="undocumented")
|
| 989 |
|
| 990 |
with gr.Row(equal_height=False, variant="default"):
|
| 991 |
gpu_duration_gui = gr.Number(minimum=5, maximum=240, value=20, show_label=False, container=False, info="GPU time duration (seconds)")
|
|
|
|
| 1165 |
return gr.Slider(minimum=-val_lora, maximum=val_lora, step=0.01, value=1.0, label=label, visible=visible)
|
| 1166 |
|
| 1167 |
def lora_textbox(label):
|
| 1168 |
+
return gr.Textbox(label=label, info="Example of prompt:", value="None", buttons=["copy"], interactive=False, visible=False)
|
| 1169 |
|
| 1170 |
with gr.Row():
|
| 1171 |
with gr.Column():
|
|
|
|
| 1236 |
search_civitai_button_lora = gr.Button("Search on Civitai")
|
| 1237 |
search_civitai_desc_lora = gr.Markdown(value="", visible=False, elem_classes="desc")
|
| 1238 |
with gr.Accordion("Select from Gallery", open=False):
|
| 1239 |
+
search_civitai_gallery_lora = gr.Gallery([], label="Results", allow_preview=False, columns=5, buttons=["download", "fullscreen"], interactive=False)
|
| 1240 |
search_civitai_result_lora = gr.Dropdown(label="Search Results", choices=[("", "")], value="", allow_custom_value=True, visible=False)
|
| 1241 |
with gr.Row():
|
| 1242 |
text_lora = gr.Textbox(label="LoRA's download URL", placeholder="https://civitai.com/api/download/models/28907", info="It has to be .safetensors files, and you can also download them from Hugging Face.", lines=1, scale=4)
|
|
|
|
| 1320 |
use_textual_inversion_gui = gr.CheckboxGroup(choices=get_embed_list(get_model_pipeline(model_name_gui.value)) if active_textual_inversion_gui.value else [], value=None, label="Use Textual Invertion in prompt")
|
| 1321 |
def update_textual_inversion_gui(active_textual_inversion_gui, model_name_gui):
|
| 1322 |
return gr.update(choices=get_embed_list(get_model_pipeline(model_name_gui)) if active_textual_inversion_gui else [])
|
| 1323 |
+
active_textual_inversion_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui], api_visibility="undocumented")
|
| 1324 |
+
model_name_gui.change(update_textual_inversion_gui, [active_textual_inversion_gui, model_name_gui], [use_textual_inversion_gui], api_visibility="undocumented")
|
| 1325 |
|
| 1326 |
with gr.Accordion("ControlNet / Img2img / Inpaint", open=False, visible=True) as menu_i2i:
|
| 1327 |
with gr.Row():
|
|
|
|
| 1359 |
change_preprocessor_choices,
|
| 1360 |
[task_gui],
|
| 1361 |
[preprocessor_name_gui],
|
| 1362 |
+
api_visibility="undocumented",
|
| 1363 |
)
|
| 1364 |
|
| 1365 |
with gr.Row():
|
|
|
|
| 1419 |
gr.Info(f"{len(sd_gen.model.STYLE_NAMES)} styles loaded")
|
| 1420 |
return gr.update(value=None, choices=sd_gen.model.STYLE_NAMES)
|
| 1421 |
|
| 1422 |
+
style_button.click(load_json_style_file, [style_json_gui], [style_prompt_gui], api_visibility="undocumented")
|
| 1423 |
|
| 1424 |
with gr.Accordion("Other settings", open=False, visible=True) as menu_other:
|
| 1425 |
with gr.Row():
|
|
|
|
| 1541 |
|
| 1542 |
def change_visibility_canvas():
|
| 1543 |
return gr.update(visible=True, interactive=True), gr.update(visible=False)
|
| 1544 |
+
show_canvas.click(change_visibility_canvas, [], [image_base, show_canvas], api_visibility="undocumented")
|
| 1545 |
|
| 1546 |
invert_mask = gr.Checkbox(value=False, label="Invert mask")
|
| 1547 |
btn = gr.Button("Create mask")
|
|
|
|
| 1555 |
|
| 1556 |
def send_img(img_source, img_result):
|
| 1557 |
return img_source, img_result
|
| 1558 |
+
btn_send.click(send_img, [img_source, img_result], [image_control, image_mask_gui], api_visibility="undocumented")
|
| 1559 |
|
| 1560 |
with gr.Tab("PNG Info"):
|
| 1561 |
with gr.Row():
|
|
|
|
| 1563 |
image_metadata = gr.Image(label="Image with metadata", type="pil", sources=["upload"])
|
| 1564 |
|
| 1565 |
with gr.Column():
|
| 1566 |
+
result_metadata = gr.Textbox(label="Metadata", show_label=True, buttons=["copy"], interactive=False, container=True, max_lines=99)
|
| 1567 |
|
| 1568 |
image_metadata.change(
|
| 1569 |
fn=extract_exif_data,
|
|
|
|
| 1601 |
[menu_model, menu_from_image, menu_negative, menu_gen, menu_hires, menu_lora, menu_advanced,
|
| 1602 |
menu_example, task_gui, quick_speed_gui],
|
| 1603 |
queue=False,
|
| 1604 |
+
api_visibility="undocumented",
|
| 1605 |
)
|
| 1606 |
+
model_name_gui.change(get_t2i_model_info, [model_name_gui], [model_info_gui], queue=False, api_visibility="undocumented")
|
| 1607 |
+
translate_prompt_gui.click(translate_to_en, [prompt_gui], [prompt_gui], queue=False, api_visibility="undocumented")\
|
| 1608 |
+
.then(translate_to_en, [neg_prompt_gui], [neg_prompt_gui], queue=False, api_visibility="undocumented")
|
| 1609 |
|
| 1610 |
gr.on(
|
| 1611 |
triggers=[quick_model_type_gui.change, quick_genre_gui.change, quick_speed_gui.change, quick_aspect_gui.change],
|
|
|
|
| 1614 |
outputs=[quality_selector_gui, style_selector_gui, sampler_selector_gui, optimization_gui, insert_prompt_gui],
|
| 1615 |
queue=False,
|
| 1616 |
trigger_mode="once",
|
| 1617 |
+
api_visibility="undocumented",
|
| 1618 |
)
|
| 1619 |
gr.on(
|
| 1620 |
triggers=[quality_selector_gui.change, style_selector_gui.change, insert_prompt_gui.change],
|
|
|
|
| 1623 |
outputs=[prompt_gui, neg_prompt_gui, quick_model_type_gui],
|
| 1624 |
queue=False,
|
| 1625 |
trigger_mode="once",
|
| 1626 |
+
api_visibility="undocumented",
|
| 1627 |
)
|
| 1628 |
sampler_selector_gui.change(set_sampler_settings, [sampler_selector_gui], [sampler_gui, steps_gui, cfg_gui, clip_skip_gui, img_width_gui, img_height_gui, optimization_gui], queue=False)
|
| 1629 |
optimization_gui.change(set_optimization, [optimization_gui, steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], [steps_gui, cfg_gui, sampler_gui, clip_skip_gui, lora5_gui, lora_scale_5_gui], queue=False)
|
|
|
|
| 1646 |
lora7_gui, lora_scale_7_gui, lora7_info_gui, lora7_copy_gui, lora7_desc_gui],
|
| 1647 |
queue=False,
|
| 1648 |
trigger_mode="once",
|
| 1649 |
+
api_visibility="undocumented",
|
| 1650 |
)
|
| 1651 |
+
lora1_copy_gui.click(apply_lora_prompt, [prompt_gui, lora1_info_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1652 |
+
lora2_copy_gui.click(apply_lora_prompt, [prompt_gui, lora2_info_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1653 |
+
lora3_copy_gui.click(apply_lora_prompt, [prompt_gui, lora3_info_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1654 |
+
lora4_copy_gui.click(apply_lora_prompt, [prompt_gui, lora4_info_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1655 |
+
lora5_copy_gui.click(apply_lora_prompt, [prompt_gui, lora5_info_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1656 |
+
lora6_copy_gui.click(apply_lora_prompt, [prompt_gui, lora6_info_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1657 |
+
lora7_copy_gui.click(apply_lora_prompt, [prompt_gui, lora7_info_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1658 |
gr.on(
|
| 1659 |
triggers=[search_civitai_button_lora.click, search_civitai_query_lora.submit],
|
| 1660 |
fn=search_civitai_lora,
|
|
|
|
| 1663 |
outputs=[search_civitai_result_lora, search_civitai_desc_lora, search_civitai_button_lora, search_civitai_query_lora, search_civitai_gallery_lora],
|
| 1664 |
queue=True,
|
| 1665 |
scroll_to_output=True,
|
| 1666 |
+
api_visibility="undocumented",
|
| 1667 |
)
|
| 1668 |
+
search_civitai_result_lora.change(select_civitai_lora, [search_civitai_result_lora], [text_lora, search_civitai_desc_lora], queue=False, scroll_to_output=True, api_visibility="undocumented")
|
| 1669 |
+
search_civitai_gallery_lora.select(update_civitai_selection, None, [search_civitai_result_lora], queue=False, api_visibility="undocumented")
|
| 1670 |
+
button_lora.click(get_my_lora, [text_lora, romanize_text], [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui, lora6_gui, lora7_gui, new_lora_status], scroll_to_output=True, api_visibility="undocumented")
|
| 1671 |
+
upload_button_lora.upload(upload_file_lora, [upload_button_lora], [file_output_lora, upload_button_lora], api_visibility="undocumented").success(
|
| 1672 |
+
move_file_lora, [file_output_lora], [lora1_gui, lora2_gui, lora3_gui, lora4_gui, lora5_gui, lora6_gui, lora7_gui], scroll_to_output=True, api_visibility="undocumented")
|
| 1673 |
|
| 1674 |
+
use_textual_inversion_gui.change(set_textual_inversion_prompt, [use_textual_inversion_gui, prompt_gui, neg_prompt_gui, prompt_syntax_gui], [prompt_gui, neg_prompt_gui], api_visibility="undocumented")
|
| 1675 |
|
| 1676 |
generate_from_image_btn_gui.click(
|
| 1677 |
+
lambda: ("", "", ""), None, [series_dbt, character_dbt, prompt_gui], queue=False, api_visibility="undocumented",
|
| 1678 |
).success(
|
| 1679 |
predict_tags_wd,
|
| 1680 |
[input_image_gui, prompt_gui, image_algorithms, general_threshold_gui, character_threshold_gui],
|
| 1681 |
[series_dbt, character_dbt, prompt_gui, copy_button_dbt],
|
| 1682 |
+
api_visibility="undocumented",
|
| 1683 |
).success(
|
| 1684 |
+
compose_prompt_to_copy, [character_dbt, series_dbt, prompt_gui], [prompt_gui], queue=False, api_visibility="undocumented",
|
| 1685 |
).success(
|
| 1686 |
+
remove_specific_prompt, [prompt_gui, keep_tags_gui], [prompt_gui], queue=False, api_visibility="undocumented",
|
| 1687 |
).success(
|
| 1688 |
+
convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False, api_visibility="undocumented",
|
| 1689 |
).success(
|
| 1690 |
+
insert_recom_prompt, [prompt_gui, neg_prompt_gui, recom_prompt_gui], [prompt_gui, neg_prompt_gui], queue=False, api_visibility="undocumented",
|
| 1691 |
)
|
| 1692 |
|
| 1693 |
+
prompt_type_button.click(convert_danbooru_to_e621_prompt, [prompt_gui, prompt_type_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1694 |
+
random_character_gui.click(select_random_character, [series_dbt, character_dbt], [series_dbt, character_dbt], queue=False, api_visibility="undocumented")
|
| 1695 |
generate_db_random_button.click(
|
| 1696 |
v2_random_prompt,
|
| 1697 |
[prompt_gui, series_dbt, character_dbt,
|
| 1698 |
rating_dbt, aspect_ratio_dbt, length_dbt, identity_dbt, ban_tags_dbt, model_name_dbt],
|
| 1699 |
[prompt_gui, series_dbt, character_dbt],
|
| 1700 |
+
api_visibility="undocumented",
|
| 1701 |
).success(
|
| 1702 |
+
convert_danbooru_to_e621_prompt, [prompt_gui, tag_type_gui], [prompt_gui], queue=False, api_visibility="undocumented",
|
| 1703 |
)
|
| 1704 |
|
| 1705 |
+
translate_prompt_button.click(translate_prompt, [prompt_gui], [prompt_gui], queue=False, api_visibility="undocumented")
|
| 1706 |
+
translate_prompt_button.click(translate_prompt, [character_dbt], [character_dbt], queue=False, api_visibility="undocumented")
|
| 1707 |
+
translate_prompt_button.click(translate_prompt, [series_dbt], [series_dbt], queue=False, api_visibility="undocumented")
|
| 1708 |
|
| 1709 |
generate_button.click(
|
| 1710 |
fn=insert_model_recom_prompt,
|
| 1711 |
inputs=[prompt_gui, neg_prompt_gui, model_name_gui, recom_prompt_gui],
|
| 1712 |
outputs=[prompt_gui, neg_prompt_gui],
|
| 1713 |
+
api_visibility="private",
|
| 1714 |
queue=False,
|
| 1715 |
).success(
|
| 1716 |
fn=sd_gen.load_new_model,
|
|
|
|
| 1853 |
api_name="sd_gen_generate_pipeline",
|
| 1854 |
queue=True,
|
| 1855 |
show_progress="full",
|
| 1856 |
+
).success(save_gallery_images, [result_images, model_name_gui], [result_images, result_images_files], queue=False, api_visibility="undocumented")\
|
| 1857 |
+
.success(save_gallery_history, [result_images, result_images_files, history_gallery, history_files], [history_gallery, history_files], queue=False, api_visibility="undocumented")
|
| 1858 |
|
| 1859 |
with gr.Tab("Danbooru Tags Transformer with WD Tagger", render=True):
|
| 1860 |
with gr.Column(scale=2):
|
|
|
|
| 1893 |
generate_btn = gr.Button(value="GENERATE TAGS", size="lg", variant="primary")
|
| 1894 |
with gr.Row():
|
| 1895 |
with gr.Group():
|
| 1896 |
+
output_text = gr.TextArea(label="Output tags", interactive=False, buttons=["copy"])
|
| 1897 |
with gr.Row():
|
| 1898 |
copy_btn = gr.Button(value="Copy to clipboard", size="sm", interactive=False)
|
| 1899 |
copy_prompt_btn = gr.Button(value="Copy to primary prompt", size="sm", interactive=False)
|
| 1900 |
with gr.Group():
|
| 1901 |
+
output_text_pony = gr.TextArea(label="Output tags (Pony e621 style)", interactive=False, buttons=["copy"])
|
| 1902 |
with gr.Row():
|
| 1903 |
copy_btn_pony = gr.Button(value="Copy to clipboard", size="sm", interactive=False)
|
| 1904 |
copy_prompt_btn_pony = gr.Button(value="Copy to primary prompt", size="sm", interactive=False)
|
| 1905 |
description_ui()
|
| 1906 |
|
| 1907 |
+
translate_input_prompt_button.click(translate_prompt, inputs=[input_general], outputs=[input_general], queue=False, api_visibility="undocumented")
|
| 1908 |
+
translate_input_prompt_button.click(translate_prompt, inputs=[input_character], outputs=[input_character], queue=False, api_visibility="undocumented")
|
| 1909 |
+
translate_input_prompt_button.click(translate_prompt, inputs=[input_copyright], outputs=[input_copyright], queue=False, api_visibility="undocumented")
|
| 1910 |
|
| 1911 |
generate_from_image_btn.click(
|
| 1912 |
+
lambda: ("", "", ""), None, [input_copyright, input_character, input_general], queue=False, api_visibility="undocumented",
|
| 1913 |
).success(
|
| 1914 |
predict_tags_wd,
|
| 1915 |
[input_image, input_general, image_algorithms, general_threshold, character_threshold],
|
| 1916 |
[input_copyright, input_character, input_general, copy_input_btn],
|
| 1917 |
+
api_visibility="undocumented",
|
| 1918 |
).success(
|
| 1919 |
+
remove_specific_prompt, inputs=[input_general, keep_tags], outputs=[input_general], queue=False, api_visibility="undocumented",
|
| 1920 |
).success(
|
| 1921 |
+
convert_danbooru_to_e621_prompt, inputs=[input_general, input_tag_type], outputs=[input_general], queue=False, api_visibility="undocumented",
|
| 1922 |
).success(
|
| 1923 |
+
insert_recom_prompt, inputs=[input_general, dummy_np, recom_prompt], outputs=[input_general, dummy_np], queue=False, api_visibility="undocumented",
|
| 1924 |
).success(lambda: gr.update(interactive=True), None, [copy_prompt_btn_input], queue=False)
|
| 1925 |
+
copy_input_btn.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy], api_visibility="undocumented")\
|
| 1926 |
+
.success(gradio_copy_text, inputs=[input_tags_to_copy], js=COPY_ACTION_JS, api_visibility="undocumented")
|
| 1927 |
+
copy_prompt_btn_input.click(compose_prompt_to_copy, inputs=[input_character, input_copyright, input_general], outputs=[input_tags_to_copy], api_visibility="undocumented")\
|
| 1928 |
+
.success(gradio_copy_prompt, inputs=[input_tags_to_copy], outputs=[prompt_gui], api_visibility="undocumented")
|
| 1929 |
|
| 1930 |
+
pick_random_character.click(select_random_character, [input_copyright, input_character], [input_copyright, input_character], api_visibility="undocumented")
|
| 1931 |
|
| 1932 |
generate_btn.click(
|
| 1933 |
v2_upsampling_prompt,
|
| 1934 |
[model_name, input_copyright, input_character, input_general,
|
| 1935 |
input_rating, input_aspect_ratio, input_length, input_identity, input_ban_tags],
|
| 1936 |
[output_text],
|
| 1937 |
+
api_visibility="undocumented",
|
| 1938 |
).success(
|
| 1939 |
+
convert_danbooru_to_e621_prompt, inputs=[output_text, tag_type], outputs=[output_text_pony], queue=False, api_visibility="undocumented",
|
| 1940 |
).success(
|
| 1941 |
+
insert_recom_prompt, inputs=[output_text, dummy_np, recom_animagine], outputs=[output_text, dummy_np], queue=False, api_visibility="undocumented",
|
| 1942 |
).success(
|
| 1943 |
+
insert_recom_prompt, inputs=[output_text_pony, dummy_np, recom_pony], outputs=[output_text_pony, dummy_np], queue=False, api_visibility="undocumented",
|
| 1944 |
).success(lambda: (gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)),
|
| 1945 |
+
None, [copy_btn, copy_btn_pony, copy_prompt_btn, copy_prompt_btn_pony], queue=False, api_visibility="undocumented")
|
| 1946 |
+
copy_btn.click(gradio_copy_text, inputs=[output_text], js=COPY_ACTION_JS, api_visibility="undocumented")
|
| 1947 |
+
copy_btn_pony.click(gradio_copy_text, inputs=[output_text_pony], js=COPY_ACTION_JS, api_visibility="undocumented")
|
| 1948 |
+
copy_prompt_btn.click(gradio_copy_prompt, inputs=[output_text], outputs=[prompt_gui], api_visibility="undocumented")
|
| 1949 |
+
copy_prompt_btn_pony.click(gradio_copy_prompt, inputs=[output_text_pony], outputs=[prompt_gui], api_visibility="undocumented")
|
| 1950 |
|
| 1951 |
from typing import Any, Dict, List, Optional, Tuple, Generator
|
| 1952 |
# 1) Helper: model loader (keeps existing behavior)
|
|
|
|
| 2284 |
yield from _generate_image(argv)
|
| 2285 |
|
| 2286 |
# 5) Register two APIs with explicit signatures
|
| 2287 |
+
gr.api(generate_image, api_name="generate_image", api_visibility="public", queue=True, concurrency_id="gpu")
|
| 2288 |
+
gr.api(generate_image_stream, api_name="generate_image_stream", api_visibility="public", queue=True, concurrency_id="gpu")
|
| 2289 |
|
| 2290 |
gr.DuplicateButton(value="Duplicate Space for private use (This demo does not work on CPU. Requires GPU Space)")
|
| 2291 |
|
|
|
|
| 2299 |
ssr_mode=args.ssr,
|
| 2300 |
mcp_server=False,
|
| 2301 |
allowed_paths=[allowed_path],
|
| 2302 |
+
theme=args.theme,
|
| 2303 |
+
css=CSS,
|
| 2304 |
)
|
| 2305 |
## END MOD
|
env.py
CHANGED
|
@@ -50,6 +50,8 @@ LOAD_DIFFUSERS_FORMAT_MODEL = [
|
|
| 50 |
'Raelina/Raehoshi-illust-XL-8.1',
|
| 51 |
'Raelina/Raehoshi-illust-XL-9',
|
| 52 |
'Raelina/Raehoshi-illust-XL-9.1',
|
|
|
|
|
|
|
| 53 |
'Raelina/Raehoshi-illust-vpred',
|
| 54 |
'camenduru/FLUX.1-dev-diffusers',
|
| 55 |
'black-forest-labs/FLUX.1-schnell',
|
|
|
|
| 50 |
'Raelina/Raehoshi-illust-XL-8.1',
|
| 51 |
'Raelina/Raehoshi-illust-XL-9',
|
| 52 |
'Raelina/Raehoshi-illust-XL-9.1',
|
| 53 |
+
'Raelina/Raehoshi-illust-XL-10',
|
| 54 |
+
'Raelina/Raehoshi-illust-XL-11',
|
| 55 |
'Raelina/Raehoshi-illust-vpred',
|
| 56 |
'camenduru/FLUX.1-dev-diffusers',
|
| 57 |
'black-forest-labs/FLUX.1-schnell',
|
modutils.py
CHANGED
|
@@ -218,6 +218,8 @@ CIVITAI_RESOLVE_NEGATIVE_CACHE: dict[str, str] = {}
|
|
| 218 |
CIVITAI_VERSION_JSON_CACHE: dict[str, dict] = {}
|
| 219 |
CIVITAI_VERSION_NEGATIVE_CACHE: dict[str, str] = {}
|
| 220 |
CIVITAI_WGET_FRESH_RETRY_LIMIT = 1
|
|
|
|
|
|
|
| 221 |
CIVITAI_API_PROBE_TIMEOUT = (3.0, 8.0)
|
| 222 |
CIVITAI_API_RETRYABLE_STATUSES = frozenset([404, 405, 429, 500, 502, 503, 504])
|
| 223 |
CIVITAI_ACTIVE_API_ORIGIN = ""
|
|
@@ -492,6 +494,20 @@ def extract_civitai_model_version_id(url: str):
|
|
| 492 |
return ""
|
| 493 |
return ""
|
| 494 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 495 |
def get_civitai_query_filters(url: str):
|
| 496 |
try:
|
| 497 |
parts = get_civitai_url_parts(url)
|
|
@@ -706,6 +722,16 @@ def pick_civitai_file_from_version_json(json_data, source_url: str = ""):
|
|
| 706 |
files = json_data.get("files", []) if isinstance(json_data, dict) else []
|
| 707 |
if not isinstance(files, list) or not files:
|
| 708 |
return {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 709 |
version_id = str((json_data or {}).get("id") or "")
|
| 710 |
filters = get_civitai_query_filters(source_url)
|
| 711 |
candidates = []
|
|
@@ -786,41 +812,61 @@ def request_json_data(url, api_key: str = ""):
|
|
| 786 |
return None
|
| 787 |
|
| 788 |
endpoint_path = f"/model-versions/{model_version_id}"
|
| 789 |
-
|
| 790 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 791 |
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
headers=headers,
|
| 796 |
-
timeout=CIVITAI_METADATA_TIMEOUT,
|
| 797 |
-
api_key=effective_api_key,
|
| 798 |
-
session=session,
|
| 799 |
-
stream=True,
|
| 800 |
-
allow_not_found=True,
|
| 801 |
-
)
|
| 802 |
-
if result.status_code == 404:
|
| 803 |
-
print(f"Civitai metadata lookup status=404: {endpoint_url}")
|
| 804 |
-
cache_put(CIVITAI_VERSION_NEGATIVE_CACHE, model_version_id, "status=404")
|
| 805 |
-
return None
|
| 806 |
-
if not json_data:
|
| 807 |
-
print(f"Civitai metadata lookup returned empty JSON: {endpoint_url}")
|
| 808 |
-
cache_put(CIVITAI_VERSION_NEGATIVE_CACHE, model_version_id, "empty_json")
|
| 809 |
-
return None
|
| 810 |
-
cache_put(CIVITAI_VERSION_JSON_CACHE, model_version_id, copy.deepcopy(json_data))
|
| 811 |
-
if normalized_url and normalized_url != raw_url:
|
| 812 |
-
cache_put(CIVITAI_RESOLVE_CACHE, raw_url, normalized_url)
|
| 813 |
-
return json_data
|
| 814 |
-
except Exception as e:
|
| 815 |
-
print(f"Civitai metadata lookup failed: {endpoint_url} {type(e).__name__}: {sanitize_sensitive_log_text(e)}")
|
| 816 |
-
return None
|
| 817 |
|
| 818 |
class ModelInformation:
|
| 819 |
def __init__(self, json_data, source_url: str = ""):
|
| 820 |
selected_file = pick_civitai_file_from_version_json(json_data, source_url=source_url)
|
|
|
|
| 821 |
self.model_version_id = json_data.get("id", "")
|
| 822 |
self.model_id = json_data.get("modelId", "")
|
| 823 |
-
self.download_url = selected_file.get("downloadUrl", "") or json_data.get("downloadUrl", "")
|
| 824 |
self.model_url = f"{get_civitai_canonical_web_origin()}/models/{self.model_id}?modelVersionId={self.model_version_id}"
|
| 825 |
self.filename_url = selected_file.get("name", "") or ""
|
| 826 |
self.description = json_data.get("description", "")
|
|
@@ -1005,7 +1051,41 @@ def guess_downloaded_file_path(directory, before_files, expected_filename=""):
|
|
| 1005 |
|
| 1006 |
return None
|
| 1007 |
|
| 1008 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1009 |
expected_name = str(expected_filename or "").strip()
|
| 1010 |
if not expected_name:
|
| 1011 |
return ""
|
|
@@ -1021,7 +1101,7 @@ def get_existing_completed_download_path(directory, expected_filename=""):
|
|
| 1021 |
candidate_paths.append(legacy_nested_path)
|
| 1022 |
|
| 1023 |
for candidate_path in candidate_paths:
|
| 1024 |
-
if
|
| 1025 |
return str(candidate_path)
|
| 1026 |
|
| 1027 |
return ""
|
|
@@ -1064,6 +1144,7 @@ def download_things(directory, url, hf_token="", civitai_api_key="", romanize=Fa
|
|
| 1064 |
if normalized_url != url:
|
| 1065 |
print(f"Civitai download URL normalized: {sanitize_url_for_log(url)} -> {sanitize_url_for_log(normalized_url)}")
|
| 1066 |
model_profile = retrieve_model_info(normalized_url, api_key=civitai_api_key)
|
|
|
|
| 1067 |
if model_profile and model_profile.download_url:
|
| 1068 |
url = model_profile.download_url
|
| 1069 |
filename = model_profile.filename_url or ""
|
|
@@ -1087,7 +1168,7 @@ def download_things(directory, url, hf_token="", civitai_api_key="", romanize=Fa
|
|
| 1087 |
print(f"Filename: {filename}")
|
| 1088 |
print(f"[civitai] resolved signed host={signed_host or '-'} url={sanitize_url_for_log(url)}")
|
| 1089 |
|
| 1090 |
-
existing_completed_path = get_existing_completed_download_path(directory, expected_filename=filename)
|
| 1091 |
if existing_completed_path:
|
| 1092 |
print(f"[civitai] using existing completed file path={existing_completed_path}")
|
| 1093 |
downloaded_file_path = existing_completed_path
|
|
@@ -1139,10 +1220,14 @@ def download_things(directory, url, hf_token="", civitai_api_key="", romanize=Fa
|
|
| 1139 |
if download_status != 0:
|
| 1140 |
log_download_error("civitai", "command_failed", url=url, status=download_status)
|
| 1141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1142 |
if not downloaded_file_path:
|
| 1143 |
-
|
| 1144 |
-
if not downloaded_file_path:
|
| 1145 |
-
existing_completed_path = get_existing_completed_download_path(directory, expected_filename=filename)
|
| 1146 |
if existing_completed_path:
|
| 1147 |
print(f"[civitai] using existing completed file path={existing_completed_path}")
|
| 1148 |
downloaded_file_path = existing_completed_path
|
|
@@ -1773,7 +1858,6 @@ def get_lora_info(lora_path: str):
|
|
| 1773 |
label = ""
|
| 1774 |
md = "None"
|
| 1775 |
if not lora_path or lora_path == "None":
|
| 1776 |
-
print("LoRA file not found.")
|
| 1777 |
return is_valid, label, tag, md
|
| 1778 |
path = Path(lora_path)
|
| 1779 |
new_path = Path(f'{path.parent.name}/{escape_lora_basename(path.stem)}{path.suffix}')
|
|
|
|
| 218 |
CIVITAI_VERSION_JSON_CACHE: dict[str, dict] = {}
|
| 219 |
CIVITAI_VERSION_NEGATIVE_CACHE: dict[str, str] = {}
|
| 220 |
CIVITAI_WGET_FRESH_RETRY_LIMIT = 1
|
| 221 |
+
CIVITAI_METADATA_RECONNECT_ATTEMPTS = 3
|
| 222 |
+
CIVITAI_METADATA_RECONNECT_BACKOFF = 0.8
|
| 223 |
CIVITAI_API_PROBE_TIMEOUT = (3.0, 8.0)
|
| 224 |
CIVITAI_API_RETRYABLE_STATUSES = frozenset([404, 405, 429, 500, 502, 503, 504])
|
| 225 |
CIVITAI_ACTIVE_API_ORIGIN = ""
|
|
|
|
| 494 |
return ""
|
| 495 |
return ""
|
| 496 |
|
| 497 |
+
def extract_civitai_file_id(url: str):
|
| 498 |
+
try:
|
| 499 |
+
parts = get_civitai_url_parts(url)
|
| 500 |
+
qs = urllib.parse.parse_qs(parts.query)
|
| 501 |
+
for key, values in qs.items():
|
| 502 |
+
if str(key).casefold() != "fileid" or not values:
|
| 503 |
+
continue
|
| 504 |
+
value = str(values[0] or "").strip()
|
| 505 |
+
if value.isdigit():
|
| 506 |
+
return value
|
| 507 |
+
except Exception:
|
| 508 |
+
return ""
|
| 509 |
+
return ""
|
| 510 |
+
|
| 511 |
def get_civitai_query_filters(url: str):
|
| 512 |
try:
|
| 513 |
parts = get_civitai_url_parts(url)
|
|
|
|
| 722 |
files = json_data.get("files", []) if isinstance(json_data, dict) else []
|
| 723 |
if not isinstance(files, list) or not files:
|
| 724 |
return {}
|
| 725 |
+
explicit_file_id = extract_civitai_file_id(source_url)
|
| 726 |
+
if explicit_file_id:
|
| 727 |
+
for file_info in files:
|
| 728 |
+
if not isinstance(file_info, dict):
|
| 729 |
+
continue
|
| 730 |
+
candidate_id = str(file_info.get("id") or file_info.get("fileId") or "").strip()
|
| 731 |
+
if candidate_id == explicit_file_id:
|
| 732 |
+
return dict(file_info)
|
| 733 |
+
print(f"[civitai] explicit fileId={explicit_file_id} not present in model version metadata")
|
| 734 |
+
return {}
|
| 735 |
version_id = str((json_data or {}).get("id") or "")
|
| 736 |
filters = get_civitai_query_filters(source_url)
|
| 737 |
candidates = []
|
|
|
|
| 812 |
return None
|
| 813 |
|
| 814 |
endpoint_path = f"/model-versions/{model_version_id}"
|
| 815 |
+
last_error = None
|
| 816 |
+
for attempt in range(1, CIVITAI_METADATA_RECONNECT_ATTEMPTS + 1):
|
| 817 |
+
session = create_retry_session()
|
| 818 |
+
headers = get_civitai_headers(effective_api_key)
|
| 819 |
+
if attempt > 1:
|
| 820 |
+
headers["Connection"] = "close"
|
| 821 |
+
endpoint_url = ""
|
| 822 |
+
try:
|
| 823 |
+
json_data, endpoint_url, result = request_civitai_api_json(
|
| 824 |
+
endpoint_path,
|
| 825 |
+
headers=headers,
|
| 826 |
+
timeout=CIVITAI_METADATA_TIMEOUT,
|
| 827 |
+
api_key=effective_api_key,
|
| 828 |
+
session=session,
|
| 829 |
+
stream=True,
|
| 830 |
+
allow_not_found=True,
|
| 831 |
+
)
|
| 832 |
+
if result.status_code == 404:
|
| 833 |
+
print(f"Civitai metadata lookup status=404: {endpoint_url}")
|
| 834 |
+
cache_put(CIVITAI_VERSION_NEGATIVE_CACHE, model_version_id, "status=404")
|
| 835 |
+
return None
|
| 836 |
+
if not json_data:
|
| 837 |
+
print(f"Civitai metadata lookup returned empty JSON: {endpoint_url}")
|
| 838 |
+
cache_put(CIVITAI_VERSION_NEGATIVE_CACHE, model_version_id, "empty_json")
|
| 839 |
+
return None
|
| 840 |
+
cache_put(CIVITAI_VERSION_JSON_CACHE, model_version_id, copy.deepcopy(json_data))
|
| 841 |
+
if normalized_url and normalized_url != raw_url:
|
| 842 |
+
cache_put(CIVITAI_RESOLVE_CACHE, raw_url, normalized_url)
|
| 843 |
+
return json_data
|
| 844 |
+
except Exception as e:
|
| 845 |
+
last_error = e
|
| 846 |
+
print(
|
| 847 |
+
f"[civitai] metadata reconnect attempt={attempt}/{CIVITAI_METADATA_RECONNECT_ATTEMPTS} "
|
| 848 |
+
f"url={sanitize_url_for_log(endpoint_url or endpoint_path)} "
|
| 849 |
+
f"error={type(e).__name__}: {sanitize_sensitive_log_text(e)}"
|
| 850 |
+
)
|
| 851 |
+
finally:
|
| 852 |
+
try:
|
| 853 |
+
session.close()
|
| 854 |
+
except Exception:
|
| 855 |
+
pass
|
| 856 |
+
if attempt < CIVITAI_METADATA_RECONNECT_ATTEMPTS:
|
| 857 |
+
time.sleep(min(2.5, CIVITAI_METADATA_RECONNECT_BACKOFF * attempt))
|
| 858 |
|
| 859 |
+
if last_error is not None:
|
| 860 |
+
print(f"Civitai metadata lookup failed after reconnects: {type(last_error).__name__}: {sanitize_sensitive_log_text(last_error)}")
|
| 861 |
+
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 862 |
|
| 863 |
class ModelInformation:
|
| 864 |
def __init__(self, json_data, source_url: str = ""):
|
| 865 |
selected_file = pick_civitai_file_from_version_json(json_data, source_url=source_url)
|
| 866 |
+
explicit_file_id = extract_civitai_file_id(source_url)
|
| 867 |
self.model_version_id = json_data.get("id", "")
|
| 868 |
self.model_id = json_data.get("modelId", "")
|
| 869 |
+
self.download_url = selected_file.get("downloadUrl", "") or ("" if explicit_file_id else json_data.get("downloadUrl", ""))
|
| 870 |
self.model_url = f"{get_civitai_canonical_web_origin()}/models/{self.model_id}?modelVersionId={self.model_version_id}"
|
| 871 |
self.filename_url = selected_file.get("name", "") or ""
|
| 872 |
self.description = json_data.get("description", "")
|
|
|
|
| 1051 |
|
| 1052 |
return None
|
| 1053 |
|
| 1054 |
+
def get_civitai_expected_size_bytes(file_info):
|
| 1055 |
+
if not isinstance(file_info, dict):
|
| 1056 |
+
return 0
|
| 1057 |
+
raw_size_kb = file_info.get("sizeKB")
|
| 1058 |
+
if raw_size_kb is None:
|
| 1059 |
+
raw_size_kb = file_info.get("sizeKb")
|
| 1060 |
+
try:
|
| 1061 |
+
size_kb = float(raw_size_kb)
|
| 1062 |
+
except (TypeError, ValueError):
|
| 1063 |
+
return 0
|
| 1064 |
+
if size_kb <= 0:
|
| 1065 |
+
return 0
|
| 1066 |
+
return max(1, int(round(size_kb * 1024.0)))
|
| 1067 |
+
|
| 1068 |
+
def is_civitai_file_complete(path, file_info=None, *, log_mismatch=False):
|
| 1069 |
+
candidate = Path(path)
|
| 1070 |
+
if not candidate.exists() or not candidate.is_file():
|
| 1071 |
+
return False
|
| 1072 |
+
expected_size = get_civitai_expected_size_bytes(file_info)
|
| 1073 |
+
if expected_size <= 0:
|
| 1074 |
+
return True
|
| 1075 |
+
try:
|
| 1076 |
+
actual_size = int(candidate.stat().st_size)
|
| 1077 |
+
except OSError:
|
| 1078 |
+
return False
|
| 1079 |
+
tolerance = 4096
|
| 1080 |
+
complete = abs(actual_size - expected_size) <= tolerance
|
| 1081 |
+
if not complete and log_mismatch:
|
| 1082 |
+
print(
|
| 1083 |
+
f"[civitai] existing file size mismatch; treating as incomplete "
|
| 1084 |
+
f"path={candidate} actual={actual_size} expected={expected_size}"
|
| 1085 |
+
)
|
| 1086 |
+
return complete
|
| 1087 |
+
|
| 1088 |
+
def get_existing_completed_download_path(directory, expected_filename="", file_info=None):
|
| 1089 |
expected_name = str(expected_filename or "").strip()
|
| 1090 |
if not expected_name:
|
| 1091 |
return ""
|
|
|
|
| 1101 |
candidate_paths.append(legacy_nested_path)
|
| 1102 |
|
| 1103 |
for candidate_path in candidate_paths:
|
| 1104 |
+
if is_civitai_file_complete(candidate_path, file_info=file_info, log_mismatch=True):
|
| 1105 |
return str(candidate_path)
|
| 1106 |
|
| 1107 |
return ""
|
|
|
|
| 1144 |
if normalized_url != url:
|
| 1145 |
print(f"Civitai download URL normalized: {sanitize_url_for_log(url)} -> {sanitize_url_for_log(normalized_url)}")
|
| 1146 |
model_profile = retrieve_model_info(normalized_url, api_key=civitai_api_key)
|
| 1147 |
+
selected_file = model_profile.selected_file if model_profile else {}
|
| 1148 |
if model_profile and model_profile.download_url:
|
| 1149 |
url = model_profile.download_url
|
| 1150 |
filename = model_profile.filename_url or ""
|
|
|
|
| 1168 |
print(f"Filename: {filename}")
|
| 1169 |
print(f"[civitai] resolved signed host={signed_host or '-'} url={sanitize_url_for_log(url)}")
|
| 1170 |
|
| 1171 |
+
existing_completed_path = get_existing_completed_download_path(directory, expected_filename=filename, file_info=selected_file)
|
| 1172 |
if existing_completed_path:
|
| 1173 |
print(f"[civitai] using existing completed file path={existing_completed_path}")
|
| 1174 |
downloaded_file_path = existing_completed_path
|
|
|
|
| 1220 |
if download_status != 0:
|
| 1221 |
log_download_error("civitai", "command_failed", url=url, status=download_status)
|
| 1222 |
|
| 1223 |
+
if not downloaded_file_path and download_status == 0:
|
| 1224 |
+
candidate_path = guess_downloaded_file_path(directory, before_files, expected_filename=filename)
|
| 1225 |
+
if candidate_path and is_civitai_file_complete(candidate_path, file_info=selected_file, log_mismatch=True):
|
| 1226 |
+
downloaded_file_path = candidate_path
|
| 1227 |
+
elif candidate_path:
|
| 1228 |
+
log_download_error("civitai", "size_mismatch", url=url, detail=f"path={candidate_path}")
|
| 1229 |
if not downloaded_file_path:
|
| 1230 |
+
existing_completed_path = get_existing_completed_download_path(directory, expected_filename=filename, file_info=selected_file)
|
|
|
|
|
|
|
| 1231 |
if existing_completed_path:
|
| 1232 |
print(f"[civitai] using existing completed file path={existing_completed_path}")
|
| 1233 |
downloaded_file_path = existing_completed_path
|
|
|
|
| 1858 |
label = ""
|
| 1859 |
md = "None"
|
| 1860 |
if not lora_path or lora_path == "None":
|
|
|
|
| 1861 |
return is_valid, label, tag, md
|
| 1862 |
path = Path(lora_path)
|
| 1863 |
new_path = Path(f'{path.parent.name}/{escape_lora_basename(path.stem)}{path.suffix}')
|
requirements.txt
CHANGED
|
@@ -1,22 +1,23 @@
|
|
| 1 |
-
stablepy==0.6.5
|
| 2 |
-
diffusers
|
| 3 |
-
transformers
|
| 4 |
-
accelerate
|
| 5 |
-
huggingface_hub
|
| 6 |
-
spaces
|
| 7 |
-
torch==2.8.0
|
| 8 |
-
numpy<2
|
| 9 |
-
gdown
|
| 10 |
-
opencv-python
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
| 1 |
+
stablepy==0.6.5
|
| 2 |
+
diffusers
|
| 3 |
+
transformers>=4.47.1,<5,!=4.57.0
|
| 4 |
+
accelerate
|
| 5 |
+
huggingface_hub
|
| 6 |
+
spaces
|
| 7 |
+
torch==2.8.0
|
| 8 |
+
numpy<2
|
| 9 |
+
gdown
|
| 10 |
+
opencv-python
|
| 11 |
+
#dartrs
|
| 12 |
+
git+https://github.com/John6666cat/dartrs
|
| 13 |
+
translatepy
|
| 14 |
+
timm
|
| 15 |
+
rapidfuzz
|
| 16 |
+
pandas
|
| 17 |
+
safetensors
|
| 18 |
+
sentencepiece
|
| 19 |
+
unidecode
|
| 20 |
+
matplotlib-inline
|
| 21 |
+
mediapipe==0.10.13
|
| 22 |
+
einops
|
| 23 |
+
# pydantic==2.10.6
|