|
|
|
|
|
""" |
|
|
Hugging Face Space: GGUF Model Converter |
|
|
A web interface for converting Hugging Face models to GGUF format |
|
|
|
|
|
This Space provides: |
|
|
1. Web interface for model conversion |
|
|
2. Progress tracking and logging |
|
|
3. Automatic upload to Hugging Face |
|
|
4. Resource monitoring |
|
|
""" |
|
|
|
|
|
import os |
|
|
import sys |
|
|
import subprocess |
|
|
import shutil |
|
|
import logging |
|
|
import tempfile |
|
|
import threading |
|
|
import queue |
|
|
import time |
|
|
import psutil |
|
|
import gc |
|
|
from pathlib import Path |
|
|
from typing import Optional, List, Dict, Any |
|
|
from datetime import datetime |
|
|
|
|
|
import gradio as gr |
|
|
import torch |
|
|
|
|
|
|
|
|
try: |
|
|
from huggingface_hub import HfApi, login, create_repo, snapshot_download |
|
|
from transformers import AutoConfig, AutoTokenizer |
|
|
HF_HUB_AVAILABLE = True |
|
|
except ImportError: |
|
|
HF_HUB_AVAILABLE = False |
|
|
|
|
|
|
|
|
logging.basicConfig( |
|
|
level=logging.INFO, |
|
|
format='%(asctime)s - %(levelname)s - %(message)s' |
|
|
) |
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
conversion_progress = queue.Queue() |
|
|
current_status = {"status": "idle", "progress": 0, "message": "Ready"} |
|
|
|
|
|
class SpaceGGUFConverter: |
|
|
def __init__(self): |
|
|
"""Initialize the GGUF converter for Hugging Face Spaces""" |
|
|
self.temp_dir = None |
|
|
self.llama_cpp_dir = None |
|
|
self.hf_token = None |
|
|
|
|
|
def set_hf_token(self, token: str): |
|
|
"""Set the Hugging Face token""" |
|
|
self.hf_token = token |
|
|
if token: |
|
|
login(token=token) |
|
|
return "β
HF Token set successfully!" |
|
|
return "β Invalid token" |
|
|
|
|
|
def update_progress(self, status: str, progress: int, message: str): |
|
|
"""Update the global progress status""" |
|
|
global current_status |
|
|
current_status = { |
|
|
"status": status, |
|
|
"progress": progress, |
|
|
"message": message, |
|
|
"timestamp": datetime.now().strftime("%H:%M:%S") |
|
|
} |
|
|
conversion_progress.put(current_status.copy()) |
|
|
|
|
|
def check_resources(self) -> Dict[str, Any]: |
|
|
"""Check available system resources""" |
|
|
try: |
|
|
memory = psutil.virtual_memory() |
|
|
disk = psutil.disk_usage('/') |
|
|
|
|
|
return { |
|
|
"memory_total": f"{memory.total / (1024**3):.1f} GB", |
|
|
"memory_available": f"{memory.available / (1024**3):.1f} GB", |
|
|
"memory_percent": memory.percent, |
|
|
"disk_total": f"{disk.total / (1024**3):.1f} GB", |
|
|
"disk_free": f"{disk.free / (1024**3):.1f} GB", |
|
|
"disk_percent": disk.percent, |
|
|
"cpu_count": psutil.cpu_count(), |
|
|
"gpu_available": torch.cuda.is_available(), |
|
|
"gpu_memory": f"{torch.cuda.get_device_properties(0).total_memory / (1024**3):.1f} GB" if torch.cuda.is_available() else "N/A" |
|
|
} |
|
|
except Exception as e: |
|
|
return {"error": str(e)} |
|
|
|
|
|
def validate_model(self, model_id: str) -> tuple[bool, str]: |
|
|
"""Validate if the model exists and get basic info""" |
|
|
try: |
|
|
if not HF_HUB_AVAILABLE: |
|
|
return False, "β Required packages not available" |
|
|
|
|
|
self.update_progress("validating", 10, f"Validating model: {model_id}") |
|
|
|
|
|
|
|
|
config = AutoConfig.from_pretrained(model_id, trust_remote_code=False) |
|
|
|
|
|
|
|
|
try: |
|
|
api = HfApi() |
|
|
model_info = api.model_info(model_id) |
|
|
|
|
|
|
|
|
if hasattr(config, 'num_parameters'): |
|
|
params = config.num_parameters() |
|
|
elif hasattr(config, 'n_params'): |
|
|
params = config.n_params |
|
|
else: |
|
|
|
|
|
params = "Unknown" |
|
|
|
|
|
estimated_size = f"~{params/1e9:.1f}B parameters" if isinstance(params, (int, float)) else params |
|
|
|
|
|
return True, f"β
Valid model found!\nParameters: {estimated_size}\nArchitecture: {config.model_type if hasattr(config, 'model_type') else 'Unknown'}" |
|
|
|
|
|
except Exception as e: |
|
|
return True, f"β
Model accessible (size estimation failed: {str(e)})" |
|
|
|
|
|
except Exception as e: |
|
|
return False, f"β Model validation failed: {str(e)}" |
|
|
|
|
|
def setup_environment(self) -> bool: |
|
|
"""Set up the environment for GGUF conversion""" |
|
|
try: |
|
|
self.update_progress("setup", 20, "Setting up conversion environment...") |
|
|
|
|
|
|
|
|
self.temp_dir = tempfile.mkdtemp(prefix="gguf_space_") |
|
|
logger.info(f"Created temporary directory: {self.temp_dir}") |
|
|
|
|
|
|
|
|
self.llama_cpp_dir = os.path.join(self.temp_dir, "llama.cpp") |
|
|
self.update_progress("setup", 30, "Downloading llama.cpp...") |
|
|
|
|
|
result = subprocess.run([ |
|
|
"git", "clone", "--depth", "1", |
|
|
"https://github.com/ggerganov/llama.cpp.git", |
|
|
self.llama_cpp_dir |
|
|
], capture_output=True, text=True) |
|
|
|
|
|
if result.returncode != 0: |
|
|
raise Exception(f"Failed to clone llama.cpp: {result.stderr}") |
|
|
|
|
|
|
|
|
self.update_progress("setup", 50, "Building llama.cpp (this may take a few minutes)...") |
|
|
|
|
|
original_dir = os.getcwd() |
|
|
try: |
|
|
os.chdir(self.llama_cpp_dir) |
|
|
|
|
|
|
|
|
configure_result = subprocess.run([ |
|
|
"cmake", "-S", ".", "-B", "build", |
|
|
"-DCMAKE_BUILD_TYPE=Release", |
|
|
"-DLLAMA_BUILD_TESTS=OFF", |
|
|
"-DLLAMA_BUILD_EXAMPLES=ON" |
|
|
], capture_output=True, text=True) |
|
|
|
|
|
if configure_result.returncode != 0: |
|
|
raise Exception(f"CMake configure failed: {configure_result.stderr}") |
|
|
|
|
|
|
|
|
build_result = subprocess.run([ |
|
|
"cmake", "--build", "build", "--config", "Release", "-j" |
|
|
], capture_output=True, text=True) |
|
|
|
|
|
if build_result.returncode != 0: |
|
|
raise Exception(f"CMake build failed: {build_result.stderr}") |
|
|
|
|
|
finally: |
|
|
os.chdir(original_dir) |
|
|
|
|
|
self.update_progress("setup", 70, "Environment setup complete!") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
self.update_progress("error", 0, f"Setup failed: {str(e)}") |
|
|
logger.error(f"Environment setup failed: {e}") |
|
|
return False |
|
|
|
|
|
def convert_model( |
|
|
self, |
|
|
model_id: str, |
|
|
output_repo: str, |
|
|
quantizations: List[str], |
|
|
hf_token: str, |
|
|
private_repo: bool = False |
|
|
) -> tuple[bool, str]: |
|
|
"""Convert model to GGUF format""" |
|
|
try: |
|
|
if not hf_token: |
|
|
return False, "β Hugging Face token is required" |
|
|
|
|
|
|
|
|
self.set_hf_token(hf_token) |
|
|
|
|
|
|
|
|
valid, validation_msg = self.validate_model(model_id) |
|
|
if not valid: |
|
|
return False, validation_msg |
|
|
|
|
|
|
|
|
resources = self.check_resources() |
|
|
if resources.get("memory_percent", 100) > 90: |
|
|
return False, "β Insufficient memory available (>90% used)" |
|
|
|
|
|
|
|
|
if not self.setup_environment(): |
|
|
return False, "β Failed to setup environment" |
|
|
|
|
|
|
|
|
self.update_progress("downloading", 80, f"Downloading model: {model_id}") |
|
|
model_dir = os.path.join(self.temp_dir, "original_model") |
|
|
|
|
|
try: |
|
|
snapshot_download( |
|
|
repo_id=model_id, |
|
|
local_dir=model_dir, |
|
|
token=hf_token |
|
|
) |
|
|
except Exception as e: |
|
|
return False, f"β Failed to download model: {str(e)}" |
|
|
|
|
|
|
|
|
self.update_progress("converting", 85, "Converting to GGUF format...") |
|
|
gguf_dir = os.path.join(self.temp_dir, "gguf_output") |
|
|
os.makedirs(gguf_dir, exist_ok=True) |
|
|
|
|
|
|
|
|
convert_script = os.path.join(self.llama_cpp_dir, "convert_hf_to_gguf.py") |
|
|
f16_output = os.path.join(gguf_dir, "model-f16.gguf") |
|
|
|
|
|
convert_result = subprocess.run([ |
|
|
sys.executable, convert_script, |
|
|
model_dir, |
|
|
"--outfile", f16_output, |
|
|
"--outtype", "f16" |
|
|
], capture_output=True, text=True) |
|
|
|
|
|
if convert_result.returncode != 0: |
|
|
return False, f"β F16 conversion failed: {convert_result.stderr}" |
|
|
|
|
|
|
|
|
quantize_binary = self._find_quantize_binary() |
|
|
if not quantize_binary: |
|
|
return False, "β Could not find llama-quantize binary" |
|
|
|
|
|
|
|
|
successful_quants = ["f16"] |
|
|
for i, quant in enumerate(quantizations): |
|
|
if quant == "f16": |
|
|
continue |
|
|
|
|
|
progress = 85 + (10 * i / len(quantizations)) |
|
|
self.update_progress("converting", int(progress), f"Creating {quant} quantization...") |
|
|
|
|
|
quant_output = os.path.join(gguf_dir, f"model-{quant}.gguf") |
|
|
|
|
|
quant_result = subprocess.run([ |
|
|
quantize_binary, |
|
|
f16_output, |
|
|
quant_output, |
|
|
quant.upper() |
|
|
], capture_output=True, text=True) |
|
|
|
|
|
if quant_result.returncode == 0: |
|
|
successful_quants.append(quant) |
|
|
else: |
|
|
logger.warning(f"Failed to create {quant} quantization: {quant_result.stderr}") |
|
|
|
|
|
|
|
|
self._create_model_card(model_id, gguf_dir, successful_quants) |
|
|
|
|
|
|
|
|
self.update_progress("uploading", 95, f"Uploading to {output_repo}...") |
|
|
|
|
|
try: |
|
|
api = HfApi(token=hf_token) |
|
|
create_repo(output_repo, private=private_repo, exist_ok=True, token=hf_token) |
|
|
|
|
|
for file_path in Path(gguf_dir).rglob("*"): |
|
|
if file_path.is_file(): |
|
|
relative_path = file_path.relative_to(gguf_dir) |
|
|
api.upload_file( |
|
|
path_or_fileobj=str(file_path), |
|
|
path_in_repo=str(relative_path), |
|
|
repo_id=output_repo, |
|
|
repo_type="model", |
|
|
token=hf_token |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
return False, f"β Upload failed: {str(e)}" |
|
|
|
|
|
self.update_progress("complete", 100, "Conversion completed successfully!") |
|
|
|
|
|
return True, f"""β
Conversion completed successfully! |
|
|
|
|
|
π **Results:** |
|
|
- Successfully created: {', '.join(successful_quants)} quantizations |
|
|
- Uploaded to: https://huggingface.co/{output_repo} |
|
|
- Files created: {len(successful_quants)} GGUF files + README.md |
|
|
|
|
|
π **Links:** |
|
|
- View model: https://huggingface.co/{output_repo} |
|
|
- Download files: https://huggingface.co/{output_repo}/tree/main |
|
|
""" |
|
|
|
|
|
except Exception as e: |
|
|
self.update_progress("error", 0, f"Conversion failed: {str(e)}") |
|
|
return False, f"β Conversion failed: {str(e)}" |
|
|
|
|
|
finally: |
|
|
|
|
|
self._cleanup() |
|
|
gc.collect() |
|
|
|
|
|
def _find_quantize_binary(self) -> Optional[str]: |
|
|
"""Find the llama-quantize binary""" |
|
|
possible_locations = [ |
|
|
os.path.join(self.llama_cpp_dir, "build", "bin", "llama-quantize"), |
|
|
os.path.join(self.llama_cpp_dir, "build", "llama-quantize"), |
|
|
os.path.join(self.llama_cpp_dir, "build", "llama-quantize.exe"), |
|
|
os.path.join(self.llama_cpp_dir, "build", "bin", "llama-quantize.exe") |
|
|
] |
|
|
|
|
|
for location in possible_locations: |
|
|
if os.path.exists(location): |
|
|
return location |
|
|
|
|
|
return None |
|
|
|
|
|
def _create_model_card(self, original_model_id: str, output_dir: str, quantizations: List[str]): |
|
|
"""Create a model card for the GGUF model""" |
|
|
|
|
|
quant_table = [] |
|
|
for quant in quantizations: |
|
|
filename = f"model-{quant}.gguf" |
|
|
if quant == "f16": |
|
|
desc = "Original precision (largest file)" |
|
|
elif "q4" in quant: |
|
|
desc = "4-bit quantization (good balance)" |
|
|
elif "q5" in quant: |
|
|
desc = "5-bit quantization (higher quality)" |
|
|
elif "q8" in quant: |
|
|
desc = "8-bit quantization (high quality)" |
|
|
else: |
|
|
desc = "Quantized version" |
|
|
|
|
|
quant_table.append(f"| {filename} | {quant.upper()} | {desc} |") |
|
|
|
|
|
model_card_content = f"""--- |
|
|
language: |
|
|
- en |
|
|
library_name: gguf |
|
|
base_model: {original_model_id} |
|
|
tags: |
|
|
- gguf |
|
|
- quantized |
|
|
- llama.cpp |
|
|
- converted |
|
|
license: apache-2.0 |
|
|
--- |
|
|
|
|
|
# {original_model_id} - GGUF |
|
|
|
|
|
This repository contains GGUF quantizations of [{original_model_id}](https://huggingface.co/{original_model_id}). |
|
|
|
|
|
**Converted using [HF GGUF Converter Space](https://huggingface.co/spaces/)** |
|
|
|
|
|
## About GGUF |
|
|
|
|
|
GGUF is a quantization method that allows you to run large language models on consumer hardware by reducing the precision of the model weights. |
|
|
|
|
|
## Files |
|
|
|
|
|
| Filename | Quant type | Description | |
|
|
| -------- | ---------- | ----------- | |
|
|
{chr(10).join(quant_table)} |
|
|
|
|
|
## Usage |
|
|
|
|
|
You can use these models with llama.cpp or any other GGUF-compatible inference engine. |
|
|
|
|
|
### llama.cpp |
|
|
|
|
|
```bash |
|
|
./llama-cli -m model-q4_0.gguf -p "Your prompt here" |
|
|
``` |
|
|
|
|
|
### Python (using llama-cpp-python) |
|
|
|
|
|
```python |
|
|
from llama_cpp import Llama |
|
|
|
|
|
llm = Llama(model_path="model-q4_0.gguf") |
|
|
output = llm("Your prompt here", max_tokens=512) |
|
|
print(output['choices'][0]['text']) |
|
|
``` |
|
|
|
|
|
## Original Model |
|
|
|
|
|
This is a quantized version of [{original_model_id}](https://huggingface.co/{original_model_id}). Please refer to the original model card for more information about the model's capabilities, training data, and usage guidelines. |
|
|
|
|
|
## Conversion Details |
|
|
|
|
|
- Converted using llama.cpp |
|
|
- Original model downloaded from Hugging Face |
|
|
- Multiple quantization levels provided for different use cases |
|
|
- Conversion completed on: {datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC")} |
|
|
|
|
|
## License |
|
|
|
|
|
This model inherits the license from the original model. Please check the original model's license for usage terms. |
|
|
""" |
|
|
|
|
|
model_card_path = os.path.join(output_dir, "README.md") |
|
|
with open(model_card_path, "w", encoding="utf-8") as f: |
|
|
f.write(model_card_content) |
|
|
|
|
|
def _cleanup(self): |
|
|
"""Clean up temporary files""" |
|
|
if self.temp_dir and os.path.exists(self.temp_dir): |
|
|
try: |
|
|
shutil.rmtree(self.temp_dir) |
|
|
logger.info("Cleaned up temporary files") |
|
|
except Exception as e: |
|
|
logger.warning(f"Failed to cleanup: {e}") |
|
|
|
|
|
|
|
|
converter = SpaceGGUFConverter() |
|
|
|
|
|
def get_current_status(): |
|
|
"""Get current conversion status""" |
|
|
global current_status |
|
|
return f"""**Status:** {current_status['status']} |
|
|
**Progress:** {current_status['progress']}% |
|
|
**Message:** {current_status['message']} |
|
|
**Time:** {current_status.get('timestamp', 'N/A')}""" |
|
|
|
|
|
def validate_model_interface(model_id: str): |
|
|
"""Interface function for model validation""" |
|
|
if not model_id.strip(): |
|
|
return "β Please enter a model ID" |
|
|
|
|
|
valid, message = converter.validate_model(model_id.strip()) |
|
|
return message |
|
|
|
|
|
def check_resources_interface(): |
|
|
"""Interface function for resource checking""" |
|
|
resources = converter.check_resources() |
|
|
if "error" in resources: |
|
|
return f"β Error checking resources: {resources['error']}" |
|
|
|
|
|
return f"""## π» System Resources |
|
|
|
|
|
**Memory:** |
|
|
- Total: {resources['memory_total']} |
|
|
- Available: {resources['memory_available']} ({100-resources['memory_percent']:.1f}% free) |
|
|
- Usage: {resources['memory_percent']:.1f}% |
|
|
|
|
|
**Storage:** |
|
|
- Total: {resources['disk_total']} |
|
|
- Free: {resources['disk_free']} ({100-resources['disk_percent']:.1f}% free) |
|
|
- Usage: {resources['disk_percent']:.1f}% |
|
|
|
|
|
**Compute:** |
|
|
- CPU Cores: {resources['cpu_count']} |
|
|
- GPU Available: {'β
Yes' if resources['gpu_available'] else 'β No'} |
|
|
- GPU Memory: {resources['gpu_memory']} |
|
|
|
|
|
**Status:** {'π’ Good' if resources['memory_percent'] < 80 and resources['disk_percent'] < 80 else 'π‘ Limited' if resources['memory_percent'] < 90 else 'π΄ Critical'} |
|
|
""" |
|
|
|
|
|
def convert_model_interface( |
|
|
model_id: str, |
|
|
output_repo: str, |
|
|
hf_token: str, |
|
|
quant_f16: bool, |
|
|
quant_q4_0: bool, |
|
|
quant_q4_1: bool, |
|
|
quant_q5_0: bool, |
|
|
quant_q5_1: bool, |
|
|
quant_q8_0: bool, |
|
|
private_repo: bool |
|
|
): |
|
|
"""Interface function for model conversion""" |
|
|
|
|
|
|
|
|
if not model_id.strip(): |
|
|
return "β Please enter a model ID" |
|
|
|
|
|
if not output_repo.strip(): |
|
|
return "β Please enter an output repository name" |
|
|
|
|
|
if not hf_token.strip(): |
|
|
return "β Please enter your Hugging Face token" |
|
|
|
|
|
|
|
|
quantizations = [] |
|
|
if quant_f16: |
|
|
quantizations.append("f16") |
|
|
if quant_q4_0: |
|
|
quantizations.append("q4_0") |
|
|
if quant_q4_1: |
|
|
quantizations.append("q4_1") |
|
|
if quant_q5_0: |
|
|
quantizations.append("q5_0") |
|
|
if quant_q5_1: |
|
|
quantizations.append("q5_1") |
|
|
if quant_q8_0: |
|
|
quantizations.append("q8_0") |
|
|
|
|
|
if not quantizations: |
|
|
return "β Please select at least one quantization type" |
|
|
|
|
|
|
|
|
success, message = converter.convert_model( |
|
|
model_id.strip(), |
|
|
output_repo.strip(), |
|
|
quantizations, |
|
|
hf_token.strip(), |
|
|
private_repo |
|
|
) |
|
|
|
|
|
return message |
|
|
|
|
|
|
|
|
def create_interface(): |
|
|
"""Create the Gradio interface""" |
|
|
|
|
|
with gr.Blocks( |
|
|
title="π€ GGUF Model Converter", |
|
|
theme=gr.themes.Soft(), |
|
|
css=""" |
|
|
.status-box { |
|
|
background-color: #f0f0f0; |
|
|
padding: 10px; |
|
|
border-radius: 5px; |
|
|
margin: 10px 0; |
|
|
} |
|
|
""" |
|
|
) as demo: |
|
|
|
|
|
gr.Markdown(""" |
|
|
# π€ GGUF Model Converter |
|
|
|
|
|
Convert Hugging Face models to GGUF format for use with llama.cpp and other inference engines. |
|
|
|
|
|
β οΈ **Important Notes:** |
|
|
- Large models (>7B parameters) may take a long time and require significant memory |
|
|
- Make sure you have sufficient disk space (models can be several GB) |
|
|
- You need a Hugging Face token with write access to upload models |
|
|
""") |
|
|
|
|
|
with gr.Tab("π§ Model Converter"): |
|
|
with gr.Row(): |
|
|
with gr.Column(scale=2): |
|
|
gr.Markdown("### π Model Configuration") |
|
|
|
|
|
model_id_input = gr.Textbox( |
|
|
label="Model ID", |
|
|
placeholder="e.g., microsoft/DialoGPT-small", |
|
|
info="Hugging Face model repository ID" |
|
|
) |
|
|
|
|
|
validate_btn = gr.Button("β
Validate Model", variant="secondary") |
|
|
validation_output = gr.Markdown() |
|
|
|
|
|
output_repo_input = gr.Textbox( |
|
|
label="Output Repository", |
|
|
placeholder="e.g., your-username/model-name-GGUF", |
|
|
info="Where to upload the converted model" |
|
|
) |
|
|
|
|
|
hf_token_input = gr.Textbox( |
|
|
label="Hugging Face Token", |
|
|
type="password", |
|
|
placeholder="hf_xxxxxxxxxxxxxxxx", |
|
|
info="Get your token from https://huggingface.co/settings/tokens" |
|
|
) |
|
|
|
|
|
private_repo_checkbox = gr.Checkbox( |
|
|
label="Make repository private", |
|
|
value=False |
|
|
) |
|
|
|
|
|
with gr.Column(scale=1): |
|
|
gr.Markdown("### ποΈ Quantization Options") |
|
|
|
|
|
quant_f16 = gr.Checkbox(label="F16 (Original precision)", value=True) |
|
|
quant_q4_0 = gr.Checkbox(label="Q4_0 (Small, fast)", value=True) |
|
|
quant_q4_1 = gr.Checkbox(label="Q4_1 (Small, balanced)", value=False) |
|
|
quant_q5_0 = gr.Checkbox(label="Q5_0 (Medium, good quality)", value=False) |
|
|
quant_q5_1 = gr.Checkbox(label="Q5_1 (Medium, better quality)", value=False) |
|
|
quant_q8_0 = gr.Checkbox(label="Q8_0 (Large, high quality)", value=False) |
|
|
|
|
|
gr.Markdown("### π Start Conversion") |
|
|
convert_btn = gr.Button("π Convert Model", variant="primary", size="lg") |
|
|
|
|
|
conversion_output = gr.Markdown() |
|
|
|
|
|
with gr.Tab("π System Status"): |
|
|
gr.Markdown("### π» Resource Monitor") |
|
|
|
|
|
refresh_btn = gr.Button("π Refresh Resources", variant="secondary") |
|
|
resources_output = gr.Markdown() |
|
|
|
|
|
gr.Markdown("### π Conversion Status") |
|
|
status_btn = gr.Button("π Check Status", variant="secondary") |
|
|
status_output = gr.Markdown(get_current_status()) |
|
|
|
|
|
with gr.Tab("π Help & Examples"): |
|
|
gr.Markdown(""" |
|
|
## π― Quick Start Guide |
|
|
|
|
|
1. **Enter Model ID**: Use any Hugging Face model ID (e.g., `microsoft/DialoGPT-small`) |
|
|
2. **Validate Model**: Click "Validate Model" to check if the model is accessible |
|
|
3. **Set Output Repository**: Choose where to upload (e.g., `your-username/model-name-GGUF`) |
|
|
4. **Add HF Token**: Get your token from [Hugging Face Settings](https://huggingface.co/settings/tokens) |
|
|
5. **Select Quantizations**: Choose which formats to create |
|
|
6. **Convert**: Click "Convert Model" and wait for completion |
|
|
|
|
|
## π Quantization Guide |
|
|
|
|
|
- **F16**: Original precision, largest file size, best quality |
|
|
- **Q4_0**: 4-bit quantization, smallest size, good for most uses |
|
|
- **Q4_1**: 4-bit with better quality than Q4_0 |
|
|
- **Q5_0/Q5_1**: 5-bit quantization, balance of size and quality |
|
|
- **Q8_0**: 8-bit quantization, high quality, larger files |
|
|
|
|
|
## π‘ Tips for Success |
|
|
|
|
|
- Start with small models (< 1B parameters) to test |
|
|
- Use Q4_0 for mobile/edge deployment |
|
|
- Use Q8_0 or F16 for best quality |
|
|
- Monitor system resources in the Status tab |
|
|
- Large models may take 30+ minutes to convert |
|
|
|
|
|
## π§ Supported Models |
|
|
|
|
|
This converter works with most language models that use standard architectures: |
|
|
- LLaMA, LLaMA 2, Code Llama |
|
|
- Mistral, Mixtral |
|
|
- Phi, Phi-2, Phi-3 |
|
|
- Qwen, ChatGLM |
|
|
- And many others! |
|
|
""") |
|
|
|
|
|
|
|
|
validate_btn.click( |
|
|
fn=validate_model_interface, |
|
|
inputs=[model_id_input], |
|
|
outputs=[validation_output] |
|
|
) |
|
|
|
|
|
convert_btn.click( |
|
|
fn=convert_model_interface, |
|
|
inputs=[ |
|
|
model_id_input, |
|
|
output_repo_input, |
|
|
hf_token_input, |
|
|
quant_f16, |
|
|
quant_q4_0, |
|
|
quant_q4_1, |
|
|
quant_q5_0, |
|
|
quant_q5_1, |
|
|
quant_q8_0, |
|
|
private_repo_checkbox |
|
|
], |
|
|
outputs=[conversion_output] |
|
|
) |
|
|
|
|
|
refresh_btn.click( |
|
|
fn=check_resources_interface, |
|
|
outputs=[resources_output] |
|
|
) |
|
|
|
|
|
status_btn.click( |
|
|
fn=get_current_status, |
|
|
outputs=[status_output] |
|
|
) |
|
|
|
|
|
|
|
|
demo.load(fn=check_resources_interface, outputs=[resources_output]) |
|
|
|
|
|
return demo |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo = create_interface() |
|
|
demo.launch( |
|
|
server_name="0.0.0.0", |
|
|
server_port=7860, |
|
|
share=False, |
|
|
show_error=True |
|
|
) |