codemichaeld commited on
Commit
bd8eca9
Β·
verified Β·
1 Parent(s): bbea6dc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +227 -3
app.py CHANGED
@@ -1,7 +1,231 @@
1
  import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
  demo.launch()
 
1
  import gradio as gr
2
+ import os
3
+ import tempfile
4
+ import shutil
5
+ import re
6
+ import json
7
+ import datetime
8
+ from pathlib import Path
9
+ from huggingface_hub import HfApi, hf_hub_download, snapshot_download
10
+ from safetensors.torch import load_file
11
+ import torch
12
+ import subprocess
13
 
14
+ # --- Conversion Function: Safetensors (UNet) β†’ GGUF ---
15
+ def convert_unet_to_gguf(safetensors_path, output_dir, progress=gr.Progress()):
16
+ """
17
+ Converts a UNet safetensors file to GGUF using gguf-connector's CLI (t2 or t).
18
+ Assumes the file is named 'unet.safetensors'.
19
+ """
20
+ progress(0.1, desc="Starting UNet to GGUF conversion...")
21
+
22
+ try:
23
+ # Ensure gguf-connector is available
24
+ import gguf_connector # noqa
25
+
26
+ # Copy input to working dir because ggc expects files in current dir
27
+ work_dir = tempfile.mkdtemp()
28
+ input_path = os.path.join(work_dir, "unet.safetensors")
29
+ shutil.copy(safetensors_path, input_path)
30
+
31
+ # GGUF output will be named automatically like unet.safetensors -> unet.gguf
32
+ gguf_output_path = os.path.join(work_dir, "unet.gguf")
33
+
34
+ progress(0.3, desc="Running gguf-connector (t2: safetensors β†’ GGUF)...")
35
+
36
+ # Use 'ggc t2' for conversion (beta: unlimited)
37
+ # This is interactive, so we must simulate input via echo or expect
38
+ # But since ggc t2 may be interactive, we try non-interactive fallback:
39
+ # Unfortunately, ggc does not support non-interactive mode robustly.
40
+ # So we simulate by running in dir and hoping it picks the only file.
41
+
42
+ # Change working dir so ggc sees the file
43
+ original_cwd = os.getcwd()
44
+ os.chdir(work_dir)
45
+
46
+ try:
47
+ # Launch ggc t2 and auto-select first file via input redirection
48
+ # This is fragile but best-effort
49
+ result = subprocess.run(
50
+ ["ggc", "t2"],
51
+ input="1\n", # select first model
52
+ text=True,
53
+ capture_output=True,
54
+ timeout=300
55
+ )
56
+ if result.returncode != 0:
57
+ raise RuntimeError(f"ggc t2 failed: {result.stderr}")
58
+ finally:
59
+ os.chdir(original_cwd)
60
+
61
+ if not os.path.exists(gguf_output_path):
62
+ # Try alternative naming
63
+ candidates = [f for f in os.listdir(work_dir) if f.endswith(".gguf")]
64
+ if not candidates:
65
+ raise FileNotFoundError("No GGUF file generated by ggc t2")
66
+ gguf_output_path = os.path.join(work_dir, candidates[0])
67
+
68
+ # Move to output dir
69
+ final_gguf_path = os.path.join(output_dir, "unet.gguf")
70
+ shutil.move(gguf_output_path, final_gguf_path)
71
+
72
+ # Also save minimal config
73
+ config_path = os.path.join(output_dir, "config.json")
74
+ with open(config_path, "w") as f:
75
+ json.dump({
76
+ "model_type": "unet",
77
+ "format": "gguf",
78
+ "source": "converted from safetensors"
79
+ }, f)
80
+
81
+ progress(1.0, desc="Conversion to GGUF complete!")
82
+ return True, "UNet converted to GGUF successfully."
83
+
84
+ except Exception as e:
85
+ return False, str(e)
86
+ finally:
87
+ if 'work_dir' in locals():
88
+ shutil.rmtree(work_dir, ignore_errors=True)
89
+
90
+ # --- Main Processing Function ---
91
+ def process_and_upload_unet_to_gguf(repo_url, hf_token, new_repo_id, private_repo, progress=gr.Progress()):
92
+ if not all([repo_url, hf_token, new_repo_id]):
93
+ return None, "❌ Error: Please fill in all fields.", ""
94
+
95
+ if not re.match(r"^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$", new_repo_id):
96
+ return None, "❌ Error: Invalid repository ID format. Use 'username/model-name'.", ""
97
+
98
+ temp_dir = tempfile.mkdtemp()
99
+ output_dir = tempfile.mkdtemp()
100
+
101
+ try:
102
+ # Authenticate
103
+ progress(0.05, desc="Logging into Hugging Face...")
104
+ api = HfApi(token=hf_token)
105
+ user_info = api.whoami()
106
+ user_name = user_info['name']
107
+ progress(0.1, desc=f"Logged in as {user_name}.")
108
+
109
+ # Parse source repo
110
+ clean_url = repo_url.strip().rstrip("/")
111
+ if "huggingface.co" not in clean_url:
112
+ return None, "❌ Source must be a Hugging Face model repo.", ""
113
+ src_repo_id = clean_url.replace("https://huggingface.co/", "")
114
+
115
+ # Download only unet.safetensors
116
+ progress(0.15, desc="Downloading unet.safetensors...")
117
+ safetensors_path = hf_hub_download(
118
+ repo_id=src_repo_id,
119
+ filename="unet.safetensors",
120
+ cache_dir=temp_dir,
121
+ token=hf_token
122
+ )
123
+ progress(0.3, desc="Download complete.")
124
+
125
+ # Convert
126
+ success, msg = convert_unet_to_gguf(safetensors_path, output_dir, progress)
127
+ if not success:
128
+ return None, f"❌ Conversion failed: {msg}", ""
129
+
130
+ # Create new repo
131
+ progress(0.8, desc="Creating new repository...")
132
+ api.create_repo(
133
+ repo_id=new_repo_id,
134
+ private=private_repo,
135
+ repo_type="model",
136
+ exist_ok=True
137
+ )
138
+
139
+ # Generate README
140
+ readme = f"""---
141
+ library_name: diffusers
142
+ tags:
143
+ - gguf
144
+ - unet
145
+ - diffusion
146
+ - converted-by-gradio
147
+ ---
148
+
149
+ # GGUF UNet Model
150
+
151
+ Converted from: [`{src_repo_id}`](https://huggingface.co/{src_repo_id})
152
+ File: `unet.safetensors` β†’ `unet.gguf`
153
+
154
+ Converted by: {user_name}
155
+ Date: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
156
+
157
+ > ⚠️ This is a GGUF-quantized UNet for storage efficiency. Use with compatible GGUF-aware inference engines.
158
+ """
159
+ with open(os.path.join(output_dir, "README.md"), "w") as f:
160
+ f.write(readme)
161
+
162
+ # Upload
163
+ progress(0.9, desc="Uploading to Hugging Face Hub...")
164
+ api.upload_folder(
165
+ repo_id=new_repo_id,
166
+ folder_path=output_dir,
167
+ repo_type="model",
168
+ token=hf_token,
169
+ commit_message="Upload UNet GGUF conversion"
170
+ )
171
+
172
+ progress(1.0, desc="βœ… Done!")
173
+ result_html = f"""
174
+ βœ… Success!
175
+ Your GGUF UNet is uploaded to: [{new_repo_id}](https://huggingface.co/{new_repo_id})
176
+ Visibility: {'Private' if private_repo else 'Public'}
177
+ """
178
+ return gr.HTML(result_html), "βœ… Conversion and upload successful!", ""
179
+
180
+ except Exception as e:
181
+ return None, f"❌ Error: {str(e)}", ""
182
+ finally:
183
+ shutil.rmtree(temp_dir, ignore_errors=True)
184
+ shutil.rmtree(output_dir, ignore_errors=True)
185
+
186
+ # --- Gradio UI ---
187
+ with gr.Blocks(title="UNet Safetensors β†’ GGUF Converter") as demo:
188
+ gr.Markdown("# πŸ”„ UNet (Safetensors) to GGUF Converter")
189
+ gr.Markdown("Converts `unet.safetensors` from a Hugging Face model repo to GGUF format for compact storage.")
190
+
191
+ with gr.Row():
192
+ with gr.Column():
193
+ repo_url = gr.Textbox(
194
+ label="Source Model Repository URL",
195
+ placeholder="https://huggingface.co/Yabo/FramePainter",
196
+ info="Must contain 'unet.safetensors'"
197
+ )
198
+ hf_token = gr.Textbox(
199
+ label="Hugging Face Token",
200
+ type="password",
201
+ info="Write-access token from https://huggingface.co/settings/tokens"
202
+ )
203
+ with gr.Column():
204
+ new_repo_id = gr.Textbox(
205
+ label="New Repository ID",
206
+ placeholder="your-username/framepainter-unet-gguf",
207
+ info="Format: username/model-name"
208
+ )
209
+ private_repo = gr.Checkbox(label="Make Private", value=False)
210
+
211
+ convert_btn = gr.Button("πŸš€ Convert & Upload", variant="primary")
212
+
213
+ with gr.Row():
214
+ status_output = gr.Markdown()
215
+ repo_link_output = gr.HTML()
216
+
217
+ convert_btn.click(
218
+ fn=process_and_upload_unet_to_gguf,
219
+ inputs=[repo_url, hf_token, new_repo_id, private_repo],
220
+ outputs=[repo_link_output, status_output],
221
+ show_progress=True
222
+ )
223
+
224
+ gr.Examples(
225
+ examples=[
226
+ ["https://huggingface.co/Yabo/FramePainter"]
227
+ ],
228
+ inputs=[repo_url]
229
+ )
230
 
 
231
  demo.launch()