-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmac.sh
More file actions
484 lines (411 loc) · 18.1 KB
/
Copy pathmac.sh
File metadata and controls
484 lines (411 loc) · 18.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
#!/bin/bash
set -o pipefail
# Logging functions
log_message() {
local message="$1"
if [[ -n "${message// }" ]]; then
echo "[LAUNCHER_LOGGER] [MODEL_INSTALL_LLAMA] --message \"$message\""
fi
}
log_error() {
local message="$1"
if [[ -n "${message// }" ]]; then
echo "[LAUNCHER_LOGGER] [MODEL_INSTALL_LLAMA] --error \"$message\"" >&2
fi
}
# Version comparison function
compare_versions() {
local installed="v$1"
local remote="$2"
# Validate version strings (basic semver check)
if [[ ! "$installed" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?([.-][a-zA-Z0-9]+)*$ ]]; then
log_error "Invalid installed version format: $installed"
return 2
fi
if [[ ! "$remote" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?([.-][a-zA-Z0-9]+)*$ ]]; then
log_error "Invalid remote version format: $remote"
return 2
fi
# Return 0 if update needed (remote > installed), 1 if no update needed, 2 if error
if [ "$installed" != "$remote" ] && [ "$(printf '%s\n' "$installed" "$remote" | sort -V | head -n1)" = "$installed" ]; then
return 0 # Update needed
else
return 1 # No update needed
fi
}
# Generic package update function
update_package() {
local package_name="$1"
local github_url="$2"
local version_source_url="$3"
local version_regex="$4"
local install_cmd="$5"
local specific_tag="$6" # Optional: if provided, install this specific tag
log_message "Checking $package_name installation..."
# If specific tag is provided, use tag-based installation
if [ -n "$specific_tag" ]; then
install_package_by_tag "$package_name" "$github_url" "$specific_tag"
return $?
fi
# Otherwise, use version-based update logic
if pip show "$package_name" &>/dev/null; then
log_message "$package_name is installed. Checking current version..."
# Get installed version
local installed_version=$(pip show "$package_name" | grep Version | awk '{print $2}')
log_message "Current $package_name version: $installed_version"
# Check if versions are actually different (only if specific tag is provided)
if [ -n "$specific_tag" ]; then
if [ "$installed_version" = "$specific_tag" ]; then
log_message "$package_name is already at the specified version ($installed_version). No update needed."
else
log_message "Version mismatch detected. Updating $package_name from $installed_version to $specific_tag..."
if pip uninstall "$package_name" -y && eval "$install_cmd"; then
log_message "$package_name updated to version $specific_tag."
else
log_error "Failed to update $package_name. Continuing with installation..."
fi
fi
else
log_message "No specific tag provided. Skipping version check for $package_name."
fi
else
log_message "Installing $package_name..."
if eval "$install_cmd"; then
log_message "$package_name installed successfully."
else
log_error "Failed to install $package_name. Continuing with installation..."
fi
fi
}
# Install package by specific tag
install_package_by_tag() {
local package_name="$1"
local github_url="$2"
local tag="$3"
log_message "Checking $package_name installation for tag: $tag"
# Check if package is already installed
if pip show "$package_name" &>/dev/null; then
local installed_version=$(pip show "$package_name" | grep Version | awk '{print $2}')
log_message "Current $package_name version: $installed_version"
# Try to get more detailed information about the installed package
local installed_location=$(pip show "$package_name" | grep Location | awk '{print $2}')
local is_git_install=false
local installed_git_ref=""
# Check if this is a git installation
if [ -d "$installed_location/$package_name/.git" ]; then
is_git_install=true
# Try to get the git reference (tag/branch/commit)
if [ -f "$installed_location/$package_name/.git/HEAD" ]; then
installed_git_ref=$(cat "$installed_location/$package_name/.git/HEAD" 2>/dev/null | sed 's|refs/heads/||' | sed 's|refs/tags/||')
fi
fi
# Check for tag mismatch
local needs_update=false
local mismatch_reason=""
if [ "$is_git_install" = true ] && [ -n "$installed_git_ref" ]; then
# For git installations, compare the git reference
if [ "$installed_git_ref" != "$tag" ]; then
needs_update=true
mismatch_reason="Git reference mismatch: installed=$installed_git_ref, desired=$tag"
fi
else
# For non-git installations or when we can't determine git ref, compare version
if [ "$installed_version" != "$tag" ]; then
needs_update=true
mismatch_reason="Version mismatch: installed=$installed_version, desired=$tag"
fi
fi
if [ "$needs_update" = true ]; then
log_message "Tag mismatch detected: $mismatch_reason"
log_message "Updating $package_name to tag $tag..."
pip uninstall "$package_name" -y || {
log_error "Failed to uninstall $package_name"
return 1
}
else
log_message "$package_name is already installed with the correct tag ($tag). No update needed."
return 0
fi
else
log_message "$package_name not found. Installing from tag $tag..."
fi
# Install from specific tag
local install_cmd="pip install git+${github_url}@v${tag}"
log_message "Installing with command: $install_cmd"
if eval "$install_cmd"; then
log_message "$package_name installed successfully from tag $tag."
return 0
else
log_error "Failed to install $package_name from tag $tag."
return 1
fi
}
# List available tags for a GitHub repository
list_available_tags() {
local repo_url="$1"
local package_name="$2"
log_message "Fetching available tags for $package_name..."
# Extract owner/repo from GitHub URL
local repo_path=$(echo "$repo_url" | sed 's|https://github.com/||' | sed 's|\.git$||')
# Use GitHub API to get tags
local api_url="https://api.github.com/repos/$repo_path/tags"
local temp_file=$(mktemp)
if curl -s --connect-timeout 10 --max-time 30 "$api_url" > "$temp_file" 2>/dev/null; then
local tags=$(cat "$temp_file" | grep '"name"' | cut -d'"' -f4 | head -10)
rm -f "$temp_file"
if [ -n "$tags" ]; then
log_message "Available tags for $package_name (showing latest 10):"
echo "$tags" | while read -r tag; do
echo " - $tag"
done
else
log_message "No tags found for $package_name"
fi
else
rm -f "$temp_file"
log_error "Failed to fetch tags for $package_name"
fi
}
# Show detailed installation status for a package
show_package_status() {
local package_name="$1"
local desired_tag="$2"
log_message "Checking status of $package_name..."
if pip show "$package_name" &>/dev/null; then
local installed_version=$(pip show "$package_name" | grep Version | awk '{print $2}')
local installed_location=$(pip show "$package_name" | grep Location | awk '{print $2}')
log_message " ✓ $package_name is installed"
log_message " Version: $installed_version"
log_message " Location: $installed_location"
# Check if it's a git installation
if [ -d "$installed_location/$package_name/.git" ]; then
local git_ref=""
if [ -f "$installed_location/$package_name/.git/HEAD" ]; then
git_ref=$(cat "$installed_location/$package_name/.git/HEAD" 2>/dev/null | sed 's|refs/heads/||' | sed 's|refs/tags/||')
fi
log_message " Git reference: $git_ref"
if [ -n "$desired_tag" ]; then
if [ "$git_ref" = "$desired_tag" ]; then
log_message " ✓ Tag match: Installed tag matches desired tag ($desired_tag)"
else
log_message " ✗ Tag mismatch: Installed tag ($git_ref) != desired tag ($desired_tag)"
fi
fi
else
log_message " Installation type: Standard pip package"
if [ -n "$desired_tag" ]; then
if [ "$installed_version" = "$desired_tag" ]; then
log_message " ✓ Version match: Installed version matches desired tag ($desired_tag)"
else
log_message " ✗ Version mismatch: Installed version ($installed_version) != desired tag ($desired_tag)"
fi
fi
fi
else
log_message " ✗ $package_name is not installed"
if [ -n "$desired_tag" ]; then
log_message " Will install from tag: $desired_tag"
else
log_message " Will install latest version"
fi
fi
}
# Install mlx-openai-server using pip with specific version
install_mlx_openai_server_pip() {
local version="$1"
local package_name="mlx-openai-server"
log_message "Checking $package_name installation..."
if [ -n "$version" ]; then
log_message "Will install $package_name version: $version"
# Check if already installed with the correct version
if pip show "$package_name" &>/dev/null; then
local installed_version=$(pip show "$package_name" | grep Version | awk '{print $2}')
log_message "Current $package_name version: $installed_version"
if [ "$installed_version" = "$version" ]; then
log_message "$package_name is already installed with the correct version ($version). No update needed."
return 0
else
log_message "Version mismatch detected. Updating $package_name from $installed_version to $version..."
pip uninstall "$package_name" -y || {
log_error "Failed to uninstall $package_name"
return 1
}
fi
fi
# Install specific version
local install_cmd="pip install ${package_name}==${version}"
log_message "Installing with command: $install_cmd"
if eval "$install_cmd"; then
log_message "$package_name installed successfully with version $version."
return 0
else
log_error "Failed to install $package_name version $version."
return 1
fi
else
log_message "No version specified for $package_name. Installing latest version..."
# Check if already installed
if pip show "$package_name" &>/dev/null; then
local installed_version=$(pip show "$package_name" | grep Version | awk '{print $2}')
log_message "Current $package_name version: $installed_version"
log_message "$package_name is already installed. No update needed."
return 0
fi
# Install latest version
local install_cmd="pip install ${package_name}"
log_message "Installing with command: $install_cmd"
if eval "$install_cmd"; then
log_message "$package_name installed successfully with latest version."
return 0
else
log_error "Failed to install $package_name."
return 1
fi
fi
}
# Configuration section for package versions
#
# USAGE:
# 1. Edit the variables below to specify exact tags/versions
# 2. Or set environment variables before running the script:
# export MLX_FLUX_TAG="v1.0.0"
# export ETERNAL_ZOO_TAG="v0.1.0"
# ./mac.sh
# 3. Or modify the script to call list_available_tags() to see available versions
#
# Examples:
# MLX_FLUX_TAG="v1.0.0" # Install specific version
# MLX_FLUX_TAG="" # Install latest version (default)
# MLX_FLUX_TAG="main" # Install from main branch
# MLX_FLUX_TAG="feature-xyz" # Install from specific branch
# Use environment variable if set, otherwise use default (empty means latest)
: "${MLX_FLUX_TAG:=}" # Leave empty for latest, or set specific tag
: "${MLX_OPENAI_SERVER_TAG:=}" # Leave empty for latest, or set specific tag
: "${ETERNAL_ZOO_TAG:=}" # Leave empty for latest, or set specific tag
# Uncomment the lines below to see available tags before installation
# list_available_tags "https://github.com/0x9334/mlx-flux.git" "mlx-flux"
# list_available_tags "https://github.com/eternalai-org/eternal-zoo.git" "eternal-zoo"
# Display current configuration
if [ -n "$MLX_FLUX_TAG" ]; then
log_message "Will install mlx-flux from tag: $MLX_FLUX_TAG"
else
log_message "Will install mlx-flux from latest version"
fi
if [ -n "$ETERNAL_ZOO_TAG" ]; then
log_message "Will install eternal-zoo from tag: $ETERNAL_ZOO_TAG"
else
log_message "Will install eternal-zoo from latest version"
fi
if [ -n "$MLX_OPENAI_SERVER_TAG" ]; then
log_message "Will install mlx-openai-server version: $MLX_OPENAI_SERVER_TAG"
else
log_message "Will install mlx-openai-server from latest version"
fi
# Show current installation status
log_message "Current installation status:"
show_package_status "mlx-flux" "$MLX_FLUX_TAG"
show_package_status "mlx-openai-server" "$MLX_OPENAI_SERVER_TAG"
show_package_status "eternal-zoo" "$ETERNAL_ZOO_TAG"
# Error handling function
handle_error() {
local exit_code=$1
local error_msg=$2
log_error "$error_msg (Exit code: $exit_code)"
# Clean up if needed
if [[ -n "$VIRTUAL_ENV" ]]; then
log_message "Deactivating virtual environment..."
deactivate 2>/dev/null || true
fi
exit $exit_code
}
command_exists() {
command -v "$1" &> /dev/null
}
export PATH="/opt/homebrew/bin/:$PATH"
export PATH="$HOME/homebrew/bin:$PATH"
# Step 1: Ensure Homebrew is installed and set PATH
if ! command_exists brew; then
log_error "Homebrew is not installed. Please install Homebrew first: https://brew.sh/"
exit 1
fi
BREW_PREFIX=$(brew --prefix)
export PATH="$BREW_PREFIX/bin:$PATH"
log_message "Homebrew found at $BREW_PREFIX. PATH updated for this session."
# Step 2: Install Python 3.11
if brew list python@3.11 >/dev/null 2>&1; then
PYTHON_CMD=$(brew --prefix python@3.11)/bin/python3.11
else
brew install python@3.11
PYTHON_CMD=$(brew --prefix python@3.11)/bin/python3.11
fi
log_message "Using Python at: $PYTHON_CMD"
# Step 3: Update PATH in .zshrc for future sessions
log_message "Checking if PATH update is needed in .zshrc..."
if ! grep -q "export PATH=\"/usr/local/bin:\$PATH\"" ~/.zshrc 2>/dev/null; then
if [ -f ~/.zshrc ]; then
log_message "Backing up current .zshrc..."
cp ~/.zshrc ~/.zshrc.backup.$(date +%Y%m%d%H%M%S) || handle_error $? "Failed to backup .zshrc"
else
log_message "No existing .zshrc found. Skipping backup."
fi
log_message "Updating PATH in .zshrc for brew at /usr/local/bin..."
echo "export PATH=\"/usr/local/bin:\$PATH\"" >> ~/.zshrc || handle_error $? "Failed to update .zshrc"
log_message "Please restart your terminal or run 'source ~/.zshrc' for future sessions."
else
log_message "PATH already updated in .zshrc."
fi
# Step 4: Install pigz
log_message "Checking for pigz installation..."
if command_exists pigz; then
log_message "pigz is already installed."
else
log_message "Installing pigz..."
brew install pigz || handle_error $? "Failed to install pigz"
log_message "pigz installed successfully."
fi
#Step 5: Install llama.cpp
log_message "Checking llama.cpp version..."
brew install llama.cpp || handle_error $? "Failed to install llama.cpp"
# Step 6: Create and activate virtual environment
VENV_PATH=".eternal-zoo"
log_message "Checking if virtual environment exists..."
if [ -d "$VENV_PATH" ]; then
# Determine Python version used by the existing venv
if [ -x "$VENV_PATH/bin/python3" ]; then
VENV_PYTHON="$VENV_PATH/bin/python3"
elif [ -x "$VENV_PATH/bin/python" ]; then
VENV_PYTHON="$VENV_PATH/bin/python"
else
VENV_PYTHON=""
fi
if [ -n "$VENV_PYTHON" ]; then
VENV_PY_VERSION=$("$VENV_PYTHON" -c 'import sys; print(".".join(map(str, sys.version_info[:2])))' 2>/dev/null || echo "unknown")
if [ "$VENV_PY_VERSION" != "3.11" ]; then
log_message "Existing virtual environment uses Python $VENV_PY_VERSION. Removing..."
rm -rf "$VENV_PATH"
else
log_message "Existing virtual environment uses Python 3.11. Keeping it."
fi
else
log_message "Existing virtual environment has no valid Python executable. Removing..."
rm -rf "$VENV_PATH"
fi
fi
# Create venv only if it does not exist (or was removed above)
if [ ! -d "$VENV_PATH" ]; then
log_message "Creating virtual environment 'eternal-zoo'..."
"$PYTHON_CMD" -m venv "$VENV_PATH" || handle_error $? "Failed to create virtual environment"
fi
log_message "Activating virtual environment..."
source "$VENV_PATH/bin/activate" || handle_error $? "Failed to activate virtual environment"
log_message "Virtual environment activated."
# Step 7: Install mlx-openai-server dependencies
if install_mlx_openai_server_pip "$MLX_OPENAI_SERVER_TAG"; then
log_message "mlx-openai-server installation completed successfully."
else
log_error "mlx-openai-server installation failed. This may happen on Intel Macs or due to compatibility issues. Continuing with installation..."
fi
# Step 8: Install eternal-zoo toolkit
update_package "eternal-zoo" "https://github.com/eternalai-org/eternal-zoo.git" "https://raw.githubusercontent.com/eternalai-org/eternal-zoo/main/eternal_zoo/__init__.py" "__version__ = \"[0-9.]*\"" "pip install git+https://github.com/eternalai-org/eternal-zoo.git" "$ETERNAL_ZOO_TAG"
log_message "Setup completed successfully."
log_message "Setup completed successfully."