webscout 6.4__py3-none-any.whl → 6.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webscout might be problematic. Click here for more details.
- webscout/AIutel.py +7 -54
- webscout/DWEBS.py +48 -26
- webscout/{YTdownloader.py → Extra/YTToolkit/YTdownloader.py} +990 -1103
- webscout/Extra/YTToolkit/__init__.py +3 -0
- webscout/{transcriber.py → Extra/YTToolkit/transcriber.py} +1 -1
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -0
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -0
- webscout/Extra/YTToolkit/ytapi/extras.py +45 -0
- webscout/Extra/YTToolkit/ytapi/https.py +88 -0
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -0
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -0
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -0
- webscout/Extra/YTToolkit/ytapi/query.py +37 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +60 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -0
- webscout/Extra/YTToolkit/ytapi/video.py +102 -0
- webscout/Extra/__init__.py +2 -1
- webscout/Extra/autocoder/rawdog.py +679 -680
- webscout/Extra/gguf.py +441 -441
- webscout/Extra/markdownlite/__init__.py +862 -0
- webscout/Extra/weather_ascii.py +2 -2
- webscout/Provider/PI.py +292 -221
- webscout/Provider/Perplexity.py +6 -14
- webscout/Provider/Reka.py +0 -1
- webscout/Provider/TTS/__init__.py +5 -1
- webscout/Provider/TTS/deepgram.py +183 -0
- webscout/Provider/TTS/elevenlabs.py +137 -0
- webscout/Provider/TTS/gesserit.py +151 -0
- webscout/Provider/TTS/murfai.py +139 -0
- webscout/Provider/TTS/parler.py +134 -107
- webscout/Provider/TTS/streamElements.py +360 -275
- webscout/Provider/TTS/utils.py +280 -0
- webscout/Provider/TTS/voicepod.py +116 -116
- webscout/Provider/__init__.py +146 -146
- webscout/Provider/meta.py +794 -779
- webscout/Provider/typegpt.py +1 -2
- webscout/__init__.py +24 -28
- webscout/litprinter/__init__.py +831 -830
- webscout/optimizers.py +269 -269
- webscout/prompt_manager.py +279 -279
- webscout/scout/__init__.py +11 -0
- webscout/scout/core.py +884 -0
- webscout/scout/element.py +459 -0
- webscout/scout/parsers/__init__.py +69 -0
- webscout/scout/parsers/html5lib_parser.py +172 -0
- webscout/scout/parsers/html_parser.py +236 -0
- webscout/scout/parsers/lxml_parser.py +178 -0
- webscout/scout/utils.py +38 -0
- webscout/update_checker.py +125 -125
- webscout/version.py +1 -1
- webscout/zeroart/__init__.py +55 -0
- webscout/zeroart/base.py +61 -0
- webscout/zeroart/effects.py +99 -0
- webscout/zeroart/fonts.py +816 -0
- webscout/zerodir/__init__.py +225 -0
- {webscout-6.4.dist-info → webscout-6.5.dist-info}/METADATA +12 -68
- {webscout-6.4.dist-info → webscout-6.5.dist-info}/RECORD +62 -37
- webscout/Agents/Onlinesearcher.py +0 -182
- webscout/Agents/__init__.py +0 -2
- webscout/Agents/functioncall.py +0 -248
- webscout/Bing_search.py +0 -251
- webscout/gpt4free.py +0 -666
- webscout/requestsHTMLfix.py +0 -775
- webscout/webai.py +0 -2590
- {webscout-6.4.dist-info → webscout-6.5.dist-info}/LICENSE.md +0 -0
- {webscout-6.4.dist-info → webscout-6.5.dist-info}/WHEEL +0 -0
- {webscout-6.4.dist-info → webscout-6.5.dist-info}/entry_points.txt +0 -0
- {webscout-6.4.dist-info → webscout-6.5.dist-info}/top_level.txt +0 -0
webscout/Extra/gguf.py
CHANGED
|
@@ -1,441 +1,441 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Yo fam! 🔥 Welcome to GGUF Converter - your ultimate tool for converting models to GGUF format! 💪
|
|
3
|
-
|
|
4
|
-
- Converting HuggingFace models to GGUF format 🚀
|
|
5
|
-
- Multiple quantization methods for different needs 🎯
|
|
6
|
-
- Easy upload back to HuggingFace Hub 📤
|
|
7
|
-
|
|
8
|
-
Usage:
|
|
9
|
-
>>> python -m webscout.Extra.gguf convert -m "OEvortex/HelpingAI-Lite-1.5T" -q "q4_k_m,q5_k_m"
|
|
10
|
-
>>> # With upload options:
|
|
11
|
-
>>> python -m webscout.Extra.gguf convert -m "your-model" -u "username" -t "token" -q "q4_k_m"
|
|
12
|
-
|
|
13
|
-
Features:
|
|
14
|
-
- Smart dependency checking 🔍
|
|
15
|
-
- CUDA support detection ⚡
|
|
16
|
-
- Progress tracking that keeps it real 📈
|
|
17
|
-
- Multiple quantization options 🎮
|
|
18
|
-
|
|
19
|
-
Join the squad on Discord and level up your AI game! 🎮
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
import subprocess
|
|
23
|
-
import os
|
|
24
|
-
import sys
|
|
25
|
-
import shutil
|
|
26
|
-
from pathlib import Path
|
|
27
|
-
from typing import List, Optional, Dict, Any
|
|
28
|
-
from
|
|
29
|
-
from rich.console import Console
|
|
30
|
-
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn
|
|
31
|
-
from rich.panel import Panel
|
|
32
|
-
from rich.table import Table
|
|
33
|
-
from ..Litlogger import LitLogger, LogFormat, ColorScheme
|
|
34
|
-
from ..swiftcli import CLI, option
|
|
35
|
-
|
|
36
|
-
# Initialize LitLogger with ocean vibes
|
|
37
|
-
logger = LitLogger(
|
|
38
|
-
name="GGUFConverter",
|
|
39
|
-
format=LogFormat.MODERN_EMOJI,
|
|
40
|
-
color_scheme=ColorScheme.OCEAN
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
console = Console()
|
|
44
|
-
|
|
45
|
-
class ConversionError(Exception):
|
|
46
|
-
"""Custom exception for when things don't go as planned! ⚠️"""
|
|
47
|
-
pass
|
|
48
|
-
|
|
49
|
-
class ModelConverter:
|
|
50
|
-
"""Handles the conversion of Hugging Face models to GGUF format."""
|
|
51
|
-
|
|
52
|
-
VALID_METHODS = {
|
|
53
|
-
"q2_k": "2-bit quantization",
|
|
54
|
-
"q3_k_l": "3-bit quantization (large)",
|
|
55
|
-
"q3_k_m": "3-bit quantization (medium)",
|
|
56
|
-
"q3_k_s": "3-bit quantization (small)",
|
|
57
|
-
"q4_0": "4-bit quantization (version 0)",
|
|
58
|
-
"q4_1": "4-bit quantization (version 1)",
|
|
59
|
-
"q4_k_m": "4-bit quantization (medium)",
|
|
60
|
-
"q4_k_s": "4-bit quantization (small)",
|
|
61
|
-
"q5_0": "5-bit quantization (version 0)",
|
|
62
|
-
"q5_1": "5-bit quantization (version 1)",
|
|
63
|
-
"q5_k_m": "5-bit quantization (medium)",
|
|
64
|
-
"q5_k_s": "5-bit quantization (small)",
|
|
65
|
-
"q6_k": "6-bit quantization",
|
|
66
|
-
"q8_0": "8-bit quantization"
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
def __init__(self, model_id: str, username: Optional[str] = None,
|
|
70
|
-
token: Optional[str] = None, quantization_methods: str = "q4_k_m,q5_k_m"):
|
|
71
|
-
self.model_id = model_id
|
|
72
|
-
self.username = username
|
|
73
|
-
self.token = token
|
|
74
|
-
self.quantization_methods = quantization_methods.split(',')
|
|
75
|
-
self.model_name = model_id.split('/')[-1]
|
|
76
|
-
self.workspace = Path(os.getcwd())
|
|
77
|
-
|
|
78
|
-
def validate_inputs(self) -> None:
|
|
79
|
-
"""Validates all input parameters."""
|
|
80
|
-
if not '/' in self.model_id:
|
|
81
|
-
raise ValueError("Invalid model ID format. Expected format: 'organization/model-name'")
|
|
82
|
-
|
|
83
|
-
invalid_methods = [m for m in self.quantization_methods if m not in self.VALID_METHODS]
|
|
84
|
-
if invalid_methods:
|
|
85
|
-
raise ValueError(
|
|
86
|
-
f"Invalid quantization methods: {', '.join(invalid_methods)}.\n"
|
|
87
|
-
f"Valid methods are: {', '.join(self.VALID_METHODS.keys())}"
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
if bool(self.username) != bool(self.token):
|
|
91
|
-
raise ValueError("Both username and token must be provided for upload, or neither.")
|
|
92
|
-
|
|
93
|
-
@staticmethod
|
|
94
|
-
def check_dependencies() -> Dict[str, bool]:
|
|
95
|
-
"""Check if all required dependencies are installed."""
|
|
96
|
-
dependencies = {
|
|
97
|
-
'git': 'Git version control',
|
|
98
|
-
'pip3': 'Python package installer',
|
|
99
|
-
'huggingface-cli': 'Hugging Face CLI',
|
|
100
|
-
'nvcc': 'NVIDIA CUDA Compiler (optional)'
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
status = {}
|
|
104
|
-
for cmd, desc in dependencies.items():
|
|
105
|
-
status[cmd] = subprocess.run(['which', cmd], capture_output=True, text=True).returncode == 0
|
|
106
|
-
|
|
107
|
-
return status
|
|
108
|
-
|
|
109
|
-
def setup_llama_cpp(self) -> None:
|
|
110
|
-
"""Sets up and builds llama.cpp repository."""
|
|
111
|
-
llama_path = self.workspace / "llama.cpp"
|
|
112
|
-
|
|
113
|
-
with console.status("[bold green]Setting up llama.cpp...") as status:
|
|
114
|
-
if not llama_path.exists():
|
|
115
|
-
logger.info("Cloning llama.cpp repository...")
|
|
116
|
-
subprocess.run(['git', 'clone', 'https://github.com/ggerganov/llama.cpp'], check=True)
|
|
117
|
-
|
|
118
|
-
os.chdir(llama_path)
|
|
119
|
-
logger.info("Installing requirements...")
|
|
120
|
-
subprocess.run(['pip3', 'install', '-r', 'requirements.txt'], check=True)
|
|
121
|
-
|
|
122
|
-
has_cuda = subprocess.run(['nvcc', '--version'], capture_output=True).returncode == 0
|
|
123
|
-
|
|
124
|
-
logger.info("Building llama.cpp...")
|
|
125
|
-
subprocess.run(['make', 'clean'], check=True)
|
|
126
|
-
if has_cuda:
|
|
127
|
-
status.update("[bold green]Building with CUDA support...")
|
|
128
|
-
subprocess.run(['make', 'LLAMA_CUBLAS=1'], check=True)
|
|
129
|
-
else:
|
|
130
|
-
status.update("[bold yellow]Building without CUDA support...")
|
|
131
|
-
subprocess.run(['make'], check=True)
|
|
132
|
-
|
|
133
|
-
os.chdir(self.workspace)
|
|
134
|
-
|
|
135
|
-
def display_config(self) -> None:
|
|
136
|
-
"""Displays the current configuration in a formatted table."""
|
|
137
|
-
table = Table(title="Configuration", show_header=True, header_style="bold magenta")
|
|
138
|
-
table.add_column("Setting", style="cyan")
|
|
139
|
-
table.add_column("Value", style="green")
|
|
140
|
-
|
|
141
|
-
table.add_row("Model ID", self.model_id)
|
|
142
|
-
table.add_row("Model Name", self.model_name)
|
|
143
|
-
table.add_row("Username", self.username or "Not provided")
|
|
144
|
-
table.add_row("Token", "****" if self.token else "Not provided")
|
|
145
|
-
table.add_row("Quantization Methods", "\n".join(
|
|
146
|
-
f"{method} ({self.VALID_METHODS[method]})"
|
|
147
|
-
for method in self.quantization_methods
|
|
148
|
-
))
|
|
149
|
-
|
|
150
|
-
console.print(Panel(table))
|
|
151
|
-
|
|
152
|
-
def convert(self) -> None:
|
|
153
|
-
"""Performs the model conversion process."""
|
|
154
|
-
try:
|
|
155
|
-
# Display banner and configuration
|
|
156
|
-
console.print(f"[bold green]{figlet_format('GGUF Converter')}
|
|
157
|
-
self.display_config()
|
|
158
|
-
|
|
159
|
-
# Validate inputs
|
|
160
|
-
self.validate_inputs()
|
|
161
|
-
|
|
162
|
-
# Check dependencies
|
|
163
|
-
deps = self.check_dependencies()
|
|
164
|
-
missing = [name for name, installed in deps.items() if not installed and name != 'nvcc']
|
|
165
|
-
if missing:
|
|
166
|
-
raise ConversionError(f"Missing required dependencies: {', '.join(missing)}")
|
|
167
|
-
|
|
168
|
-
# Setup llama.cpp
|
|
169
|
-
self.setup_llama_cpp()
|
|
170
|
-
|
|
171
|
-
# Create and execute conversion script
|
|
172
|
-
script_path = self.workspace / "gguf.sh"
|
|
173
|
-
if not script_path.exists():
|
|
174
|
-
self._create_conversion_script(script_path)
|
|
175
|
-
|
|
176
|
-
# Prepare command
|
|
177
|
-
command = ["bash", str(script_path), "-m", self.model_id]
|
|
178
|
-
if self.username and self.token:
|
|
179
|
-
command.extend(["-u", self.username, "-t", self.token])
|
|
180
|
-
command.extend(["-q", ",".join(self.quantization_methods)])
|
|
181
|
-
|
|
182
|
-
# Execute conversion with progress tracking
|
|
183
|
-
with Progress(
|
|
184
|
-
SpinnerColumn(),
|
|
185
|
-
TextColumn("[progress.description]{task.description}"),
|
|
186
|
-
BarColumn(),
|
|
187
|
-
TaskProgressColumn(),
|
|
188
|
-
console=console
|
|
189
|
-
) as progress:
|
|
190
|
-
task = progress.add_task("Converting model...", total=None)
|
|
191
|
-
|
|
192
|
-
process = subprocess.Popen(
|
|
193
|
-
command,
|
|
194
|
-
stdout=subprocess.PIPE,
|
|
195
|
-
stderr=subprocess.PIPE,
|
|
196
|
-
text=True,
|
|
197
|
-
bufsize=1,
|
|
198
|
-
universal_newlines=True
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
while True:
|
|
202
|
-
output = process.stdout.readline()
|
|
203
|
-
if output == '' and process.poll() is not None:
|
|
204
|
-
break
|
|
205
|
-
if output:
|
|
206
|
-
progress.update(task, description=output.strip())
|
|
207
|
-
logger.info(output.strip())
|
|
208
|
-
|
|
209
|
-
stderr = process.stderr.read()
|
|
210
|
-
if stderr:
|
|
211
|
-
logger.warning(stderr)
|
|
212
|
-
|
|
213
|
-
if process.returncode != 0:
|
|
214
|
-
raise ConversionError(f"Conversion failed with return code {process.returncode}")
|
|
215
|
-
|
|
216
|
-
progress.update(task, completed=True)
|
|
217
|
-
|
|
218
|
-
# Display success message
|
|
219
|
-
console.print(Panel.fit(
|
|
220
|
-
"[bold green]✓[/] Conversion completed successfully!\n\n"
|
|
221
|
-
f"[cyan]Output files can be found in: {self.workspace / self.model_name}[/]",
|
|
222
|
-
title="Success",
|
|
223
|
-
border_style="green"
|
|
224
|
-
))
|
|
225
|
-
|
|
226
|
-
except Exception as e:
|
|
227
|
-
console.print(Panel.fit(
|
|
228
|
-
f"[bold red]✗[/] {str(e)}",
|
|
229
|
-
title="Error",
|
|
230
|
-
border_style="red"
|
|
231
|
-
))
|
|
232
|
-
raise
|
|
233
|
-
|
|
234
|
-
def _create_conversion_script(self, script_path: Path) -> None:
|
|
235
|
-
"""Creates the conversion shell script."""
|
|
236
|
-
script_content = """cat << "EOF"
|
|
237
|
-
Made with love in India
|
|
238
|
-
EOF
|
|
239
|
-
|
|
240
|
-
# Default values
|
|
241
|
-
MODEL_ID=""
|
|
242
|
-
USERNAME=""
|
|
243
|
-
TOKEN=""
|
|
244
|
-
QUANTIZATION_METHODS="q4_k_m,q5_k_m" # Default to "q4_k_m,q5_k_m" if not provided
|
|
245
|
-
|
|
246
|
-
# Display help/usage information
|
|
247
|
-
usage() {
|
|
248
|
-
echo "Usage: $0 -m MODEL_ID [-u USERNAME] [-t TOKEN] [-q QUANTIZATION_METHODS]"
|
|
249
|
-
echo
|
|
250
|
-
echo "Options:"
|
|
251
|
-
echo " -m MODEL_ID Required: Set the HF model ID"
|
|
252
|
-
echo " -u USERNAME Optional: Set the username"
|
|
253
|
-
echo " -t TOKEN Optional: Set the token"
|
|
254
|
-
echo " -q QUANTIZATION_METHODS Optional: Set the quantization methods (default: q4_k_m,q5_k_m)"
|
|
255
|
-
echo " -h Display this help and exit"
|
|
256
|
-
echo
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
# Parse command-line options
|
|
260
|
-
while getopts ":m:u:t:q:h" opt; do
|
|
261
|
-
case ${opt} in
|
|
262
|
-
m )
|
|
263
|
-
MODEL_ID=$OPTARG
|
|
264
|
-
;;
|
|
265
|
-
u )
|
|
266
|
-
USERNAME=$OPTARG
|
|
267
|
-
;;
|
|
268
|
-
t )
|
|
269
|
-
TOKEN=$OPTARG
|
|
270
|
-
;;
|
|
271
|
-
q )
|
|
272
|
-
QUANTIZATION_METHODS=$OPTARG
|
|
273
|
-
;;
|
|
274
|
-
h )
|
|
275
|
-
usage
|
|
276
|
-
exit 0
|
|
277
|
-
;;
|
|
278
|
-
\? )
|
|
279
|
-
echo "Invalid Option: -$OPTARG" 1>&2
|
|
280
|
-
usage
|
|
281
|
-
exit 1
|
|
282
|
-
;;
|
|
283
|
-
: )
|
|
284
|
-
echo "Invalid Option: -$OPTARG requires an argument" 1>&2
|
|
285
|
-
usage
|
|
286
|
-
exit 1
|
|
287
|
-
;;
|
|
288
|
-
esac
|
|
289
|
-
done
|
|
290
|
-
shift $((OPTIND -1))
|
|
291
|
-
|
|
292
|
-
# Ensure MODEL_ID is provided
|
|
293
|
-
if [ -z "$MODEL_ID" ]; then
|
|
294
|
-
echo "Error: MODEL_ID is required."
|
|
295
|
-
usage
|
|
296
|
-
exit 1
|
|
297
|
-
fi
|
|
298
|
-
|
|
299
|
-
# # Echoing the arguments for checking
|
|
300
|
-
# echo "MODEL_ID: $MODEL_ID"
|
|
301
|
-
# echo "USERNAME: ${USERNAME:-'Not provided'}"
|
|
302
|
-
# echo "TOKEN: ${TOKEN:-'Not provided'}"
|
|
303
|
-
# echo "QUANTIZATION_METHODS: $QUANTIZATION_METHODS"
|
|
304
|
-
|
|
305
|
-
# Splitting string into an array for quantization methods, if provided
|
|
306
|
-
IFS=',' read -r -a QUANTIZATION_METHOD_ARRAY <<< "$QUANTIZATION_METHODS"
|
|
307
|
-
echo "Quantization Methods: ${QUANTIZATION_METHOD_ARRAY[@]}"
|
|
308
|
-
|
|
309
|
-
MODEL_NAME=$(echo "$MODEL_ID" | awk -F'/' '{print $NF}')
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
# ----------- llama.cpp setup block-----------
|
|
313
|
-
# Check if llama.cpp is already installed and skip the build step if it is
|
|
314
|
-
if [ ! -d "llama.cpp" ]; then
|
|
315
|
-
echo "llama.cpp not found. Cloning and setting up..."
|
|
316
|
-
git clone https://github.com/ggerganov/llama.cpp
|
|
317
|
-
cd llama.cpp && git pull
|
|
318
|
-
# Install required packages
|
|
319
|
-
pip3 install -r requirements.txt
|
|
320
|
-
# Build llama.cpp as it's freshly cloned
|
|
321
|
-
if ! command -v nvcc &> /dev/null
|
|
322
|
-
then
|
|
323
|
-
echo "nvcc could not be found, building llama without LLAMA_CUBLAS"
|
|
324
|
-
make clean && make
|
|
325
|
-
else
|
|
326
|
-
make clean && LLAMA_CUBLAS=1 make
|
|
327
|
-
fi
|
|
328
|
-
cd ..
|
|
329
|
-
else
|
|
330
|
-
echo "llama.cpp found. Assuming it's already built and up to date."
|
|
331
|
-
# Optionally, still update dependencies
|
|
332
|
-
# cd llama.cpp && pip3 install -r requirements.txt && cd ..
|
|
333
|
-
fi
|
|
334
|
-
# ----------- llama.cpp setup block-----------
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
# Download model
|
|
339
|
-
#todo : shall we put condition to check if model has been already downloaded? similar to autogguf?
|
|
340
|
-
echo "Downloading the model..."
|
|
341
|
-
huggingface-cli download "$MODEL_ID" --local-dir "./${MODEL_NAME}" --local-dir-use-symlinks False --revision main
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
# Convert to fp16
|
|
345
|
-
FP16="${MODEL_NAME}/${MODEL_NAME,,}.fp16.bin"
|
|
346
|
-
echo "Converting the model to fp16..."
|
|
347
|
-
python3 llama.cpp/convert_hf_to_gguf.py "$MODEL_NAME" --outtype f16 --outfile "$FP16"
|
|
348
|
-
|
|
349
|
-
# Quantize the model
|
|
350
|
-
echo "Quantizing the model..."
|
|
351
|
-
for METHOD in "${QUANTIZATION_METHOD_ARRAY[@]}"; do
|
|
352
|
-
QTYPE="${MODEL_NAME}/${MODEL_NAME,,}.${METHOD^^}.gguf"
|
|
353
|
-
./llama.cpp/llama-quantize "$FP16" "$QTYPE" "$METHOD"
|
|
354
|
-
done
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
# Check if USERNAME and TOKEN are provided
|
|
358
|
-
if [[ -n "$USERNAME" && -n "$TOKEN" ]]; then
|
|
359
|
-
|
|
360
|
-
# Login to Hugging Face
|
|
361
|
-
echo "Logging in to Hugging Face..."
|
|
362
|
-
huggingface-cli login --token "$TOKEN"
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
# Uploading .gguf, .md files, and config.json
|
|
366
|
-
echo "Uploading .gguf, .md files, and config.json..."
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
# Define a temporary directory
|
|
370
|
-
TEMP_DIR="./temp_upload_dir"
|
|
371
|
-
|
|
372
|
-
# Create the temporary directory
|
|
373
|
-
mkdir -p "${TEMP_DIR}"
|
|
374
|
-
|
|
375
|
-
# Copy the specific files to the temporary directory
|
|
376
|
-
find "./${MODEL_NAME}" -type f \( -name "*.gguf" -o -name "*.md" -o -name "config.json" \) -exec cp {} "${TEMP_DIR}/" \;
|
|
377
|
-
|
|
378
|
-
# Upload the temporary directory to Hugging Face
|
|
379
|
-
huggingface-cli upload "${USERNAME}/${MODEL_NAME}-GGUF" "${TEMP_DIR}" --private
|
|
380
|
-
|
|
381
|
-
# Remove the temporary directory after upload
|
|
382
|
-
rm -rf "${TEMP_DIR}"
|
|
383
|
-
echo "Upload completed."
|
|
384
|
-
else
|
|
385
|
-
echo "USERNAME and TOKEN must be provided for upload."
|
|
386
|
-
fi
|
|
387
|
-
|
|
388
|
-
echo "Script completed."
|
|
389
|
-
"""
|
|
390
|
-
script_path.write_text(script_content)
|
|
391
|
-
script_path.chmod(0o755)
|
|
392
|
-
|
|
393
|
-
# Initialize CLI with HAI vibes
|
|
394
|
-
app = CLI(
|
|
395
|
-
name="gguf",
|
|
396
|
-
help="Convert HuggingFace models to GGUF format with style! 🔥",
|
|
397
|
-
version="1.0.0"
|
|
398
|
-
)
|
|
399
|
-
|
|
400
|
-
@app.command(name="convert")
|
|
401
|
-
@option("-m", "--model-id", help="The HuggingFace model ID (e.g., 'OEvortex/HelpingAI-Lite-1.5T')", required=True)
|
|
402
|
-
@option("-u", "--username", help="Your HuggingFace username for uploads", default=None)
|
|
403
|
-
@option("-t", "--token", help="Your HuggingFace API token for uploads", default=None)
|
|
404
|
-
@option("-q", "--quantization", help="Comma-separated quantization methods", default="q4_k_m,q5_k_m")
|
|
405
|
-
def convert_command(model_id: str, username: Optional[str] = None,
|
|
406
|
-
token: Optional[str] = None, quantization: str = "q4_k_m,q5_k_m"):
|
|
407
|
-
"""
|
|
408
|
-
Convert and quantize HuggingFace models to GGUF format! 🚀
|
|
409
|
-
|
|
410
|
-
Args:
|
|
411
|
-
model_id (str): Your model's HF ID (like 'OEvortex/HelpingAI-Lite-1.5T') 🎯
|
|
412
|
-
username (str, optional): Your HF username for uploads 👤
|
|
413
|
-
token (str, optional): Your HF API token 🔑
|
|
414
|
-
quantization (str): Quantization methods (default: q4_k_m,q5_k_m) 🎮
|
|
415
|
-
|
|
416
|
-
Example:
|
|
417
|
-
>>> python -m webscout.Extra.gguf convert \\
|
|
418
|
-
... -m "OEvortex/HelpingAI-Lite-1.5T" \\
|
|
419
|
-
... -q "q4_k_m,q5_k_m"
|
|
420
|
-
"""
|
|
421
|
-
try:
|
|
422
|
-
converter = ModelConverter(
|
|
423
|
-
model_id=model_id,
|
|
424
|
-
username=username,
|
|
425
|
-
token=token,
|
|
426
|
-
quantization_methods=quantization
|
|
427
|
-
)
|
|
428
|
-
converter.convert()
|
|
429
|
-
except (ConversionError, ValueError) as e:
|
|
430
|
-
logger.error(f"Conversion failed: {str(e)}")
|
|
431
|
-
sys.exit(1)
|
|
432
|
-
except Exception as e:
|
|
433
|
-
logger.error(f"Unexpected error: {str(e)}")
|
|
434
|
-
sys.exit(1)
|
|
435
|
-
|
|
436
|
-
def main():
|
|
437
|
-
"""Fire up the GGUF converter! 🚀"""
|
|
438
|
-
app.run()
|
|
439
|
-
|
|
440
|
-
if __name__ == "__main__":
|
|
441
|
-
main()
|
|
1
|
+
"""
|
|
2
|
+
Yo fam! 🔥 Welcome to GGUF Converter - your ultimate tool for converting models to GGUF format! 💪
|
|
3
|
+
|
|
4
|
+
- Converting HuggingFace models to GGUF format 🚀
|
|
5
|
+
- Multiple quantization methods for different needs 🎯
|
|
6
|
+
- Easy upload back to HuggingFace Hub 📤
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
>>> python -m webscout.Extra.gguf convert -m "OEvortex/HelpingAI-Lite-1.5T" -q "q4_k_m,q5_k_m"
|
|
10
|
+
>>> # With upload options:
|
|
11
|
+
>>> python -m webscout.Extra.gguf convert -m "your-model" -u "username" -t "token" -q "q4_k_m"
|
|
12
|
+
|
|
13
|
+
Features:
|
|
14
|
+
- Smart dependency checking 🔍
|
|
15
|
+
- CUDA support detection ⚡
|
|
16
|
+
- Progress tracking that keeps it real 📈
|
|
17
|
+
- Multiple quantization options 🎮
|
|
18
|
+
|
|
19
|
+
Join the squad on Discord and level up your AI game! 🎮
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import subprocess
|
|
23
|
+
import os
|
|
24
|
+
import sys
|
|
25
|
+
import shutil
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import List, Optional, Dict, Any
|
|
28
|
+
from webscout.zeroart import figlet_format
|
|
29
|
+
from rich.console import Console
|
|
30
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn
|
|
31
|
+
from rich.panel import Panel
|
|
32
|
+
from rich.table import Table
|
|
33
|
+
from ..Litlogger import LitLogger, LogFormat, ColorScheme
|
|
34
|
+
from ..swiftcli import CLI, option
|
|
35
|
+
|
|
36
|
+
# Initialize LitLogger with ocean vibes
|
|
37
|
+
logger = LitLogger(
|
|
38
|
+
name="GGUFConverter",
|
|
39
|
+
format=LogFormat.MODERN_EMOJI,
|
|
40
|
+
color_scheme=ColorScheme.OCEAN
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
console = Console()
|
|
44
|
+
|
|
45
|
+
class ConversionError(Exception):
|
|
46
|
+
"""Custom exception for when things don't go as planned! ⚠️"""
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
class ModelConverter:
|
|
50
|
+
"""Handles the conversion of Hugging Face models to GGUF format."""
|
|
51
|
+
|
|
52
|
+
VALID_METHODS = {
|
|
53
|
+
"q2_k": "2-bit quantization",
|
|
54
|
+
"q3_k_l": "3-bit quantization (large)",
|
|
55
|
+
"q3_k_m": "3-bit quantization (medium)",
|
|
56
|
+
"q3_k_s": "3-bit quantization (small)",
|
|
57
|
+
"q4_0": "4-bit quantization (version 0)",
|
|
58
|
+
"q4_1": "4-bit quantization (version 1)",
|
|
59
|
+
"q4_k_m": "4-bit quantization (medium)",
|
|
60
|
+
"q4_k_s": "4-bit quantization (small)",
|
|
61
|
+
"q5_0": "5-bit quantization (version 0)",
|
|
62
|
+
"q5_1": "5-bit quantization (version 1)",
|
|
63
|
+
"q5_k_m": "5-bit quantization (medium)",
|
|
64
|
+
"q5_k_s": "5-bit quantization (small)",
|
|
65
|
+
"q6_k": "6-bit quantization",
|
|
66
|
+
"q8_0": "8-bit quantization"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
def __init__(self, model_id: str, username: Optional[str] = None,
|
|
70
|
+
token: Optional[str] = None, quantization_methods: str = "q4_k_m,q5_k_m"):
|
|
71
|
+
self.model_id = model_id
|
|
72
|
+
self.username = username
|
|
73
|
+
self.token = token
|
|
74
|
+
self.quantization_methods = quantization_methods.split(',')
|
|
75
|
+
self.model_name = model_id.split('/')[-1]
|
|
76
|
+
self.workspace = Path(os.getcwd())
|
|
77
|
+
|
|
78
|
+
def validate_inputs(self) -> None:
|
|
79
|
+
"""Validates all input parameters."""
|
|
80
|
+
if not '/' in self.model_id:
|
|
81
|
+
raise ValueError("Invalid model ID format. Expected format: 'organization/model-name'")
|
|
82
|
+
|
|
83
|
+
invalid_methods = [m for m in self.quantization_methods if m not in self.VALID_METHODS]
|
|
84
|
+
if invalid_methods:
|
|
85
|
+
raise ValueError(
|
|
86
|
+
f"Invalid quantization methods: {', '.join(invalid_methods)}.\n"
|
|
87
|
+
f"Valid methods are: {', '.join(self.VALID_METHODS.keys())}"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if bool(self.username) != bool(self.token):
|
|
91
|
+
raise ValueError("Both username and token must be provided for upload, or neither.")
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def check_dependencies() -> Dict[str, bool]:
|
|
95
|
+
"""Check if all required dependencies are installed."""
|
|
96
|
+
dependencies = {
|
|
97
|
+
'git': 'Git version control',
|
|
98
|
+
'pip3': 'Python package installer',
|
|
99
|
+
'huggingface-cli': 'Hugging Face CLI',
|
|
100
|
+
'nvcc': 'NVIDIA CUDA Compiler (optional)'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
status = {}
|
|
104
|
+
for cmd, desc in dependencies.items():
|
|
105
|
+
status[cmd] = subprocess.run(['which', cmd], capture_output=True, text=True).returncode == 0
|
|
106
|
+
|
|
107
|
+
return status
|
|
108
|
+
|
|
109
|
+
def setup_llama_cpp(self) -> None:
|
|
110
|
+
"""Sets up and builds llama.cpp repository."""
|
|
111
|
+
llama_path = self.workspace / "llama.cpp"
|
|
112
|
+
|
|
113
|
+
with console.status("[bold green]Setting up llama.cpp...") as status:
|
|
114
|
+
if not llama_path.exists():
|
|
115
|
+
logger.info("Cloning llama.cpp repository...")
|
|
116
|
+
subprocess.run(['git', 'clone', 'https://github.com/ggerganov/llama.cpp'], check=True)
|
|
117
|
+
|
|
118
|
+
os.chdir(llama_path)
|
|
119
|
+
logger.info("Installing requirements...")
|
|
120
|
+
subprocess.run(['pip3', 'install', '-r', 'requirements.txt'], check=True)
|
|
121
|
+
|
|
122
|
+
has_cuda = subprocess.run(['nvcc', '--version'], capture_output=True).returncode == 0
|
|
123
|
+
|
|
124
|
+
logger.info("Building llama.cpp...")
|
|
125
|
+
subprocess.run(['make', 'clean'], check=True)
|
|
126
|
+
if has_cuda:
|
|
127
|
+
status.update("[bold green]Building with CUDA support...")
|
|
128
|
+
subprocess.run(['make', 'LLAMA_CUBLAS=1'], check=True)
|
|
129
|
+
else:
|
|
130
|
+
status.update("[bold yellow]Building without CUDA support...")
|
|
131
|
+
subprocess.run(['make'], check=True)
|
|
132
|
+
|
|
133
|
+
os.chdir(self.workspace)
|
|
134
|
+
|
|
135
|
+
def display_config(self) -> None:
|
|
136
|
+
"""Displays the current configuration in a formatted table."""
|
|
137
|
+
table = Table(title="Configuration", show_header=True, header_style="bold magenta")
|
|
138
|
+
table.add_column("Setting", style="cyan")
|
|
139
|
+
table.add_column("Value", style="green")
|
|
140
|
+
|
|
141
|
+
table.add_row("Model ID", self.model_id)
|
|
142
|
+
table.add_row("Model Name", self.model_name)
|
|
143
|
+
table.add_row("Username", self.username or "Not provided")
|
|
144
|
+
table.add_row("Token", "****" if self.token else "Not provided")
|
|
145
|
+
table.add_row("Quantization Methods", "\n".join(
|
|
146
|
+
f"{method} ({self.VALID_METHODS[method]})"
|
|
147
|
+
for method in self.quantization_methods
|
|
148
|
+
))
|
|
149
|
+
|
|
150
|
+
console.print(Panel(table))
|
|
151
|
+
|
|
152
|
+
def convert(self) -> None:
|
|
153
|
+
"""Performs the model conversion process."""
|
|
154
|
+
try:
|
|
155
|
+
# Display banner and configuration
|
|
156
|
+
console.print(f"[bold green]{figlet_format('GGUF Converter')}")
|
|
157
|
+
self.display_config()
|
|
158
|
+
|
|
159
|
+
# Validate inputs
|
|
160
|
+
self.validate_inputs()
|
|
161
|
+
|
|
162
|
+
# Check dependencies
|
|
163
|
+
deps = self.check_dependencies()
|
|
164
|
+
missing = [name for name, installed in deps.items() if not installed and name != 'nvcc']
|
|
165
|
+
if missing:
|
|
166
|
+
raise ConversionError(f"Missing required dependencies: {', '.join(missing)}")
|
|
167
|
+
|
|
168
|
+
# Setup llama.cpp
|
|
169
|
+
self.setup_llama_cpp()
|
|
170
|
+
|
|
171
|
+
# Create and execute conversion script
|
|
172
|
+
script_path = self.workspace / "gguf.sh"
|
|
173
|
+
if not script_path.exists():
|
|
174
|
+
self._create_conversion_script(script_path)
|
|
175
|
+
|
|
176
|
+
# Prepare command
|
|
177
|
+
command = ["bash", str(script_path), "-m", self.model_id]
|
|
178
|
+
if self.username and self.token:
|
|
179
|
+
command.extend(["-u", self.username, "-t", self.token])
|
|
180
|
+
command.extend(["-q", ",".join(self.quantization_methods)])
|
|
181
|
+
|
|
182
|
+
# Execute conversion with progress tracking
|
|
183
|
+
with Progress(
|
|
184
|
+
SpinnerColumn(),
|
|
185
|
+
TextColumn("[progress.description]{task.description}"),
|
|
186
|
+
BarColumn(),
|
|
187
|
+
TaskProgressColumn(),
|
|
188
|
+
console=console
|
|
189
|
+
) as progress:
|
|
190
|
+
task = progress.add_task("Converting model...", total=None)
|
|
191
|
+
|
|
192
|
+
process = subprocess.Popen(
|
|
193
|
+
command,
|
|
194
|
+
stdout=subprocess.PIPE,
|
|
195
|
+
stderr=subprocess.PIPE,
|
|
196
|
+
text=True,
|
|
197
|
+
bufsize=1,
|
|
198
|
+
universal_newlines=True
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
while True:
|
|
202
|
+
output = process.stdout.readline()
|
|
203
|
+
if output == '' and process.poll() is not None:
|
|
204
|
+
break
|
|
205
|
+
if output:
|
|
206
|
+
progress.update(task, description=output.strip())
|
|
207
|
+
logger.info(output.strip())
|
|
208
|
+
|
|
209
|
+
stderr = process.stderr.read()
|
|
210
|
+
if stderr:
|
|
211
|
+
logger.warning(stderr)
|
|
212
|
+
|
|
213
|
+
if process.returncode != 0:
|
|
214
|
+
raise ConversionError(f"Conversion failed with return code {process.returncode}")
|
|
215
|
+
|
|
216
|
+
progress.update(task, completed=True)
|
|
217
|
+
|
|
218
|
+
# Display success message
|
|
219
|
+
console.print(Panel.fit(
|
|
220
|
+
"[bold green]✓[/] Conversion completed successfully!\n\n"
|
|
221
|
+
f"[cyan]Output files can be found in: {self.workspace / self.model_name}[/]",
|
|
222
|
+
title="Success",
|
|
223
|
+
border_style="green"
|
|
224
|
+
))
|
|
225
|
+
|
|
226
|
+
except Exception as e:
|
|
227
|
+
console.print(Panel.fit(
|
|
228
|
+
f"[bold red]✗[/] {str(e)}",
|
|
229
|
+
title="Error",
|
|
230
|
+
border_style="red"
|
|
231
|
+
))
|
|
232
|
+
raise
|
|
233
|
+
|
|
234
|
+
def _create_conversion_script(self, script_path: Path) -> None:
|
|
235
|
+
"""Creates the conversion shell script."""
|
|
236
|
+
script_content = """cat << "EOF"
|
|
237
|
+
Made with love in India
|
|
238
|
+
EOF
|
|
239
|
+
|
|
240
|
+
# Default values
|
|
241
|
+
MODEL_ID=""
|
|
242
|
+
USERNAME=""
|
|
243
|
+
TOKEN=""
|
|
244
|
+
QUANTIZATION_METHODS="q4_k_m,q5_k_m" # Default to "q4_k_m,q5_k_m" if not provided
|
|
245
|
+
|
|
246
|
+
# Display help/usage information
|
|
247
|
+
usage() {
|
|
248
|
+
echo "Usage: $0 -m MODEL_ID [-u USERNAME] [-t TOKEN] [-q QUANTIZATION_METHODS]"
|
|
249
|
+
echo
|
|
250
|
+
echo "Options:"
|
|
251
|
+
echo " -m MODEL_ID Required: Set the HF model ID"
|
|
252
|
+
echo " -u USERNAME Optional: Set the username"
|
|
253
|
+
echo " -t TOKEN Optional: Set the token"
|
|
254
|
+
echo " -q QUANTIZATION_METHODS Optional: Set the quantization methods (default: q4_k_m,q5_k_m)"
|
|
255
|
+
echo " -h Display this help and exit"
|
|
256
|
+
echo
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
# Parse command-line options
|
|
260
|
+
while getopts ":m:u:t:q:h" opt; do
|
|
261
|
+
case ${opt} in
|
|
262
|
+
m )
|
|
263
|
+
MODEL_ID=$OPTARG
|
|
264
|
+
;;
|
|
265
|
+
u )
|
|
266
|
+
USERNAME=$OPTARG
|
|
267
|
+
;;
|
|
268
|
+
t )
|
|
269
|
+
TOKEN=$OPTARG
|
|
270
|
+
;;
|
|
271
|
+
q )
|
|
272
|
+
QUANTIZATION_METHODS=$OPTARG
|
|
273
|
+
;;
|
|
274
|
+
h )
|
|
275
|
+
usage
|
|
276
|
+
exit 0
|
|
277
|
+
;;
|
|
278
|
+
\? )
|
|
279
|
+
echo "Invalid Option: -$OPTARG" 1>&2
|
|
280
|
+
usage
|
|
281
|
+
exit 1
|
|
282
|
+
;;
|
|
283
|
+
: )
|
|
284
|
+
echo "Invalid Option: -$OPTARG requires an argument" 1>&2
|
|
285
|
+
usage
|
|
286
|
+
exit 1
|
|
287
|
+
;;
|
|
288
|
+
esac
|
|
289
|
+
done
|
|
290
|
+
shift $((OPTIND -1))
|
|
291
|
+
|
|
292
|
+
# Ensure MODEL_ID is provided
|
|
293
|
+
if [ -z "$MODEL_ID" ]; then
|
|
294
|
+
echo "Error: MODEL_ID is required."
|
|
295
|
+
usage
|
|
296
|
+
exit 1
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
# # Echoing the arguments for checking
|
|
300
|
+
# echo "MODEL_ID: $MODEL_ID"
|
|
301
|
+
# echo "USERNAME: ${USERNAME:-'Not provided'}"
|
|
302
|
+
# echo "TOKEN: ${TOKEN:-'Not provided'}"
|
|
303
|
+
# echo "QUANTIZATION_METHODS: $QUANTIZATION_METHODS"
|
|
304
|
+
|
|
305
|
+
# Splitting string into an array for quantization methods, if provided
|
|
306
|
+
IFS=',' read -r -a QUANTIZATION_METHOD_ARRAY <<< "$QUANTIZATION_METHODS"
|
|
307
|
+
echo "Quantization Methods: ${QUANTIZATION_METHOD_ARRAY[@]}"
|
|
308
|
+
|
|
309
|
+
MODEL_NAME=$(echo "$MODEL_ID" | awk -F'/' '{print $NF}')
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
# ----------- llama.cpp setup block-----------
|
|
313
|
+
# Check if llama.cpp is already installed and skip the build step if it is
|
|
314
|
+
if [ ! -d "llama.cpp" ]; then
|
|
315
|
+
echo "llama.cpp not found. Cloning and setting up..."
|
|
316
|
+
git clone https://github.com/ggerganov/llama.cpp
|
|
317
|
+
cd llama.cpp && git pull
|
|
318
|
+
# Install required packages
|
|
319
|
+
pip3 install -r requirements.txt
|
|
320
|
+
# Build llama.cpp as it's freshly cloned
|
|
321
|
+
if ! command -v nvcc &> /dev/null
|
|
322
|
+
then
|
|
323
|
+
echo "nvcc could not be found, building llama without LLAMA_CUBLAS"
|
|
324
|
+
make clean && make
|
|
325
|
+
else
|
|
326
|
+
make clean && LLAMA_CUBLAS=1 make
|
|
327
|
+
fi
|
|
328
|
+
cd ..
|
|
329
|
+
else
|
|
330
|
+
echo "llama.cpp found. Assuming it's already built and up to date."
|
|
331
|
+
# Optionally, still update dependencies
|
|
332
|
+
# cd llama.cpp && pip3 install -r requirements.txt && cd ..
|
|
333
|
+
fi
|
|
334
|
+
# ----------- llama.cpp setup block-----------
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
# Download model
|
|
339
|
+
#todo : shall we put condition to check if model has been already downloaded? similar to autogguf?
|
|
340
|
+
echo "Downloading the model..."
|
|
341
|
+
huggingface-cli download "$MODEL_ID" --local-dir "./${MODEL_NAME}" --local-dir-use-symlinks False --revision main
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
# Convert to fp16
|
|
345
|
+
FP16="${MODEL_NAME}/${MODEL_NAME,,}.fp16.bin"
|
|
346
|
+
echo "Converting the model to fp16..."
|
|
347
|
+
python3 llama.cpp/convert_hf_to_gguf.py "$MODEL_NAME" --outtype f16 --outfile "$FP16"
|
|
348
|
+
|
|
349
|
+
# Quantize the model
|
|
350
|
+
echo "Quantizing the model..."
|
|
351
|
+
for METHOD in "${QUANTIZATION_METHOD_ARRAY[@]}"; do
|
|
352
|
+
QTYPE="${MODEL_NAME}/${MODEL_NAME,,}.${METHOD^^}.gguf"
|
|
353
|
+
./llama.cpp/llama-quantize "$FP16" "$QTYPE" "$METHOD"
|
|
354
|
+
done
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
# Check if USERNAME and TOKEN are provided
|
|
358
|
+
if [[ -n "$USERNAME" && -n "$TOKEN" ]]; then
|
|
359
|
+
|
|
360
|
+
# Login to Hugging Face
|
|
361
|
+
echo "Logging in to Hugging Face..."
|
|
362
|
+
huggingface-cli login --token "$TOKEN"
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
# Uploading .gguf, .md files, and config.json
|
|
366
|
+
echo "Uploading .gguf, .md files, and config.json..."
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# Define a temporary directory
|
|
370
|
+
TEMP_DIR="./temp_upload_dir"
|
|
371
|
+
|
|
372
|
+
# Create the temporary directory
|
|
373
|
+
mkdir -p "${TEMP_DIR}"
|
|
374
|
+
|
|
375
|
+
# Copy the specific files to the temporary directory
|
|
376
|
+
find "./${MODEL_NAME}" -type f \( -name "*.gguf" -o -name "*.md" -o -name "config.json" \) -exec cp {} "${TEMP_DIR}/" \;
|
|
377
|
+
|
|
378
|
+
# Upload the temporary directory to Hugging Face
|
|
379
|
+
huggingface-cli upload "${USERNAME}/${MODEL_NAME}-GGUF" "${TEMP_DIR}" --private
|
|
380
|
+
|
|
381
|
+
# Remove the temporary directory after upload
|
|
382
|
+
rm -rf "${TEMP_DIR}"
|
|
383
|
+
echo "Upload completed."
|
|
384
|
+
else
|
|
385
|
+
echo "USERNAME and TOKEN must be provided for upload."
|
|
386
|
+
fi
|
|
387
|
+
|
|
388
|
+
echo "Script completed."
|
|
389
|
+
"""
|
|
390
|
+
script_path.write_text(script_content)
|
|
391
|
+
script_path.chmod(0o755)
|
|
392
|
+
|
|
393
|
+
# Initialize CLI with HAI vibes
|
|
394
|
+
app = CLI(
|
|
395
|
+
name="gguf",
|
|
396
|
+
help="Convert HuggingFace models to GGUF format with style! 🔥",
|
|
397
|
+
version="1.0.0"
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
@app.command(name="convert")
|
|
401
|
+
@option("-m", "--model-id", help="The HuggingFace model ID (e.g., 'OEvortex/HelpingAI-Lite-1.5T')", required=True)
|
|
402
|
+
@option("-u", "--username", help="Your HuggingFace username for uploads", default=None)
|
|
403
|
+
@option("-t", "--token", help="Your HuggingFace API token for uploads", default=None)
|
|
404
|
+
@option("-q", "--quantization", help="Comma-separated quantization methods", default="q4_k_m,q5_k_m")
|
|
405
|
+
def convert_command(model_id: str, username: Optional[str] = None,
|
|
406
|
+
token: Optional[str] = None, quantization: str = "q4_k_m,q5_k_m"):
|
|
407
|
+
"""
|
|
408
|
+
Convert and quantize HuggingFace models to GGUF format! 🚀
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
model_id (str): Your model's HF ID (like 'OEvortex/HelpingAI-Lite-1.5T') 🎯
|
|
412
|
+
username (str, optional): Your HF username for uploads 👤
|
|
413
|
+
token (str, optional): Your HF API token 🔑
|
|
414
|
+
quantization (str): Quantization methods (default: q4_k_m,q5_k_m) 🎮
|
|
415
|
+
|
|
416
|
+
Example:
|
|
417
|
+
>>> python -m webscout.Extra.gguf convert \\
|
|
418
|
+
... -m "OEvortex/HelpingAI-Lite-1.5T" \\
|
|
419
|
+
... -q "q4_k_m,q5_k_m"
|
|
420
|
+
"""
|
|
421
|
+
try:
|
|
422
|
+
converter = ModelConverter(
|
|
423
|
+
model_id=model_id,
|
|
424
|
+
username=username,
|
|
425
|
+
token=token,
|
|
426
|
+
quantization_methods=quantization
|
|
427
|
+
)
|
|
428
|
+
converter.convert()
|
|
429
|
+
except (ConversionError, ValueError) as e:
|
|
430
|
+
logger.error(f"Conversion failed: {str(e)}")
|
|
431
|
+
sys.exit(1)
|
|
432
|
+
except Exception as e:
|
|
433
|
+
logger.error(f"Unexpected error: {str(e)}")
|
|
434
|
+
sys.exit(1)
|
|
435
|
+
|
|
436
|
+
def main():
|
|
437
|
+
"""Fire up the GGUF converter! 🚀"""
|
|
438
|
+
app.run()
|
|
439
|
+
|
|
440
|
+
if __name__ == "__main__":
|
|
441
|
+
main()
|