webscout 6.2b0__py3-none-any.whl → 6.4__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.

Files changed (97) hide show
  1. webscout/AIauto.py +191 -176
  2. webscout/AIbase.py +112 -239
  3. webscout/AIutel.py +488 -1130
  4. webscout/Agents/functioncall.py +248 -198
  5. webscout/Bing_search.py +250 -153
  6. webscout/DWEBS.py +454 -178
  7. webscout/Extra/__init__.py +2 -1
  8. webscout/Extra/autocoder/__init__.py +9 -0
  9. webscout/Extra/autocoder/autocoder_utiles.py +121 -0
  10. webscout/Extra/autocoder/rawdog.py +681 -0
  11. webscout/Extra/autollama.py +246 -195
  12. webscout/Extra/gguf.py +441 -226
  13. webscout/Extra/weather.py +172 -67
  14. webscout/LLM.py +442 -100
  15. webscout/Litlogger/__init__.py +681 -0
  16. webscout/Local/formats.py +4 -2
  17. webscout/Provider/Amigo.py +19 -10
  18. webscout/Provider/Andi.py +0 -33
  19. webscout/Provider/Blackboxai.py +4 -204
  20. webscout/Provider/DARKAI.py +1 -1
  21. webscout/Provider/EDITEE.py +1 -1
  22. webscout/Provider/Llama3.py +1 -1
  23. webscout/Provider/Marcus.py +137 -0
  24. webscout/Provider/NinjaChat.py +1 -1
  25. webscout/Provider/PI.py +221 -207
  26. webscout/Provider/Perplexity.py +598 -598
  27. webscout/Provider/RoboCoders.py +206 -0
  28. webscout/Provider/TTI/AiForce/__init__.py +22 -0
  29. webscout/Provider/TTI/AiForce/async_aiforce.py +257 -0
  30. webscout/Provider/TTI/AiForce/sync_aiforce.py +242 -0
  31. webscout/Provider/TTI/Nexra/__init__.py +22 -0
  32. webscout/Provider/TTI/Nexra/async_nexra.py +286 -0
  33. webscout/Provider/TTI/Nexra/sync_nexra.py +258 -0
  34. webscout/Provider/TTI/PollinationsAI/__init__.py +23 -0
  35. webscout/Provider/TTI/PollinationsAI/async_pollinations.py +330 -0
  36. webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +285 -0
  37. webscout/Provider/TTI/__init__.py +3 -4
  38. webscout/Provider/TTI/artbit/__init__.py +22 -0
  39. webscout/Provider/TTI/artbit/async_artbit.py +184 -0
  40. webscout/Provider/TTI/artbit/sync_artbit.py +176 -0
  41. webscout/Provider/TTI/blackbox/__init__.py +4 -0
  42. webscout/Provider/TTI/blackbox/async_blackbox.py +212 -0
  43. webscout/Provider/TTI/{blackboximage.py → blackbox/sync_blackbox.py} +199 -153
  44. webscout/Provider/TTI/deepinfra/__init__.py +4 -0
  45. webscout/Provider/TTI/deepinfra/async_deepinfra.py +227 -0
  46. webscout/Provider/TTI/deepinfra/sync_deepinfra.py +199 -0
  47. webscout/Provider/TTI/huggingface/__init__.py +22 -0
  48. webscout/Provider/TTI/huggingface/async_huggingface.py +199 -0
  49. webscout/Provider/TTI/huggingface/sync_huggingface.py +195 -0
  50. webscout/Provider/TTI/imgninza/__init__.py +4 -0
  51. webscout/Provider/TTI/imgninza/async_ninza.py +214 -0
  52. webscout/Provider/TTI/{imgninza.py → imgninza/sync_ninza.py} +209 -136
  53. webscout/Provider/TTI/talkai/__init__.py +4 -0
  54. webscout/Provider/TTI/talkai/async_talkai.py +229 -0
  55. webscout/Provider/TTI/talkai/sync_talkai.py +207 -0
  56. webscout/Provider/__init__.py +146 -132
  57. webscout/Provider/askmyai.py +158 -0
  58. webscout/Provider/cerebras.py +227 -206
  59. webscout/Provider/geminiapi.py +208 -198
  60. webscout/Provider/llama3mitril.py +180 -0
  61. webscout/Provider/llmchat.py +203 -0
  62. webscout/Provider/mhystical.py +176 -0
  63. webscout/Provider/perplexitylabs.py +265 -0
  64. webscout/Provider/talkai.py +196 -0
  65. webscout/Provider/twitterclone.py +251 -244
  66. webscout/Provider/typegpt.py +359 -0
  67. webscout/__init__.py +28 -23
  68. webscout/__main__.py +5 -5
  69. webscout/cli.py +327 -347
  70. webscout/conversation.py +227 -0
  71. webscout/exceptions.py +161 -29
  72. webscout/litagent/__init__.py +172 -0
  73. webscout/litprinter/__init__.py +831 -0
  74. webscout/optimizers.py +270 -0
  75. webscout/prompt_manager.py +279 -0
  76. webscout/swiftcli/__init__.py +810 -0
  77. webscout/transcriber.py +479 -551
  78. webscout/update_checker.py +125 -0
  79. webscout/version.py +1 -1
  80. webscout-6.4.dist-info/LICENSE.md +211 -0
  81. {webscout-6.2b0.dist-info → webscout-6.4.dist-info}/METADATA +34 -55
  82. webscout-6.4.dist-info/RECORD +154 -0
  83. webscout/Provider/TTI/AIuncensored.py +0 -103
  84. webscout/Provider/TTI/Nexra.py +0 -120
  85. webscout/Provider/TTI/PollinationsAI.py +0 -138
  86. webscout/Provider/TTI/WebSimAI.py +0 -142
  87. webscout/Provider/TTI/aiforce.py +0 -160
  88. webscout/Provider/TTI/artbit.py +0 -141
  89. webscout/Provider/TTI/deepinfra.py +0 -148
  90. webscout/Provider/TTI/huggingface.py +0 -155
  91. webscout/models.py +0 -23
  92. webscout-6.2b0.dist-info/LICENSE.md +0 -50
  93. webscout-6.2b0.dist-info/RECORD +0 -118
  94. /webscout/{g4f.py → gpt4free.py} +0 -0
  95. {webscout-6.2b0.dist-info → webscout-6.4.dist-info}/WHEEL +0 -0
  96. {webscout-6.2b0.dist-info → webscout-6.4.dist-info}/entry_points.txt +0 -0
  97. {webscout-6.2b0.dist-info → webscout-6.4.dist-info}/top_level.txt +0 -0
webscout/Extra/gguf.py CHANGED
@@ -1,226 +1,441 @@
1
- # webscout/Extra/gguf.py
2
- import subprocess
3
- import os
4
- from pyfiglet import figlet_format
5
- from rich.console import Console
6
-
7
- console = Console()
8
-
9
- def convert(model_id, username=None, token=None, quantization_methods="q4_k_m,q5_k_m"):
10
- """Converts and quantizes a Hugging Face model to GGUF format.
11
-
12
- Args:
13
- model_id (str): The Hugging Face model ID (e.g., 'google/flan-t5-xl').
14
- username (str, optional): Your Hugging Face username. Required for uploads.
15
- token (str, optional): Your Hugging Face API token. Required for uploads.
16
- quantization_methods (str, optional): Comma-separated quantization methods.
17
- Defaults to "q4_k_m,q5_k_m".
18
-
19
- Raises:
20
- ValueError: If an invalid quantization method is provided.
21
- """
22
-
23
- console.print(f"[bold green]{figlet_format('GGUF Converter')}[/]\n", justify="center")
24
- # List of valid quantization methods
25
- valid_methods = [
26
- "q2_k", "q3_k_l", "q3_k_m", "q3_k_s",
27
- "q4_0", "q4_1", "q4_k_m", "q4_k_s",
28
- "q5_0", "q5_1", "q5_k_m", "q5_k_s",
29
- "q6_k", "q8_0"
30
- ]
31
-
32
- # Validate the selected quantization methods
33
- selected_methods_list = quantization_methods.split(',')
34
- for method in selected_methods_list:
35
- if method not in valid_methods:
36
- raise ValueError(f"Invalid method: {method}. Please select from the available methods: {', '.join(valid_methods)}")
37
-
38
- # Construct the absolute path to the shell script
39
- script_path = os.path.join(os.getcwd(), "gguf.sh")
40
- if not os.path.exists(script_path):
41
- # Create autollama.sh with the content provided
42
- with open(script_path, "w") as f:
43
- f.write("""
44
- cat << "EOF"
45
- Made with love in India
46
- EOF
47
-
48
- # Default values
49
- MODEL_ID=""
50
- USERNAME=""
51
- TOKEN=""
52
- QUANTIZATION_METHODS="q4_k_m,q5_k_m" # Default to "q4_k_m,q5_k_m" if not provided
53
-
54
- # Display help/usage information
55
- usage() {
56
- echo "Usage: $0 -m MODEL_ID [-u USERNAME] [-t TOKEN] [-q QUANTIZATION_METHODS]"
57
- echo
58
- echo "Options:"
59
- echo " -m MODEL_ID Required: Set the HF model ID"
60
- echo " -u USERNAME Optional: Set the username"
61
- echo " -t TOKEN Optional: Set the token"
62
- echo " -q QUANTIZATION_METHODS Optional: Set the quantization methods (default: q4_k_m,q5_k_m)"
63
- echo " -h Display this help and exit"
64
- echo
65
- }
66
-
67
- # Parse command-line options
68
- while getopts ":m:u:t:q:h" opt; do
69
- case ${opt} in
70
- m )
71
- MODEL_ID=$OPTARG
72
- ;;
73
- u )
74
- USERNAME=$OPTARG
75
- ;;
76
- t )
77
- TOKEN=$OPTARG
78
- ;;
79
- q )
80
- QUANTIZATION_METHODS=$OPTARG
81
- ;;
82
- h )
83
- usage
84
- exit 0
85
- ;;
86
- \? )
87
- echo "Invalid Option: -$OPTARG" 1>&2
88
- usage
89
- exit 1
90
- ;;
91
- : )
92
- echo "Invalid Option: -$OPTARG requires an argument" 1>&2
93
- usage
94
- exit 1
95
- ;;
96
- esac
97
- done
98
- shift $((OPTIND -1))
99
-
100
- # Ensure MODEL_ID is provided
101
- if [ -z "$MODEL_ID" ]; then
102
- echo "Error: MODEL_ID is required."
103
- usage
104
- exit 1
105
- fi
106
-
107
- # # Echoing the arguments for checking
108
- # echo "MODEL_ID: $MODEL_ID"
109
- # echo "USERNAME: ${USERNAME:-'Not provided'}"
110
- # echo "TOKEN: ${TOKEN:-'Not provided'}"
111
- # echo "QUANTIZATION_METHODS: $QUANTIZATION_METHODS"
112
-
113
- # Splitting string into an array for quantization methods, if provided
114
- IFS=',' read -r -a QUANTIZATION_METHOD_ARRAY <<< "$QUANTIZATION_METHODS"
115
- echo "Quantization Methods: ${QUANTIZATION_METHOD_ARRAY[@]}"
116
-
117
- MODEL_NAME=$(echo "$MODEL_ID" | awk -F'/' '{print $NF}')
118
-
119
-
120
- # ----------- llama.cpp setup block-----------
121
- # Check if llama.cpp is already installed and skip the build step if it is
122
- if [ ! -d "llama.cpp" ]; then
123
- echo "llama.cpp not found. Cloning and setting up..."
124
- git clone https://github.com/ggerganov/llama.cpp
125
- cd llama.cpp && git pull
126
- # Install required packages
127
- pip3 install -r requirements.txt
128
- # Build llama.cpp as it's freshly cloned
129
- if ! command -v nvcc &> /dev/null
130
- then
131
- echo "nvcc could not be found, building llama without LLAMA_CUBLAS"
132
- make clean && make
133
- else
134
- make clean && LLAMA_CUBLAS=1 make
135
- fi
136
- cd ..
137
- else
138
- echo "llama.cpp found. Assuming it's already built and up to date."
139
- # Optionally, still update dependencies
140
- # cd llama.cpp && pip3 install -r requirements.txt && cd ..
141
- fi
142
- # ----------- llama.cpp setup block-----------
143
-
144
-
145
-
146
-
147
- # Download model
148
- #todo : shall we put condition to check if model has been already downloaded? similar to autogguf?
149
- echo "Downloading the model..."
150
- huggingface-cli download "$MODEL_ID" --local-dir "./${MODEL_NAME}" --local-dir-use-symlinks False --revision main
151
-
152
-
153
- # Convert to fp16
154
- FP16="${MODEL_NAME}/${MODEL_NAME,,}.fp16.bin"
155
- echo "Converting the model to fp16..."
156
- python3 llama.cpp/convert_hf_to_gguf.py "$MODEL_NAME" --outtype f16 --outfile "$FP16"
157
-
158
- # Quantize the model
159
- echo "Quantizing the model..."
160
- for METHOD in "${QUANTIZATION_METHOD_ARRAY[@]}"; do
161
- QTYPE="${MODEL_NAME}/${MODEL_NAME,,}.${METHOD^^}.gguf"
162
- ./llama.cpp/llama-quantize "$FP16" "$QTYPE" "$METHOD"
163
- done
164
-
165
-
166
- # Check if USERNAME and TOKEN are provided
167
- if [[ -n "$USERNAME" && -n "$TOKEN" ]]; then
168
-
169
- # Login to Hugging Face
170
- echo "Logging in to Hugging Face..."
171
- huggingface-cli login --token "$TOKEN"
172
-
173
-
174
- # Uploading .gguf, .md files, and config.json
175
- echo "Uploading .gguf, .md files, and config.json..."
176
-
177
-
178
- # Define a temporary directory
179
- TEMP_DIR="./temp_upload_dir"
180
-
181
- # Create the temporary directory
182
- mkdir -p "${TEMP_DIR}"
183
-
184
- # Copy the specific files to the temporary directory
185
- find "./${MODEL_NAME}" -type f \( -name "*.gguf" -o -name "*.md" -o -name "config.json" \) -exec cp {} "${TEMP_DIR}/" \;
186
-
187
- # Upload the temporary directory to Hugging Face
188
- huggingface-cli upload "${USERNAME}/${MODEL_NAME}-GGUF" "${TEMP_DIR}" --private
189
-
190
- # Remove the temporary directory after upload
191
- rm -rf "${TEMP_DIR}"
192
- echo "Upload completed."
193
- else
194
- echo "USERNAME and TOKEN must be provided for upload."
195
- fi
196
-
197
- echo "Script completed."
198
- """)
199
- # Make autollama.sh executable (using chmod)
200
- os.chmod(script_path, 0o755)
201
-
202
- # Construct the command
203
- command = ["bash", script_path, "-m", model_id]
204
-
205
- if username:
206
- command.extend(["-u", username])
207
-
208
- if token:
209
- command.extend(["-t", token])
210
-
211
- if quantization_methods:
212
- command.extend(["-q", quantization_methods])
213
-
214
- # Execute the command
215
- process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
216
-
217
- # Print the output and error in real-time
218
- for line in process.stdout:
219
- print(line, end='')
220
-
221
- for line in process.stderr:
222
- print(line, end='')
223
-
224
- process.wait()
225
-
226
-
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 pyfiglet 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')}[/]\n", justify="center")
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()