Fix GGUF export cwd confusion: remove os.chdir, use absolute paths

Remove os.chdir(save_directory) from export.py which was causing all of
unsloth-zoo's relative-path internals (check_llama_cpp, use_local_gguf,
_download_convert_hf_to_gguf) to resolve against the export directory
instead of the repo root. This caused llama.cpp to be cloned inside each
export dir and destroyed the repo root's llama-server build on cleanup.

Now passes absolute paths to save_pretrained_gguf so unsloth resolves
llama.cpp from the repo root where setup.sh already built it.

Also builds llama-quantize in setup.sh (needed by unsloth-zoo's export
pipeline) and symlinks it to llama.cpp root for check_llama_cpp().
This commit is contained in:
Roland Tannous 2026-02-25 03:30:54 +04:00
commit 7adb69581e
2 changed files with 38 additions and 44 deletions

View file

@ -206,10 +206,11 @@ else
fi
fi
# ── 8. Build llama-server for GGUF inference ──
# ── 8. Build llama.cpp binaries for GGUF inference + export ──
# Builds in-tree at $REPO/llama.cpp/. This directory is shared with
# unsloth-zoo's GGUF export pipeline — if converter/quantize are missing,
# unsloth-zoo will rebuild them on first export. We only build llama-server here.
# unsloth-zoo's GGUF export pipeline. We build:
# - llama-server: for GGUF model inference
# - llama-quantize: for GGUF export quantization (symlinked to root for check_llama_cpp())
LLAMA_SERVER_BIN="$SCRIPT_DIR/llama.cpp/build/bin/llama-server"
if [ -f "$LLAMA_SERVER_BIN" ]; then
echo ""
@ -272,12 +273,25 @@ else
run_quiet "build llama-server" cmake --build "$LLAMA_CPP_DIR/build" --config Release --target llama-server -j"$NCPU" || BUILD_OK=false
fi
# Also build llama-quantize (needed by unsloth-zoo's GGUF export pipeline)
if [ "$BUILD_OK" = true ]; then
run_quiet "build llama-quantize" cmake --build "$LLAMA_CPP_DIR/build" --config Release --target llama-quantize -j"$NCPU" || true
# Symlink to llama.cpp root — check_llama_cpp() looks for the binary there
QUANTIZE_BIN="$LLAMA_CPP_DIR/build/bin/llama-quantize"
if [ -f "$QUANTIZE_BIN" ]; then
ln -sf build/bin/llama-quantize "$LLAMA_CPP_DIR/llama-quantize"
fi
fi
if [ "$BUILD_OK" = true ]; then
if [ -f "$LLAMA_SERVER_BIN" ]; then
echo "✅ llama-server built at $LLAMA_SERVER_BIN"
else
echo "⚠️ llama-server binary not found after build — GGUF inference won't be available"
fi
if [ -f "$LLAMA_CPP_DIR/llama-quantize" ]; then
echo "✅ llama-quantize available for GGUF export"
fi
else
echo "⚠️ llama-server build failed — GGUF inference won't be available, but everything else works"
fi

View file

@ -378,53 +378,33 @@ class ExportBackend:
# Save locally if requested
if save_directory:
logger.info(f"Saving GGUF model locally to: {save_directory}")
# Resolve to absolute path so unsloth's relative-path internals
# (check_llama_cpp, use_local_gguf, _download_convert_hf_to_gguf)
# all resolve against the repo root cwd, NOT the export directory.
abs_save_dir = os.path.abspath(save_directory)
logger.info(f"Saving GGUF model locally to: {abs_save_dir}")
# Create the directory if it doesn't exist
os.makedirs(save_directory, exist_ok=True)
os.makedirs(abs_save_dir, exist_ok=True)
# Get the base filename for the GGUF file
import shutil
original_dir = os.getcwd()
# On WSL, patch out sudo check before llama.cpp build
_apply_wsl_sudo_patch()
try:
# Change to target directory
os.chdir(save_directory)
logger.info(f"Changed directory to: {save_directory}")
# Enable verbose logging so subprocess errors are printed
os.environ["UNSLOTH_ENABLE_LOGGING"] = "1"
# On WSL, patch out sudo check before llama.cpp build
_apply_wsl_sudo_patch()
# Pass absolute path — no os.chdir needed.
# unsloth saves model files into this directory, while
# check_llama_cpp("llama.cpp") resolves against cwd (repo root)
# where setup.sh already built llama.cpp with quantizer.
model_save_path = os.path.join(abs_save_dir, "model")
self.current_model.save_pretrained_gguf(
model_save_path,
self.current_tokenizer,
quantization_method=quant_method
)
# Now save (will save in current directory)
self.current_model.save_pretrained_gguf(
"model", # Base filename
self.current_tokenizer,
quantization_method=quant_method
)
logger.info(f"GGUF model saved successfully in {save_directory}")
# Check if llama.cpp directory was created here
llama_cpp_in_target = os.path.join(save_directory, "llama.cpp")
llama_cpp_in_original = os.path.join(original_dir, "llama.cpp")
if os.path.exists(llama_cpp_in_target):
logger.info(f"Found llama.cpp directory in {save_directory}")
# Remove llama.cpp from original directory if it exists
if os.path.exists(llama_cpp_in_original):
logger.info(f"Removing existing llama.cpp in {original_dir}")
shutil.rmtree(llama_cpp_in_original)
# Move llama.cpp back to original directory
logger.info(f"Moving llama.cpp to {original_dir}")
shutil.move(llama_cpp_in_target, llama_cpp_in_original)
logger.info(f"Successfully moved llama.cpp back to original directory")
finally:
# Always change back to original directory
os.chdir(original_dir)
logger.info(f"Changed back to original directory: {original_dir}")
logger.info(f"GGUF model saved successfully in {abs_save_dir}")
# Push to hub if requested
if push_to_hub: