Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| import shlex | |
| import subprocess | |
| from pathlib import Path | |
| from tempfile import TemporaryDirectory | |
| from textwrap import dedent | |
| import numpy as np | |
| import streamlit as st | |
| import torch | |
| from PIL import Image | |
| from transformers import CLIPTokenizer | |
| def hex_to_rgb(s: str) -> tuple[int, int, int]: | |
| value = s.lstrip("#") | |
| return (int(value[:2], 16), int(value[2:4], 16), int(value[4:6], 16)) | |
| st.header("Color Textual Inversion") | |
| with st.expander(label="info"): | |
| with open("info.txt", "r", encoding="utf-8") as f: | |
| st.markdown(f.read()) | |
| duplicate_button = """<a class="duplicate-button" style="display:inline-block" target="_blank" href="https://huggingface.co/spaces/Bingsu/color_textual_inversion?duplicate=true"><img style="margin: 0" src="https://img.shields.io/badge/-Duplicate%20Space-blue?labelColor=white&style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAP5JREFUOE+lk7FqAkEURY+ltunEgFXS2sZGIbXfEPdLlnxJyDdYB62sbbUKpLbVNhyYFzbrrA74YJlh9r079973psed0cvUD4A+4HoCjsA85X0Dfn/RBLBgBDxnQPfAEJgBY+A9gALA4tcbamSzS4xq4FOQAJgCDwV2CPKV8tZAJcAjMMkUe1vX+U+SMhfAJEHasQIWmXNN3abzDwHUrgcRGmYcgKe0bxrblHEB4E/pndMazNpSZGcsZdBlYJcEL9Afo75molJyM2FxmPgmgPqlWNLGfwZGG6UiyEvLzHYDmoPkDDiNm9JR9uboiONcBXrpY1qmgs21x1QwyZcpvxt9NS09PlsPAAAAAElFTkSuQmCC&logoWidth=14" alt="Duplicate Space"></a>""" | |
| st.markdown(duplicate_button, unsafe_allow_html=True) | |
| col1, col2 = st.columns([15, 85]) | |
| color = col1.color_picker("Pick a color", "#00f900") | |
| col2.text_input("", color, disabled=True) | |
| emb_name = st.text_input("Embedding name", color.lstrip("#").upper()) | |
| init_token = st.text_input("Initializer token", "init token name") | |
| rgb = hex_to_rgb(color) | |
| img_array = np.zeros((128, 128, 3), dtype=np.uint8) | |
| for i in range(3): | |
| img_array[..., i] = rgb[i] | |
| dataset_temp = TemporaryDirectory(prefix="dataset_", dir=".") | |
| dataset_path = Path(dataset_temp.name) | |
| output_temp = TemporaryDirectory(prefix="output_", dir=".") | |
| output_path = Path(output_temp.name) | |
| img_path = dataset_path / f"{emb_name}.png" | |
| Image.fromarray(img_array).save(img_path) | |
| with st.sidebar: | |
| model_name = st.text_input("Model name", "Linaqruf/anything-v3.0") | |
| steps = st.slider("Steps", 1, 100, value=1, step=1) | |
| learning_rate = st.text_input("Learning rate", "0.001") | |
| learning_rate = float(learning_rate) | |
| tokenizer = CLIPTokenizer.from_pretrained(model_name, subfolder="tokenizer") | |
| # case 1: init_token is not a single token | |
| token = tokenizer.tokenize(init_token) | |
| if len(token) > 1: | |
| st.warning("Initializer token must be a single token") | |
| st.stop() | |
| # case 2: init_token already exists in the tokenizer | |
| num_added_tokens = tokenizer.add_tokens(emb_name) | |
| if num_added_tokens == 0: | |
| st.warning(f"The tokenizer already contains the token {emb_name}") | |
| st.stop() | |
| cmd = """ | |
| accelerate launch textual_inversion.py \ | |
| --pretrained_model_name_or_path={model_name} \ | |
| --train_data_dir={dataset_path} \ | |
| --learnable_property="style" \ | |
| --placeholder_token="{emb_name}" \ | |
| --initializer_token="{init}" \ | |
| --resolution=128 \ | |
| --train_batch_size=1 \ | |
| --repeats=1 \ | |
| --gradient_accumulation_steps=1 \ | |
| --max_train_steps={steps} \ | |
| --learning_rate={lr} \ | |
| --output_dir={output_path} \ | |
| --only_save_embeds | |
| """.strip() | |
| cmd = dedent(cmd).format( | |
| model_name=model_name, | |
| dataset_path=dataset_path.as_posix(), | |
| emb_name=emb_name, | |
| init=init_token, | |
| steps=steps, | |
| lr=learning_rate, | |
| output_path=output_path.as_posix(), | |
| ) | |
| cmd = shlex.split(cmd) | |
| result_path = output_path / "learned_embeds.bin" | |
| captured = "" | |
| start_button = st.button("Start") | |
| download_button = st.empty() | |
| if start_button: | |
| with st.spinner("Training..."): | |
| placeholder = st.empty() | |
| p = subprocess.Popen( | |
| cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8" | |
| ) | |
| while line := p.stderr.readline(): | |
| captured += line | |
| placeholder.code(captured, language="bash") | |
| if not result_path.exists(): | |
| st.stop() | |
| # fix unknown file volume bug | |
| trained_emb = torch.load(result_path, map_location="cpu") | |
| for k, v in trained_emb.items(): | |
| trained_emb[k] = torch.from_numpy(v.numpy()) | |
| torch.save(trained_emb, result_path) | |
| file = result_path.read_bytes() | |
| download_button.download_button(f"Download {emb_name}.pt", file, f"{emb_name}.pt") | |
| st.download_button(f"Download {emb_name}.pt ", file, f"{emb_name}.pt") | |
| dataset_temp.cleanup() | |
| output_temp.cleanup() | |