Spaces:
Running
Running
Upload 12 files
Browse filesHello! I'm back with some updates!
1. Removed Florence as it's outdated and there are already many alternatives available on HF. If I find another suitable alternative, I'll try to implement it.
2. After some experimentation with colors, I managed to create a new Gradio theme, which has both dark and light versions.
3. Realized that some models are good at tagging, while others aren't, but sometimes the 'bad' models are more accurate. This gave me an idea... So, I implemented a script to run two models. It basically tags images twice, replaces duplicates, and outputs a diversified result.
4. Lastly, fixed some minor issues.
It took me 3 days, but finally managed to finish! Have fun!
- .gitattributes +1 -0
- app.py +317 -430
- images/1girl.png +2 -2
- modules/beautify_model.py +99 -0
- modules/classifyTags.py +156 -157
- modules/florence2.py +90 -90
- modules/tag_enhancer.py +12 -13
- pre-requirements.txt +6 -1
- requirements.txt +21 -25
- themes/theme_schema@0.0.1.json +1 -1
.gitattributes
CHANGED
|
@@ -28,3 +28,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 28 |
1girl.png filter=lfs diff=lfs merge=lfs -text
|
| 29 |
images/image1.png filter=lfs diff=lfs merge=lfs -text
|
| 30 |
images/image2.png filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 28 |
1girl.png filter=lfs diff=lfs merge=lfs -text
|
| 29 |
images/image1.png filter=lfs diff=lfs merge=lfs -text
|
| 30 |
images/image2.png filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
images/1girl.png filter=lfs diff=lfs merge=lfs -text
|
app.py
CHANGED
|
@@ -1,28 +1,21 @@
|
|
| 1 |
-
import os,io,copy,json,requests,spaces,gradio as gr,numpy as np
|
| 2 |
-
import argparse,huggingface_hub,onnxruntime as rt,pandas as pd,traceback,tempfile,zipfile,re,ast,time
|
| 3 |
-
from datetime import datetime,timezone
|
| 4 |
from collections import defaultdict
|
| 5 |
-
from PIL import Image,ImageOps
|
| 6 |
-
from modules.booru import booru_gradio,on_select
|
| 7 |
from apscheduler.schedulers.background import BackgroundScheduler
|
| 8 |
-
from modules.classifyTags import classify_tags,process_tags
|
| 9 |
-
from modules.
|
| 10 |
-
from modules.tag_enhancer import
|
| 11 |
-
from modules.florence2 import process_image,single_task_list,update_task_dropdown
|
| 12 |
|
| 13 |
os.environ['PYTORCH_ENABLE_MPS_FALLBACK']='1'
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
TITLE = "Multi-Tagger v1.
|
| 16 |
DESCRIPTION = """
|
| 17 |
-
Multi-Tagger is a versatile application for advanced image analysis and captioning.
|
| 18 |
-
|
| 19 |
-
- **Automatic Tag Categorization**: Tags are grouped into categories.
|
| 20 |
-
- **Tag Enhancement**: Boost your prompts with enhanced descriptions using a built-in prompt enhancer.
|
| 21 |
-
- **Reorganizer**: Use a reorganizer model to format tags into a natural-language description.
|
| 22 |
-
- **Batch Support**: Upload and process multiple images simultaneously.
|
| 23 |
-
- **Downloadable Output**: Get almost all results as downloadable `.txt`, `.json`, and `.png` files in a `.zip` archive.
|
| 24 |
-
- **Image Fetcher**: Search for images from **Gelbooru** using flexible tag filters.
|
| 25 |
-
- **CUDA** and **CPU** support.
|
| 26 |
"""
|
| 27 |
|
| 28 |
# Dataset v3 series of models:
|
|
@@ -44,75 +37,59 @@ SWINV2_MODEL_IS_DSV1_REPO = "deepghs/idolsankaku-swinv2-tagger-v1"
|
|
| 44 |
MODEL_FILENAME = "model.onnx"
|
| 45 |
LABEL_FILENAME = "selected_tags.csv"
|
| 46 |
|
| 47 |
-
kaomojis=['0_0','(o)_(o)','+_+','+_-','._.','<o>_<o>','<|>_<|>','=_=','>_<','3_3','6_9','>_o','@_@','^_^','o_o','u_u','x_x','|_|','||_||']
|
| 48 |
-
def parse_args()->argparse.Namespace:parser=argparse.ArgumentParser();parser.add_argument('--score-slider-step',type=float,default=.05);parser.add_argument('--score-general-threshold',type=float,default=.35);parser.add_argument('--score-character-threshold',type=float,default=.85);parser.add_argument('--share',action='store_true');return parser.parse_args()
|
| 49 |
-
def load_labels(dataframe)->list[str]:name_series=dataframe['name'];name_series=name_series.map(lambda x:x.replace('_',' ')if x not in kaomojis else x);tag_names=name_series.tolist();rating_indexes=list(np.where(dataframe['category']==9)[0]);general_indexes=list(np.where(dataframe['category']==0)[0]);character_indexes=list(np.where(dataframe['category']==4)[0]);return tag_names,rating_indexes,general_indexes,character_indexes
|
| 50 |
def mcut_threshold(probs):sorted_probs=probs[probs.argsort()[::-1]];difs=sorted_probs[:-1]-sorted_probs[1:];t=difs.argmax();thresh=(sorted_probs[t]+sorted_probs[t+1])/2;return thresh
|
| 51 |
-
|
| 52 |
class Timer:
|
| 53 |
-
def __init__(self):self.start_time=time.perf_counter();self.checkpoints=[('Start',self.start_time)]
|
| 54 |
-
def checkpoint(self,label='Checkpoint'):now=time.perf_counter();self.checkpoints.append((label,now))
|
| 55 |
-
def report(self,is_clear_checkpoints=True):
|
| 56 |
-
max_label_length=max(len(label)for(label,_)in self.checkpoints);prev_time=self.checkpoints[0][1]
|
| 57 |
-
for(label,curr_time)in self.checkpoints[1:]:elapsed=curr_time-prev_time;print(f"{label.ljust(max_label_length)}: {elapsed:.3f} seconds");prev_time=curr_time
|
| 58 |
if is_clear_checkpoints:self.checkpoints.clear();self.checkpoint()
|
| 59 |
def report_all(self):
|
| 60 |
-
print('\n> Execution Time Report:');max_label_length=max(len(label)for(label,_)in self.checkpoints)if len(self.checkpoints)>0 else 0;prev_time=self.start_time
|
| 61 |
-
for(label,curr_time)in self.checkpoints[1:]:elapsed=curr_time-prev_time;print(f"{label.ljust(max_label_length)}: {elapsed:.3f} seconds");prev_time=curr_time
|
| 62 |
total_time=self.checkpoints[-1][1]-self.start_time;print(f"{'Total Execution Time'.ljust(max_label_length)}: {total_time:.3f} seconds\n");self.checkpoints.clear()
|
| 63 |
-
def restart(self):self.start_time=time.perf_counter();self.checkpoints=[('Start',self.start_time)]
|
| 64 |
class Predictor:
|
| 65 |
def __init__(self):
|
| 66 |
self.model_target_size = None
|
| 67 |
self.last_loaded_repo = None
|
| 68 |
def download_model(self, model_repo):
|
| 69 |
-
csv_path = huggingface_hub.hf_hub_download(
|
| 70 |
-
|
| 71 |
-
LABEL_FILENAME,
|
| 72 |
-
)
|
| 73 |
-
model_path = huggingface_hub.hf_hub_download(
|
| 74 |
-
model_repo,
|
| 75 |
-
MODEL_FILENAME,
|
| 76 |
-
)
|
| 77 |
return csv_path, model_path
|
| 78 |
def load_model(self, model_repo):
|
| 79 |
if model_repo == self.last_loaded_repo:
|
| 80 |
return
|
| 81 |
-
|
| 82 |
csv_path, model_path = self.download_model(model_repo)
|
| 83 |
-
|
| 84 |
tags_df = pd.read_csv(csv_path)
|
| 85 |
sep_tags = load_labels(tags_df)
|
| 86 |
-
|
| 87 |
self.tag_names = sep_tags[0]
|
| 88 |
self.rating_indexes = sep_tags[1]
|
| 89 |
self.general_indexes = sep_tags[2]
|
| 90 |
self.character_indexes = sep_tags[3]
|
| 91 |
-
|
| 92 |
model = rt.InferenceSession(model_path)
|
| 93 |
_, height, width, _ = model.get_inputs()[0].shape
|
| 94 |
self.model_target_size = height
|
| 95 |
-
|
| 96 |
self.last_loaded_repo = model_repo
|
| 97 |
self.model = model
|
| 98 |
def prepare_image(self, path):
|
| 99 |
image = Image.open(path)
|
| 100 |
image = image.convert("RGBA")
|
| 101 |
target_size = self.model_target_size
|
| 102 |
-
|
| 103 |
canvas = Image.new("RGBA", image.size, (255, 255, 255))
|
| 104 |
canvas.alpha_composite(image)
|
| 105 |
image = canvas.convert("RGB")
|
| 106 |
-
|
| 107 |
# Pad image to square
|
| 108 |
image_shape = image.size
|
| 109 |
max_dim = max(image_shape)
|
| 110 |
pad_left = (max_dim - image_shape[0]) // 2
|
| 111 |
pad_top = (max_dim - image_shape[1]) // 2
|
| 112 |
-
|
| 113 |
padded_image = Image.new("RGB", (max_dim, max_dim), (255, 255, 255))
|
| 114 |
padded_image.paste(image, (pad_left, pad_top))
|
| 115 |
-
|
| 116 |
# Resize
|
| 117 |
if max_dim != target_size:
|
| 118 |
padded_image = padded_image.resize(
|
|
@@ -134,211 +111,229 @@ class Predictor:
|
|
| 134 |
else:
|
| 135 |
with open(file_path, 'w+', encoding="utf-8") as file:
|
| 136 |
file.write(content)
|
| 137 |
-
|
| 138 |
return file_path
|
| 139 |
-
|
| 140 |
def predict(
|
| 141 |
self,
|
| 142 |
gallery,
|
| 143 |
model_repo,
|
|
|
|
| 144 |
general_thresh,
|
| 145 |
general_mcut_enabled,
|
| 146 |
character_thresh,
|
| 147 |
character_mcut_enabled,
|
| 148 |
characters_merge_enabled,
|
| 149 |
-
|
| 150 |
additional_tags_prepend,
|
| 151 |
additional_tags_append,
|
| 152 |
tag_results,
|
| 153 |
progress=gr.Progress()
|
| 154 |
):
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
current_progress += progressRatio/progressTotal;
|
| 168 |
-
progress(current_progress, desc="Initialize
|
| 169 |
-
timer.checkpoint(f"Initialize
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
#
|
| 221 |
-
|
| 222 |
-
rating = dict(ratings_names)
|
| 223 |
-
|
| 224 |
-
# Then we have general tags: pick any where prediction confidence > threshold
|
| 225 |
-
general_names = [labels[i] for i in self.general_indexes]
|
| 226 |
-
|
| 227 |
if general_mcut_enabled:
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
character_names = [labels[i] for i in self.character_indexes]
|
| 236 |
-
|
| 237 |
if character_mcut_enabled:
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
)
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
current_progress += progressRatio/progressTotal;
|
| 289 |
-
progress(current_progress, desc=f"image{idx:02d},
|
| 290 |
-
timer.checkpoint(f"image{idx:02d},
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
|
|
|
| 342 |
def get_selection_from_gallery(gallery: list, tag_results: dict, selected_state: gr.SelectData):
|
| 343 |
if not selected_state:
|
| 344 |
return selected_state
|
|
@@ -350,20 +345,20 @@ def get_selection_from_gallery(gallery: list, tag_results: dict, selected_state:
|
|
| 350 |
"character_res": "",
|
| 351 |
"general_res": "",
|
| 352 |
"unclassified_tags": "{}",
|
| 353 |
-
"
|
| 354 |
}
|
| 355 |
if selected_state.value["image"]["path"] in tag_results:
|
| 356 |
tag_result = tag_results[selected_state.value["image"]["path"]]
|
| 357 |
-
return (selected_state.value["image"]["path"], selected_state.value["caption"]), tag_result["strings"], tag_result["strings2"], tag_result["classified_tags"], tag_result["rating"], tag_result["character_res"], tag_result["general_res"], tag_result["unclassified_tags"], tag_result["
|
| 358 |
-
def append_gallery(gallery:list,image:str):
|
| 359 |
if gallery is None:gallery=[]
|
| 360 |
-
if not image:return gallery,None
|
| 361 |
-
gallery.append(image);return gallery,None
|
| 362 |
-
def extend_gallery(gallery:list,images):
|
| 363 |
if gallery is None:gallery=[]
|
| 364 |
if not images:return gallery
|
| 365 |
gallery.extend(images);return gallery
|
| 366 |
-
def remove_image_from_gallery(gallery:list,selected_image:str):
|
| 367 |
if not gallery or not selected_image:return gallery
|
| 368 |
selected_image=ast.literal_eval(selected_image)
|
| 369 |
if selected_image in gallery:gallery.remove(selected_image)
|
|
@@ -371,26 +366,25 @@ def remove_image_from_gallery(gallery:list,selected_image:str):
|
|
| 371 |
args = parse_args()
|
| 372 |
predictor = Predictor()
|
| 373 |
dropdown_list = [
|
| 374 |
-
EVA02_LARGE_MODEL_DSV3_REPO,
|
| 375 |
-
SWINV2_MODEL_DSV3_REPO,
|
| 376 |
-
CONV_MODEL_DSV3_REPO,
|
| 377 |
-
VIT_MODEL_DSV3_REPO,
|
| 378 |
-
VIT_LARGE_MODEL_DSV3_REPO,
|
| 379 |
# ---
|
| 380 |
-
MOAT_MODEL_DSV2_REPO,
|
| 381 |
-
SWIN_MODEL_DSV2_REPO,
|
| 382 |
-
CONV_MODEL_DSV2_REPO,
|
| 383 |
-
CONV2_MODEL_DSV2_REPO,
|
| 384 |
-
VIT_MODEL_DSV2_REPO,
|
| 385 |
# ---
|
| 386 |
-
SWINV2_MODEL_IS_DSV1_REPO,
|
| 387 |
-
EVA02_LARGE_MODEL_IS_DSV1_REPO,
|
| 388 |
]
|
| 389 |
-
|
| 390 |
def _restart_space():
|
| 391 |
HF_TOKEN=os.getenv('HF_TOKEN')
|
| 392 |
if not HF_TOKEN:raise ValueError('HF_TOKEN environment variable is not set.')
|
| 393 |
-
huggingface_hub.HfApi().restart_space(repo_id='Werli/Multi-Tagger',token=HF_TOKEN,factory_reboot=False)
|
| 394 |
scheduler=BackgroundScheduler()
|
| 395 |
# Add a job to restart the space every 2 days (172800 seconds)
|
| 396 |
restart_space_job = scheduler.add_job(_restart_space, "interval", seconds=172800)
|
|
@@ -399,235 +393,128 @@ next_run_time_utc=restart_space_job.next_run_time.astimezone(timezone.utc)
|
|
| 399 |
NEXT_RESTART=f"Next Restart: {next_run_time_utc.strftime('%Y-%m-%d %H:%M:%S')} (UTC) - The space will restart every 2 days to ensure stability and performance. It uses a background scheduler to handle the restart process."
|
| 400 |
|
| 401 |
css = """
|
| 402 |
-
#
|
| 403 |
-
|
| 404 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
"""
|
| 406 |
-
|
| 407 |
-
with gr.Blocks(title=TITLE, css=css, theme=gr.themes.Soft(), fill_width=True) as demo:
|
| 408 |
gr.Markdown(value=f"<h1 style='text-align: center; margin-bottom: 1rem'>{TITLE}</h1>")
|
| 409 |
-
gr.Markdown(value=DESCRIPTION)
|
| 410 |
-
gr.Markdown(
|
| 411 |
with gr.Tab(label="Waifu Diffusion"):
|
| 412 |
with gr.Row():
|
| 413 |
with gr.Column():
|
| 414 |
-
submit = gr.Button(value="
|
| 415 |
with gr.Column(variant="panel"):
|
| 416 |
# Create an Image component for uploading images
|
| 417 |
image_input = gr.Image(label="Upload an Image or clicking paste from clipboard button", type="filepath", sources=["upload", "clipboard"], height=150)
|
| 418 |
with gr.Row():
|
| 419 |
upload_button = gr.UploadButton("Upload multiple images", file_types=["image"], file_count="multiple", size="sm")
|
| 420 |
remove_button = gr.Button("Remove Selected Image", size="sm")
|
| 421 |
-
gallery = gr.Gallery(
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
0,
|
| 430 |
-
1,
|
| 431 |
-
step=args.score_slider_step,
|
| 432 |
-
value=args.score_general_threshold,
|
| 433 |
-
label="General Tags Threshold",
|
| 434 |
-
scale=3,
|
| 435 |
-
)
|
| 436 |
-
general_mcut_enabled = gr.Checkbox(
|
| 437 |
-
value=False,
|
| 438 |
-
label="Use MCut threshold",
|
| 439 |
-
scale=1,
|
| 440 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 441 |
with gr.Row():
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
1,
|
| 445 |
-
step=args.score_slider_step,
|
| 446 |
-
value=args.score_character_threshold,
|
| 447 |
-
label="Character Tags Threshold",
|
| 448 |
-
scale=3,
|
| 449 |
-
)
|
| 450 |
-
character_mcut_enabled = gr.Checkbox(
|
| 451 |
-
value=False,
|
| 452 |
-
label="Use MCut threshold",
|
| 453 |
-
scale=1,
|
| 454 |
-
)
|
| 455 |
with gr.Row():
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
label="Merge characters into the string output",
|
| 459 |
-
scale=1,
|
| 460 |
-
)
|
| 461 |
with gr.Row():
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
label="Reorganizer Model",
|
| 466 |
-
info="Use a model to create a description for you",
|
| 467 |
-
)
|
| 468 |
with gr.Row():
|
| 469 |
additional_tags_prepend = gr.Text(label="Prepend Additional tags (comma split)")
|
| 470 |
additional_tags_append = gr.Text(label="Append Additional tags (comma split)")
|
| 471 |
with gr.Row():
|
| 472 |
clear = gr.ClearButton(
|
| 473 |
-
components=[
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
general_thresh,
|
| 477 |
-
general_mcut_enabled,
|
| 478 |
-
character_thresh,
|
| 479 |
-
character_mcut_enabled,
|
| 480 |
-
characters_merge_enabled,
|
| 481 |
-
reorganizer_model_repo,
|
| 482 |
-
additional_tags_prepend,
|
| 483 |
-
additional_tags_append,
|
| 484 |
-
],
|
| 485 |
-
variant="secondary",
|
| 486 |
-
size="lg",
|
| 487 |
-
)
|
| 488 |
with gr.Column(variant="panel"):
|
| 489 |
-
download_file = gr.File(label="Download
|
| 490 |
character_res = gr.Label(label="Output (characters)") # 1
|
| 491 |
-
sorted_general_strings = gr.Textbox(label="Output
|
| 492 |
-
final_categorized_output = gr.Textbox(label="Categorized
|
| 493 |
-
pe_generate_btn = gr.Button(value="
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
categorized = gr.JSON(label="Categorized (tags)
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
unclassified
|
| 500 |
-
clear.add(
|
| 501 |
-
[
|
| 502 |
-
download_file,
|
| 503 |
-
sorted_general_strings,
|
| 504 |
-
final_categorized_output,
|
| 505 |
-
categorized,
|
| 506 |
-
rating,
|
| 507 |
-
character_res,
|
| 508 |
-
general_res,
|
| 509 |
-
unclassified,
|
| 510 |
-
prompt_enhancer_model,
|
| 511 |
-
enhanced_tags,
|
| 512 |
-
]
|
| 513 |
-
)
|
| 514 |
tag_results = gr.State({})
|
| 515 |
# Define the event listener to add the uploaded image to the gallery
|
| 516 |
image_input.change(append_gallery, inputs=[gallery, image_input], outputs=[gallery, image_input])
|
| 517 |
-
# When the upload button is clicked,
|
| 518 |
upload_button.upload(extend_gallery, inputs=[gallery, upload_button], outputs=gallery)
|
| 519 |
# Event to update the selected image when an image is clicked in the gallery
|
| 520 |
selected_image = gr.Textbox(label="Selected Image", visible=False)
|
| 521 |
-
gallery.select(get_selection_from_gallery,inputs=[gallery, tag_results],outputs=[selected_image, sorted_general_strings, final_categorized_output, categorized, rating, character_res, general_res, unclassified,
|
| 522 |
# Event to remove a selected image from the gallery
|
| 523 |
remove_button.click(remove_image_from_gallery, inputs=[gallery, selected_image], outputs=gallery)
|
| 524 |
-
# Event to for the Prompt
|
| 525 |
-
pe_generate_btn.click(lambda tags,model:
|
| 526 |
-
submit.click(
|
| 527 |
-
predictor.predict,
|
| 528 |
-
inputs=[
|
| 529 |
-
gallery,
|
| 530 |
-
model_repo,
|
| 531 |
-
general_thresh,
|
| 532 |
-
general_mcut_enabled,
|
| 533 |
-
character_thresh,
|
| 534 |
-
character_mcut_enabled,
|
| 535 |
-
characters_merge_enabled,
|
| 536 |
-
reorganizer_model_repo,
|
| 537 |
-
additional_tags_prepend,
|
| 538 |
-
additional_tags_append,
|
| 539 |
-
tag_results,
|
| 540 |
-
],
|
| 541 |
-
outputs=[download_file, sorted_general_strings, final_categorized_output, categorized, rating, character_res, general_res, unclassified, tag_results,],
|
| 542 |
-
)
|
| 543 |
gr.Examples(
|
| 544 |
[["images/1girl.png", VIT_LARGE_MODEL_DSV3_REPO, 0.35, False, 0.85, False]],
|
| 545 |
-
inputs=[
|
| 546 |
-
|
| 547 |
-
model_repo,
|
| 548 |
-
general_thresh,
|
| 549 |
-
general_mcut_enabled,
|
| 550 |
-
character_thresh,
|
| 551 |
-
character_mcut_enabled,
|
| 552 |
-
],
|
| 553 |
-
)
|
| 554 |
-
with gr.Tab(label="Florence 2 Image Captioning"):
|
| 555 |
-
with gr.Row():
|
| 556 |
-
with gr.Column(variant="panel"):
|
| 557 |
-
input_img = gr.Image(label="Input Picture")
|
| 558 |
-
task_type = gr.Radio(choices=['Single task', 'Cascaded task'], label='Task type selector', value='Single task')
|
| 559 |
-
task_prompt = gr.Dropdown(choices=single_task_list, label="Task Prompt", value="Caption")
|
| 560 |
-
task_type.change(fn=update_task_dropdown, inputs=task_type, outputs=task_prompt)
|
| 561 |
-
text_input = gr.Textbox(label="Text Input (optional)")
|
| 562 |
-
submit_btn = gr.Button(value="Submit")
|
| 563 |
-
with gr.Column(variant="panel"):
|
| 564 |
-
output_text = gr.Textbox(label="Output Text", show_label=True, show_copy_button=True, lines=8)
|
| 565 |
-
output_img = gr.Image(label="Output Image")
|
| 566 |
-
gr.Examples(
|
| 567 |
-
examples=[
|
| 568 |
-
["images/image1.png", 'Object Detection'],
|
| 569 |
-
["images/image2.png", 'OCR with Region']
|
| 570 |
-
],
|
| 571 |
-
inputs=[input_img, task_prompt],
|
| 572 |
-
outputs=[output_text, output_img],
|
| 573 |
-
fn=process_image,
|
| 574 |
-
cache_examples=False,
|
| 575 |
-
label='Try examples'
|
| 576 |
-
)
|
| 577 |
-
submit_btn.click(process_image, [input_img, task_prompt, text_input], [output_text, output_img])
|
| 578 |
with gr.Tab("Booru Image Fetcher"):
|
| 579 |
with gr.Row():
|
| 580 |
with gr.Column():
|
| 581 |
gr.Markdown("### ⚙️ Search Parameters")
|
| 582 |
-
site = gr.Dropdown(label="Select Source", choices=["Gelbooru", "Rule34", "Xbooru"], value="Xbooru")
|
| 583 |
-
Tags = gr.Textbox(label="Tags (comma-separated)", placeholder="e.g. solo,
|
| 584 |
-
exclude_tags = gr.Textbox(label="Exclude Tags (comma-separated)", placeholder="e.g. animated,
|
| 585 |
score = gr.Number(label="Minimum Score", value=0)
|
| 586 |
count = gr.Slider(label="Number of Images", minimum=1, maximum=20, step=1, value=1)
|
| 587 |
Safe = gr.Checkbox(label="Include Safe", value=True)
|
| 588 |
Questionable = gr.Checkbox(label="Include Questionable", value=True)
|
| 589 |
-
Explicit = gr.Checkbox(label="Include Explicit", value=False)
|
| 590 |
submit_btn = gr.Button("Fetch Images", variant="primary")
|
| 591 |
-
|
| 592 |
with gr.Column():
|
| 593 |
gr.Markdown("### 📄 Results")
|
| 594 |
images_output = gr.Gallery(label="Images", columns=3, rows=2, object_fit="contain", height=500)
|
| 595 |
-
tags_output = gr.Textbox(label="Tags", placeholder="Select an image to
|
| 596 |
post_url_output = gr.Textbox(label="Post URL", lines=1, show_copy_button=True)
|
| 597 |
image_url_output = gr.Textbox(label="Image URL", lines=1, show_copy_button=True)
|
| 598 |
-
|
| 599 |
# State to store tags, URLs
|
| 600 |
tags_state = gr.State([])
|
| 601 |
post_url_state = gr.State([])
|
| 602 |
image_url_state = gr.State([])
|
| 603 |
-
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
inputs=[Tags, exclude_tags, score, count, Safe, Questionable, Explicit, site],
|
| 607 |
-
outputs=[images_output, tags_state, post_url_state, image_url_state],
|
| 608 |
-
)
|
| 609 |
-
|
| 610 |
-
images_output.select(
|
| 611 |
-
fn=on_select,
|
| 612 |
-
inputs=[tags_state, post_url_state, image_url_state],
|
| 613 |
-
outputs=[tags_output, post_url_output, image_url_output],
|
| 614 |
-
)
|
| 615 |
-
gr.Markdown("""
|
| 616 |
-
---
|
| 617 |
-
ComfyUI version: [Comfyui-Gelbooru](https://github.com/1mckw/Comfyui-Gelbooru)
|
| 618 |
-
""")
|
| 619 |
-
with gr.Tab(label="Categorizer++"):
|
| 620 |
with gr.Row():
|
| 621 |
with gr.Column(variant="panel"):
|
| 622 |
-
input_tags = gr.Textbox(label="Input Tags", placeholder="1girl,
|
| 623 |
-
submit_button = gr.Button(value="
|
| 624 |
with gr.Column(variant="panel"):
|
| 625 |
categorized_string = gr.Textbox(label="Categorized (string)", show_label=True, show_copy_button=True, lines=8)
|
| 626 |
categorized_json = gr.JSON(label="Categorized (tags) - JSON")
|
| 627 |
submit_button.click(process_tags, inputs=[input_tags], outputs=[categorized_string, categorized_json])
|
| 628 |
with gr.Column(variant="panel"):
|
| 629 |
-
pe_generate_btn = gr.Button(value="
|
| 630 |
-
|
| 631 |
-
|
| 632 |
-
pe_generate_btn.click(lambda tags,model:
|
| 633 |
-
demo.queue(max_size=
|
|
|
|
| 1 |
+
import os, io, copy, json, requests, spaces, gradio as gr, numpy as np
|
| 2 |
+
import argparse, huggingface_hub, onnxruntime as rt, pandas as pd, traceback, tempfile, zipfile, re, ast, time
|
| 3 |
+
from datetime import datetime, timezone
|
| 4 |
from collections import defaultdict
|
| 5 |
+
from PIL import Image, ImageOps
|
| 6 |
+
from modules.booru import booru_gradio, on_select
|
| 7 |
from apscheduler.schedulers.background import BackgroundScheduler
|
| 8 |
+
from modules.classifyTags import classify_tags, process_tags
|
| 9 |
+
from modules.beautify_model import beautify_list, beautify_class
|
| 10 |
+
from modules.tag_enhancer import prompt_summarizer
|
|
|
|
| 11 |
|
| 12 |
os.environ['PYTORCH_ENABLE_MPS_FALLBACK']='1'
|
| 13 |
+
os.environ['OMP_NUM_THREADS'] = '8' # Optimize CPU utilization? Test...
|
| 14 |
+
#os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
|
| 15 |
|
| 16 |
+
TITLE = "Multi-Tagger v1.3"
|
| 17 |
DESCRIPTION = """
|
| 18 |
+
Multi-Tagger is a versatile application for advanced image analysis and captioning. Supports <b>CUDA</b> and <b>CPU</b>.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
"""
|
| 20 |
|
| 21 |
# Dataset v3 series of models:
|
|
|
|
| 37 |
MODEL_FILENAME = "model.onnx"
|
| 38 |
LABEL_FILENAME = "selected_tags.csv"
|
| 39 |
|
| 40 |
+
kaomojis=['0_0', '(o)_(o)', '+_+', '+_-', '._.', '<o>_<o>', '<|>_<|>', '=_=', '>_<', '3_3', '6_9', '>_o', '@_@', '^_^', 'o_o', 'u_u', 'x_x', '|_|', '||_||']
|
| 41 |
+
def parse_args()->argparse.Namespace:parser=argparse.ArgumentParser();parser.add_argument('--score-slider-step', type=float, default=.05);parser.add_argument('--score-general-threshold', type=float, default=.35);parser.add_argument('--score-character-threshold', type=float, default=.85);parser.add_argument('--share', action='store_true');return parser.parse_args()
|
| 42 |
+
def load_labels(dataframe)->list[str]:name_series=dataframe['name'];name_series=name_series.map(lambda x:x.replace('_', ' ')if x not in kaomojis else x);tag_names=name_series.tolist();rating_indexes=list(np.where(dataframe['category']==9)[0]);general_indexes=list(np.where(dataframe['category']==0)[0]);character_indexes=list(np.where(dataframe['category']==4)[0]);return tag_names, rating_indexes, general_indexes, character_indexes
|
| 43 |
def mcut_threshold(probs):sorted_probs=probs[probs.argsort()[::-1]];difs=sorted_probs[:-1]-sorted_probs[1:];t=difs.argmax();thresh=(sorted_probs[t]+sorted_probs[t+1])/2;return thresh
|
|
|
|
| 44 |
class Timer:
|
| 45 |
+
def __init__(self):self.start_time=time.perf_counter();self.checkpoints=[('Start', self.start_time)]
|
| 46 |
+
def checkpoint(self, label='Checkpoint'):now=time.perf_counter();self.checkpoints.append((label, now))
|
| 47 |
+
def report(self, is_clear_checkpoints=True):
|
| 48 |
+
max_label_length=max(len(label)for(label, _)in self.checkpoints);prev_time=self.checkpoints[0][1]
|
| 49 |
+
for(label, curr_time)in self.checkpoints[1:]:elapsed=curr_time-prev_time;print(f"{label.ljust(max_label_length)}: {elapsed:.3f} seconds");prev_time=curr_time
|
| 50 |
if is_clear_checkpoints:self.checkpoints.clear();self.checkpoint()
|
| 51 |
def report_all(self):
|
| 52 |
+
print('\n> Execution Time Report:');max_label_length=max(len(label)for(label, _)in self.checkpoints)if len(self.checkpoints)>0 else 0;prev_time=self.start_time
|
| 53 |
+
for(label, curr_time)in self.checkpoints[1:]:elapsed=curr_time-prev_time;print(f"{label.ljust(max_label_length)}: {elapsed:.3f} seconds");prev_time=curr_time
|
| 54 |
total_time=self.checkpoints[-1][1]-self.start_time;print(f"{'Total Execution Time'.ljust(max_label_length)}: {total_time:.3f} seconds\n");self.checkpoints.clear()
|
| 55 |
+
def restart(self):self.start_time=time.perf_counter();self.checkpoints=[('Start', self.start_time)]
|
| 56 |
class Predictor:
|
| 57 |
def __init__(self):
|
| 58 |
self.model_target_size = None
|
| 59 |
self.last_loaded_repo = None
|
| 60 |
def download_model(self, model_repo):
|
| 61 |
+
csv_path = huggingface_hub.hf_hub_download(model_repo, LABEL_FILENAME, )
|
| 62 |
+
model_path = huggingface_hub.hf_hub_download(model_repo, MODEL_FILENAME, )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
return csv_path, model_path
|
| 64 |
def load_model(self, model_repo):
|
| 65 |
if model_repo == self.last_loaded_repo:
|
| 66 |
return
|
|
|
|
| 67 |
csv_path, model_path = self.download_model(model_repo)
|
|
|
|
| 68 |
tags_df = pd.read_csv(csv_path)
|
| 69 |
sep_tags = load_labels(tags_df)
|
|
|
|
| 70 |
self.tag_names = sep_tags[0]
|
| 71 |
self.rating_indexes = sep_tags[1]
|
| 72 |
self.general_indexes = sep_tags[2]
|
| 73 |
self.character_indexes = sep_tags[3]
|
|
|
|
| 74 |
model = rt.InferenceSession(model_path)
|
| 75 |
_, height, width, _ = model.get_inputs()[0].shape
|
| 76 |
self.model_target_size = height
|
|
|
|
| 77 |
self.last_loaded_repo = model_repo
|
| 78 |
self.model = model
|
| 79 |
def prepare_image(self, path):
|
| 80 |
image = Image.open(path)
|
| 81 |
image = image.convert("RGBA")
|
| 82 |
target_size = self.model_target_size
|
|
|
|
| 83 |
canvas = Image.new("RGBA", image.size, (255, 255, 255))
|
| 84 |
canvas.alpha_composite(image)
|
| 85 |
image = canvas.convert("RGB")
|
|
|
|
| 86 |
# Pad image to square
|
| 87 |
image_shape = image.size
|
| 88 |
max_dim = max(image_shape)
|
| 89 |
pad_left = (max_dim - image_shape[0]) // 2
|
| 90 |
pad_top = (max_dim - image_shape[1]) // 2
|
|
|
|
| 91 |
padded_image = Image.new("RGB", (max_dim, max_dim), (255, 255, 255))
|
| 92 |
padded_image.paste(image, (pad_left, pad_top))
|
|
|
|
| 93 |
# Resize
|
| 94 |
if max_dim != target_size:
|
| 95 |
padded_image = padded_image.resize(
|
|
|
|
| 111 |
else:
|
| 112 |
with open(file_path, 'w+', encoding="utf-8") as file:
|
| 113 |
file.write(content)
|
|
|
|
| 114 |
return file_path
|
|
|
|
| 115 |
def predict(
|
| 116 |
self,
|
| 117 |
gallery,
|
| 118 |
model_repo,
|
| 119 |
+
model_repo_2,
|
| 120 |
general_thresh,
|
| 121 |
general_mcut_enabled,
|
| 122 |
character_thresh,
|
| 123 |
character_mcut_enabled,
|
| 124 |
characters_merge_enabled,
|
| 125 |
+
beautify_model_repo,
|
| 126 |
additional_tags_prepend,
|
| 127 |
additional_tags_append,
|
| 128 |
tag_results,
|
| 129 |
progress=gr.Progress()
|
| 130 |
):
|
| 131 |
+
# Clear tag_results before starting a new prediction
|
| 132 |
+
tag_results.clear()
|
| 133 |
+
gallery_len = len(gallery)
|
| 134 |
+
print(f"Predict load model: {model_repo}, gallery length: {gallery_len}")
|
| 135 |
+
timer = Timer() # Create a timer
|
| 136 |
+
progressRatio = 0.5 if beautify_model_repo else 1
|
| 137 |
+
progressTotal = gallery_len + 1
|
| 138 |
+
current_progress = 0
|
| 139 |
+
# Initialize variables that need to be accessible throughout the function
|
| 140 |
+
final_categorized_output = ""
|
| 141 |
+
categorized_output_strings = []
|
| 142 |
+
txt_infos = []
|
| 143 |
+
output_dir = tempfile.mkdtemp()
|
| 144 |
+
if not os.path.exists(output_dir):
|
| 145 |
+
os.makedirs(output_dir)
|
| 146 |
+
self.load_model(model_repo)
|
| 147 |
+
current_progress += progressRatio/progressTotal;
|
| 148 |
+
progress(current_progress, desc="Initialize wd model finished")
|
| 149 |
+
timer.checkpoint(f"Initialize wd model")
|
| 150 |
+
if beautify_model_repo:
|
| 151 |
+
print(f"Load model {beautify_model_repo}")
|
| 152 |
+
beautify = beautify_class(beautify_model_repo, loadModel=True)
|
| 153 |
current_progress += progressRatio/progressTotal;
|
| 154 |
+
progress(current_progress, desc="Initialize beautify model finished")
|
| 155 |
+
timer.checkpoint(f"Initialize beautify model")
|
| 156 |
+
timer.report()
|
| 157 |
+
# Dictionary to track counters for each filename
|
| 158 |
+
name_counters = defaultdict(int)
|
| 159 |
+
for idx, value in enumerate(gallery):
|
| 160 |
+
try:
|
| 161 |
+
image_path = value[0]
|
| 162 |
+
image_name = os.path.splitext(os.path.basename(image_path))[0]
|
| 163 |
+
# Increment the counter for the current name
|
| 164 |
+
name_counters[image_name] += 1
|
| 165 |
+
if name_counters[image_name] > 1:
|
| 166 |
+
image_name = f"{image_name}_{name_counters[image_name]:02d}"
|
| 167 |
+
image = self.prepare_image(image_path)
|
| 168 |
+
# Run first model
|
| 169 |
+
print(f"Gallery {idx:02d}: Starting run first model ({model_repo})...")
|
| 170 |
+
self.load_model(model_repo)
|
| 171 |
+
input_name = self.model.get_inputs()[0].name
|
| 172 |
+
label_name = self.model.get_outputs()[0].name
|
| 173 |
+
preds = self.model.run([label_name], {input_name: image})[0]
|
| 174 |
+
labels = list(zip(self.tag_names, preds[0].astype(float)))
|
| 175 |
+
# Process first model results
|
| 176 |
+
ratings_names = [labels[i] for i in self.rating_indexes]
|
| 177 |
+
rating = dict(ratings_names)
|
| 178 |
+
|
| 179 |
+
general_names = [labels[i] for i in self.general_indexes]
|
| 180 |
+
if general_mcut_enabled:
|
| 181 |
+
general_probs = np.array([x[1] for x in general_names])
|
| 182 |
+
general_thresh_temp = mcut_threshold(general_probs)
|
| 183 |
+
else:
|
| 184 |
+
general_thresh_temp = general_thresh
|
| 185 |
+
general_res = [x for x in general_names if x[1] > general_thresh_temp]
|
| 186 |
+
general_res = dict(general_res)
|
| 187 |
+
character_names = [labels[i] for i in self.character_indexes]
|
| 188 |
+
if character_mcut_enabled:
|
| 189 |
+
character_probs = np.array([x[1] for x in character_names])
|
| 190 |
+
character_thresh_temp = mcut_threshold(character_probs)
|
| 191 |
+
character_thresh_temp = max(0.15, character_thresh_temp)
|
| 192 |
+
else:
|
| 193 |
+
character_thresh_temp = character_thresh
|
| 194 |
+
character_res = [x for x in character_names if x[1] > character_thresh_temp]
|
| 195 |
+
character_res = dict(character_res)
|
| 196 |
+
# Collect tags from first model
|
| 197 |
+
character_list_1 = list(character_res.keys())
|
| 198 |
+
sorted_general_list_1 = sorted(general_res.items(), key=lambda x: x[1], reverse=True)
|
| 199 |
+
sorted_general_list_1 = [x[0] for x in sorted_general_list_1]
|
| 200 |
+
# Run second model if selected and different from first
|
| 201 |
+
if model_repo_2 and model_repo_2 != model_repo:
|
| 202 |
+
print(f"Gallery {idx:02d}: Starting run second model ({model_repo_2})...")
|
| 203 |
+
self.load_model(model_repo_2)
|
| 204 |
+
preds_2 = self.model.run([label_name], {input_name: image})[0]
|
| 205 |
+
labels_2 = list(zip(self.tag_names, preds_2[0].astype(float)))
|
| 206 |
+
# Process second model results
|
| 207 |
+
general_names_2 = [labels_2[i] for i in self.general_indexes]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
if general_mcut_enabled:
|
| 209 |
+
general_probs_2 = np.array([x[1] for x in general_names_2])
|
| 210 |
+
general_thresh_temp_2 = mcut_threshold(general_probs_2)
|
| 211 |
+
else:
|
| 212 |
+
general_thresh_temp_2 = general_thresh
|
| 213 |
+
general_res_2 = [x for x in general_names_2 if x[1] > general_thresh_temp_2]
|
| 214 |
+
general_res_2 = dict(general_res_2)
|
| 215 |
+
character_names_2 = [labels_2[i] for i in self.character_indexes]
|
|
|
|
|
|
|
| 216 |
if character_mcut_enabled:
|
| 217 |
+
character_probs_2 = np.array([x[1] for x in character_names_2])
|
| 218 |
+
character_thresh_temp_2 = mcut_threshold(character_probs_2)
|
| 219 |
+
character_thresh_temp_2 = max(0.15, character_thresh_temp_2)
|
| 220 |
+
else:
|
| 221 |
+
character_thresh_temp_2 = character_thresh
|
| 222 |
+
character_res_2 = [x for x in character_names_2 if x[1] > character_thresh_temp_2]
|
| 223 |
+
character_res_2 = dict(character_res_2)
|
| 224 |
+
# Collect tags from second model
|
| 225 |
+
character_list_2 = list(character_res_2.keys())
|
| 226 |
+
sorted_general_list_2 = sorted(general_res_2.items(), key=lambda x: x[1], reverse=True)
|
| 227 |
+
sorted_general_list_2 = [x[0] for x in sorted_general_list_2]
|
| 228 |
+
# Combine results from both models (+ remove duplicates)
|
| 229 |
+
combined_character_list = list(set(character_list_1 + character_list_2))
|
| 230 |
+
combined_general_list = list(set(sorted_general_list_1 + sorted_general_list_2))
|
| 231 |
+
else:
|
| 232 |
+
# Only first model was used
|
| 233 |
+
combined_character_list = character_list_1
|
| 234 |
+
combined_general_list = sorted_general_list_1
|
| 235 |
+
# Remove values from combined_character_list that already exist in combined_general_list
|
| 236 |
+
combined_character_list = [item for item in combined_character_list if item not in combined_general_list]
|
| 237 |
+
# Handle prepend/append tags
|
| 238 |
+
prepend_list = [tag.strip() for tag in additional_tags_prepend.split(",") if tag.strip()]
|
| 239 |
+
append_list = [tag.strip() for tag in additional_tags_append.split(",") if tag.strip()]
|
| 240 |
+
if prepend_list and append_list:
|
| 241 |
+
append_list = [item for item in append_list if item not in prepend_list]
|
| 242 |
+
# Remove values from combined_general_list that already exist in prepend_list or append_list
|
| 243 |
+
if prepend_list:
|
| 244 |
+
combined_general_list = [item for item in combined_general_list if item not in prepend_list]
|
| 245 |
+
if append_list:
|
| 246 |
+
combined_general_list = [item for item in combined_general_list if item not in append_list]
|
| 247 |
+
combined_general_list = prepend_list + combined_general_list + append_list
|
| 248 |
+
sorted_general_strings = ", ".join((combined_character_list if characters_merge_enabled else []) + combined_general_list).replace("(", "\\(").replace(")", "\\)")
|
| 249 |
+
classified_tags, unclassified_tags = classify_tags(combined_general_list)
|
| 250 |
+
# Create a single string of ALL categorized tags for the current image
|
| 251 |
+
categorized_output_string = ', '.join([', '.join(tags) for tags in classified_tags.values()])
|
| 252 |
+
categorized_output_strings.append(categorized_output_string)
|
| 253 |
+
# Collect all categorized output strings into a single string
|
| 254 |
+
final_categorized_output = ', '.join(categorized_output_strings).replace("(", "\\(").replace(")", "\\)")
|
| 255 |
+
# Create a .txt file for "Output (string)" and "Categorized Output (string)"
|
| 256 |
+
txt_content = f"Output (string): {sorted_general_strings}\nCategorized Output (string): {final_categorized_output}"
|
| 257 |
+
txt_file = self.create_file(txt_content, output_dir, f"{image_name}_output.txt")
|
| 258 |
+
txt_infos.append({"path": txt_file, "name": f"{image_name}_output.txt"})
|
| 259 |
+
# Create a .json file for "Categorized (tags)"
|
| 260 |
+
json_content = json.dumps(classified_tags, indent=4)
|
| 261 |
+
json_file = self.create_file(json_content, output_dir, f"{image_name}_categorized_tags.json")
|
| 262 |
+
txt_infos.append({"path": json_file, "name": f"{image_name}_categorized_tags.json"})
|
| 263 |
+
# Save a copy of the uploaded image in PNG format
|
| 264 |
+
image_path = value[0]
|
| 265 |
+
image = Image.open(image_path)
|
| 266 |
+
image.save(os.path.join(output_dir, f"{image_name}.png"), format="PNG")
|
| 267 |
+
txt_infos.append({"path": os.path.join(output_dir, f"{image_name}.png"), "name": f"{image_name}.png"})
|
| 268 |
+
current_progress += progressRatio/progressTotal;
|
| 269 |
+
progress(current_progress, desc=f"image{idx:02d}, predict finished")
|
| 270 |
+
timer.checkpoint(f"image{idx:02d}, predict finished")
|
| 271 |
+
if beautify_model_repo:
|
| 272 |
+
print(f"Starting beautify...")
|
| 273 |
+
beautify_strings = beautify.beautify(sorted_general_strings)
|
| 274 |
+
# Handle potential None returns from beautify
|
| 275 |
+
if beautify_strings is None:
|
| 276 |
+
beautify_strings = "Beautify failed - see console logs"
|
| 277 |
+
else:
|
| 278 |
+
beautify_strings = re.sub(r"Title:", "", beautify_strings)
|
| 279 |
+
beautify_strings = re.sub(r"\n+", ",", beautify_strings)
|
| 280 |
+
beautify_strings = re.sub(r",,+", ",", beautify_strings)
|
| 281 |
+
sorted_general_strings += ",\n\n" + beautify_strings
|
| 282 |
current_progress += progressRatio/progressTotal;
|
| 283 |
+
progress(current_progress, desc=f"image{idx:02d}, beautify finished!")
|
| 284 |
+
timer.checkpoint(f"image{idx:02d}, beautify finished!")
|
| 285 |
+
txt_file = self.create_file(sorted_general_strings, output_dir, image_name + ".txt")
|
| 286 |
+
txt_infos.append({"path":txt_file, "name": image_name + ".txt"})
|
| 287 |
+
|
| 288 |
+
# Store the result in tag_results using image_path as the key
|
| 289 |
+
tag_results[image_path] = {
|
| 290 |
+
"strings": sorted_general_strings,
|
| 291 |
+
"strings2": categorized_output_string, # Store the categorized output string here
|
| 292 |
+
"classified_tags": classified_tags,
|
| 293 |
+
"rating": rating,
|
| 294 |
+
"character_res": character_res,
|
| 295 |
+
"general_res": general_res,
|
| 296 |
+
"unclassified_tags": unclassified_tags,
|
| 297 |
+
"summarize_tags": "" # Initialize as empty string
|
| 298 |
+
}
|
| 299 |
+
timer.report()
|
| 300 |
+
except Exception as e:
|
| 301 |
+
print(traceback.format_exc())
|
| 302 |
+
print("Error predict: " + str(e))
|
| 303 |
+
# Zip creation logic:
|
| 304 |
+
download = []
|
| 305 |
+
if txt_infos is not None and len(txt_infos) > 0:
|
| 306 |
+
downloadZipPath = os.path.join(output_dir, "Multi-Tagger-" + datetime.now().strftime("%Y%m%d-%H%M%S") + ".zip")
|
| 307 |
+
with zipfile.ZipFile(downloadZipPath, 'w', zipfile.ZIP_DEFLATED) as taggers_zip:
|
| 308 |
+
for info in txt_infos:
|
| 309 |
+
# Get file name from lookup
|
| 310 |
+
taggers_zip.write(info["path"], arcname=info["name"])
|
| 311 |
+
download.append(downloadZipPath)
|
| 312 |
+
# End zip creation logic
|
| 313 |
+
|
| 314 |
+
if beautify_model_repo:
|
| 315 |
+
beautify.release_vram()
|
| 316 |
+
del beautify
|
| 317 |
+
progress(1, desc=f"Predict completed")
|
| 318 |
+
timer.report_all() # Print all recorded times
|
| 319 |
+
print("Predict is complete.")
|
| 320 |
+
# Make sure all required variables are returned with proper defaults
|
| 321 |
+
if 'sorted_general_strings' not in locals():
|
| 322 |
+
sorted_general_strings = ""
|
| 323 |
+
if 'final_categorized_output' not in locals():
|
| 324 |
+
final_categorized_output = ""
|
| 325 |
+
if 'classified_tags' not in locals():
|
| 326 |
+
classified_tags = {}
|
| 327 |
+
if 'rating' not in locals():
|
| 328 |
+
rating = {}
|
| 329 |
+
if 'character_res' not in locals():
|
| 330 |
+
character_res = {}
|
| 331 |
+
if 'general_res' not in locals():
|
| 332 |
+
general_res = {}
|
| 333 |
+
if 'unclassified_tags' not in locals():
|
| 334 |
+
unclassified_tags = []
|
| 335 |
+
|
| 336 |
+
return download, sorted_general_strings, final_categorized_output, classified_tags, rating, character_res, general_res, unclassified_tags, tag_results
|
| 337 |
def get_selection_from_gallery(gallery: list, tag_results: dict, selected_state: gr.SelectData):
|
| 338 |
if not selected_state:
|
| 339 |
return selected_state
|
|
|
|
| 345 |
"character_res": "",
|
| 346 |
"general_res": "",
|
| 347 |
"unclassified_tags": "{}",
|
| 348 |
+
"summarize_tags": ""
|
| 349 |
}
|
| 350 |
if selected_state.value["image"]["path"] in tag_results:
|
| 351 |
tag_result = tag_results[selected_state.value["image"]["path"]]
|
| 352 |
+
return (selected_state.value["image"]["path"], selected_state.value["caption"]), tag_result["strings"], tag_result["strings2"], tag_result["classified_tags"], tag_result["rating"], tag_result["character_res"], tag_result["general_res"], tag_result["unclassified_tags"], tag_result["summarize_tags"]
|
| 353 |
+
def append_gallery(gallery:list, image:str):
|
| 354 |
if gallery is None:gallery=[]
|
| 355 |
+
if not image:return gallery, None
|
| 356 |
+
gallery.append(image);return gallery, None
|
| 357 |
+
def extend_gallery(gallery:list, images):
|
| 358 |
if gallery is None:gallery=[]
|
| 359 |
if not images:return gallery
|
| 360 |
gallery.extend(images);return gallery
|
| 361 |
+
def remove_image_from_gallery(gallery:list, selected_image:str):
|
| 362 |
if not gallery or not selected_image:return gallery
|
| 363 |
selected_image=ast.literal_eval(selected_image)
|
| 364 |
if selected_image in gallery:gallery.remove(selected_image)
|
|
|
|
| 366 |
args = parse_args()
|
| 367 |
predictor = Predictor()
|
| 368 |
dropdown_list = [
|
| 369 |
+
EVA02_LARGE_MODEL_DSV3_REPO,
|
| 370 |
+
SWINV2_MODEL_DSV3_REPO,
|
| 371 |
+
CONV_MODEL_DSV3_REPO,
|
| 372 |
+
VIT_MODEL_DSV3_REPO,
|
| 373 |
+
VIT_LARGE_MODEL_DSV3_REPO,
|
| 374 |
# ---
|
| 375 |
+
MOAT_MODEL_DSV2_REPO,
|
| 376 |
+
SWIN_MODEL_DSV2_REPO,
|
| 377 |
+
CONV_MODEL_DSV2_REPO,
|
| 378 |
+
CONV2_MODEL_DSV2_REPO,
|
| 379 |
+
VIT_MODEL_DSV2_REPO,
|
| 380 |
# ---
|
| 381 |
+
SWINV2_MODEL_IS_DSV1_REPO,
|
| 382 |
+
EVA02_LARGE_MODEL_IS_DSV1_REPO,
|
| 383 |
]
|
|
|
|
| 384 |
def _restart_space():
|
| 385 |
HF_TOKEN=os.getenv('HF_TOKEN')
|
| 386 |
if not HF_TOKEN:raise ValueError('HF_TOKEN environment variable is not set.')
|
| 387 |
+
huggingface_hub.HfApi().restart_space(repo_id='Werli/Multi-Tagger', token=HF_TOKEN, factory_reboot=False)
|
| 388 |
scheduler=BackgroundScheduler()
|
| 389 |
# Add a job to restart the space every 2 days (172800 seconds)
|
| 390 |
restart_space_job = scheduler.add_job(_restart_space, "interval", seconds=172800)
|
|
|
|
| 393 |
NEXT_RESTART=f"Next Restart: {next_run_time_utc.strftime('%Y-%m-%d %H:%M:%S')} (UTC) - The space will restart every 2 days to ensure stability and performance. It uses a background scheduler to handle the restart process."
|
| 394 |
|
| 395 |
css = """
|
| 396 |
+
#custom-gallery {--row-height: 180px;display: grid;grid-auto-rows: min-content;gap: 10px;}
|
| 397 |
+
#custom-gallery .thumbnail-item {height: var(--row-height);width: 100%;position: relative;overflow: hidden;border-radius: 8px;box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);transition: transform 0.2s ease, box-shadow 0.2s ease;}
|
| 398 |
+
#custom-gallery .thumbnail-item:hover {transform: translateY(-3px);box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);}
|
| 399 |
+
#custom-gallery .thumbnail-item img {width: auto;height: 100%;max-width: 100%;max-height: var(--row-height);object-fit: contain;margin: 0 auto;display: block;}
|
| 400 |
+
#custom-gallery .thumbnail-item img.portrait {max-width: 100%;}
|
| 401 |
+
#custom-gallery .thumbnail-item img.landscape {max-height: 100%;}
|
| 402 |
+
.gallery-container {max-height: 500px;overflow-y: auto;padding-right: 0px;--size-80: 500px;}
|
| 403 |
+
.thumbnails {display: flex;position: absolute;bottom: 0;width: 120px;overflow-x: scroll;padding-top: 320px;padding-bottom: 280px;padding-left: 4px;flex-wrap: wrap;}
|
| 404 |
+
#custom-gallery .thumbnail-item img {width: auto;height: 100%;max-width: 100%;max-height: var(--row-height);object-fit: initial;width: fit-content;margin: 0px auto;display: block;}
|
| 405 |
"""
|
| 406 |
+
with gr.Blocks(title=TITLE, css=css, theme="Werli/Multi-Tagger", fill_width=True) as demo:
|
|
|
|
| 407 |
gr.Markdown(value=f"<h1 style='text-align: center; margin-bottom: 1rem'>{TITLE}</h1>")
|
| 408 |
+
#gr.Markdown(value=DESCRIPTION)
|
| 409 |
+
gr.Markdown(value=f"<p style='text-align: center;'>{DESCRIPTION}</p>")
|
| 410 |
with gr.Tab(label="Waifu Diffusion"):
|
| 411 |
with gr.Row():
|
| 412 |
with gr.Column():
|
| 413 |
+
submit = gr.Button(value="SUBMIT", variant="primary", size="lg")
|
| 414 |
with gr.Column(variant="panel"):
|
| 415 |
# Create an Image component for uploading images
|
| 416 |
image_input = gr.Image(label="Upload an Image or clicking paste from clipboard button", type="filepath", sources=["upload", "clipboard"], height=150)
|
| 417 |
with gr.Row():
|
| 418 |
upload_button = gr.UploadButton("Upload multiple images", file_types=["image"], file_count="multiple", size="sm")
|
| 419 |
remove_button = gr.Button("Remove Selected Image", size="sm")
|
| 420 |
+
gallery = gr.Gallery(
|
| 421 |
+
columns=2,
|
| 422 |
+
show_share_button=False,
|
| 423 |
+
interactive=True,
|
| 424 |
+
height="auto",
|
| 425 |
+
label="Grid of images",
|
| 426 |
+
preview=False,
|
| 427 |
+
elem_id="custom-gallery" # Added for custom styling
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
)
|
| 429 |
+
with gr.Column(variant="panel"):
|
| 430 |
+
model_repo = gr.Dropdown(dropdown_list, value=EVA02_LARGE_MODEL_DSV3_REPO, label="1st Model", )
|
| 431 |
+
PLUS = "+?"
|
| 432 |
+
gr.Markdown(value=f"<p style='text-align: center;'>{PLUS}</p>")
|
| 433 |
+
model_repo_2 = gr.Dropdown([None] + dropdown_list, value=None, label="2nd Model (Optional)", info="Select another model for diversified results.", )
|
| 434 |
with gr.Row():
|
| 435 |
+
general_thresh = gr.Slider(0, 1, step=args.score_slider_step, value=args.score_general_threshold, label="General Tags Threshold", scale=3, )
|
| 436 |
+
general_mcut_enabled = gr.Checkbox(value=False, label="Use MCut threshold", scale=1, )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 437 |
with gr.Row():
|
| 438 |
+
character_thresh = gr.Slider(0, 1, step=args.score_slider_step, value=args.score_character_threshold, label="Character Tags Threshold", scale=3, )
|
| 439 |
+
character_mcut_enabled = gr.Checkbox(value=False, label="Use MCut threshold", scale=1, )
|
|
|
|
|
|
|
|
|
|
| 440 |
with gr.Row():
|
| 441 |
+
characters_merge_enabled = gr.Checkbox(value=True, label="Merge characters into the string output", scale=1, )
|
| 442 |
+
with gr.Row():
|
| 443 |
+
beautify_model_repo = gr.Dropdown([None] + beautify_list, value=None, label="Beautify Model", info="Use a model to describe or 'beautify' a single image into a readable English article.", )
|
|
|
|
|
|
|
|
|
|
| 444 |
with gr.Row():
|
| 445 |
additional_tags_prepend = gr.Text(label="Prepend Additional tags (comma split)")
|
| 446 |
additional_tags_append = gr.Text(label="Append Additional tags (comma split)")
|
| 447 |
with gr.Row():
|
| 448 |
clear = gr.ClearButton(
|
| 449 |
+
components=[gallery, model_repo, general_thresh, general_mcut_enabled, character_thresh, character_mcut_enabled, characters_merge_enabled, beautify_model_repo, additional_tags_prepend, additional_tags_append, ], variant="secondary", size="lg", )
|
| 450 |
+
with gr.Row():
|
| 451 |
+
rating = gr.Label(label="Rating")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 452 |
with gr.Column(variant="panel"):
|
| 453 |
+
download_file = gr.File(label="Download") # 0
|
| 454 |
character_res = gr.Label(label="Output (characters)") # 1
|
| 455 |
+
sorted_general_strings = gr.Textbox(label="Output", show_label=True, show_copy_button=True, lines=5) # 2
|
| 456 |
+
final_categorized_output = gr.Textbox(label="Categorized", info="If tagging multiple images and got long tags, please select an image to display tags correctly.", show_label=True, show_copy_button=True, lines=5) # 3
|
| 457 |
+
pe_generate_btn = gr.Button(value="SUMMARIZE TAGS", size="lg", variant="primary") # 4
|
| 458 |
+
summarize_tags = gr.Textbox(label="Summarized Tags", show_label=True, show_copy_button=True, lines=6) # 5
|
| 459 |
+
prompt_summarizer_model = gr.Radio(["Medium", "Long", "Flux"], label="Model Choice", value="Medium", info="Summarize your prompts with medium or long answers. It's recommended for Flux.") # 6
|
| 460 |
+
categorized = gr.JSON(label="Categorized (tags) - JSON") # 7
|
| 461 |
+
general_res = gr.Label(label="Output (tags)") # 8
|
| 462 |
+
unclassified = gr.JSON(label="Unclassified (tags)") # 9
|
| 463 |
+
clear.add([download_file, sorted_general_strings, final_categorized_output, categorized, rating, character_res, general_res, unclassified, prompt_summarizer_model, summarize_tags, ])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 464 |
tag_results = gr.State({})
|
| 465 |
# Define the event listener to add the uploaded image to the gallery
|
| 466 |
image_input.change(append_gallery, inputs=[gallery, image_input], outputs=[gallery, image_input])
|
| 467 |
+
# When the upload button is clicked, add the new images to the gallery
|
| 468 |
upload_button.upload(extend_gallery, inputs=[gallery, upload_button], outputs=gallery)
|
| 469 |
# Event to update the selected image when an image is clicked in the gallery
|
| 470 |
selected_image = gr.Textbox(label="Selected Image", visible=False)
|
| 471 |
+
gallery.select(get_selection_from_gallery, inputs=[gallery, tag_results], outputs=[selected_image, sorted_general_strings, final_categorized_output, categorized, rating, character_res, general_res, unclassified, summarize_tags])
|
| 472 |
# Event to remove a selected image from the gallery
|
| 473 |
remove_button.click(remove_image_from_gallery, inputs=[gallery, selected_image], outputs=gallery)
|
| 474 |
+
# Event to for the Prompt Beautify Button
|
| 475 |
+
pe_generate_btn.click(lambda tags, model:prompt_summarizer('', '', tags, model)[0], inputs=[final_categorized_output, prompt_summarizer_model], outputs=[summarize_tags])
|
| 476 |
+
submit.click(predictor.predict, inputs=[gallery, model_repo, model_repo_2, general_thresh, general_mcut_enabled, character_thresh, character_mcut_enabled, characters_merge_enabled, beautify_model_repo, additional_tags_prepend, additional_tags_append, tag_results, ], outputs=[download_file, sorted_general_strings, final_categorized_output, categorized, rating, character_res, general_res, unclassified, tag_results, ], )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 477 |
gr.Examples(
|
| 478 |
[["images/1girl.png", VIT_LARGE_MODEL_DSV3_REPO, 0.35, False, 0.85, False]],
|
| 479 |
+
inputs=[image_input, model_repo, general_thresh, general_mcut_enabled, character_thresh, character_mcut_enabled, ],)
|
| 480 |
+
gr.Markdown(NEXT_RESTART)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
with gr.Tab("Booru Image Fetcher"):
|
| 482 |
with gr.Row():
|
| 483 |
with gr.Column():
|
| 484 |
gr.Markdown("### ⚙️ Search Parameters")
|
| 485 |
+
site = gr.Dropdown(label="Select Source", choices=["Gelbooru (Not working)", "Rule34", "Xbooru"], value="Xbooru")
|
| 486 |
+
Tags = gr.Textbox(label="Tags (comma-separated)", placeholder="e.g. solo, 1girl, 1boy, artist name, character, black hair, granblue fantasy, ...", lines=3)
|
| 487 |
+
exclude_tags = gr.Textbox(label="Exclude Tags (comma-separated)", placeholder="e.g. animated, watermark, username, ...", lines=3)
|
| 488 |
score = gr.Number(label="Minimum Score", value=0)
|
| 489 |
count = gr.Slider(label="Number of Images", minimum=1, maximum=20, step=1, value=1)
|
| 490 |
Safe = gr.Checkbox(label="Include Safe", value=True)
|
| 491 |
Questionable = gr.Checkbox(label="Include Questionable", value=True)
|
| 492 |
+
Explicit = gr.Checkbox(label="Include Explicit (18+)", value=False)
|
| 493 |
submit_btn = gr.Button("Fetch Images", variant="primary")
|
|
|
|
| 494 |
with gr.Column():
|
| 495 |
gr.Markdown("### 📄 Results")
|
| 496 |
images_output = gr.Gallery(label="Images", columns=3, rows=2, object_fit="contain", height=500)
|
| 497 |
+
tags_output = gr.Textbox(label="Tags", placeholder="Select an image to display tags", lines=6, show_copy_button=True)
|
| 498 |
post_url_output = gr.Textbox(label="Post URL", lines=1, show_copy_button=True)
|
| 499 |
image_url_output = gr.Textbox(label="Image URL", lines=1, show_copy_button=True)
|
|
|
|
| 500 |
# State to store tags, URLs
|
| 501 |
tags_state = gr.State([])
|
| 502 |
post_url_state = gr.State([])
|
| 503 |
image_url_state = gr.State([])
|
| 504 |
+
submit_btn.click(fn=booru_gradio, inputs=[Tags, exclude_tags, score, count, Safe, Questionable, Explicit, site], outputs=[images_output, tags_state, post_url_state, image_url_state], )
|
| 505 |
+
images_output.select(fn=on_select, inputs=[tags_state, post_url_state, image_url_state], outputs=[tags_output, post_url_output, image_url_output], )
|
| 506 |
+
with gr.Tab(label="Misc"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 507 |
with gr.Row():
|
| 508 |
with gr.Column(variant="panel"):
|
| 509 |
+
input_tags = gr.Textbox(label="Input Tags", placeholder="1girl, cat, horns, blue hair, ...\nor\n? 1girl 1234567? cat 1234567? horns 1234567? blue hair 1234567? ...", lines=4)
|
| 510 |
+
submit_button = gr.Button(value="SUBMIT", variant="primary", size="lg")
|
| 511 |
with gr.Column(variant="panel"):
|
| 512 |
categorized_string = gr.Textbox(label="Categorized (string)", show_label=True, show_copy_button=True, lines=8)
|
| 513 |
categorized_json = gr.JSON(label="Categorized (tags) - JSON")
|
| 514 |
submit_button.click(process_tags, inputs=[input_tags], outputs=[categorized_string, categorized_json])
|
| 515 |
with gr.Column(variant="panel"):
|
| 516 |
+
pe_generate_btn = gr.Button(value="SUMMARIZE TAGS", size="lg", variant="primary")
|
| 517 |
+
summarize_tags = gr.Textbox(label="Summarized Tags", show_label=True, show_copy_button=True, lines=5)
|
| 518 |
+
prompt_summarizer_model = gr.Radio(["Medium", "Long", "Flux"], label="Model Choice", value="Medium", info="Summarize your prompts with medium or long answers. It's recommended for Flux.")
|
| 519 |
+
pe_generate_btn.click(lambda tags, model:prompt_summarizer('', '', tags, model)[0], inputs=[categorized_string, prompt_summarizer_model], outputs=[summarize_tags])
|
| 520 |
+
demo.queue(max_size=10).launch(show_error=True)
|
images/1girl.png
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
modules/beautify_model.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import io,copy,requests,spaces,gradio as gr,numpy as np
|
| 3 |
+
from transformers import T5ForConditionalGeneration, T5Tokenizer
|
| 4 |
+
|
| 5 |
+
LAMINI_PROMPT_LONG= "gokaygokay/Lamini-Prompt-Enchance-Long"
|
| 6 |
+
|
| 7 |
+
class beautify_class:
|
| 8 |
+
def __init__(self, repoId: str, device: str = None, loadModel: bool = False):
|
| 9 |
+
self.modelPath = self.download_model(repoId)
|
| 10 |
+
if device is None:
|
| 11 |
+
import torch
|
| 12 |
+
self.totalVram = 0
|
| 13 |
+
if torch.cuda.is_available():
|
| 14 |
+
try:
|
| 15 |
+
deviceId = torch.cuda.current_device()
|
| 16 |
+
self.totalVram = torch.cuda.get_device_properties(deviceId).total_memory / (1024 * 1024 * 1024)
|
| 17 |
+
except Exception as e:
|
| 18 |
+
print(traceback.format_exc())
|
| 19 |
+
print("Error detect vram: " + str(e))
|
| 20 |
+
device = "cuda" if self.totalVram > (8 if "8B" in repoId else 4) else "cpu"
|
| 21 |
+
else:
|
| 22 |
+
device = "cpu"
|
| 23 |
+
self.device = device
|
| 24 |
+
self.system_prompt = "Summarize, beautify and enhance the following English labels describing a single image into a readable English article:\n\n"
|
| 25 |
+
if loadModel:
|
| 26 |
+
self.load_model()
|
| 27 |
+
|
| 28 |
+
def download_model(self, repoId):
|
| 29 |
+
import huggingface_hub
|
| 30 |
+
allowPatterns = [
|
| 31 |
+
#"tf_model.h5",
|
| 32 |
+
#"model.ckpt.index",
|
| 33 |
+
#"flax_model.msgpack",
|
| 34 |
+
#"pytorch_model.bin",
|
| 35 |
+
"config.json",
|
| 36 |
+
"generation_config.json",
|
| 37 |
+
"model.safetensors",
|
| 38 |
+
"tokenizer.json",
|
| 39 |
+
"tokenizer_config.json",
|
| 40 |
+
"special_tokens_map.json",
|
| 41 |
+
"vocab.json",
|
| 42 |
+
"added_tokens.json",
|
| 43 |
+
"spiece.model"
|
| 44 |
+
]
|
| 45 |
+
kwargs = {"allow_patterns": allowPatterns,}
|
| 46 |
+
try:
|
| 47 |
+
return huggingface_hub.snapshot_download(repoId, **kwargs)
|
| 48 |
+
except (huggingface_hub.utils.HfHubHTTPError, requests.exceptions.ConnectionError) as exception:
|
| 49 |
+
import warnings
|
| 50 |
+
warnings.warn(
|
| 51 |
+
"An error occurred while synchronizing the model %s from the Hugging Face Hub:\n%s",
|
| 52 |
+
repoId,
|
| 53 |
+
exception,
|
| 54 |
+
)
|
| 55 |
+
warnings.warn(
|
| 56 |
+
"Trying to load the model directly from the local cache, if it exists."
|
| 57 |
+
)
|
| 58 |
+
kwargs["local_files_only"] = True
|
| 59 |
+
return huggingface_hub.snapshot_download(repoId, **kwargs)
|
| 60 |
+
|
| 61 |
+
def load_model(self):
|
| 62 |
+
import transformers
|
| 63 |
+
try:
|
| 64 |
+
print('\n\nLoading model: %s\n\n' % self.modelPath)
|
| 65 |
+
self.Tokenizer = T5Tokenizer.from_pretrained(self.modelPath)
|
| 66 |
+
self.Model = T5ForConditionalGeneration.from_pretrained(self.modelPath).to(self.device)
|
| 67 |
+
except Exception as e:
|
| 68 |
+
self.release_vram()
|
| 69 |
+
raise e
|
| 70 |
+
|
| 71 |
+
def release_vram(self):
|
| 72 |
+
try:
|
| 73 |
+
import torch
|
| 74 |
+
if torch.cuda.is_available():
|
| 75 |
+
if getattr(self, "Model", None) is not None:
|
| 76 |
+
self.Model.to('cpu')
|
| 77 |
+
del self.Model
|
| 78 |
+
if getattr(self, "Tokenizer", None) is not None:
|
| 79 |
+
del self.Tokenizer
|
| 80 |
+
import gc
|
| 81 |
+
gc.collect()
|
| 82 |
+
torch.cuda.empty_cache()
|
| 83 |
+
print("release vram end.")
|
| 84 |
+
except Exception as e:
|
| 85 |
+
print(traceback.format_exc())
|
| 86 |
+
print("Error release vram: " + str(e))
|
| 87 |
+
|
| 88 |
+
def beautify(self, text: str, max_length: int = 400):
|
| 89 |
+
try:
|
| 90 |
+
input_ids = self.Tokenizer(self.system_prompt + text, return_tensors="pt").input_ids.to(self.device)
|
| 91 |
+
output = self.Model.generate(input_ids, max_length=max_length, no_repeat_ngram_size=3, num_beams=2, early_stopping=True)
|
| 92 |
+
result = self.Tokenizer.decode(output[0], skip_special_tokens=True)
|
| 93 |
+
return result
|
| 94 |
+
except Exception as e:
|
| 95 |
+
print(traceback.format_exc())
|
| 96 |
+
print("Error found: " + str(e))
|
| 97 |
+
return None
|
| 98 |
+
|
| 99 |
+
beautify_list=[LAMINI_PROMPT_LONG]
|
modules/classifyTags.py
CHANGED
|
@@ -1,157 +1,156 @@
|
|
| 1 |
-
from collections import defaultdict
|
| 2 |
-
import re
|
| 3 |
-
# Define grouping rules (categories and keywords)
|
| 4 |
-
# Provided categories and reversed_categories
|
| 5 |
-
categories={
|
| 6 |
-
'Explicit':['sex', '69', 'paizuri', 'cum', 'precum', 'areola_slip', 'hetero', 'erection', 'oral', 'fellatio', 'yaoi', 'ejaculation', 'ejaculating', 'masturbation', 'handjob', 'bulge', 'rape', '_rape', 'doggystyle', 'threesome', 'missionary', 'object_insertion', 'nipple', 'nipples', 'pussy', 'anus', 'penis', 'groin', 'testicles', 'testicle', 'anal', 'cameltoe', 'areolae', 'dildo', 'clitoris', 'top-down_bottom-up', 'gag', 'groping', 'gagged', 'gangbang', 'orgasm', 'femdom', 'incest', 'bukkake', 'breast_out', 'vaginal', 'vagina', 'public_indecency', 'breast_sucking', 'folded', 'cunnilingus', '_cunnilingus', 'foreskin', 'bestiality', 'footjob', 'uterus', 'womb', 'flaccid', 'defloration', 'butt_plug', 'cowgirl_position', 'reverse_cowgirl_position', 'squatting_cowgirl_position', 'reverse_upright_straddle', 'irrumatio', 'deepthroat', 'pokephilia', 'gaping', 'orgy', 'cleft_of_venus', 'futanari', 'futasub', 'futa', 'cumdrip', 'fingering', 'vibrator', 'partially_visible_vulva', 'penetration', 'penetrated', 'cumshot', 'exhibitionism', 'breast_milk', 'grinding', 'clitoral', 'urethra', 'phimosis', 'cervix', 'impregnation', 'tribadism', 'molestation', 'pubic_hair', 'clothed_female_nude_male', 'clothed_male_nude_female', 'clothed_female_nude_female', 'clothed_male_nude_male', 'sex_machine', 'milking_machine', 'ovum', 'chikan', 'pussy_juice_drip_through_clothes', 'ejaculating_while_penetrated', 'suspended_congress', 'reverse_suspended_congress', 'spread_pussy_under_clothes', 'anilingus', 'reach-around', 'humping', 'consensual_tentacles', 'tentacle_pit', 'cum_in_'],
|
| 7 |
-
'Appearance Status':['backless', 'bandaged_neck', 'bleeding', 'blood', '_blood', 'blush', 'body_writing', 'bodypaint', 'bottomless', 'breath', 'bruise', 'butt_crack', 'cold', 'covered_mouth', 'crack', 'cross-section', 'crotchless', 'crying', 'curvy', 'cuts', 'dirty', 'dripping', 'drunk', 'from_mouth', 'glowing', 'hairy', 'halterneck', 'hot', 'injury', 'latex', 'leather', 'levitation', 'lipstick_mark', '_markings', 'makeup', 'mole', 'moles', 'no_bra', 'nosebleed', 'nude', 'outfit', 'pantylines', 'peeing', 'piercing', '_piercing', 'piercings', 'pregnant', 'public_nudity', 'reverse', '_skin', '_submerged', 'saliva', 'scar', 'scratches', 'see-through', 'shadow', 'shibari', 'sideless', 'skindentation', 'sleeping', 'tan', 'soap_bubbles', 'steam', 'steaming_body', 'stitches', 'sweat', 'sweatdrop', 'sweaty', 'tanlines', 'tattoo', 'tattoo', 'tears', 'topless', 'transparent', 'trefoil', 'trembling', 'veins', 'visible_air', 'wardrobe_malfunction', 'wet', 'x-ray', 'unconscious', 'handprint'],
|
| 8 |
-
'Action Pose':['afloat', 'afterimage', 'against_fourth_wall', 'against_wall', 'aiming', 'all_fours',"another's_mouth",'arm_', 'arm_support', 'arms_', 'arms_behind_back', 'asphyxiation', 'attack', 'back', 'ballet', 'bara', 'bathing', 'battle', 'bdsm', 'beckoning', 'bent_over', 'bite_mark', 'biting', 'bondage', 'breast_suppress', 'breathing', 'burning', 'bust_cup', 'carry', 'carrying', 'caught', 'chained', 'cheek_squash', 'chewing', 'cigarette', 'clapping', 'closed_eye', 'come_hither', 'cooking', 'covering', 'cuddling', 'dancing', '_docking', 'destruction', 'dorsiflexion', 'dreaming', 'dressing', 'drinking', 'driving', 'dropping', 'eating', 'exercise', 'expansion', 'exposure', 'facing', 'failure', 'fallen_down', 'falling', 'feeding', 'fetal_position', 'fighting', 'finger_on_trigger', 'finger_to_cheek', 'finger_to_mouth', 'firing', 'fishing', 'flashing', 'fleeing', 'flexible', 'flexing', 'floating', 'flying', 'fourth_wall', 'freediving', 'frogtie', '_grab', 'girl_on_top', 'giving', 'grabbing', 'grabbing_', 'gymnastics', '_hold', 'hadanugi_dousa', 'hairdressing', 'hand_', 'hand_on', 'hand_on_wall', 'hands_', 'headpat', 'hiding', 'holding', 'hug', 'hugging', 'imagining', 'in_container', 'in_mouth', 'in_palm', 'jealous', 'jumping', 'kabedon', 'kicking', 'kiss', 'kissing', 'kneeling', '_lift', 'lactation', 'laundry', 'licking', 'lifted_by_self', 'looking', 'lowleg', 'lying', 'melting', 'midair', 'moaning', '_open', 'on_back', 'on_bed', 'on_ground', 'on_lap', 'on_one_knee', 'one_eye_closed', 'open_', 'over_mouth', 'own_mouth', '_peek', '_pose', '_press', '_pull', 'padding', 'paint', 'painting_(action)', 'palms_together', 'pee', 'peeking', 'pervert', 'petting', 'pigeon-toed', 'piggyback', 'pinching', 'pinky_out', 'pinned', 'plantar_flexion', 'planted', 'playing', 'pocky', 'pointing', 'poke', 'poking', 'pouring', 'pov', 'praying', 'presenting', 'profanity', 'pulled_by_self', 'pulling', 'pump_action', 'punching', '_rest', 'raised', 'reaching', 'reading', 'reclining', 'reverse_grip', 'riding', 'running', '_slip', 'salute', 'screaming', 'seiza', 'selfie', 'sewing', 'shaking', 'shoe_dangle', 'shopping', 'shouting', 'showering', 'shushing', 'singing', 'sitting', 'slapping', 'smell', 'smelling', 'smoking', 'smother', 'solo', 'spanked', 'spill', 'spilling', 'spinning', 'splashing', 'split', 'squatting', 'squeezed', 'breasts_squeezed_together', 'standing', 'standing_on_', 'staring', 'straddling', 'strangling', 'stretching', 'surfing', 'suspension', 'swimming', 'talking', 'teardrop', 'tearing_clothes', 'throwing', 'tied_up', 'tiptoes', 'toe_scrunch', 'toothbrush', 'trigger_discipline', 'tripping', 'tsundere', 'turning_head', 'twitching', 'two-handed', 'tying', '_up', 'unbuttoned', 'undressed', 'undressing', 'unsheathed', 'unsheathing', 'unzipped', 'unzipping', 'upright_straddle', 'v', 'V', 'vore', '_wielding', 'wading', 'walk-in', 'walking', 'wariza', 'waving', 'wedgie', 'wrestling', 'writing', 'yawning', 'yokozuwari', '_conscious', 'massage', 'struggling', 'shrugging', 'drugged', 'tentacles_under_clothes', 'restrained_by_tentacles', 'tentacles_around_arms', 'tentacles_around_legs', 'restrained_legs', 'restrained_tail', 'restrained_arms', 'tentacles_on_female', 'archery', 'cleaning', 'tempura', 'facepalm', 'sadism'],
|
| 9 |
-
'Headwear':['antennae', 'antlers', 'aura', 'bandaged_head', 'bandana', 'bandeau', 'beanie', 'beanie', 'beret', 'bespectacled', 'blindfold', 'bonnet', '_cap', 'circlet', 'crown', '_drill', '_drills', 'diadem', '_eyewear', 'ear_covers', 'ear_ornament', 'ear_tag', 'earbuds', 'earclip', 'earmuffs', 'earphones', 'earpiece', 'earring', 'earrings', 'eyeliner', 'eyepatch', 'eyewear_on_head', 'facial', 'fedora', 'glasses', 'goggles', '_headwear', 'hachimaki', 'hair_bobbles', 'hair_ornament', 'hair_rings', 'hair_tie', 'hairband', 'hairclip', 'hairpin', 'hairpods', 'halo', 'hat', 'head-mounted_display', 'head_wreath', 'headband', 'headdress', 'headgear', 'headphones', 'headpiece', 'headset', 'helm', 'helmet', 'hood', 'kabuto_(helmet)', 'kanzashi', '_mask', 'maid_headdress', 'mask', 'mask', 'mechanical_ears', 'mechanical_eye', 'mechanical_horns', 'mob_cap', 'monocle', 'neck_ruff', 'nightcap', 'on_head', 'pince-nez', 'qingdai_guanmao', 'scarf_over_mouth', 'scrunchie', 'sunglasses',"tam_o'_shanter",'tate_eboshi', 'tiara', 'topknot', 'turban', 'veil', 'visor', 'wig', 'mitre', 'tricorne', 'bicorne'],
|
| 10 |
-
'Handwear':['arm_warmers', 'armband', 'armlet', 'bandaged_arm', 'bandaged_fingers', 'bandaged_hand', 'bandaged_wrist', 'bangle', 'bracelet', 'bracelets', 'bracer', 'cuffs', 'elbow_pads', '_gauntlets', '_glove', '_gloves', 'gauntlets', 'gloves', 'kote', 'kurokote', 'mechanical_arm', 'mechanical_arms', 'mechanical_hands', 'mittens', 'mitts', 'nail_polish', 'prosthetic_arm', 'wrist_cuffs', 'wrist_guards', 'wristband', 'yugake'],
|
| 11 |
-
'One-Piece Outfit':['bodystocking', 'bodysuit', 'dress', 'furisode', 'gown', 'hanfu', 'jumpsuit', 'kimono', 'leotard', 'microdress', 'one-piece', 'overalls', 'robe', 'spacesuit', 'sundress', 'yukata'],
|
| 12 |
-
'Upper Body Clothing':['aiguillette', 'apron', '_apron', 'armor', '_armor', 'ascot', 'babydoll', 'bikini', '_bikini', 'blazer', '_blazer', 'blouse', '_blouse', 'bowtie', '_bowtie', 'bra', '_bra', 'breast_curtain', 'breast_curtains', 'breast_pocket', 'breastplate', 'bustier', 'camisole', 'cape', 'capelet', 'cardigan', 'center_opening', 'chemise', 'chest_jewel', 'choker', 'cloak', 'coat', 'coattails', 'collar', '_collar', 'corset', 'criss-cross_halter', 'crop_top', 'dougi', 'feather_boa', 'gakuran', 'hagoromo', 'hanten_(clothes)', 'haori', 'harem_pants', 'harness', 'hoodie', 'jacket', '_jacket', 'japanese_clothes', 'kappougi', 'kariginu', 'lapels', 'lingerie', '_lingerie', 'maid', 'mechanical_wings', 'mizu_happi', 'muneate', 'neckerchief', 'necktie', 'negligee', 'nightgown', 'pajamas', '_pajamas', 'pauldron', 'pauldrons', 'plunging_neckline', 'raincoat', 'rei_no_himo', 'sailor_collar', 'sarashi', 'scarf', 'serafuku', 'shawl', 'shirt', 'shoulder_', 'sleepwear', 'sleeve', 'sleeveless', 'sleeves', '_sleeves', 'sode', 'spaghetti_strap', 'sportswear', 'strapless', 'suit', 'sundress', 'suspenders', 'sweater', 'swimsuit', '_top', '_torso', 't-shirt', 'tabard', 'tailcoat', 'tank_top', 'tasuki', 'tie_clip', 'tunic', 'turtleneck', 'tuxedo', '_uniform', 'undershirt', 'uniform', 'v-neck', 'vambraces', 'vest', 'waistcoat'],
|
| 13 |
-
'Lower Body Clothing':['bare_hips', 'bloomers', 'briefs', 'buruma', 'crotch_seam', 'cutoffs', 'denim', 'faulds', 'fundoshi', 'g-string', 'garter_straps', 'hakama', 'hip_vent', 'jeans', 'knee_pads', 'loincloth', 'mechanical_tail', 'microskirt', 'miniskirt', 'overskirt', 'panties', 'pants', 'pantsu', 'panty_straps', 'pelvic_curtain', 'petticoat', 'sarong', 'shorts', 'side_slit', 'skirt', 'sweatpants', 'swim_trunks', 'thong', 'underwear', 'waist_cape'],
|
| 14 |
-
'Foot & Legwear':['anklet', 'bandaged_leg', 'boot', 'boots', '_footwear', 'flats', 'flip-flops', 'geta', 'greaves', '_heels', 'kneehigh', 'kneehighs', '_legwear', 'leg_warmers', 'leggings', 'loafers', 'mary_janes', 'mechanical_legs', 'okobo', 'over-kneehighs', 'pantyhose', 'prosthetic_leg', 'pumps', '_shoe', '_sock', 'sandals', 'shoes', 'skates', 'slippers', 'sneakers', 'socks', 'spikes', 'tabi', 'tengu-geta', 'thigh_strap', 'thighhighs', 'uwabaki', 'zouri', 'legband', 'ankleband'],
|
| 15 |
-
'Other Accessories':['alternate_', 'anklet', 'badge', 'beads', 'belt', 'belts', 'bow', 'brooch', 'buckle', 'button', 'buttons', '_clothes', '_costume', '_cutout', 'casual', 'charm', 'clothes_writing', 'clothing_aside', 'costume', 'cow_print', 'cross', 'd-pad', 'double-breasted', 'drawstring', 'epaulettes', 'fabric', 'fishnets', 'floral_print', 'formal', 'frills', '_garter', 'gem', 'holster', 'jewelry', '_knot', 'lace', 'lanyard', 'leash', 'magatama', 'mechanical_parts', 'medal', 'medallion', 'naked_bandage', 'necklace', '_ornament', '(ornament)', 'o-ring', 'obi', 'obiage', 'obijime', '_pin', '_print', 'padlock', 'patterned_clothing', 'pendant', 'piercing', 'plaid', 'pocket', 'polka_dot', 'pom_pom_(clothes)', 'pom_pom_(clothes)', 'pouch', 'ribbon', '_ribbon', '_stripe', '_stripes', 'sash', 'shackles', 'shimenawa', 'shrug_(clothing)', 'skin_tight', 'spandex', 'strap', 'sweatband', '_trim', 'tassel', 'zettai_ryouiki', 'zipper'],
|
| 16 |
-
'Facial Expression':['ahegao', 'anger_vein', 'angry', 'annoyed', 'confused', 'drooling', 'embarrassed', 'expressionless', 'eye_contact', '_face', 'frown', 'fucked_silly', 'furrowed_brow', 'glaring', 'gloom_(expression)', 'grimace', 'grin', 'happy', 'jitome', 'laughing', '_mouth', 'nervous', 'notice_lines', 'o_o', 'parted_lips', 'pout', 'puff_of_air', 'restrained', 'sad', 'sanpaku', 'scared', 'scowl', 'serious', 'shaded_face', 'shy', 'sigh', 'sleepy', 'smile', 'smirk', 'smug', 'snot', 'spoken_ellipsis', 'spoken_exclamation_mark', 'spoken_interrobang', 'spoken_question_mark', 'squiggle', 'surprised', 'tareme', 'tearing_up', 'thinking', 'tongue', 'tongue_out', 'torogao', 'tsurime', 'turn_pale', 'wide-eyed', 'wince', 'worried', 'heartbeat'],
|
| 17 |
-
'Facial Emoji':['!!', '!', '!?', '+++', '+_+', '...', '...?', '._.', '03:00', '0_0', ':/', ':3', ':<', ':>', ':>=', ':d', ':i', ':o', ':p', ':q', ':t', ':x', ':|', ';(', ';)', ';3', ';d', ';o', ';p', ';q', '=_=', '>:(', '>:)', '>_<', '>_o', '>o<', '?', '??', '@_@', '\\m/', '\n/', '\\o/', '\\||/', '^^^', '^_^', 'c:', 'd:', 'o_o', 'o3o', 'u_u', 'w', 'x', 'x_x', 'xd', 'zzz', '|_|'],
|
| 18 |
-
'Head':['afro', 'ahoge', 'animal_ear_fluff', '_bangs', '_bun', 'bald', 'beard', 'blunt_bangs', 'blunt_ends', 'bob_cut', 'bowl_cut', 'braid', 'braids', 'buzz_cut', 'circle_cut', 'colored_tips', 'cowlick', 'dot_nose', 'dreadlocks', '_ear', '_ears', '_eye', '_eyes', 'enpera', 'eyeball', 'eyebrow', 'eyebrow_cut', 'eyebrows', 'eyelashes', 'eyeshadow', 'faceless', 'facepaint', 'facial_mark', 'fang', 'forehead', 'freckles', 'goatee', '_hair', '_horn', '_horns', 'hair_', 'hair_bun', 'hair_flaps', 'hair_intakes', 'hair_tubes', 'half_updo', 'head_tilt', 'heterochromia', 'hime_cut', 'hime_cut', 'horns', 'in_eye', 'inverted_bob', 'kemonomimi_mode', 'lips', 'mascara', 'mohawk', 'mouth_', 'mustache', 'nose', 'one-eyed', 'one_eye', 'one_side_up', '_pupils', 'parted_bangs', 'pompadour', 'ponytail', 'ringlets', '_sclera', 'sideburns', 'sidecut', 'sidelock', 'sidelocks', 'skull', 'snout', 'stubble', 'swept_bangs', 'tails', 'teeth', 'third_eye', 'twintails', 'two_side_up', 'undercut', 'updo', 'v-shaped_eyebrows', 'whiskers', 'tentacle_hair'],
|
| 19 |
-
'Hands':['_arm', '_arms', 'claws', '_finger', '_fingers', 'fingernails', '_hand', '_nail', '_nails', 'palms', 'rings', 'thumbs_up'],
|
| 20 |
-
'Upper Body':['abs', 'armpit', 'armpits', 'backboob', 'belly', 'biceps', 'breast_rest', 'breasts', 'button_gap', 'cleavage', 'collarbone', 'dimples_of_venus', 'downblouse', 'flat_chest', 'linea_alba', 'median_furrow', 'midriff', 'nape', 'navel', 'pectorals', 'ribs', '_shoulder', '_shoulders', 'shoulder_blades', 'sideboob', 'sidetail', 'spine', 'stomach', 'strap_gap', 'toned', 'underboob', 'underbust'],
|
| 21 |
-
'Lower Body':['ankles', 'ass', 'barefoot', 'crotch', 'feet', 'highleg', 'hip_bones', 'hooves', 'kneepits', 'knees', 'legs', 'soles', 'tail', 'thigh_gap', 'thighlet', 'thighs', 'toenail', 'toenails', 'toes', 'wide_hips'],
|
| 22 |
-
'Creature':['(animal)', 'anglerfish', 'animal', 'bear', 'bee', 'bird', 'bug', 'butterfly', 'cat', 'chick', 'chicken', 'chinese_zodiac', 'clownfish', 'coral', 'crab', 'creature', 'crow', 'dog', 'dove', 'dragon', 'duck', 'eagle', 'fish', 'fish', 'fox', 'fox', 'frog', 'frog', 'goldfish', 'hamster', 'horse', 'jellyfish', 'ladybug', 'lion', 'mouse', 'octopus', 'owl', 'panda', 'penguin', 'pig', 'pigeon', 'rabbit', 'rooster', 'seagull', 'shark', 'sheep', 'shrimp', 'snail', 'snake', 'squid', 'starfish', 'tanuki', 'tentacles', 'goo_tentacles', 'plant_tentacles', 'crotch_tentacles', 'mechanical_tentacles', 'squidward_tentacles', 'suction_tentacles', 'penis_tentacles', 'translucent_tentacles', 'back_tentacles', 'red_tentacles', 'green_tentacles', 'blue_tentacles', 'black_tentacles', 'pink_tentacles', 'purple_tentacles', 'face_tentacles', 'tentacles_everywhere', 'milking_tentacles', 'tiger', 'turtle', 'weasel', 'whale', 'wolf', 'parrot', 'sparrow', 'unicorn'],
|
| 23 |
-
'Plant':['bamboo', 'bouquet', 'branch', 'bush', 'cherry_blossoms', 'clover', 'daisy', '(flower)', 'flower', 'flower', 'gourd', 'hibiscus', 'holly', 'hydrangea', 'leaf', 'lily_pad', 'lotus', 'moss', 'palm_leaf', 'palm_tree', 'petals', 'plant', 'plum_blossoms', 'rose', 'spider_lily', 'sunflower', 'thorns', 'tree', 'tulip', 'vines', 'wisteria', 'acorn'],
|
| 24 |
-
'Food':['apple', 'baguette', 'banana', 'baozi', 'beans', 'bento', 'berry', 'blueberry', 'bread', 'broccoli', 'burger', 'cabbage', 'cake', 'candy', 'carrot', 'cheese', 'cherry', 'chili_pepper', 'chocolate', 'coconut', 'cookie', 'corn', 'cream', 'crepe', 'cucumber', 'cucumber', 'cupcake', 'curry', 'dango', 'dessert', 'doughnut', 'egg', 'eggplant', '_(food)', '_(fruit)', 'food', 'french_fries', 'fruit', 'grapes', 'ice_cream', 'icing', 'lemon', 'lettuce', 'lollipop', 'macaron', 'mandarin_orange', 'meat', 'melon', 'mochi', 'mushroom', 'noodles', 'omelet', 'omurice', 'onigiri', 'onion', 'pancake', 'parfait', 'pasties', 'pastry', 'peach', 'pineapple', 'pizza', 'popsicle', 'potato', 'pudding', 'pumpkin', 'radish', 'ramen', 'raspberry', 'rice', 'roasted_sweet_potato', 'sandwich', 'sausage', 'seaweed', 'skewer', 'spitroast', 'spring_onion', 'strawberry', 'sushi', 'sweet_potato', 'sweets', 'taiyaki', 'takoyaki', 'tamagoyaki', 'tempurakanbea', 'toast', 'tomato', 'vegetable', 'wagashi', 'wagashi', 'watermelon', 'jam', 'popcorn'],
|
| 25 |
-
'Beverage':['alcohol', 'beer', 'coffee', 'cola', 'drink', 'juice', 'juice_box', 'milk', 'sake', 'soda', 'tea', '_tea', 'whiskey', 'wine', 'cocktail'],
|
| 26 |
-
'Music':['band', 'baton_(conducting)', 'beamed', 'cello', 'concert', 'drum', 'drumsticks', 'eighth_note', 'flute', 'guitar', 'harp', 'horn', '(instrument)', 'idol', 'instrument', 'k-pop', 'lyre', '(music)', 'megaphone', 'microphone', 'music', 'musical_note', 'phonograph', 'piano', 'plectrum', 'quarter_note', 'recorder', 'sixteenth_note', 'sound_effects', 'trumpet', 'utaite', 'violin', 'whistle'],
|
| 27 |
-
'Weapons & Equipment':['ammunition', 'arrow_(projectile)', 'axe', 'bandolier', 'baseball_bat', 'beretta_92', 'bolt_action', 'bomb', 'bullet', 'bullpup', 'cannon', 'chainsaw', 'crossbow', 'dagger', 'energy_sword', 'explosive', 'fighter_jet', 'gohei', 'grenade', 'gun', 'hammer', 'handgun', 'holstered', 'jet', 'katana', 'knife', 'kunai', 'lance', 'mallet', 'nata_(tool)', 'polearm', 'quiver', 'rapier', 'revolver', 'rifle', 'rocket_launcher', 'scabbard', 'scope', 'scythe', 'sheath', 'sheathed', 'shield', 'shotgun', 'shuriken', 'spear', 'staff', 'suppressor', 'sword', 'tank', 'tantou', 'torpedo', 'trident', '(weapon)', 'wand', 'weapon', 'whip', 'yumi_(bow)', 'h&k_hk416', 'rocket_launcher', 'heckler_&_koch', '_weapon'],
|
| 28 |
-
'Vehicles':['aircraft', 'airplane', 'bicycle', 'boat', 'car', 'caterpillar_tracks', 'flight_deck', 'helicopter', 'motor_vehicle', 'motorcycle', 'ship', 'spacecraft', 'spoiler_(automobile)', 'train', 'truck', 'watercraft', 'wheel', 'wheelbarrow', 'wheelchair', 'inflatable_raft'],
|
| 29 |
-
'Buildings':['apartment', 'aquarium', 'architecture', 'balcony', 'building', 'cafe', 'castle', 'church', 'gym', 'hallway', 'hospital', 'house', 'library', '(place)', 'porch', 'restaurant', 'restroom', 'rooftop', 'shop', 'skyscraper', 'stadium', 'stage', 'temple', 'toilet', 'tower', 'train_station', 'veranda'],
|
| 30 |
-
'Indoor':['bath', 'bathroom', 'bathtub', 'bed', 'bed_sheet', 'bedroom', 'blanket', 'bookshelf', 'carpet', 'ceiling', 'chair', 'chalkboard', 'classroom', 'counter', 'cupboard', 'curtains', 'cushion', 'dakimakura', 'desk', 'door', 'doorway', 'drawer', '_floor', 'floor', 'futon', 'indoors', 'interior', 'kitchen', 'kotatsu', 'locker', 'mirror', 'pillow', 'room', 'rug', 'school_desk', 'shelf', 'shouji', 'sink', 'sliding_doors', 'stairs', 'stool', 'storeroom', 'table', 'tatami', 'throne', 'window', 'windowsill', 'bathhouse', 'chest_of_drawers'],
|
| 31 |
-
'Outdoor':['alley', 'arch', 'beach', 'bridge', 'bus_stop', 'bush', 'cave', '(city)', 'city', 'cliff', 'crescent', 'crosswalk', 'day', 'desert', 'fence', 'ferris_wheel', 'field', 'forest', 'grass', 'graveyard', 'hill', 'lake', 'lamppost', 'moon', 'mountain', 'night', 'ocean', 'onsen', 'outdoors', 'path', 'pool', 'poolside', 'railing', 'railroad', 'river', 'road', 'rock', 'sand', 'shore', 'sky', 'smokestack', 'snow', 'snowball', 'snowman', 'street', 'sun', 'sunlight', 'sunset', 'tent', 'torii', 'town', 'tree', 'turret', 'utility_pole', 'valley', 'village', 'waterfall'],
|
| 32 |
-
'Objects':['anchor', 'android', 'armchair', '(bottle)', 'backpack', 'bag', 'ball', 'balloon', 'bandages', 'bandaid', 'bandaids', 'banknote', 'banner', 'barcode', 'barrel', 'baseball', 'basket', 'basketball', 'beachball', 'bell', 'bench', 'binoculars', 'board_game', 'bone', 'book', 'bottle', 'bowl', 'box', 'box_art', 'briefcase', 'broom', 'bucket', '(chess)', '(computer)', '(computing)', '(container)', 'cage', 'calligraphy_brush', 'camera', 'can', 'candle', 'candlestand', 'cane', 'card', 'cartridge', 'cellphone', 'chain', 'chandelier', 'chess', 'chess_piece', 'choko_(cup)', 'chopsticks', 'cigar', 'clipboard', 'clock', 'clothesline', 'coin', 'comb', 'computer', 'condom', 'controller', 'cosmetics', 'couch', 'cowbell', 'crazy_straw', 'cup', 'cutting_board', 'dice', 'digital_media_player', 'doll', 'drawing_tablet', 'drinking_straw', 'easel', 'electric_fan', 'emblem', 'envelope', 'eraser', 'feathers', 'figure', 'fire', 'fishing_rod', 'flag', 'flask', 'folding_fan', 'fork', 'frying_pan', '(gemstone)', 'game_console', 'gears', 'gemstone', 'gift', 'glass', 'glowstick', 'gold', 'handbag', 'handcuffs', 'handheld_game_console', 'hose', 'id_card', 'innertube', 'iphone',"jack-o'-lantern",'jar', 'joystick', 'key', 'keychain', 'kiseru', 'ladder', 'ladle', 'lamp', 'lantern', 'laptop', 'letter', 'letterboxed', 'lifebuoy', 'lipstick', 'liquid', 'lock', 'lotion', '_machine', 'map', 'marker', 'model_kit', 'money', 'monitor', 'mop', 'mug', 'needle', 'newspaper', 'nintendo', 'nintendo_switch', 'notebook', '(object)', 'ofuda', 'orb', 'origami', '(playing_card)', 'pack', 'paddle', 'paintbrush', 'pan', 'paper', 'parasol', 'patch', 'pc', 'pen', 'pencil', 'pencil', 'pendant_watch', 'phone', 'pill', 'pinwheel', 'plate', 'playstation', 'pocket_watch', 'pointer', 'poke_ball', 'pole', 'quill', 'racket', 'randoseru', 'remote_control', 'ring', 'rope', 'sack', 'saddle', 'sakazuki', 'satchel', 'saucer', 'scissors', 'scroll', 'seashell', 'seatbelt', 'shell', 'shide', 'shopping_cart', 'shovel', 'shower_head', 'silk', 'sketchbook', 'smartphone', 'soap', 'sparkler', 'spatula', 'speaker', 'spoon', 'statue', 'stethoscope', 'stick', 'sticker', 'stopwatch', 'string', 'stuffed_', 'stylus', 'suction_cups', 'suitcase', 'surfboard', 'syringe', 'talisman', 'tanzaku', 'tape', 'teacup', 'teapot', 'teddy_bear', 'television', 'test_tube', 'tiles', 'tokkuri', 'tombstone', 'torch', 'towel', 'toy', 'traffic_cone', 'tray', 'treasure_chest', 'uchiwa', 'umbrella', 'vase', 'vial', 'video_game', 'viewfinder', 'volleyball', 'wallet', 'watch', 'watch', 'whisk', 'whiteboard', 'wreath', 'wrench', 'wristwatch', 'yunomi', 'ace_of_hearts', 'inkwell', 'compass', 'ipod', 'sunscreen', 'rocket', 'cobblestone'],
|
| 33 |
-
'Character Design':['+boys', '+girls', '1other', '39', '_boys', '_challenge', '_connection', '_female', '_fur', '_girls', '_interface', '_male', '_man', '_person', 'abyssal_ship', 'age_difference', 'aged_down', 'aged_up', 'albino', 'alien', 'alternate_muscle_size', 'ambiguous_gender', 'amputee', 'androgynous', 'angel', 'animalization', 'ass-to-ass', 'assault_visor', 'au_ra', 'baby', 'bartender', 'beak', 'bishounen', 'borrowed_character', 'boxers', 'boy', 'breast_envy', 'breathing_fire', 'bride', 'broken', 'brother_and_sister', 'brothers', 'camouflage', 'cheating_(relationship)', 'cheerleader', 'chibi', 'child', 'clone', 'command_spell', 'comparison', 'contemporary', 'corpse', 'corruption', 'cosplay', 'couple', 'creature_and_personification', 'crossdressing', 'crossover', 'cyberpunk', 'cyborg', 'cyclops', 'damaged', 'dancer', 'danmaku', 'darkness', 'death', 'defeat', 'demon', 'disembodied_', 'draph', 'drone', 'duel', 'dwarf', 'egyptian', 'electricity', 'elezen', 'elf', 'enmaided', 'erune', 'everyone', 'evolutionary_line', 'expressions', 'fairy', 'family', 'fangs', 'fantasy', 'fashion', 'fat', 'father_and_daughter', 'father_and_son', 'fewer_digits', 'fins', 'flashback', 'fluffy', 'fumo_(doll)', 'furry', 'fusion', 'fuuin_no_tsue', 'gameplay_mechanics', 'genderswap', 'ghost', 'giant', 'giantess', 'gibson_les_paul', 'girl', 'goblin', 'groom', 'guro', 'gyaru', 'habit', 'harem', 'harpy', 'harvin', 'heads_together', 'health_bar', 'height_difference', 'hitodama', 'horror_(theme)', 'humanization', 'husband_and_wife', 'hydrokinesis', 'hypnosis', 'hyur', 'idol', 'insignia', 'instant_loss', 'interracial', 'interspecies', 'japari_bun', 'jeweled_branch_of_hourai', 'jiangshi', 'jirai_kei', 'joints', 'karakasa_obake', 'keyhole', 'kitsune', 'knight', 'kodona', 'kogal', 'kyuubi', 'lamia', 'left-handed', 'loli', 'lolita', 'look-alike', 'machinery', 'magic', 'male_focus', 'manly', 'matching_outfits', 'mature_female', 'mecha', 'mermaid', 'meta', 'miko', 'milestone_celebration', 'military', 'mind_control', 'miniboy', 'minigirl',"miqo'te",'monster', 'monsterification', 'mother_and_daughter', 'mother_and_son', 'multiple_others', 'muscular', 'nanodesu_(phrase)', 'narrow_waist', 'nekomata', 'netorare', 'ninja', 'no_humans', 'nontraditional', 'nun', 'nurse', 'object_namesake', 'obliques', 'office_lady', 'old', 'on_body', 'onee-shota', 'oni', 'orc', 'others', 'otoko_no_ko', 'oversized_object', 'paint_splatter', 'pantyshot', 'pawpads', 'persona', 'personality', 'personification', 'pet_play', 'petite', 'pirate', 'playboy_bunny', 'player_2', 'plugsuit', 'plump', 'poi', 'pokemon', 'police', 'policewoman', 'pom_pom_(cheerleading)', 'princess', 'prosthesis', 'pun', 'puppet', 'race_queen', 'radio_antenna', 'real_life_insert', 'redesign', 'reverse_trap', 'rigging', 'robot', 'rod_of_remorse', 'sailor', 'salaryman', 'samurai', 'sangvis_ferri', 'scales', 'scene_reference', 'school', 'sheikah', 'shota', 'shrine', 'siblings', 'side-by-side', 'sidesaddle', 'sisters', 'size_difference', 'skeleton', 'skinny', 'slave', 'slime_(substance)', 'soldier', 'spiked_shell', 'spokencharacter', 'steampunk', 'streetwear', 'striker_unit', 'strongman', 'submerged', 'suggestive', 'super_saiyan', 'superhero', 'surreal', 'take_your_pick', 'tall', 'talons', 'taur', 'teacher', 'team_rocket', 'three-dimensional_maneuver_gear', 'time_paradox', 'tomboy', 'traditional_youkai', 'transformation', 'trick_or_treat', 'tusks', 'twins', 'ufo', 'under_covers', 'v-fin', 'v-fin', 'vampire', 'virtual_youtuber', 'waitress', 'watching_television', 'wedding', 'what', 'when_you_see_it', 'wife_and_wife', 'wing', 'wings', 'witch', 'world_war_ii', 'yandere', 'year_of', 'yes', 'yin_yang', 'yordle',"you're_doing_it_wrong",'you_gonna_get_raped', 'yukkuri_shiteitte_ne', 'yuri', 'zombie', '(alice_in_wonderland)', '(arknights)', '(blue_archive)', '(cosplay)', '(creature)', '(emblem)', '(evangelion)', '(fate)', '(fate/stay_night)', '(ff11)', '(fire_emblem)', '(genshin_impact)', '(grimm)', '(houseki_no_kuni)', '(hyouka)', '(idolmaster)', '(jojo)', '(kancolle)', '(kantai_collection)', '(kill_la_kill)', '(league_of_legends)', '(legends)', '(lyomsnpmp)', '(machimazo)', '(madoka_magica)', '(mecha)', '(meme)', '(nier:automata)', '(organ)', '(overwatch)', '(pokemon)', '(project_moon)', '(project_sekai)', '(sao)', '(senran_kagura)', '(splatoon)', '(touhou)', '(tsukumo_sana)', '(youkai_watch)', '(yu-gi-oh!_gx)', '(zelda)', 'sextuplets', 'imperial_japanese_army', 'extra_faces', '_miku'],
|
| 34 |
-
'Composition':['abstract', 'anime_coloring', 'animification', 'back-to-back', 'bad_anatomy', 'blurry', 'border', 'bound', 'cameo', 'cheek-to-cheek', 'chromatic_aberration', 'close-up', 'collage', 'color_guide', 'colorful', 'comic', 'contrapposto', 'cover', 'cowboy_shot', 'crosshatching', 'depth_of_field', 'dominatrix', 'dutch_angle', '_focus', 'face-to-face', 'fake_screenshot', 'film_grain', 'fisheye', 'flat_color', 'foreshortening', 'from_above', 'from_behind', 'from_below', 'from_side', 'full_body', 'glitch', 'greyscale', 'halftone', 'head_only', 'heads-up_display', 'high_contrast', 'horizon', '_inset', 'inset', 'jaggy_lines', '1koma', '2koma', '3koma', '4koma', '5koma', 'leaning', 'leaning_forward', 'leaning_to_the_side', 'left-to-right_manga', 'lens_flare', 'limited_palette', 'lineart', 'lineup', 'lower_body', '(medium)', 'marker_(medium)', 'meme', 'mixed_media', 'monochrome', 'multiple_views', 'muted_color', 'oekaki', 'on_side', 'out_of_frame', 'outline', 'painting', 'parody', 'partially_colored', 'partially_underwater_shot', 'perspective', 'photorealistic', 'picture_frame', 'pillarboxed', 'portrait', 'poster_(object)', 'product_placement', 'profile', 'realistic', 'recording', 'retro_artstyle', '(style)', '_style', 'sandwiched', 'science_fiction', 'sepia', 'shikishi', 'side-by-side', 'sideways', 'sideways_glance', 'silhouette', 'sketch', 'spot_color', 'still_life', 'straight-on', 'symmetry', '(texture)', 'tachi-e', 'taking_picture', 'tegaki', 'too_many', 'traditional_media', 'turnaround', 'underwater', 'upper_body', 'upside-down', 'upskirt', 'variations', 'wide_shot', '_design', 'symbolism', 'rounded_corners', 'surrounded'],
|
| 35 |
-
'Season':['akeome', 'anniversary', 'autumn', 'birthday', 'christmas', '_day', 'festival', 'halloween', 'kotoyoro', 'nengajou', 'new_year', 'spring_(season)', 'summer', 'tanabata', 'valentine', 'winter'],
|
| 36 |
-
'Background':['_background', 'backlighting', 'bloom', 'bokeh', 'brick_wall', 'bubble', 'cable', 'caustics', 'cityscape', 'cloud', 'confetti', 'constellation', 'contrail', 'crowd', 'crystal', 'dark', 'debris', 'dusk', 'dust', 'egasumi', 'embers', 'emphasis_lines', 'energy', 'evening', 'explosion', 'fireworks', 'fog', 'footprints', 'glint', 'graffiti', 'ice', 'industrial_pipe', 'landscape', 'light', 'light_particles', 'light_rays', 'lightning', 'lights', 'moonlight', 'motion_blur', 'motion_lines', 'mountainous_horizon', 'nature', '(planet)', 'pagoda', 'people', 'pillar', 'planet', 'power_lines', 'puddle', 'rain', 'rainbow', 'reflection', 'ripples', 'rubble', 'ruins', 'scenery', 'shade', 'shooting_star', 'sidelighting', 'smoke', 'snowflakes', 'snowing', 'space', 'sparkle', 'sparks', 'speed_lines', 'spider_web', 'spotlight', 'star_(sky)', 'stone_wall', 'sunbeam', 'sunburst', 'sunrise', '_theme', 'tile_wall', 'twilight', 'wall_clock', 'wall_of_text', 'water', 'waves', 'wind', 'wire', 'wooden_wall', 'lighthouse'],
|
| 37 |
-
'Patterns':['arrow', 'bass_clef', 'blank_censor', 'circle', 'cube', 'heart', 'hexagon', 'hexagram', 'light_censor', '(pattern)', 'pattern', 'pentagram', 'roman_numeral', '(shape)', '(symbol)', 'shape', 'sign', 'symbol', 'tally', 'treble_clef', 'triangle', 'tube', 'yagasuri'],
|
| 38 |
-
'Censorship':['blur_censor', '_censor', '_censoring', 'censored', 'character_censor', 'convenient', 'hair_censor', 'heart_censor', 'identity_censor', 'maebari', 'novelty_censor', 'soap_censor', 'steam_censor', 'tail_censor', 'uncensored'],
|
| 39 |
-
'Others':['2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024', 'artist', 'artist_name', 'artistic_error', 'asian', '(company)', 'character_name', 'content_rating', 'copyright', 'cover_page', 'dated', 'english_text', 'japan', 'layer', 'logo', 'name', 'numbered', 'page_number', 'pixiv_id', '
|
| 40 |
-
'Quality Tags':['masterpiece', '_quality', 'highres', 'absurdres', 'ultra-detailed', 'lowres']}
|
| 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 |
-
|
| 76 |
-
|
| 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 |
-
if
|
| 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 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
#
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
return categorized_string, categorized_json, "" # Initialize enhanced_prompt as empty
|
|
|
|
| 1 |
+
from collections import defaultdict
|
| 2 |
+
import re
|
| 3 |
+
# Define grouping rules (categories and keywords)
|
| 4 |
+
# Provided categories and reversed_categories
|
| 5 |
+
categories={
|
| 6 |
+
'Explicit':['sex', '69', 'paizuri', 'cum', 'precum', 'areola_slip', 'hetero', 'erection', 'oral', 'fellatio', 'yaoi', 'ejaculation', 'ejaculating', 'masturbation', 'handjob', 'bulge', 'rape', '_rape', 'doggystyle', 'threesome', 'missionary', 'object_insertion', 'nipple', 'nipples', 'pussy', 'anus', 'penis', 'groin', 'testicles', 'testicle', 'anal', 'cameltoe', 'areolae', 'dildo', 'clitoris', 'top-down_bottom-up', 'gag', 'groping', 'gagged', 'gangbang', 'orgasm', 'femdom', 'incest', 'bukkake', 'breast_out', 'vaginal', 'vagina', 'public_indecency', 'breast_sucking', 'folded', 'cunnilingus', '_cunnilingus', 'foreskin', 'bestiality', 'footjob', 'uterus', 'womb', 'flaccid', 'defloration', 'butt_plug', 'cowgirl_position', 'reverse_cowgirl_position', 'squatting_cowgirl_position', 'reverse_upright_straddle', 'irrumatio', 'deepthroat', 'pokephilia', 'gaping', 'orgy', 'cleft_of_venus', 'futanari', 'futasub', 'futa', 'cumdrip', 'fingering', 'vibrator', 'partially_visible_vulva', 'penetration', 'penetrated', 'cumshot', 'exhibitionism', 'breast_milk', 'grinding', 'clitoral', 'urethra', 'phimosis', 'cervix', 'impregnation', 'tribadism', 'molestation', 'pubic_hair', 'clothed_female_nude_male', 'clothed_male_nude_female', 'clothed_female_nude_female', 'clothed_male_nude_male', 'sex_machine', 'milking_machine', 'ovum', 'chikan', 'pussy_juice_drip_through_clothes', 'ejaculating_while_penetrated', 'suspended_congress', 'reverse_suspended_congress', 'spread_pussy_under_clothes', 'anilingus', 'reach-around', 'humping', 'consensual_tentacles', 'tentacle_pit', 'cum_in_'],
|
| 7 |
+
'Appearance Status':['backless', 'bandaged_neck', 'bleeding', 'blood', '_blood', 'blush', 'body_writing', 'bodypaint', 'bottomless', 'breath', 'bruise', 'butt_crack', 'cold', 'covered_mouth', 'crack', 'cross-section', 'crotchless', 'crying', 'curvy', 'cuts', 'dirty', 'dripping', 'drunk', 'from_mouth', 'glowing', 'hairy', 'halterneck', 'hot', 'injury', 'latex', 'leather', 'levitation', 'lipstick_mark', '_markings', 'makeup', 'mole', 'moles', 'no_bra', 'nosebleed', 'nude', 'outfit', 'pantylines', 'peeing', 'piercing', '_piercing', 'piercings', 'pregnant', 'public_nudity', 'reverse', '_skin', '_submerged', 'saliva', 'scar', 'scratches', 'see-through', 'shadow', 'shibari', 'sideless', 'skindentation', 'sleeping', 'tan', 'soap_bubbles', 'steam', 'steaming_body', 'stitches', 'sweat', 'sweatdrop', 'sweaty', 'tanlines', 'tattoo', 'tattoo', 'tears', 'topless', 'transparent', 'trefoil', 'trembling', 'veins', 'visible_air', 'wardrobe_malfunction', 'wet', 'x-ray', 'unconscious', 'handprint'],
|
| 8 |
+
'Action Pose':['afloat', 'afterimage', 'against_fourth_wall', 'against_wall', 'aiming', 'all_fours',"another's_mouth",'arm_', 'arm_support', 'arms_', 'arms_behind_back', 'asphyxiation', 'attack', 'back', 'ballet', 'bara', 'bathing', 'battle', 'bdsm', 'beckoning', 'bent_over', 'bite_mark', 'biting', 'bondage', 'breast_suppress', 'breathing', 'burning', 'bust_cup', 'carry', 'carrying', 'caught', 'chained', 'cheek_squash', 'chewing', 'cigarette', 'clapping', 'closed_eye', 'come_hither', 'cooking', 'covering', 'cuddling', 'dancing', '_docking', 'destruction', 'dorsiflexion', 'dreaming', 'dressing', 'drinking', 'driving', 'dropping', 'eating', 'exercise', 'expansion', 'exposure', 'facing', 'failure', 'fallen_down', 'falling', 'feeding', 'fetal_position', 'fighting', 'finger_on_trigger', 'finger_to_cheek', 'finger_to_mouth', 'firing', 'fishing', 'flashing', 'fleeing', 'flexible', 'flexing', 'floating', 'flying', 'fourth_wall', 'freediving', 'frogtie', '_grab', 'girl_on_top', 'giving', 'grabbing', 'grabbing_', 'gymnastics', '_hold', 'hadanugi_dousa', 'hairdressing', 'hand_', 'hand_on', 'hand_on_wall', 'hands_', 'headpat', 'hiding', 'holding', 'hug', 'hugging', 'imagining', 'in_container', 'in_mouth', 'in_palm', 'jealous', 'jumping', 'kabedon', 'kicking', 'kiss', 'kissing', 'kneeling', '_lift', 'lactation', 'laundry', 'licking', 'lifted_by_self', 'looking', 'lowleg', 'lying', 'melting', 'midair', 'moaning', '_open', 'on_back', 'on_bed', 'on_ground', 'on_lap', 'on_one_knee', 'one_eye_closed', 'open_', 'over_mouth', 'own_mouth', '_peek', '_pose', '_press', '_pull', 'padding', 'paint', 'painting_(action)', 'palms_together', 'pee', 'peeking', 'pervert', 'petting', 'pigeon-toed', 'piggyback', 'pinching', 'pinky_out', 'pinned', 'plantar_flexion', 'planted', 'playing', 'pocky', 'pointing', 'poke', 'poking', 'pouring', 'pov', 'praying', 'presenting', 'profanity', 'pulled_by_self', 'pulling', 'pump_action', 'punching', '_rest', 'raised', 'reaching', 'reading', 'reclining', 'reverse_grip', 'riding', 'running', '_slip', 'salute', 'screaming', 'seiza', 'selfie', 'sewing', 'shaking', 'shoe_dangle', 'shopping', 'shouting', 'showering', 'shushing', 'singing', 'sitting', 'slapping', 'smell', 'smelling', 'smoking', 'smother', 'solo', 'spanked', 'spill', 'spilling', 'spinning', 'splashing', 'split', 'squatting', 'squeezed', 'breasts_squeezed_together', 'standing', 'standing_on_', 'staring', 'straddling', 'strangling', 'stretching', 'surfing', 'suspension', 'swimming', 'talking', 'teardrop', 'tearing_clothes', 'throwing', 'tied_up', 'tiptoes', 'toe_scrunch', 'toothbrush', 'trigger_discipline', 'tripping', 'tsundere', 'turning_head', 'twitching', 'two-handed', 'tying', '_up', 'unbuttoned', 'undressed', 'undressing', 'unsheathed', 'unsheathing', 'unzipped', 'unzipping', 'upright_straddle', 'v', 'V', 'vore', '_wielding', 'wading', 'walk-in', 'walking', 'wariza', 'waving', 'wedgie', 'wrestling', 'writing', 'yawning', 'yokozuwari', '_conscious', 'massage', 'struggling', 'shrugging', 'drugged', 'tentacles_under_clothes', 'restrained_by_tentacles', 'tentacles_around_arms', 'tentacles_around_legs', 'restrained_legs', 'restrained_tail', 'restrained_arms', 'tentacles_on_female', 'archery', 'cleaning', 'tempura', 'facepalm', 'sadism'],
|
| 9 |
+
'Headwear':['antennae', 'antlers', 'aura', 'bandaged_head', 'bandana', 'bandeau', 'beanie', 'beanie', 'beret', 'bespectacled', 'blindfold', 'bonnet', '_cap', 'circlet', 'crown', '_drill', '_drills', 'diadem', '_eyewear', 'ear_covers', 'ear_ornament', 'ear_tag', 'earbuds', 'earclip', 'earmuffs', 'earphones', 'earpiece', 'earring', 'earrings', 'eyeliner', 'eyepatch', 'eyewear_on_head', 'facial', 'fedora', 'glasses', 'goggles', '_headwear', 'hachimaki', 'hair_bobbles', 'hair_ornament', 'hair_rings', 'hair_tie', 'hairband', 'hairclip', 'hairpin', 'hairpods', 'halo', 'hat', 'head-mounted_display', 'head_wreath', 'headband', 'headdress', 'headgear', 'headphones', 'headpiece', 'headset', 'helm', 'helmet', 'hood', 'kabuto_(helmet)', 'kanzashi', '_mask', 'maid_headdress', 'mask', 'mask', 'mechanical_ears', 'mechanical_eye', 'mechanical_horns', 'mob_cap', 'monocle', 'neck_ruff', 'nightcap', 'on_head', 'pince-nez', 'qingdai_guanmao', 'scarf_over_mouth', 'scrunchie', 'sunglasses',"tam_o'_shanter",'tate_eboshi', 'tiara', 'topknot', 'turban', 'veil', 'visor', 'wig', 'mitre', 'tricorne', 'bicorne'],
|
| 10 |
+
'Handwear':['arm_warmers', 'armband', 'armlet', 'bandaged_arm', 'bandaged_fingers', 'bandaged_hand', 'bandaged_wrist', 'bangle', 'bracelet', 'bracelets', 'bracer', 'cuffs', 'elbow_pads', '_gauntlets', '_glove', '_gloves', 'gauntlets', 'gloves', 'kote', 'kurokote', 'mechanical_arm', 'mechanical_arms', 'mechanical_hands', 'mittens', 'mitts', 'nail_polish', 'prosthetic_arm', 'wrist_cuffs', 'wrist_guards', 'wristband', 'yugake'],
|
| 11 |
+
'One-Piece Outfit':['bodystocking', 'bodysuit', 'dress', 'furisode', 'gown', 'hanfu', 'jumpsuit', 'kimono', 'leotard', 'microdress', 'one-piece', 'overalls', 'robe', 'spacesuit', 'sundress', 'yukata'],
|
| 12 |
+
'Upper Body Clothing':['aiguillette', 'apron', '_apron', 'armor', '_armor', 'ascot', 'babydoll', 'bikini', '_bikini', 'blazer', '_blazer', 'blouse', '_blouse', 'bowtie', '_bowtie', 'bra', '_bra', 'breast_curtain', 'breast_curtains', 'breast_pocket', 'breastplate', 'bustier', 'camisole', 'cape', 'capelet', 'cardigan', 'center_opening', 'chemise', 'chest_jewel', 'choker', 'cloak', 'coat', 'coattails', 'collar', '_collar', 'corset', 'criss-cross_halter', 'crop_top', 'dougi', 'feather_boa', 'gakuran', 'hagoromo', 'hanten_(clothes)', 'haori', 'harem_pants', 'harness', 'hoodie', 'jacket', '_jacket', 'japanese_clothes', 'kappougi', 'kariginu', 'lapels', 'lingerie', '_lingerie', 'maid', 'mechanical_wings', 'mizu_happi', 'muneate', 'neckerchief', 'necktie', 'negligee', 'nightgown', 'pajamas', '_pajamas', 'pauldron', 'pauldrons', 'plunging_neckline', 'raincoat', 'rei_no_himo', 'sailor_collar', 'sarashi', 'scarf', 'serafuku', 'shawl', 'shirt', 'shoulder_', 'sleepwear', 'sleeve', 'sleeveless', 'sleeves', '_sleeves', 'sode', 'spaghetti_strap', 'sportswear', 'strapless', 'suit', 'sundress', 'suspenders', 'sweater', 'swimsuit', '_top', '_torso', 't-shirt', 'tabard', 'tailcoat', 'tank_top', 'tasuki', 'tie_clip', 'tunic', 'turtleneck', 'tuxedo', '_uniform', 'undershirt', 'uniform', 'v-neck', 'vambraces', 'vest', 'waistcoat'],
|
| 13 |
+
'Lower Body Clothing':['bare_hips', 'bloomers', 'briefs', 'buruma', 'crotch_seam', 'cutoffs', 'denim', 'faulds', 'fundoshi', 'g-string', 'garter_straps', 'hakama', 'hip_vent', 'jeans', 'knee_pads', 'loincloth', 'mechanical_tail', 'microskirt', 'miniskirt', 'overskirt', 'panties', 'pants', 'pantsu', 'panty_straps', 'pelvic_curtain', 'petticoat', 'sarong', 'shorts', 'side_slit', 'skirt', 'sweatpants', 'swim_trunks', 'thong', 'underwear', 'waist_cape'],
|
| 14 |
+
'Foot & Legwear':['anklet', 'bandaged_leg', 'boot', 'boots', '_footwear', 'flats', 'flip-flops', 'geta', 'greaves', '_heels', 'kneehigh', 'kneehighs', '_legwear', 'leg_warmers', 'leggings', 'loafers', 'mary_janes', 'mechanical_legs', 'okobo', 'over-kneehighs', 'pantyhose', 'prosthetic_leg', 'pumps', '_shoe', '_sock', 'sandals', 'shoes', 'skates', 'slippers', 'sneakers', 'socks', 'spikes', 'tabi', 'tengu-geta', 'thigh_strap', 'thighhighs', 'uwabaki', 'zouri', 'legband', 'ankleband'],
|
| 15 |
+
'Other Accessories':['alternate_', 'anklet', 'badge', 'beads', 'belt', 'belts', 'bow', 'brooch', 'buckle', 'button', 'buttons', '_clothes', '_costume', '_cutout', 'casual', 'charm', 'clothes_writing', 'clothing_aside', 'costume', 'cow_print', 'cross', 'd-pad', 'double-breasted', 'drawstring', 'epaulettes', 'fabric', 'fishnets', 'floral_print', 'formal', 'frills', '_garter', 'gem', 'holster', 'jewelry', '_knot', 'lace', 'lanyard', 'leash', 'magatama', 'mechanical_parts', 'medal', 'medallion', 'naked_bandage', 'necklace', '_ornament', '(ornament)', 'o-ring', 'obi', 'obiage', 'obijime', '_pin', '_print', 'padlock', 'patterned_clothing', 'pendant', 'piercing', 'plaid', 'pocket', 'polka_dot', 'pom_pom_(clothes)', 'pom_pom_(clothes)', 'pouch', 'ribbon', '_ribbon', '_stripe', '_stripes', 'sash', 'shackles', 'shimenawa', 'shrug_(clothing)', 'skin_tight', 'spandex', 'strap', 'sweatband', '_trim', 'tassel', 'zettai_ryouiki', 'zipper'],
|
| 16 |
+
'Facial Expression':['ahegao', 'anger_vein', 'angry', 'annoyed', 'confused', 'drooling', 'embarrassed', 'expressionless', 'eye_contact', '_face', 'frown', 'fucked_silly', 'furrowed_brow', 'glaring', 'gloom_(expression)', 'grimace', 'grin', 'happy', 'jitome', 'laughing', '_mouth', 'nervous', 'notice_lines', 'o_o', 'parted_lips', 'pout', 'puff_of_air', 'restrained', 'sad', 'sanpaku', 'scared', 'scowl', 'serious', 'shaded_face', 'shy', 'sigh', 'sleepy', 'smile', 'smirk', 'smug', 'snot', 'spoken_ellipsis', 'spoken_exclamation_mark', 'spoken_interrobang', 'spoken_question_mark', 'squiggle', 'surprised', 'tareme', 'tearing_up', 'thinking', 'tongue', 'tongue_out', 'torogao', 'tsurime', 'turn_pale', 'wide-eyed', 'wince', 'worried', 'heartbeat'],
|
| 17 |
+
'Facial Emoji':['!!', '!', '!?', '+++', '+_+', '...', '...?', '._.', '03:00', '0_0', ':/', ':3', ':<', ':>', ':>=', ':d', ':i', ':o', ':p', ':q', ':t', ':x', ':|', ';(', ';)', ';3', ';d', ';o', ';p', ';q', '=_=', '>:(', '>:)', '>_<', '>_o', '>o<', '?', '??', '@_@', '\\m/', '\n/', '\\o/', '\\||/', '^^^', '^_^', 'c:', 'd:', 'o_o', 'o3o', 'u_u', 'w', 'x', 'x_x', 'xd', 'zzz', '|_|'],
|
| 18 |
+
'Head':['afro', 'ahoge', 'animal_ear_fluff', '_bangs', '_bun', 'bald', 'beard', 'blunt_bangs', 'blunt_ends', 'bob_cut', 'bowl_cut', 'braid', 'braids', 'buzz_cut', 'circle_cut', 'colored_tips', 'cowlick', 'dot_nose', 'dreadlocks', '_ear', '_ears', '_eye', '_eyes', 'enpera', 'eyeball', 'eyebrow', 'eyebrow_cut', 'eyebrows', 'eyelashes', 'eyeshadow', 'faceless', 'facepaint', 'facial_mark', 'fang', 'forehead', 'freckles', 'goatee', '_hair', '_horn', '_horns', 'hair_', 'hair_bun', 'hair_flaps', 'hair_intakes', 'hair_tubes', 'half_updo', 'head_tilt', 'heterochromia', 'hime_cut', 'hime_cut', 'horns', 'in_eye', 'inverted_bob', 'kemonomimi_mode', 'lips', 'mascara', 'mohawk', 'mouth_', 'mustache', 'nose', 'one-eyed', 'one_eye', 'one_side_up', '_pupils', 'parted_bangs', 'pompadour', 'ponytail', 'ringlets', '_sclera', 'sideburns', 'sidecut', 'sidelock', 'sidelocks', 'skull', 'snout', 'stubble', 'swept_bangs', 'tails', 'teeth', 'third_eye', 'twintails', 'two_side_up', 'undercut', 'updo', 'v-shaped_eyebrows', 'whiskers', 'tentacle_hair'],
|
| 19 |
+
'Hands':['_arm', '_arms', 'claws', '_finger', '_fingers', 'fingernails', '_hand', '_nail', '_nails', 'palms', 'rings', 'thumbs_up'],
|
| 20 |
+
'Upper Body':['abs', 'armpit', 'armpits', 'backboob', 'belly', 'biceps', 'breast_rest', 'breasts', 'button_gap', 'cleavage', 'collarbone', 'dimples_of_venus', 'downblouse', 'flat_chest', 'linea_alba', 'median_furrow', 'midriff', 'nape', 'navel', 'pectorals', 'ribs', '_shoulder', '_shoulders', 'shoulder_blades', 'sideboob', 'sidetail', 'spine', 'stomach', 'strap_gap', 'toned', 'underboob', 'underbust'],
|
| 21 |
+
'Lower Body':['ankles', 'ass', 'barefoot', 'crotch', 'feet', 'highleg', 'hip_bones', 'hooves', 'kneepits', 'knees', 'legs', 'soles', 'tail', 'thigh_gap', 'thighlet', 'thighs', 'toenail', 'toenails', 'toes', 'wide_hips'],
|
| 22 |
+
'Creature':['(animal)', 'anglerfish', 'animal', 'bear', 'bee', 'bird', 'bug', 'butterfly', 'cat', 'chick', 'chicken', 'chinese_zodiac', 'clownfish', 'coral', 'crab', 'creature', 'crow', 'dog', 'dove', 'dragon', 'duck', 'eagle', 'fish', 'fish', 'fox', 'fox', 'frog', 'frog', 'goldfish', 'hamster', 'horse', 'jellyfish', 'ladybug', 'lion', 'mouse', 'octopus', 'owl', 'panda', 'penguin', 'pig', 'pigeon', 'rabbit', 'rooster', 'seagull', 'shark', 'sheep', 'shrimp', 'snail', 'snake', 'squid', 'starfish', 'tanuki', 'tentacles', 'goo_tentacles', 'plant_tentacles', 'crotch_tentacles', 'mechanical_tentacles', 'squidward_tentacles', 'suction_tentacles', 'penis_tentacles', 'translucent_tentacles', 'back_tentacles', 'red_tentacles', 'green_tentacles', 'blue_tentacles', 'black_tentacles', 'pink_tentacles', 'purple_tentacles', 'face_tentacles', 'tentacles_everywhere', 'milking_tentacles', 'tiger', 'turtle', 'weasel', 'whale', 'wolf', 'parrot', 'sparrow', 'unicorn'],
|
| 23 |
+
'Plant':['bamboo', 'bouquet', 'branch', 'bush', 'cherry_blossoms', 'clover', 'daisy', '(flower)', 'flower', 'flower', 'gourd', 'hibiscus', 'holly', 'hydrangea', 'leaf', 'lily_pad', 'lotus', 'moss', 'palm_leaf', 'palm_tree', 'petals', 'plant', 'plum_blossoms', 'rose', 'spider_lily', 'sunflower', 'thorns', 'tree', 'tulip', 'vines', 'wisteria', 'acorn'],
|
| 24 |
+
'Food':['apple', 'baguette', 'banana', 'baozi', 'beans', 'bento', 'berry', 'blueberry', 'bread', 'broccoli', 'burger', 'cabbage', 'cake', 'candy', 'carrot', 'cheese', 'cherry', 'chili_pepper', 'chocolate', 'coconut', 'cookie', 'corn', 'cream', 'crepe', 'cucumber', 'cucumber', 'cupcake', 'curry', 'dango', 'dessert', 'doughnut', 'egg', 'eggplant', '_(food)', '_(fruit)', 'food', 'french_fries', 'fruit', 'grapes', 'ice_cream', 'icing', 'lemon', 'lettuce', 'lollipop', 'macaron', 'mandarin_orange', 'meat', 'melon', 'mochi', 'mushroom', 'noodles', 'omelet', 'omurice', 'onigiri', 'onion', 'pancake', 'parfait', 'pasties', 'pastry', 'peach', 'pineapple', 'pizza', 'popsicle', 'potato', 'pudding', 'pumpkin', 'radish', 'ramen', 'raspberry', 'rice', 'roasted_sweet_potato', 'sandwich', 'sausage', 'seaweed', 'skewer', 'spitroast', 'spring_onion', 'strawberry', 'sushi', 'sweet_potato', 'sweets', 'taiyaki', 'takoyaki', 'tamagoyaki', 'tempurakanbea', 'toast', 'tomato', 'vegetable', 'wagashi', 'wagashi', 'watermelon', 'jam', 'popcorn'],
|
| 25 |
+
'Beverage':['alcohol', 'beer', 'coffee', 'cola', 'drink', 'juice', 'juice_box', 'milk', 'sake', 'soda', 'tea', '_tea', 'whiskey', 'wine', 'cocktail'],
|
| 26 |
+
'Music':['band', 'baton_(conducting)', 'beamed', 'cello', 'concert', 'drum', 'drumsticks', 'eighth_note', 'flute', 'guitar', 'harp', 'horn', '(instrument)', 'idol', 'instrument', 'k-pop', 'lyre', '(music)', 'megaphone', 'microphone', 'music', 'musical_note', 'phonograph', 'piano', 'plectrum', 'quarter_note', 'recorder', 'sixteenth_note', 'sound_effects', 'trumpet', 'utaite', 'violin', 'whistle'],
|
| 27 |
+
'Weapons & Equipment':['ammunition', 'arrow_(projectile)', 'axe', 'bandolier', 'baseball_bat', 'beretta_92', 'bolt_action', 'bomb', 'bullet', 'bullpup', 'cannon', 'chainsaw', 'crossbow', 'dagger', 'energy_sword', 'explosive', 'fighter_jet', 'gohei', 'grenade', 'gun', 'hammer', 'handgun', 'holstered', 'jet', 'katana', 'knife', 'kunai', 'lance', 'mallet', 'nata_(tool)', 'polearm', 'quiver', 'rapier', 'revolver', 'rifle', 'rocket_launcher', 'scabbard', 'scope', 'scythe', 'sheath', 'sheathed', 'shield', 'shotgun', 'shuriken', 'spear', 'staff', 'suppressor', 'sword', 'tank', 'tantou', 'torpedo', 'trident', '(weapon)', 'wand', 'weapon', 'whip', 'yumi_(bow)', 'h&k_hk416', 'rocket_launcher', 'heckler_&_koch', '_weapon'],
|
| 28 |
+
'Vehicles':['aircraft', 'airplane', 'bicycle', 'boat', 'car', 'caterpillar_tracks', 'flight_deck', 'helicopter', 'motor_vehicle', 'motorcycle', 'ship', 'spacecraft', 'spoiler_(automobile)', 'train', 'truck', 'watercraft', 'wheel', 'wheelbarrow', 'wheelchair', 'inflatable_raft'],
|
| 29 |
+
'Buildings':['apartment', 'aquarium', 'architecture', 'balcony', 'building', 'cafe', 'castle', 'church', 'gym', 'hallway', 'hospital', 'house', 'library', '(place)', 'porch', 'restaurant', 'restroom', 'rooftop', 'shop', 'skyscraper', 'stadium', 'stage', 'temple', 'toilet', 'tower', 'train_station', 'veranda'],
|
| 30 |
+
'Indoor':['bath', 'bathroom', 'bathtub', 'bed', 'bed_sheet', 'bedroom', 'blanket', 'bookshelf', 'carpet', 'ceiling', 'chair', 'chalkboard', 'classroom', 'counter', 'cupboard', 'curtains', 'cushion', 'dakimakura', 'desk', 'door', 'doorway', 'drawer', '_floor', 'floor', 'futon', 'indoors', 'interior', 'kitchen', 'kotatsu', 'locker', 'mirror', 'pillow', 'room', 'rug', 'school_desk', 'shelf', 'shouji', 'sink', 'sliding_doors', 'stairs', 'stool', 'storeroom', 'table', 'tatami', 'throne', 'window', 'windowsill', 'bathhouse', 'chest_of_drawers'],
|
| 31 |
+
'Outdoor':['alley', 'arch', 'beach', 'bridge', 'bus_stop', 'bush', 'cave', '(city)', 'city', 'cliff', 'crescent', 'crosswalk', 'day', 'desert', 'fence', 'ferris_wheel', 'field', 'forest', 'grass', 'graveyard', 'hill', 'lake', 'lamppost', 'moon', 'mountain', 'night', 'ocean', 'onsen', 'outdoors', 'path', 'pool', 'poolside', 'railing', 'railroad', 'river', 'road', 'rock', 'sand', 'shore', 'sky', 'smokestack', 'snow', 'snowball', 'snowman', 'street', 'sun', 'sunlight', 'sunset', 'tent', 'torii', 'town', 'tree', 'turret', 'utility_pole', 'valley', 'village', 'waterfall'],
|
| 32 |
+
'Objects':['anchor', 'android', 'armchair', '(bottle)', 'backpack', 'bag', 'ball', 'balloon', 'bandages', 'bandaid', 'bandaids', 'banknote', 'banner', 'barcode', 'barrel', 'baseball', 'basket', 'basketball', 'beachball', 'bell', 'bench', 'binoculars', 'board_game', 'bone', 'book', 'bottle', 'bowl', 'box', 'box_art', 'briefcase', 'broom', 'bucket', '(chess)', '(computer)', '(computing)', '(container)', 'cage', 'calligraphy_brush', 'camera', 'can', 'candle', 'candlestand', 'cane', 'card', 'cartridge', 'cellphone', 'chain', 'chandelier', 'chess', 'chess_piece', 'choko_(cup)', 'chopsticks', 'cigar', 'clipboard', 'clock', 'clothesline', 'coin', 'comb', 'computer', 'condom', 'controller', 'cosmetics', 'couch', 'cowbell', 'crazy_straw', 'cup', 'cutting_board', 'dice', 'digital_media_player', 'doll', 'drawing_tablet', 'drinking_straw', 'easel', 'electric_fan', 'emblem', 'envelope', 'eraser', 'feathers', 'figure', 'fire', 'fishing_rod', 'flag', 'flask', 'folding_fan', 'fork', 'frying_pan', '(gemstone)', 'game_console', 'gears', 'gemstone', 'gift', 'glass', 'glowstick', 'gold', 'handbag', 'handcuffs', 'handheld_game_console', 'hose', 'id_card', 'innertube', 'iphone',"jack-o'-lantern",'jar', 'joystick', 'key', 'keychain', 'kiseru', 'ladder', 'ladle', 'lamp', 'lantern', 'laptop', 'letter', 'letterboxed', 'lifebuoy', 'lipstick', 'liquid', 'lock', 'lotion', '_machine', 'map', 'marker', 'model_kit', 'money', 'monitor', 'mop', 'mug', 'needle', 'newspaper', 'nintendo', 'nintendo_switch', 'notebook', '(object)', 'ofuda', 'orb', 'origami', '(playing_card)', 'pack', 'paddle', 'paintbrush', 'pan', 'paper', 'parasol', 'patch', 'pc', 'pen', 'pencil', 'pencil', 'pendant_watch', 'phone', 'pill', 'pinwheel', 'plate', 'playstation', 'pocket_watch', 'pointer', 'poke_ball', 'pole', 'quill', 'racket', 'randoseru', 'remote_control', 'ring', 'rope', 'sack', 'saddle', 'sakazuki', 'satchel', 'saucer', 'scissors', 'scroll', 'seashell', 'seatbelt', 'shell', 'shide', 'shopping_cart', 'shovel', 'shower_head', 'silk', 'sketchbook', 'smartphone', 'soap', 'sparkler', 'spatula', 'speaker', 'spoon', 'statue', 'stethoscope', 'stick', 'sticker', 'stopwatch', 'string', 'stuffed_', 'stylus', 'suction_cups', 'suitcase', 'surfboard', 'syringe', 'talisman', 'tanzaku', 'tape', 'teacup', 'teapot', 'teddy_bear', 'television', 'test_tube', 'tiles', 'tokkuri', 'tombstone', 'torch', 'towel', 'toy', 'traffic_cone', 'tray', 'treasure_chest', 'uchiwa', 'umbrella', 'vase', 'vial', 'video_game', 'viewfinder', 'volleyball', 'wallet', 'watch', 'watch', 'whisk', 'whiteboard', 'wreath', 'wrench', 'wristwatch', 'yunomi', 'ace_of_hearts', 'inkwell', 'compass', 'ipod', 'sunscreen', 'rocket', 'cobblestone'],
|
| 33 |
+
'Character Design':['+boys', '+girls', '1other', '39', '_boys', '_challenge', '_connection', '_female', '_fur', '_girls', '_interface', '_male', '_man', '_person', 'abyssal_ship', 'age_difference', 'aged_down', 'aged_up', 'albino', 'alien', 'alternate_muscle_size', 'ambiguous_gender', 'amputee', 'androgynous', 'angel', 'animalization', 'ass-to-ass', 'assault_visor', 'au_ra', 'baby', 'bartender', 'beak', 'bishounen', 'borrowed_character', 'boxers', 'boy', 'breast_envy', 'breathing_fire', 'bride', 'broken', 'brother_and_sister', 'brothers', 'camouflage', 'cheating_(relationship)', 'cheerleader', 'chibi', 'child', 'clone', 'command_spell', 'comparison', 'contemporary', 'corpse', 'corruption', 'cosplay', 'couple', 'creature_and_personification', 'crossdressing', 'crossover', 'cyberpunk', 'cyborg', 'cyclops', 'damaged', 'dancer', 'danmaku', 'darkness', 'death', 'defeat', 'demon', 'disembodied_', 'draph', 'drone', 'duel', 'dwarf', 'egyptian', 'electricity', 'elezen', 'elf', 'enmaided', 'erune', 'everyone', 'evolutionary_line', 'expressions', 'fairy', 'family', 'fangs', 'fantasy', 'fashion', 'fat', 'father_and_daughter', 'father_and_son', 'fewer_digits', 'fins', 'flashback', 'fluffy', 'fumo_(doll)', 'furry', 'fusion', 'fuuin_no_tsue', 'gameplay_mechanics', 'genderswap', 'ghost', 'giant', 'giantess', 'gibson_les_paul', 'girl', 'goblin', 'groom', 'guro', 'gyaru', 'habit', 'harem', 'harpy', 'harvin', 'heads_together', 'health_bar', 'height_difference', 'hitodama', 'horror_(theme)', 'humanization', 'husband_and_wife', 'hydrokinesis', 'hypnosis', 'hyur', 'idol', 'insignia', 'instant_loss', 'interracial', 'interspecies', 'japari_bun', 'jeweled_branch_of_hourai', 'jiangshi', 'jirai_kei', 'joints', 'karakasa_obake', 'keyhole', 'kitsune', 'knight', 'kodona', 'kogal', 'kyuubi', 'lamia', 'left-handed', 'loli', 'lolita', 'look-alike', 'machinery', 'magic', 'male_focus', 'manly', 'matching_outfits', 'mature_female', 'mecha', 'mermaid', 'meta', 'miko', 'milestone_celebration', 'military', 'mind_control', 'miniboy', 'minigirl',"miqo'te",'monster', 'monsterification', 'mother_and_daughter', 'mother_and_son', 'multiple_others', 'muscular', 'nanodesu_(phrase)', 'narrow_waist', 'nekomata', 'netorare', 'ninja', 'no_humans', 'nontraditional', 'nun', 'nurse', 'object_namesake', 'obliques', 'office_lady', 'old', 'on_body', 'onee-shota', 'oni', 'orc', 'others', 'otoko_no_ko', 'oversized_object', 'paint_splatter', 'pantyshot', 'pawpads', 'persona', 'personality', 'personification', 'pet_play', 'petite', 'pirate', 'playboy_bunny', 'player_2', 'plugsuit', 'plump', 'poi', 'pokemon', 'police', 'policewoman', 'pom_pom_(cheerleading)', 'princess', 'prosthesis', 'pun', 'puppet', 'race_queen', 'radio_antenna', 'real_life_insert', 'redesign', 'reverse_trap', 'rigging', 'robot', 'rod_of_remorse', 'sailor', 'salaryman', 'samurai', 'sangvis_ferri', 'scales', 'scene_reference', 'school', 'sheikah', 'shota', 'shrine', 'siblings', 'side-by-side', 'sidesaddle', 'sisters', 'size_difference', 'skeleton', 'skinny', 'slave', 'slime_(substance)', 'soldier', 'spiked_shell', 'spokencharacter', 'steampunk', 'streetwear', 'striker_unit', 'strongman', 'submerged', 'suggestive', 'super_saiyan', 'superhero', 'surreal', 'take_your_pick', 'tall', 'talons', 'taur', 'teacher', 'team_rocket', 'three-dimensional_maneuver_gear', 'time_paradox', 'tomboy', 'traditional_youkai', 'transformation', 'trick_or_treat', 'tusks', 'twins', 'ufo', 'under_covers', 'v-fin', 'v-fin', 'vampire', 'virtual_youtuber', 'waitress', 'watching_television', 'wedding', 'what', 'when_you_see_it', 'wife_and_wife', 'wing', 'wings', 'witch', 'world_war_ii', 'yandere', 'year_of', 'yes', 'yin_yang', 'yordle',"you're_doing_it_wrong",'you_gonna_get_raped', 'yukkuri_shiteitte_ne', 'yuri', 'zombie', '(alice_in_wonderland)', '(arknights)', '(blue_archive)', '(cosplay)', '(creature)', '(emblem)', '(evangelion)', '(fate)', '(fate/stay_night)', '(ff11)', '(fire_emblem)', '(genshin_impact)', '(grimm)', '(houseki_no_kuni)', '(hyouka)', '(idolmaster)', '(jojo)', '(kancolle)', '(kantai_collection)', '(kill_la_kill)', '(league_of_legends)', '(legends)', '(lyomsnpmp)', '(machimazo)', '(madoka_magica)', '(mecha)', '(meme)', '(nier:automata)', '(organ)', '(overwatch)', '(pokemon)', '(project_moon)', '(project_sekai)', '(sao)', '(senran_kagura)', '(splatoon)', '(touhou)', '(tsukumo_sana)', '(youkai_watch)', '(yu-gi-oh!_gx)', '(zelda)', 'sextuplets', 'imperial_japanese_army', 'extra_faces', '_miku'],
|
| 34 |
+
'Composition':['abstract', 'anime_coloring', 'animification', 'back-to-back', 'bad_anatomy', 'blurry', 'border', 'bound', 'cameo', 'cheek-to-cheek', 'chromatic_aberration', 'close-up', 'collage', 'color_guide', 'colorful', 'comic', 'contrapposto', 'cover', 'cowboy_shot', 'crosshatching', 'depth_of_field', 'dominatrix', 'dutch_angle', '_focus', 'face-to-face', 'fake_screenshot', 'film_grain', 'fisheye', 'flat_color', 'foreshortening', 'from_above', 'from_behind', 'from_below', 'from_side', 'full_body', 'glitch', 'greyscale', 'halftone', 'head_only', 'heads-up_display', 'high_contrast', 'horizon', '_inset', 'inset', 'jaggy_lines', '1koma', '2koma', '3koma', '4koma', '5koma', 'leaning', 'leaning_forward', 'leaning_to_the_side', 'left-to-right_manga', 'lens_flare', 'limited_palette', 'lineart', 'lineup', 'lower_body', '(medium)', 'marker_(medium)', 'meme', 'mixed_media', 'monochrome', 'multiple_views', 'muted_color', 'oekaki', 'on_side', 'out_of_frame', 'outline', 'painting', 'parody', 'partially_colored', 'partially_underwater_shot', 'perspective', 'photorealistic', 'picture_frame', 'pillarboxed', 'portrait', 'poster_(object)', 'product_placement', 'profile', 'realistic', 'recording', 'retro_artstyle', '(style)', '_style', 'sandwiched', 'science_fiction', 'sepia', 'shikishi', 'side-by-side', 'sideways', 'sideways_glance', 'silhouette', 'sketch', 'spot_color', 'still_life', 'straight-on', 'symmetry', '(texture)', 'tachi-e', 'taking_picture', 'tegaki', 'too_many', 'traditional_media', 'turnaround', 'underwater', 'upper_body', 'upside-down', 'upskirt', 'variations', 'wide_shot', '_design', 'symbolism', 'rounded_corners', 'surrounded'],
|
| 35 |
+
'Season':['akeome', 'anniversary', 'autumn', 'birthday', 'christmas', '_day', 'festival', 'halloween', 'kotoyoro', 'nengajou', 'new_year', 'spring_(season)', 'summer', 'tanabata', 'valentine', 'winter'],
|
| 36 |
+
'Background':['_background', 'backlighting', 'bloom', 'bokeh', 'brick_wall', 'bubble', 'cable', 'caustics', 'cityscape', 'cloud', 'confetti', 'constellation', 'contrail', 'crowd', 'crystal', 'dark', 'debris', 'dusk', 'dust', 'egasumi', 'embers', 'emphasis_lines', 'energy', 'evening', 'explosion', 'fireworks', 'fog', 'footprints', 'glint', 'graffiti', 'ice', 'industrial_pipe', 'landscape', 'light', 'light_particles', 'light_rays', 'lightning', 'lights', 'moonlight', 'motion_blur', 'motion_lines', 'mountainous_horizon', 'nature', '(planet)', 'pagoda', 'people', 'pillar', 'planet', 'power_lines', 'puddle', 'rain', 'rainbow', 'reflection', 'ripples', 'rubble', 'ruins', 'scenery', 'shade', 'shooting_star', 'sidelighting', 'smoke', 'snowflakes', 'snowing', 'space', 'sparkle', 'sparks', 'speed_lines', 'spider_web', 'spotlight', 'star_(sky)', 'stone_wall', 'sunbeam', 'sunburst', 'sunrise', '_theme', 'tile_wall', 'twilight', 'wall_clock', 'wall_of_text', 'water', 'waves', 'wind', 'wire', 'wooden_wall', 'lighthouse'],
|
| 37 |
+
'Patterns':['arrow', 'bass_clef', 'blank_censor', 'circle', 'cube', 'heart', 'hexagon', 'hexagram', 'light_censor', '(pattern)', 'pattern', 'pentagram', 'roman_numeral', '(shape)', '(symbol)', 'shape', 'sign', 'symbol', 'tally', 'treble_clef', 'triangle', 'tube', 'yagasuri'],
|
| 38 |
+
'Censorship':['blur_censor', '_censor', '_censoring', 'censored', 'character_censor', 'convenient', 'hair_censor', 'heart_censor', 'identity_censor', 'maebari', 'novelty_censor', 'soap_censor', 'steam_censor', 'tail_censor', 'uncensored'],
|
| 39 |
+
'Others':['2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024', 'artist', 'artist_name', 'artistic_error', 'asian', '(company)', 'character_name', 'content_rating', 'copyright', 'cover_page', 'dated', 'english_text', 'japan', 'layer', 'logo', 'name', 'numbered', 'page_number', 'pixiv_id', 'language', 'reference_sheet', 'signature', 'speech_bubble', 'subtitled', 'text', 'thank_you', 'typo', 'username', 'wallpaper', 'watermark', 'web_address', 'screwdriver', 'translated'],
|
| 40 |
+
'Quality Tags':['masterpiece', '_quality', 'highres', 'absurdres', 'ultra-detailed', 'lowres']}
|
| 41 |
+
|
| 42 |
+
# Create reversed_categories with escaped versions for pattern matching
|
| 43 |
+
reversed_categories = {}
|
| 44 |
+
for key, values in categories.items():
|
| 45 |
+
for value in values:
|
| 46 |
+
# Store both the original and escaped version for matching
|
| 47 |
+
reversed_categories[value] = key
|
| 48 |
+
if '(' in value or ')' in value:
|
| 49 |
+
escaped_value = value.replace('(', '\\(').replace(')', '\\)')
|
| 50 |
+
reversed_categories[escaped_value] = key
|
| 51 |
+
|
| 52 |
+
# Precompute keyword lengths
|
| 53 |
+
keyword_lengths = {keyword: len(keyword) for keyword in reversed_categories}
|
| 54 |
+
|
| 55 |
+
# Trie for efficient keyword matching
|
| 56 |
+
class TrieNode:
|
| 57 |
+
def __init__(self):
|
| 58 |
+
self.children = {}
|
| 59 |
+
self.category = None
|
| 60 |
+
|
| 61 |
+
def build_trie(keywords):
|
| 62 |
+
root = TrieNode()
|
| 63 |
+
for keyword, category in reversed_categories.items():
|
| 64 |
+
node = root
|
| 65 |
+
for char in keyword:
|
| 66 |
+
if char not in node.children:
|
| 67 |
+
node.children[char] = TrieNode()
|
| 68 |
+
node = node.children[char]
|
| 69 |
+
node.category = category
|
| 70 |
+
return root
|
| 71 |
+
|
| 72 |
+
trie_root = build_trie(reversed_categories)
|
| 73 |
+
|
| 74 |
+
def find_category(trie_root, tag):
|
| 75 |
+
node = trie_root
|
| 76 |
+
for char in tag:
|
| 77 |
+
if char in node.children:
|
| 78 |
+
node = node.children[char]
|
| 79 |
+
if node.category:
|
| 80 |
+
return node.category
|
| 81 |
+
else:
|
| 82 |
+
break
|
| 83 |
+
return None
|
| 84 |
+
|
| 85 |
+
def classify_tags(tags: list[str], local_test: bool = False):
|
| 86 |
+
# Dictionary for automatic classification
|
| 87 |
+
classified_tags: defaultdict[str, list] = defaultdict(list)
|
| 88 |
+
unclassified_tags: list[str] = []
|
| 89 |
+
|
| 90 |
+
# Logic for automatic grouping
|
| 91 |
+
for tag in tags:
|
| 92 |
+
classified = False
|
| 93 |
+
|
| 94 |
+
# Keep original tag for storage, create normalized version for matching
|
| 95 |
+
tag_normalized = tag.replace(" ", "_").replace("-", "_")
|
| 96 |
+
|
| 97 |
+
# Try exact match with normalized tag
|
| 98 |
+
category = find_category(trie_root, tag_normalized)
|
| 99 |
+
|
| 100 |
+
# Also try with escaped parentheses if tag contains parentheses?
|
| 101 |
+
if not category and ('(' in tag_normalized or ')' in tag_normalized):
|
| 102 |
+
tag_escaped = tag_normalized.replace("(", "\\(").replace(")", "\\)")
|
| 103 |
+
category = find_category(trie_root, tag_escaped)
|
| 104 |
+
|
| 105 |
+
if category:
|
| 106 |
+
classified = True
|
| 107 |
+
if tag not in classified_tags[category]: # Avoid duplicates
|
| 108 |
+
classified_tags[category].append(tag)
|
| 109 |
+
else:
|
| 110 |
+
# Fuzzy match
|
| 111 |
+
tag_parts = tag_normalized.split("_")
|
| 112 |
+
found_category = None
|
| 113 |
+
for keyword, keyword_length in keyword_lengths.items():
|
| 114 |
+
if keyword in tag_normalized and keyword_length > 3:
|
| 115 |
+
found_category = reversed_categories[keyword]
|
| 116 |
+
break
|
| 117 |
+
|
| 118 |
+
if found_category and tag not in classified_tags[found_category]:
|
| 119 |
+
classified_tags[found_category].append(tag)
|
| 120 |
+
classified = True
|
| 121 |
+
|
| 122 |
+
if not classified and tag not in unclassified_tags:
|
| 123 |
+
unclassified_tags.append(tag)
|
| 124 |
+
|
| 125 |
+
if local_test:
|
| 126 |
+
# Output the grouping result
|
| 127 |
+
for category, tags_in_category in classified_tags.items():
|
| 128 |
+
print(f"{category}:")
|
| 129 |
+
print(", ".join(tags_in_category))
|
| 130 |
+
print()
|
| 131 |
+
|
| 132 |
+
if len(unclassified_tags) > 0:
|
| 133 |
+
print(f"\nUnclassified tags: {len(unclassified_tags)}")
|
| 134 |
+
print(f"{unclassified_tags[:200]}") # Display some unclassified tags
|
| 135 |
+
|
| 136 |
+
return classified_tags, unclassified_tags
|
| 137 |
+
|
| 138 |
+
# Code for "Tag Categorizer" tab
|
| 139 |
+
def process_tags(input_tags: str):
|
| 140 |
+
# Split tags using regex to handle both commas and question marks
|
| 141 |
+
tags = []
|
| 142 |
+
for tag in re.split(r'[\?.,\n]+', input_tags): # Fixed regex pattern
|
| 143 |
+
tag = tag.strip()
|
| 144 |
+
if tag:
|
| 145 |
+
tag = tag.replace('_', ' ')
|
| 146 |
+
if tag: # Only add if tag is not empty after processing
|
| 147 |
+
tags.append(tag)
|
| 148 |
+
|
| 149 |
+
# Classify the cleaned tags
|
| 150 |
+
classified_tags, unclassified_tags = classify_tags(tags)
|
| 151 |
+
|
| 152 |
+
# Create the outputs
|
| 153 |
+
categorized_string = ', '.join([tag for category in classified_tags.values() for tag in category]).replace("(", "\\(").replace(")", "\\)")
|
| 154 |
+
categorized_json = {category: tags for category, tags in classified_tags.items()}
|
| 155 |
+
|
| 156 |
+
return categorized_string, categorized_json
|
|
|
modules/florence2.py
CHANGED
|
@@ -1,91 +1,91 @@
|
|
| 1 |
-
import os,io,copy,subprocess,spaces,matplotlib.pyplot as plt,matplotlib.patches as patches,random,numpy as np
|
| 2 |
-
from PIL import Image,ImageDraw,ImageFont
|
| 3 |
-
from unittest.mock import patch
|
| 4 |
-
from transformers.dynamic_module_utils import get_imports
|
| 5 |
-
from transformers import AutoProcessor,AutoModelForCausalLM
|
| 6 |
-
import gradio as gr
|
| 7 |
-
|
| 8 |
-
def fixed_get_imports(filename:str|os.PathLike)->list[str]:
|
| 9 |
-
if not str(filename).endswith('/modeling_florence2.py'):return get_imports(filename)
|
| 10 |
-
imports=get_imports(filename)
|
| 11 |
-
if'flash_attn'in imports:imports.remove('flash_attn')
|
| 12 |
-
return imports
|
| 13 |
-
@spaces.GPU
|
| 14 |
-
def get_device_type():
|
| 15 |
-
import torch
|
| 16 |
-
if torch.cuda.is_available():return'cuda'
|
| 17 |
-
elif torch.backends.mps.is_available()and torch.backends.mps.is_built():return'mps'
|
| 18 |
-
else:return'cpu'
|
| 19 |
-
device = get_device_type()
|
| 20 |
-
if (device == "cuda"):
|
| 21 |
-
subprocess.run('pip install flash-attn --no-build-isolation', env={'FLASH_ATTENTION_SKIP_CUDA_BUILD': "TRUE"}, shell=True)
|
| 22 |
-
model = AutoModelForCausalLM.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 23 |
-
processor = AutoProcessor.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 24 |
-
model.to(device)
|
| 25 |
-
else:
|
| 26 |
-
with patch("transformers.dynamic_module_utils.get_imports", fixed_get_imports):
|
| 27 |
-
model = AutoModelForCausalLM.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 28 |
-
processor = AutoProcessor.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 29 |
-
model.to(device)
|
| 30 |
-
|
| 31 |
-
colormap=['blue','orange','green','purple','brown','pink','gray','olive','cyan','red','lime','indigo','violet','aqua','magenta','coral','gold','tan','skyblue']
|
| 32 |
-
|
| 33 |
-
def fig_to_pil(fig):buf=io.BytesIO();fig.savefig(buf,format='png');buf.seek(0);return Image.open(buf)
|
| 34 |
-
@spaces.GPU
|
| 35 |
-
def run_example(task_prompt,image,text_input=None):
|
| 36 |
-
if text_input is None:prompt=task_prompt
|
| 37 |
-
else:prompt=task_prompt+text_input
|
| 38 |
-
inputs=processor(text=prompt,images=image,return_tensors='pt').to(device);generated_ids=model.generate(input_ids=inputs['input_ids'],pixel_values=inputs['pixel_values'],max_new_tokens=1024,early_stopping=False,do_sample=False,num_beams=3);generated_text=processor.batch_decode(generated_ids,skip_special_tokens=False)[0];parsed_answer=processor.post_process_generation(generated_text,task=task_prompt,image_size=(image.width,image.height));return parsed_answer
|
| 39 |
-
def plot_bbox(image,data):
|
| 40 |
-
fig,ax=plt.subplots();ax.imshow(image)
|
| 41 |
-
for(bbox,label)in zip(data['bboxes'],data['labels']):x1,y1,x2,y2=bbox;rect=patches.Rectangle((x1,y1),x2-x1,y2-y1,linewidth=1,edgecolor='r',facecolor='none');ax.add_patch(rect);plt.text(x1,y1,label,color='white',fontsize=8,bbox=dict(facecolor='red',alpha=.5))
|
| 42 |
-
ax.axis('off');return fig
|
| 43 |
-
def draw_polygons(image,prediction,fill_mask=False):
|
| 44 |
-
draw=ImageDraw.Draw(image);scale=1
|
| 45 |
-
for(polygons,label)in zip(prediction['polygons'],prediction['labels']):
|
| 46 |
-
color=random.choice(colormap);fill_color=random.choice(colormap)if fill_mask else None
|
| 47 |
-
for _polygon in polygons:
|
| 48 |
-
_polygon=np.array(_polygon).reshape(-1,2)
|
| 49 |
-
if len(_polygon)<3:print('Invalid polygon:',_polygon);continue
|
| 50 |
-
_polygon=(_polygon*scale).reshape(-1).tolist()
|
| 51 |
-
if fill_mask:draw.polygon(_polygon,outline=color,fill=fill_color)
|
| 52 |
-
else:draw.polygon(_polygon,outline=color)
|
| 53 |
-
draw.text((_polygon[0]+8,_polygon[1]+2),label,fill=color)
|
| 54 |
-
return image
|
| 55 |
-
|
| 56 |
-
def draw_ocr_bboxes(image,prediction):
|
| 57 |
-
scale=1;draw=ImageDraw.Draw(image);bboxes,labels=prediction['quad_boxes'],prediction['labels']
|
| 58 |
-
for(box,label)in zip(bboxes,labels):color=random.choice(colormap);new_box=(np.array(box)*scale).tolist();draw.polygon(new_box,width=3,outline=color);draw.text((new_box[0]+8,new_box[1]+2),'{}'.format(label),align='right',fill=color)
|
| 59 |
-
return image
|
| 60 |
-
def convert_to_od_format(data):bboxes=data.get('bboxes',[]);labels=data.get('bboxes_labels',[]);od_results={'bboxes':bboxes,'labels':labels};return od_results
|
| 61 |
-
|
| 62 |
-
def process_image(image,task_prompt,text_input=None):
|
| 63 |
-
if isinstance(image,str):image=Image.open(image)
|
| 64 |
-
else:image=Image.fromarray(image)
|
| 65 |
-
if task_prompt=='Caption':task_prompt='<CAPTION>';results=run_example(task_prompt,image);return results[task_prompt],None
|
| 66 |
-
elif task_prompt=='Detailed Caption':task_prompt='<DETAILED_CAPTION>';results=run_example(task_prompt,image);return results[task_prompt],None
|
| 67 |
-
elif task_prompt=='More Detailed Caption':task_prompt='<MORE_DETAILED_CAPTION>';results=run_example(task_prompt,image);return results,None
|
| 68 |
-
elif task_prompt=='Caption + Grounding':task_prompt='<CAPTION>';results=run_example(task_prompt,image);text_input=results[task_prompt];task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);results['<CAPTION>']=text_input;fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 69 |
-
elif task_prompt=='Detailed Caption + Grounding':task_prompt='<DETAILED_CAPTION>';results=run_example(task_prompt,image);text_input=results[task_prompt];task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);results['<DETAILED_CAPTION>']=text_input;fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 70 |
-
elif task_prompt=='More Detailed Caption + Grounding':task_prompt='<MORE_DETAILED_CAPTION>';results=run_example(task_prompt,image);text_input=results[task_prompt];task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);results['<MORE_DETAILED_CAPTION>']=text_input;fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 71 |
-
elif task_prompt=='Object Detection':task_prompt='<OD>';results=run_example(task_prompt,image);fig=plot_bbox(image,results['<OD>']);return results,fig_to_pil(fig)
|
| 72 |
-
elif task_prompt=='Dense Region Caption':task_prompt='<DENSE_REGION_CAPTION>';results=run_example(task_prompt,image);fig=plot_bbox(image,results['<DENSE_REGION_CAPTION>']);return results,fig_to_pil(fig)
|
| 73 |
-
elif task_prompt=='Region Proposal':task_prompt='<REGION_PROPOSAL>';results=run_example(task_prompt,image);fig=plot_bbox(image,results['<REGION_PROPOSAL>']);return results,fig_to_pil(fig)
|
| 74 |
-
elif task_prompt=='Caption to Phrase Grounding':task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 75 |
-
elif task_prompt=='Referring Expression Segmentation':task_prompt='<REFERRING_EXPRESSION_SEGMENTATION>';results=run_example(task_prompt,image,text_input);output_image=copy.deepcopy(image);output_image=draw_polygons(output_image,results['<REFERRING_EXPRESSION_SEGMENTATION>'],fill_mask=True);return results,output_image
|
| 76 |
-
elif task_prompt=='Region to Segmentation':task_prompt='<REGION_TO_SEGMENTATION>';results=run_example(task_prompt,image,text_input);output_image=copy.deepcopy(image);output_image=draw_polygons(output_image,results['<REGION_TO_SEGMENTATION>'],fill_mask=True);return results,output_image
|
| 77 |
-
elif task_prompt=='Open Vocabulary Detection':task_prompt='<OPEN_VOCABULARY_DETECTION>';results=run_example(task_prompt,image,text_input);bbox_results=convert_to_od_format(results['<OPEN_VOCABULARY_DETECTION>']);fig=plot_bbox(image,bbox_results);return results,fig_to_pil(fig)
|
| 78 |
-
elif task_prompt=='Region to Category':task_prompt='<REGION_TO_CATEGORY>';results=run_example(task_prompt,image,text_input);return results,None
|
| 79 |
-
elif task_prompt=='Region to Description':task_prompt='<REGION_TO_DESCRIPTION>';results=run_example(task_prompt,image,text_input);return results,None
|
| 80 |
-
elif task_prompt=='OCR':task_prompt='<OCR>';results=run_example(task_prompt,image);return results,None
|
| 81 |
-
elif task_prompt=='OCR with Region':task_prompt='<OCR_WITH_REGION>';results=run_example(task_prompt,image);output_image=copy.deepcopy(image);output_image=draw_ocr_bboxes(output_image,results['<OCR_WITH_REGION>']);return results,output_image
|
| 82 |
-
else:return'',None # Return empty string and None for unknown task prompts
|
| 83 |
-
|
| 84 |
-
single_task_list=['Caption','Detailed Caption','More Detailed Caption','Object Detection','Dense Region Caption','Region Proposal','Caption to Phrase Grounding','Referring Expression Segmentation','Region to Segmentation','Open Vocabulary Detection','Region to Category','Region to Description','OCR','OCR with Region']
|
| 85 |
-
cascaded_task_list=['Caption + Grounding','Detailed Caption + Grounding','More Detailed Caption + Grounding']
|
| 86 |
-
|
| 87 |
-
def update_task_dropdown(choice):
|
| 88 |
-
if choice == 'Cascaded task':
|
| 89 |
-
return gr.Dropdown(choices=cascaded_task_list, value='Caption + Grounding')
|
| 90 |
-
else:
|
| 91 |
return gr.Dropdown(choices=single_task_list, value='Caption')
|
|
|
|
| 1 |
+
import os,io,copy,subprocess,spaces,matplotlib.pyplot as plt,matplotlib.patches as patches,random,numpy as np
|
| 2 |
+
from PIL import Image,ImageDraw,ImageFont
|
| 3 |
+
from unittest.mock import patch
|
| 4 |
+
from transformers.dynamic_module_utils import get_imports
|
| 5 |
+
from transformers import AutoProcessor,AutoModelForCausalLM
|
| 6 |
+
import gradio as gr
|
| 7 |
+
|
| 8 |
+
def fixed_get_imports(filename:str|os.PathLike)->list[str]:
|
| 9 |
+
if not str(filename).endswith('/modeling_florence2.py'):return get_imports(filename)
|
| 10 |
+
imports=get_imports(filename)
|
| 11 |
+
if'flash_attn'in imports:imports.remove('flash_attn')
|
| 12 |
+
return imports
|
| 13 |
+
@spaces.GPU
|
| 14 |
+
def get_device_type():
|
| 15 |
+
import torch
|
| 16 |
+
if torch.cuda.is_available():return'cuda'
|
| 17 |
+
elif torch.backends.mps.is_available()and torch.backends.mps.is_built():return'mps'
|
| 18 |
+
else:return'cpu'
|
| 19 |
+
device = get_device_type()
|
| 20 |
+
if (device == "cuda"):
|
| 21 |
+
subprocess.run('pip install flash-attn --no-build-isolation', env={'FLASH_ATTENTION_SKIP_CUDA_BUILD': "TRUE"}, shell=True)
|
| 22 |
+
model = AutoModelForCausalLM.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 23 |
+
processor = AutoProcessor.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 24 |
+
model.to(device)
|
| 25 |
+
else:
|
| 26 |
+
with patch("transformers.dynamic_module_utils.get_imports", fixed_get_imports):
|
| 27 |
+
model = AutoModelForCausalLM.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 28 |
+
processor = AutoProcessor.from_pretrained("MiaoshouAI/Florence-2-base-PromptGen-v2.0", trust_remote_code=True)
|
| 29 |
+
model.to(device)
|
| 30 |
+
|
| 31 |
+
colormap=['blue','orange','green','purple','brown','pink','gray','olive','cyan','red','lime','indigo','violet','aqua','magenta','coral','gold','tan','skyblue']
|
| 32 |
+
|
| 33 |
+
def fig_to_pil(fig):buf=io.BytesIO();fig.savefig(buf,format='png');buf.seek(0);return Image.open(buf)
|
| 34 |
+
@spaces.GPU
|
| 35 |
+
def run_example(task_prompt,image,text_input=None):
|
| 36 |
+
if text_input is None:prompt=task_prompt
|
| 37 |
+
else:prompt=task_prompt+text_input
|
| 38 |
+
inputs=processor(text=prompt,images=image,return_tensors='pt').to(device);generated_ids=model.generate(input_ids=inputs['input_ids'],pixel_values=inputs['pixel_values'],max_new_tokens=1024,early_stopping=False,do_sample=False,num_beams=3);generated_text=processor.batch_decode(generated_ids,skip_special_tokens=False)[0];parsed_answer=processor.post_process_generation(generated_text,task=task_prompt,image_size=(image.width,image.height));return parsed_answer
|
| 39 |
+
def plot_bbox(image,data):
|
| 40 |
+
fig,ax=plt.subplots();ax.imshow(image)
|
| 41 |
+
for(bbox,label)in zip(data['bboxes'],data['labels']):x1,y1,x2,y2=bbox;rect=patches.Rectangle((x1,y1),x2-x1,y2-y1,linewidth=1,edgecolor='r',facecolor='none');ax.add_patch(rect);plt.text(x1,y1,label,color='white',fontsize=8,bbox=dict(facecolor='red',alpha=.5))
|
| 42 |
+
ax.axis('off');return fig
|
| 43 |
+
def draw_polygons(image,prediction,fill_mask=False):
|
| 44 |
+
draw=ImageDraw.Draw(image);scale=1
|
| 45 |
+
for(polygons,label)in zip(prediction['polygons'],prediction['labels']):
|
| 46 |
+
color=random.choice(colormap);fill_color=random.choice(colormap)if fill_mask else None
|
| 47 |
+
for _polygon in polygons:
|
| 48 |
+
_polygon=np.array(_polygon).reshape(-1,2)
|
| 49 |
+
if len(_polygon)<3:print('Invalid polygon:',_polygon);continue
|
| 50 |
+
_polygon=(_polygon*scale).reshape(-1).tolist()
|
| 51 |
+
if fill_mask:draw.polygon(_polygon,outline=color,fill=fill_color)
|
| 52 |
+
else:draw.polygon(_polygon,outline=color)
|
| 53 |
+
draw.text((_polygon[0]+8,_polygon[1]+2),label,fill=color)
|
| 54 |
+
return image
|
| 55 |
+
|
| 56 |
+
def draw_ocr_bboxes(image,prediction):
|
| 57 |
+
scale=1;draw=ImageDraw.Draw(image);bboxes,labels=prediction['quad_boxes'],prediction['labels']
|
| 58 |
+
for(box,label)in zip(bboxes,labels):color=random.choice(colormap);new_box=(np.array(box)*scale).tolist();draw.polygon(new_box,width=3,outline=color);draw.text((new_box[0]+8,new_box[1]+2),'{}'.format(label),align='right',fill=color)
|
| 59 |
+
return image
|
| 60 |
+
def convert_to_od_format(data):bboxes=data.get('bboxes',[]);labels=data.get('bboxes_labels',[]);od_results={'bboxes':bboxes,'labels':labels};return od_results
|
| 61 |
+
|
| 62 |
+
def process_image(image,task_prompt,text_input=None):
|
| 63 |
+
if isinstance(image,str):image=Image.open(image)
|
| 64 |
+
else:image=Image.fromarray(image)
|
| 65 |
+
if task_prompt=='Caption':task_prompt='<CAPTION>';results=run_example(task_prompt,image);return results[task_prompt],None
|
| 66 |
+
elif task_prompt=='Detailed Caption':task_prompt='<DETAILED_CAPTION>';results=run_example(task_prompt,image);return results[task_prompt],None
|
| 67 |
+
elif task_prompt=='More Detailed Caption':task_prompt='<MORE_DETAILED_CAPTION>';results=run_example(task_prompt,image);return results,None
|
| 68 |
+
elif task_prompt=='Caption + Grounding':task_prompt='<CAPTION>';results=run_example(task_prompt,image);text_input=results[task_prompt];task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);results['<CAPTION>']=text_input;fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 69 |
+
elif task_prompt=='Detailed Caption + Grounding':task_prompt='<DETAILED_CAPTION>';results=run_example(task_prompt,image);text_input=results[task_prompt];task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);results['<DETAILED_CAPTION>']=text_input;fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 70 |
+
elif task_prompt=='More Detailed Caption + Grounding':task_prompt='<MORE_DETAILED_CAPTION>';results=run_example(task_prompt,image);text_input=results[task_prompt];task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);results['<MORE_DETAILED_CAPTION>']=text_input;fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 71 |
+
elif task_prompt=='Object Detection':task_prompt='<OD>';results=run_example(task_prompt,image);fig=plot_bbox(image,results['<OD>']);return results,fig_to_pil(fig)
|
| 72 |
+
elif task_prompt=='Dense Region Caption':task_prompt='<DENSE_REGION_CAPTION>';results=run_example(task_prompt,image);fig=plot_bbox(image,results['<DENSE_REGION_CAPTION>']);return results,fig_to_pil(fig)
|
| 73 |
+
elif task_prompt=='Region Proposal':task_prompt='<REGION_PROPOSAL>';results=run_example(task_prompt,image);fig=plot_bbox(image,results['<REGION_PROPOSAL>']);return results,fig_to_pil(fig)
|
| 74 |
+
elif task_prompt=='Caption to Phrase Grounding':task_prompt='<CAPTION_TO_PHRASE_GROUNDING>';results=run_example(task_prompt,image,text_input);fig=plot_bbox(image,results['<CAPTION_TO_PHRASE_GROUNDING>']);return results,fig_to_pil(fig)
|
| 75 |
+
elif task_prompt=='Referring Expression Segmentation':task_prompt='<REFERRING_EXPRESSION_SEGMENTATION>';results=run_example(task_prompt,image,text_input);output_image=copy.deepcopy(image);output_image=draw_polygons(output_image,results['<REFERRING_EXPRESSION_SEGMENTATION>'],fill_mask=True);return results,output_image
|
| 76 |
+
elif task_prompt=='Region to Segmentation':task_prompt='<REGION_TO_SEGMENTATION>';results=run_example(task_prompt,image,text_input);output_image=copy.deepcopy(image);output_image=draw_polygons(output_image,results['<REGION_TO_SEGMENTATION>'],fill_mask=True);return results,output_image
|
| 77 |
+
elif task_prompt=='Open Vocabulary Detection':task_prompt='<OPEN_VOCABULARY_DETECTION>';results=run_example(task_prompt,image,text_input);bbox_results=convert_to_od_format(results['<OPEN_VOCABULARY_DETECTION>']);fig=plot_bbox(image,bbox_results);return results,fig_to_pil(fig)
|
| 78 |
+
elif task_prompt=='Region to Category':task_prompt='<REGION_TO_CATEGORY>';results=run_example(task_prompt,image,text_input);return results,None
|
| 79 |
+
elif task_prompt=='Region to Description':task_prompt='<REGION_TO_DESCRIPTION>';results=run_example(task_prompt,image,text_input);return results,None
|
| 80 |
+
elif task_prompt=='OCR':task_prompt='<OCR>';results=run_example(task_prompt,image);return results,None
|
| 81 |
+
elif task_prompt=='OCR with Region':task_prompt='<OCR_WITH_REGION>';results=run_example(task_prompt,image);output_image=copy.deepcopy(image);output_image=draw_ocr_bboxes(output_image,results['<OCR_WITH_REGION>']);return results,output_image
|
| 82 |
+
else:return'',None # Return empty string and None for unknown task prompts
|
| 83 |
+
|
| 84 |
+
single_task_list=['Caption','Detailed Caption','More Detailed Caption','Object Detection','Dense Region Caption','Region Proposal','Caption to Phrase Grounding','Referring Expression Segmentation','Region to Segmentation','Open Vocabulary Detection','Region to Category','Region to Description','OCR','OCR with Region']
|
| 85 |
+
cascaded_task_list=['Caption + Grounding','Detailed Caption + Grounding','More Detailed Caption + Grounding']
|
| 86 |
+
|
| 87 |
+
def update_task_dropdown(choice):
|
| 88 |
+
if choice == 'Cascaded task':
|
| 89 |
+
return gr.Dropdown(choices=cascaded_task_list, value='Caption + Grounding')
|
| 90 |
+
else:
|
| 91 |
return gr.Dropdown(choices=single_task_list, value='Caption')
|
modules/tag_enhancer.py
CHANGED
|
@@ -2,7 +2,7 @@ import gradio as gr
|
|
| 2 |
import re,torch
|
| 3 |
from transformers import pipeline,AutoTokenizer,AutoModelForSeq2SeqLM
|
| 4 |
|
| 5 |
-
device = "
|
| 6 |
|
| 7 |
def load_models():
|
| 8 |
try:
|
|
@@ -16,38 +16,37 @@ def load_models():
|
|
| 16 |
print(e)
|
| 17 |
enhancer_medium = enhancer_long = enhancer_flux = None
|
| 18 |
return enhancer_medium, enhancer_long, enhancer_flux
|
| 19 |
-
|
| 20 |
enhancer_medium, enhancer_long, enhancer_flux = load_models()
|
| 21 |
|
| 22 |
-
def
|
| 23 |
if model_choice == "Medium":
|
| 24 |
result = enhancer_medium("Enhance the description: " + input_prompt)
|
| 25 |
-
|
| 26 |
|
| 27 |
pattern = r'^.*?of\s+(.*?(?:\.|$))'
|
| 28 |
-
match = re.match(pattern,
|
| 29 |
|
| 30 |
if match:
|
| 31 |
-
remaining_text =
|
| 32 |
modified_sentence = match.group(1).capitalize()
|
| 33 |
-
|
| 34 |
elif model_choice == "Flux":
|
| 35 |
-
result = enhancer_flux("
|
| 36 |
-
|
| 37 |
else: # Long
|
| 38 |
result = enhancer_long("Enhance the description: " + input_prompt)
|
| 39 |
-
|
| 40 |
|
| 41 |
-
return
|
| 42 |
|
| 43 |
-
def
|
| 44 |
characters = character.split(",") if character else []
|
| 45 |
serieses = series.split(",") if series else []
|
| 46 |
generals = general.split(",") if general else []
|
| 47 |
tags = characters + serieses + generals
|
| 48 |
cprompt = ",".join(tags) if tags else ""
|
| 49 |
|
| 50 |
-
output =
|
| 51 |
prompt = cprompt + ", " + output
|
| 52 |
|
| 53 |
return prompt, gr.update(interactive=True), gr.update(interactive=True)
|
|
|
|
| 2 |
import re,torch
|
| 3 |
from transformers import pipeline,AutoTokenizer,AutoModelForSeq2SeqLM
|
| 4 |
|
| 5 |
+
device = "cpu" if torch.cuda.is_available() else "cpu" # Switched to CPU since we are using HF with no GPU
|
| 6 |
|
| 7 |
def load_models():
|
| 8 |
try:
|
|
|
|
| 16 |
print(e)
|
| 17 |
enhancer_medium = enhancer_long = enhancer_flux = None
|
| 18 |
return enhancer_medium, enhancer_long, enhancer_flux
|
|
|
|
| 19 |
enhancer_medium, enhancer_long, enhancer_flux = load_models()
|
| 20 |
|
| 21 |
+
def summarize_prompt(input_prompt, model_choice):
|
| 22 |
if model_choice == "Medium":
|
| 23 |
result = enhancer_medium("Enhance the description: " + input_prompt)
|
| 24 |
+
summarized_text = result[0]['summary_text']
|
| 25 |
|
| 26 |
pattern = r'^.*?of\s+(.*?(?:\.|$))'
|
| 27 |
+
match = re.match(pattern, summarized_text, re.IGNORECASE | re.DOTALL)
|
| 28 |
|
| 29 |
if match:
|
| 30 |
+
remaining_text = summarized_text[match.end():].strip()
|
| 31 |
modified_sentence = match.group(1).capitalize()
|
| 32 |
+
summarized_text = modified_sentence + ' ' + remaining_text
|
| 33 |
elif model_choice == "Flux":
|
| 34 |
+
result = enhancer_flux("Enhance prompt: " + input_prompt, max_length=256)
|
| 35 |
+
summarized_text = result[0]['generated_text']
|
| 36 |
else: # Long
|
| 37 |
result = enhancer_long("Enhance the description: " + input_prompt)
|
| 38 |
+
summarized_text = result[0]['summary_text']
|
| 39 |
|
| 40 |
+
return summarized_text
|
| 41 |
|
| 42 |
+
def prompt_summarizer(character: str, series: str, general: str, model_choice: str):
|
| 43 |
characters = character.split(",") if character else []
|
| 44 |
serieses = series.split(",") if series else []
|
| 45 |
generals = general.split(",") if general else []
|
| 46 |
tags = characters + serieses + generals
|
| 47 |
cprompt = ",".join(tags) if tags else ""
|
| 48 |
|
| 49 |
+
output = summarize_prompt(cprompt, model_choice)
|
| 50 |
prompt = cprompt + ", " + output
|
| 51 |
|
| 52 |
return prompt, gr.update(interactive=True), gr.update(interactive=True)
|
pre-requirements.txt
CHANGED
|
@@ -1 +1,6 @@
|
|
| 1 |
-
pip>=23.0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pip>=23.0.0
|
| 2 |
+
transformers==4.51.0
|
| 3 |
+
huggingface-hub
|
| 4 |
+
apscheduler
|
| 5 |
+
spaces
|
| 6 |
+
pandas==2.1.2
|
requirements.txt
CHANGED
|
@@ -1,25 +1,21 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
opencv-python
|
| 23 |
-
onnxruntime>=1.12.0
|
| 24 |
-
pandas==2.1.2
|
| 25 |
-
matplotlib
|
|
|
|
| 1 |
+
--extra-index-url https://download.pytorch.org/whl/cu124
|
| 2 |
+
torch==2.5.0+cu124; sys_platform != 'darwin'
|
| 3 |
+
torchvision==0.20.0+cu124; sys_platform != 'darwin'
|
| 4 |
+
torch==2.5.0; sys_platform == 'darwin'
|
| 5 |
+
torchvision==0.20.0; sys_platform == 'darwin'
|
| 6 |
+
|
| 7 |
+
gradio
|
| 8 |
+
safetensors
|
| 9 |
+
sentencepiece
|
| 10 |
+
pillow
|
| 11 |
+
requests
|
| 12 |
+
numpy
|
| 13 |
+
timm
|
| 14 |
+
einops
|
| 15 |
+
optimum
|
| 16 |
+
accelerate
|
| 17 |
+
opencv-python
|
| 18 |
+
onnxruntime>=1.12.0
|
| 19 |
+
matplotlib
|
| 20 |
+
|
| 21 |
+
https://github.com/kingbri1/flash-attention/releases/download/v2.7.1.post1/flash_attn-2.7.1.post1+cu124torch2.5.1cxx11abiFALSE-cp310-cp310-win_amd64.whl
|
|
|
|
|
|
|
|
|
|
|
|
themes/theme_schema@0.0.1.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
{"theme": {"_font": [{"__gradio_font__": true, "name": "Montserrat", "class": "google"}, {"__gradio_font__": true, "name": "ui-sans-serif", "class": "font"}, {"__gradio_font__": true, "name": "system-ui", "class": "font"}, {"__gradio_font__": true, "name": "sans-serif", "class": "font"}], "_font_mono": [{"__gradio_font__": true, "name": "IBM Plex Mono", "class": "google"}, {"__gradio_font__": true, "name": "ui-monospace", "class": "font"}, {"__gradio_font__": true, "name": "Consolas", "class": "font"}, {"__gradio_font__": true, "name": "monospace", "class": "font"}], "_stylesheets": ["https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&display=swap", "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap"], "background_fill_primary": "white", "background_fill_primary_dark": "*neutral_950", "background_fill_secondary": "*neutral_50", "background_fill_secondary_dark": "*neutral_900", "block_background_fill": "white", "block_background_fill_dark": "*neutral_800", "block_border_color": "*border_color_primary", "block_border_color_dark": "*border_color_primary", "block_border_width": "0px", "block_info_text_color": "*body_text_color_subdued", "block_info_text_color_dark": "*body_text_color_subdued", "block_info_text_size": "*text_sm", "block_info_text_weight": "400", "block_label_background_fill": "*primary_100", "block_label_background_fill_dark": "*primary_600", "block_label_border_color": "*border_color_primary", "block_label_border_color_dark": "*border_color_primary", "block_label_border_width": "1px", "block_label_margin": "*spacing_md", "block_label_padding": "*spacing_sm *spacing_md", "block_label_radius": "*radius_md", "block_label_right_radius": "0 calc(*radius_lg - 1px) 0 calc(*radius_lg - 1px)", "block_label_text_color": "*primary_500", "block_label_text_color_dark": "*white", "block_label_text_size": "*text_md", "block_label_text_weight": "600", "block_padding": "*spacing_xl calc(*spacing_xl + 2px)", "block_radius": "*radius_lg", "block_shadow": "none", "block_title_background_fill": "*primary_100", "block_title_border_color": "none", "block_title_border_width": "0px", "block_title_padding": "*block_label_padding", "block_title_radius": "*block_label_radius", "block_title_text_color": "*primary_500", "block_title_text_color_dark": "*white", "block_title_text_size": "*text_md", "block_title_text_weight": "600", "body_background_fill": "*background_fill_primary", "body_background_fill_dark": "*background_fill_primary", "body_text_color": "*neutral_800", "body_text_color_dark": "*neutral_100", "body_text_color_subdued": "*neutral_400", "body_text_color_subdued_dark": "*neutral_400", "body_text_size": "*text_md", "body_text_weight": "400", "border_color_accent": "*primary_300", "border_color_accent_dark": "*neutral_600", "border_color_primary": "*neutral_200", "border_color_primary_dark": "*neutral_700", "button_border_width": "*input_border_width", "button_border_width_dark": "*input_border_width", "button_cancel_background_fill": "*button_secondary_background_fill", "button_cancel_background_fill_dark": "*button_secondary_background_fill", "button_cancel_background_fill_hover": "*button_secondary_background_fill_hover", "button_cancel_background_fill_hover_dark": "*button_secondary_background_fill_hover", "button_cancel_border_color": "*button_secondary_border_color", "button_cancel_border_color_dark": "*button_secondary_border_color", "button_cancel_border_color_hover": "*button_cancel_border_color", "button_cancel_border_color_hover_dark": "*button_cancel_border_color", "button_cancel_text_color": "*button_secondary_text_color", "button_cancel_text_color_dark": "*button_secondary_text_color", "button_cancel_text_color_hover": "*button_cancel_text_color", "button_cancel_text_color_hover_dark": "*button_cancel_text_color", "button_large_padding": "*spacing_lg calc(2 * *spacing_lg)", "button_large_radius": "*radius_lg", "button_large_text_size": "*text_lg", "button_large_text_weight": "600", "button_primary_background_fill": "#06AE56", "button_primary_background_fill_dark": "#06AE56", "button_primary_background_fill_hover": "#07C863", "button_primary_background_fill_hover_dark": "*primary_500", "button_primary_border_color": "#06AE56", "button_primary_border_color_dark": "#06AE56", "button_primary_border_color_hover": "*button_primary_border_color", "button_primary_border_color_hover_dark": "*button_primary_border_color", "button_primary_text_color": "#FFFFFF", "button_primary_text_color_dark": "#FFFFFF", "button_primary_text_color_hover": "*button_primary_text_color", "button_primary_text_color_hover_dark": "*button_primary_text_color", "button_secondary_background_fill": "#F2F2F2", "button_secondary_background_fill_dark": "#2B2B2B", "button_secondary_background_fill_hover": "*neutral_100", "button_secondary_background_fill_hover_dark": "*primary_500", "button_secondary_border_color": "*neutral_200", "button_secondary_border_color_dark": "*neutral_600", "button_secondary_border_color_hover": "*button_secondary_border_color", "button_secondary_border_color_hover_dark": "*button_secondary_border_color", "button_secondary_text_color": "#393939", "button_secondary_text_color_dark": "#FFFFFF", "button_secondary_text_color_hover": "*button_secondary_text_color", "button_secondary_text_color_hover_dark": "*button_secondary_text_color", "button_shadow": "*shadow_drop_lg", "button_shadow_active": "*shadow_inset", "button_shadow_hover": "*shadow_drop_lg", "button_small_padding": "*spacing_sm calc(2 * *spacing_sm)", "button_small_radius": "*radius_lg", "button_small_text_size": "*text_md", "button_small_text_weight": "400", "button_transition": "background-color 0.2s ease", "checkbox_background_color": "*background_fill_primary", "checkbox_background_color_dark": "*neutral_800", "checkbox_background_color_focus": "*checkbox_background_color", "checkbox_background_color_focus_dark": "*checkbox_background_color", "checkbox_background_color_hover": "*checkbox_background_color", "checkbox_background_color_hover_dark": "*checkbox_background_color", "checkbox_background_color_selected": "*primary_600", "checkbox_background_color_selected_dark": "*primary_700", "checkbox_border_color": "*neutral_100", "checkbox_border_color_dark": "*neutral_600", "checkbox_border_color_focus": "*primary_500", "checkbox_border_color_focus_dark": "*primary_600", "checkbox_border_color_hover": "*neutral_300", "checkbox_border_color_hover_dark": "*neutral_600", "checkbox_border_color_selected": "*primary_600", "checkbox_border_color_selected_dark": "*primary_700", "checkbox_border_radius": "*radius_sm", "checkbox_border_width": "1px", "checkbox_border_width_dark": "*input_border_width", "checkbox_check": "url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\")", "checkbox_label_background_fill": "*button_secondary_background_fill", "checkbox_label_background_fill_dark": "*button_secondary_background_fill", "checkbox_label_background_fill_hover": "*button_secondary_background_fill_hover", "checkbox_label_background_fill_hover_dark": "*button_secondary_background_fill_hover", "checkbox_label_background_fill_selected": "*primary_500", "checkbox_label_background_fill_selected_dark": "*primary_600", "checkbox_label_border_color": "*border_color_primary", "checkbox_label_border_color_dark": "*border_color_primary", "checkbox_label_border_color_hover": "*checkbox_label_border_color", "checkbox_label_border_color_hover_dark": "*checkbox_label_border_color", "checkbox_label_border_width": "*input_border_width", "checkbox_label_border_width_dark": "*input_border_width", "checkbox_label_gap": "*spacing_lg", "checkbox_label_padding": "*spacing_md calc(2 * *spacing_md)", "checkbox_label_shadow": "*shadow_drop_lg", "checkbox_label_text_color": "*body_text_color", "checkbox_label_text_color_dark": "*body_text_color", "checkbox_label_text_color_selected": "white", "checkbox_label_text_color_selected_dark": "*checkbox_label_text_color", "checkbox_label_text_size": "*text_md", "checkbox_label_text_weight": "400", "checkbox_shadow": "none", "color_accent": "*primary_500", "color_accent_soft": "*primary_50", "color_accent_soft_dark": "*neutral_700", "container_radius": "*radius_lg", "embed_radius": "*radius_lg", "error_background_fill": "#fee2e2", "error_background_fill_dark": "*background_fill_primary", "error_border_color": "#fecaca", "error_border_color_dark": "*border_color_primary", "error_border_width": "1px", "error_text_color": "#ef4444", "error_text_color_dark": "#ef4444", "font": "'Montserrat', 'ui-sans-serif', 'system-ui', sans-serif", "font_mono": "'IBM Plex Mono', 'ui-monospace', 'Consolas', monospace", "form_gap_width": "0px", "input_background_fill": "#F6F6F6", "input_background_fill_dark": "*neutral_700", "input_background_fill_focus": "*secondary_500", "input_background_fill_focus_dark": "*secondary_600", "input_background_fill_hover": "*input_background_fill", "input_background_fill_hover_dark": "*input_background_fill", "input_border_color": "*neutral_50", "input_border_color_dark": "*border_color_primary", "input_border_color_focus": "*secondary_300", "input_border_color_focus_dark": "*neutral_700", "input_border_color_hover": "*input_border_color", "input_border_color_hover_dark": "*input_border_color", "input_border_width": "0px", "input_padding": "*spacing_xl", "input_placeholder_color": "*neutral_400", "input_placeholder_color_dark": "*neutral_500", "input_radius": "*radius_lg", "input_shadow": "*shadow_drop", "input_shadow_focus": "*shadow_drop_lg", "input_text_size": "*text_md", "input_text_weight": "400", "layout_gap": "*spacing_xxl", "link_text_color": "*secondary_600", "link_text_color_active": "*secondary_600", "link_text_color_active_dark": "*secondary_500", "link_text_color_dark": "*secondary_500", "link_text_color_hover": "*secondary_700", "link_text_color_hover_dark": "*secondary_400", "link_text_color_visited": "*secondary_500", "link_text_color_visited_dark": "*secondary_600", "loader_color": "*color_accent", "neutral_100": "#f3f4f6", "neutral_200": "#e5e7eb", "neutral_300": "#d1d5db", "neutral_400": "#B2B2B2", "neutral_50": "#f9fafb", "neutral_500": "#808080", "neutral_600": "#636363", "neutral_700": "#515151", "neutral_800": "#393939", "neutral_900": "#272727", "neutral_950": "#171717", "panel_background_fill": "*background_fill_secondary", "panel_background_fill_dark": "*background_fill_secondary", "panel_border_color": "*border_color_primary", "panel_border_color_dark": "*border_color_primary", "panel_border_width": "1px", "primary_100": "rgba(2, 193, 96, 0.2)", "primary_200": "#02C160", "primary_300": "rgba(2, 193, 96, 0.32)", "primary_400": "rgba(2, 193, 96, 0.32)", "primary_50": "#02C160", "primary_500": "rgba(2, 193, 96, 1.0)", "primary_600": "rgba(2, 193, 96, 1.0)", "primary_700": "rgba(2, 193, 96, 0.32)", "primary_800": "rgba(2, 193, 96, 0.32)", "primary_900": "#02C160", "primary_950": "#02C160", "prose_header_text_weight": "600", "prose_text_size": "*text_md", "prose_text_weight": "400", "radio_circle": "url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e\")", "radius_lg": "6px", "radius_md": "4px", "radius_sm": "2px", "radius_xl": "8px", "radius_xs": "1px", "radius_xxl": "12px", "radius_xxs": "1px", "secondary_100": "#576b95", "secondary_200": "#576b95", "secondary_300": "#576b95", "secondary_400": "#576b95", "secondary_50": "#576b95", "secondary_500": "#576b95", "secondary_600": "#576b95", "secondary_700": "#576b95", "secondary_800": "#576b95", "secondary_900": "#576b95", "secondary_950": "#576b95", "section_header_text_size": "*text_md", "section_header_text_weight": "400", "shadow_drop": "0 1px 4px 0 rgb(0 0 0 / 0.1)", "shadow_drop_lg": "0 2px 5px 0 rgb(0 0 0 / 0.1)", "shadow_inset": "rgba(0,0,0,0.05) 0px 2px 4px 0px inset", "shadow_spread": "6px", "shadow_spread_dark": "1px", "slider_color": "*primary_500", "slider_color_dark": "*primary_600", "spacing_lg": "8px", "spacing_md": "6px", "spacing_sm": "4px", "spacing_xl": "10px", "spacing_xs": "2px", "spacing_xxl": "16px", "spacing_xxs": "1px", "stat_background_fill": "*primary_300", "stat_background_fill_dark": "*primary_500", "table_border_color": "*neutral_300", "table_border_color_dark": "*neutral_700", "table_even_background_fill": "white", "table_even_background_fill_dark": "*neutral_950", "table_odd_background_fill": "*neutral_50", "table_odd_background_fill_dark": "*neutral_900", "table_radius": "*radius_lg", "table_row_focus": "*color_accent_soft", "table_row_focus_dark": "*color_accent_soft", "text_lg": "16px", "text_md": "14px", "text_sm": "12px", "text_xl": "22px", "text_xs": "10px", "text_xxl": "26px", "text_xxs": "9px"}, "version": "1.0.0"}
|
|
|
|
| 1 |
+
{"theme": {"_font": [{"__gradio_font__": true, "name": "BIZ UDMincho Medium", "class": "font"}, {"__gradio_font__": true, "name": "BIZ UDMincho Medium", "class": "font"}, {"__gradio_font__": true, "name": "system-ui", "class": "font"}, {"__gradio_font__": true, "name": "sans-serif", "class": "font"}], "_font_mono": [{"__gradio_font__": true, "name": "BIZ UDMincho Medium", "class": "font"}, {"__gradio_font__": true, "name": "ui-monospace", "class": "font"}, {"__gradio_font__": true, "name": "BIZ UDMincho Medium", "class": "font"}, {"__gradio_font__": true, "name": "monospace", "class": "font"}], "_stylesheets": ["https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap"], "background_fill_primary": "#bebebef2", "background_fill_primary_dark": "*neutral_950", "background_fill_secondary": "*neutral_50", "background_fill_secondary_dark": "#160d0dad", "block_background_fill": "#e3e3e3", "block_background_fill_dark": "#160d0dad", "block_border_color": "#ffffff", "block_border_color_dark": "*border_color_primary", "block_border_width": "1px", "block_border_width_dark": "1px", "block_info_text_color": "*body_text_color_subdued", "block_info_text_color_dark": "*body_text_color_subdued", "block_info_text_size": "*text_sm", "block_info_text_weight": "400", "block_label_background_fill": "#160d0d00", "block_label_background_fill_dark": "#160d0d00", "block_label_border_color": "*border_color_primary", "block_label_border_color_dark": "*border_color_primary", "block_label_border_width": "1px", "block_label_border_width_dark": "1px", "block_label_margin": "0", "block_label_padding": "*spacing_sm *spacing_lg", "block_label_radius": "calc(*radius_lg - 1px) 0 calc(*radius_lg - 1px) 0", "block_label_right_radius": "0 calc(*radius_lg - 1px) 0 calc(*radius_lg - 1px)", "block_label_text_color": "*neutral_500", "block_label_text_color_dark": "*neutral_200", "block_label_text_size": "*text_sm", "block_label_text_weight": "400", "block_padding": "*spacing_xl calc(*spacing_xl + 2px)", "block_radius": "*radius_lg", "block_shadow": "none", "block_shadow_dark": "none", "block_title_background_fill": "none", "block_title_background_fill_dark": "none", "block_title_border_color": "none", "block_title_border_color_dark": "none", "block_title_border_width": "0px", "block_title_border_width_dark": "0px", "block_title_padding": "0", "block_title_radius": "none", "block_title_text_color": "*neutral_500", "block_title_text_color_dark": "*neutral_200", "block_title_text_size": "*text_md", "block_title_text_weight": "400", "body_background_fill": "white", "body_background_fill_dark": "#391633", "body_text_color": "#000000", "body_text_color_dark": "*neutral_100", "body_text_color_subdued": "#000000", "body_text_color_subdued_dark": "*neutral_400", "body_text_size": "*text_md", "body_text_weight": "400", "border_color_accent": "*primary_300", "border_color_accent_dark": "*neutral_600", "border_color_primary": "#ffffff00", "border_color_primary_dark": "*neutral_700", "button_border_width": "*input_border_width", "button_border_width_dark": "*input_border_width", "button_cancel_background_fill": "*button_secondary_background_fill", "button_cancel_background_fill_dark": "*secondary_300", "button_cancel_background_fill_hover": "*button_cancel_background_fill", "button_cancel_background_fill_hover_dark": "*secondary_200", "button_cancel_border_color": "*button_secondary_border_color", "button_cancel_border_color_dark": "*button_secondary_border_color", "button_cancel_border_color_hover": "*button_cancel_border_color", "button_cancel_border_color_hover_dark": "*button_cancel_border_color", "button_cancel_text_color": "*button_secondary_text_color", "button_cancel_text_color_dark": "*button_secondary_text_color", "button_cancel_text_color_hover": "*button_cancel_text_color", "button_cancel_text_color_hover_dark": "*button_cancel_text_color", "button_large_padding": "*spacing_lg calc(2 * *spacing_lg)", "button_large_radius": "*radius_lg", "button_large_text_size": "*text_lg", "button_large_text_weight": "600", "button_primary_background_fill": "#e7e7e7", "button_primary_background_fill_dark": "*primary_700", "button_primary_background_fill_hover": "#6400c5", "button_primary_background_fill_hover_dark": "*neutral_700", "button_primary_border_color": "*primary_200", "button_primary_border_color_dark": "*primary_600", "button_primary_border_color_hover": "*button_primary_border_color", "button_primary_border_color_hover_dark": "*button_primary_border_color", "button_primary_text_color": "#000000", "button_primary_text_color_dark": "white", "button_primary_text_color_hover": "#000000", "button_primary_text_color_hover_dark": "*button_primary_text_color", "button_secondary_background_fill": "#e7e7e7", "button_secondary_background_fill_dark": "*primary_700", "button_secondary_background_fill_hover": "*button_secondary_background_fill", "button_secondary_background_fill_hover_dark": "*neutral_700", "button_secondary_border_color": "*neutral_200", "button_secondary_border_color_dark": "*neutral_700", "button_secondary_border_color_hover": "*button_secondary_border_color", "button_secondary_border_color_hover_dark": "*button_secondary_border_color", "button_secondary_text_color": "#000000", "button_secondary_text_color_dark": "white", "button_secondary_text_color_hover": "*button_secondary_text_color", "button_secondary_text_color_hover_dark": "*button_secondary_text_color", "button_shadow": "none", "button_shadow_active": "none", "button_shadow_hover": "none", "button_small_padding": "*spacing_sm calc(2 * *spacing_sm)", "button_small_radius": "*radius_lg", "button_small_text_size": "*text_md", "button_small_text_weight": "400", "button_transition": "background-color 0.2s ease", "checkbox_background_color": "*background_fill_primary", "checkbox_background_color_dark": "*neutral_800", "checkbox_background_color_focus": "*checkbox_background_color", "checkbox_background_color_focus_dark": "*primary_400", "checkbox_background_color_hover": "*checkbox_background_color", "checkbox_background_color_hover_dark": "*primary_700", "checkbox_background_color_selected": "*secondary_600", "checkbox_background_color_selected_dark": "*primary_600", "checkbox_border_color": "*neutral_300", "checkbox_border_color_dark": "*neutral_700", "checkbox_border_color_focus": "*secondary_500", "checkbox_border_color_focus_dark": "*secondary_500", "checkbox_border_color_hover": "*neutral_300", "checkbox_border_color_hover_dark": "*neutral_600", "checkbox_border_color_selected": "*secondary_600", "checkbox_border_color_selected_dark": "*secondary_600", "checkbox_border_radius": "*radius_sm", "checkbox_border_width": "*input_border_width", "checkbox_border_width_dark": "*input_border_width", "checkbox_check": "url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\")", "checkbox_label_background_fill": "*button_secondary_background_fill", "checkbox_label_background_fill_dark": "*primary_700", "checkbox_label_background_fill_hover": "*button_secondary_background_fill_hover", "checkbox_label_background_fill_hover_dark": "*button_secondary_background_fill_hover", "checkbox_label_background_fill_selected": "*checkbox_label_background_fill", "checkbox_label_background_fill_selected_dark": "*checkbox_label_background_fill", "checkbox_label_border_color": "*border_color_primary", "checkbox_label_border_color_dark": "*border_color_primary", "checkbox_label_border_color_hover": "*checkbox_label_border_color", "checkbox_label_border_color_hover_dark": "*checkbox_label_border_color", "checkbox_label_border_width": "*input_border_width", "checkbox_label_border_width_dark": "*input_border_width", "checkbox_label_gap": "*spacing_lg", "checkbox_label_padding": "*spacing_md calc(2 * *spacing_md)", "checkbox_label_shadow": "none", "checkbox_label_text_color": "*body_text_color", "checkbox_label_text_color_dark": "*body_text_color", "checkbox_label_text_color_selected": "*checkbox_label_text_color", "checkbox_label_text_color_selected_dark": "*checkbox_label_text_color", "checkbox_label_text_size": "*text_md", "checkbox_label_text_weight": "400", "checkbox_shadow": "*input_shadow", "color_accent": "#000000", "color_accent_soft": "*primary_50", "color_accent_soft_dark": "*neutral_700", "container_radius": "*radius_md", "embed_radius": "*radius_lg", "error_background_fill": "#fee2e2", "error_background_fill_dark": "*background_fill_primary", "error_border_color": "#fecaca", "error_border_color_dark": "*border_color_primary", "error_border_width": "1px", "error_border_width_dark": "1px", "error_text_color": "#ef4444", "error_text_color_dark": "#ef4444", "font": "'BIZ UDMincho Medium', 'ui-sans-serif', 'system-ui', sans-serif", "font_mono": "'IBM Plex Mono', 'ui-monospace', 'Consolas', monospace", "form_gap_width": "*spacing_md", "input_background_fill": "#191919cf", "input_background_fill_dark": "*neutral_700", "input_background_fill_focus": "#3b3b3b", "input_background_fill_focus_dark": "#0a0808", "input_background_fill_hover": "*input_background_fill", "input_background_fill_hover_dark": "*input_background_fill", "input_border_color": "*border_color_primary", "input_border_color_dark": "*border_color_primary", "input_border_color_focus": "*secondary_300", "input_border_color_focus_dark": "*neutral_700", "input_border_color_hover": "*input_border_color", "input_border_color_hover_dark": "*input_border_color", "input_border_width": "0px", "input_border_width_dark": "0px", "input_padding": "*spacing_xl", "input_placeholder_color": "*neutral_400", "input_placeholder_color_dark": "*neutral_500", "input_radius": "*radius_lg", "input_shadow": "none", "input_shadow_dark": "none", "input_shadow_focus": "*input_shadow", "input_shadow_focus_dark": "*input_shadow", "input_text_size": "*text_md", "input_text_weight": "400", "layout_gap": "*spacing_xxl", "link_text_color": "*secondary_600", "link_text_color_active": "*secondary_600", "link_text_color_active_dark": "*secondary_500", "link_text_color_dark": "*secondary_500", "link_text_color_hover": "*secondary_700", "link_text_color_hover_dark": "*secondary_400", "link_text_color_visited": "*secondary_500", "link_text_color_visited_dark": "*secondary_600", "loader_color": "*color_accent", "loader_color_dark": "*color_accent", "name": "base", "neutral_100": "#f4f4f5", "neutral_200": "#e4e4e7", "neutral_300": "#d4d4d8", "neutral_400": "#a1a1aa", "neutral_50": "#fafafa", "neutral_500": "#71717a", "neutral_600": "#52525b", "neutral_700": "#1a1a1d", "neutral_800": "#101012", "neutral_900": "#0b0b0d", "neutral_950": "#070708", "panel_background_fill": "#d3d3d3", "panel_background_fill_dark": "*background_fill_secondary", "panel_border_color": "*border_color_primary", "panel_border_color_dark": "*border_color_primary", "panel_border_width": "0", "panel_border_width_dark": "0", "primary_100": "#ede9fe", "primary_200": "#ddd6fe", "primary_300": "#c4b5fd", "primary_400": "#a78bfa", "primary_50": "#f5f3ff", "primary_500": "#8b5cf6", "primary_600": "#7c3aed", "primary_700": "#6d28d9", "primary_800": "#120625", "primary_900": "#090313", "primary_950": "#0a0414", "prose_header_text_weight": "600", "prose_text_size": "*text_md", "prose_text_weight": "400", "radio_circle": "url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e\")", "radius_lg": "6px", "radius_md": "4px", "radius_sm": "2px", "radius_xl": "8px", "radius_xs": "1px", "radius_xxl": "12px", "radius_xxs": "1px", "secondary_100": "#f3e8ff", "secondary_200": "#a72d85", "secondary_300": "#72174f", "secondary_400": "#561743", "secondary_50": "#faf5ff", "secondary_500": "#a855f7", "secondary_600": "#9333ea", "secondary_700": "#7e22ce", "secondary_800": "#14061f", "secondary_900": "#0d0415", "secondary_950": "#0e0516", "section_header_text_size": "*text_md", "section_header_text_weight": "400", "shadow_drop": "rgba(0,0,0,0.05) 0px 1px 2px 0px", "shadow_drop_lg": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)", "shadow_inset": "rgba(0,0,0,0.05) 0px 2px 4px 0px inset", "shadow_spread": "3px", "shadow_spread_dark": "1px", "slider_color": "#b7b7b7", "slider_color_dark": "#3e1a1a", "spacing_lg": "6px", "spacing_md": "4px", "spacing_sm": "2px", "spacing_xl": "9px", "spacing_xs": "1px", "spacing_xxl": "12px", "spacing_xxs": "1px", "stat_background_fill": "*primary_300", "stat_background_fill_dark": "*primary_500", "table_border_color": "*neutral_300", "table_border_color_dark": "*neutral_600", "table_even_background_fill": "white", "table_even_background_fill_dark": "*neutral_950", "table_odd_background_fill": "*neutral_50", "table_odd_background_fill_dark": "*neutral_900", "table_radius": "*radius_lg", "table_row_focus": "*color_accent_soft", "table_row_focus_dark": "*color_accent_soft", "text_lg": "16px", "text_md": "13px", "text_sm": "11px", "text_xl": "20px", "text_xs": "9px", "text_xxl": "24px", "text_xxs": "8px"}, "version": "0.0.1"}
|