Skip to content

Instantly share code, notes, and snippets.

@maziyarpanahi
Forked from crasm/gguf-merge.sh
Created February 2, 2024 08:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maziyarpanahi/84ad5eae130117b86b2e295876f589c7 to your computer and use it in GitHub Desktop.
Save maziyarpanahi/84ad5eae130117b86b2e295876f589c7 to your computer and use it in GitHub Desktop.
Shell script for merging TheBloke's .gguf-split model files
#!/bin/sh
log() {
format="$1"; shift
# shellcheck disable=SC2059
>&2 printf "$format\n" "$@"
}
usage() {
>&2 cat <<EOF
usage: $(basename "$0") [-d] <model-prefix>
options:
-d (delete split files during merge, saves space)
example:
$ $(basename "$0") airoboros-l2-70b-2.1-creative.Q8_0.gguf-split-
Merging:
airoboros-l2-70b-2.1-creative.Q8_0.gguf-split-a
airoboros-l2-70b-2.1-creative.Q8_0.gguf-split-b
Into:
airoboros-l2-70b-2.1-creative.Q8_0.gguf
...
EOF
exit 1
}
# This is called by an interrupt
# shellcheck disable=SC2317
cleanup() {
if [ -n "$1" ]; then
log "$@"
else
log 'Interrupted...'
fi
if [ -w "$split_a" ] && [ -n "$split_a_size" ]; then
log 'Truncating "%s" to original size: %s bytes\n' "$split_a" "$split_a_size"
truncate -c -s "$split_a_size" "$split_a"
fi
exit 1
}
opt_delete=
while getopts 'd' opt; do
case $opt in
'd')
opt_delete='true'
shift
;;
'?')
log 'Invalid option: %s' "-$OPTARG"
usage
esac
done
if [ "$#" -ne 1 ]; then
usage
fi
model="$1"
# Load file glob into arg array
set -- "${model}"*
# Check if the glob failed to expand
if [ "$1" = "${model}*" ]; then
log 'No files found.'
exit 1
fi
split_a="$1"
split_a_size="$(stat -c '%s' "$split_a")"
target="$(echo "$split_a" | sed 's/-split-a$//')"
log 'Merging:'
log '\t%s' "$@"
log 'Into:\n\t%s\n' "$target"
>&2 printf 'Continue? [Y/n] '
read -r response
case "$response" in
[Yy]|"") ;;
*)
log 'Exiting...'
exit 0
;;
esac
# Enable cleanup hook now, since we will begin operating on the files
trap cleanup INT
# Remove $1 (...-split-a) from arg array, which is the target for the appends
shift
for i in "$@"; do
log "Appending $i"
dd if="$i" of="$split_a" bs=32M oflag=append conv=notrunc status=progress || cleanup 'dd exited with error: %s' "$?"
if [ "$opt_delete" = 'true' ]; then
rm -vf "$i" || log 'failed to rm %s' "$i"
fi
done
mv -vf "$split_a" "$target"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment