Skip to content

Commit c831622

Browse files
committed
feat(hf): add support for repository types
- add support for repository types in HF Transfer utility - add dequantize_gguf.py script - improve layout of HF Upload window
1 parent ac0f011 commit c831622

File tree

2 files changed

+143
-12
lines changed

2 files changed

+143
-12
lines changed

src/AutoGGUF.py

+38-12
Original file line numberDiff line numberDiff line change
@@ -313,38 +313,56 @@ def __init__(self, args: List[str]) -> None:
313313
self.hf_upload_dialog.setFixedWidth(500)
314314
self.hf_upload_layout = QVBoxLayout()
315315

316+
# Form layout for inputs
317+
form_layout = QFormLayout()
318+
316319
# Repo input
317-
repo_layout = QHBoxLayout()
318320
self.hf_repo_input = QLineEdit()
319-
repo_layout.addWidget(QLabel("Repository:"))
320-
repo_layout.addWidget(self.hf_repo_input)
321-
self.hf_upload_layout.addLayout(repo_layout)
321+
form_layout.addRow("Repository:", self.hf_repo_input)
322322

323323
# Remote path input
324-
remote_path_layout = QHBoxLayout()
325324
self.hf_remote_path_input = QLineEdit()
326-
remote_path_layout.addWidget(QLabel("Remote Path:"))
327-
remote_path_layout.addWidget(self.hf_remote_path_input)
328-
self.hf_upload_layout.addLayout(remote_path_layout)
325+
form_layout.addRow("Remote Path:", self.hf_remote_path_input)
329326

330327
# Local file/folder input
331328
local_path_layout = QHBoxLayout()
332329
self.hf_local_path_input = QLineEdit()
333330
local_path_button = QPushButton("Browse")
334331
local_path_button.clicked.connect(self.browse_local_path)
335-
local_path_layout.addWidget(QLabel("Local Path:"))
336332
local_path_layout.addWidget(self.hf_local_path_input)
337333
local_path_layout.addWidget(local_path_button)
338-
self.hf_upload_layout.addLayout(local_path_layout)
334+
form_layout.addRow("Local Path:", local_path_layout)
335+
336+
self.hf_upload_layout.addLayout(form_layout)
339337

340338
# Upload type (file or folder)
339+
upload_type_group = QGroupBox("Upload Type")
340+
upload_type_layout = QHBoxLayout()
341341
self.upload_type_group = QButtonGroup()
342342
self.upload_type_file = QRadioButton("File")
343343
self.upload_type_folder = QRadioButton("Folder")
344344
self.upload_type_group.addButton(self.upload_type_file)
345345
self.upload_type_group.addButton(self.upload_type_folder)
346-
self.hf_upload_layout.addWidget(self.upload_type_file)
347-
self.hf_upload_layout.addWidget(self.upload_type_folder)
346+
upload_type_layout.addWidget(self.upload_type_file)
347+
upload_type_layout.addWidget(self.upload_type_folder)
348+
upload_type_group.setLayout(upload_type_layout)
349+
self.hf_upload_layout.addWidget(upload_type_group)
350+
351+
# Repo type (dataset/space/model)
352+
repo_type_group = QGroupBox("Repository Type")
353+
repo_type_layout = QHBoxLayout()
354+
self.repo_type_group = QButtonGroup()
355+
self.repo_type_model = QRadioButton("Model")
356+
self.repo_type_dataset = QRadioButton("Dataset")
357+
self.repo_type_space = QRadioButton("Space")
358+
self.repo_type_group.addButton(self.repo_type_model)
359+
self.repo_type_group.addButton(self.repo_type_dataset)
360+
self.repo_type_group.addButton(self.repo_type_space)
361+
repo_type_layout.addWidget(self.repo_type_model)
362+
repo_type_layout.addWidget(self.repo_type_dataset)
363+
repo_type_layout.addWidget(self.repo_type_space)
364+
repo_type_group.setLayout(repo_type_layout)
365+
self.hf_upload_layout.addWidget(repo_type_group)
348366

349367
# Upload button
350368
upload_button = QPushButton("Upload")
@@ -1438,6 +1456,14 @@ def transfer_to_hf(self) -> None:
14381456
if remote_path:
14391457
command.append(remote_path)
14401458

1459+
# Add repo type argument if selected
1460+
if self.repo_type_model.isChecked():
1461+
command.append("--repo-type=model")
1462+
elif self.repo_type_dataset.isChecked():
1463+
command.append("--repo-type=dataset")
1464+
elif self.repo_type_space.isChecked():
1465+
command.append("--repo-type=space")
1466+
14411467
logs_path = self.logs_input.text()
14421468
ensure_directory(logs_path)
14431469

src/dequantize_gguf.py

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import argparse
2+
import json
3+
import sys
4+
from pathlib import Path
5+
6+
import numpy as np
7+
import torch
8+
from safetensors.torch import save_file
9+
10+
import gguf
11+
12+
13+
def dequantize_tensor(tensor):
14+
if tensor.tensor_type in [
15+
gguf.GGMLQuantizationType.F32,
16+
gguf.GGMLQuantizationType.F16,
17+
gguf.GGMLQuantizationType.BF16,
18+
]:
19+
return np.array(tensor.data)
20+
else:
21+
return tensor.data.astype(np.float32)
22+
23+
24+
def gguf_to_safetensors(gguf_path, safetensors_path, metadata_path=None):
25+
try:
26+
reader = gguf.GGUFReader(gguf_path)
27+
except Exception as e:
28+
print(f"Error reading GGUF file: {e}", file=sys.stderr)
29+
sys.exit(1)
30+
31+
tensors = {}
32+
metadata = {}
33+
34+
for tensor in reader.tensors:
35+
try:
36+
dequantized_data = dequantize_tensor(tensor)
37+
tensors[tensor.name] = torch.from_numpy(
38+
dequantized_data.reshape(tuple(reversed(tensor.shape)))
39+
)
40+
except Exception as e:
41+
print(f"Error processing tensor {tensor.name}: {e}", file=sys.stderr)
42+
continue
43+
44+
for field_name, field in reader.fields.items():
45+
if field.data:
46+
metadata[field_name] = field.parts[field.data[0]].tolist()
47+
48+
try:
49+
save_file(tensors, safetensors_path)
50+
except Exception as e:
51+
print(f"Error saving SafeTensors file: {e}", file=sys.stderr)
52+
sys.exit(1)
53+
54+
decoded_metadata = {}
55+
for key, value in metadata.items():
56+
if isinstance(value, list) and all(isinstance(item, int) for item in value):
57+
decoded_value = ""
58+
for item in value:
59+
if 48 <= item <= 57:
60+
decoded_value += str(item - 48)
61+
elif 32 <= item <= 126:
62+
decoded_value += chr(item)
63+
else:
64+
decoded_value += str(item)
65+
decoded_metadata[key] = decoded_value
66+
else:
67+
decoded_metadata[key] = value
68+
69+
if metadata_path:
70+
try:
71+
with open(metadata_path, "w") as f:
72+
json.dump(decoded_metadata, f, indent=4)
73+
except Exception as e:
74+
print(f"Error saving metadata file: {e}", file=sys.stderr)
75+
76+
77+
def main():
78+
parser = argparse.ArgumentParser(description="Convert GGUF to SafeTensors format")
79+
parser.add_argument("gguf_path", type=str, help="Path to the input GGUF file")
80+
parser.add_argument(
81+
"safetensors_path", type=str, help="Path to save the SafeTensors file"
82+
)
83+
parser.add_argument(
84+
"--metadata_path",
85+
type=str,
86+
help="Optional path to save metadata as a JSON file",
87+
)
88+
89+
args = parser.parse_args()
90+
91+
gguf_path = Path(args.gguf_path)
92+
safetensors_path = Path(args.safetensors_path)
93+
metadata_path = Path(args.metadata_path) if args.metadata_path else None
94+
95+
if not gguf_path.exists():
96+
print(f"Error: GGUF file '{gguf_path}' does not exist.", file=sys.stderr)
97+
sys.exit(1)
98+
99+
print(f"Converting {gguf_path} to {safetensors_path}")
100+
gguf_to_safetensors(gguf_path, safetensors_path, metadata_path)
101+
print("Conversion complete.")
102+
103+
104+
if __name__ == "__main__":
105+
main()

0 commit comments

Comments
 (0)