char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Vedran Miletićscripts : make the shell scripts cross-platform (#14341)e9b6350e6

char/aliceai-t5-moe
4.3 KiB179 linesraw
1#!/usr/bin/env bash
2set -euo pipefail
3
4#
5# check-requirements.sh checks all requirements files for each top-level
6# convert*.py script.
7#
8# WARNING: This is quite IO intensive, because a fresh venv is set up for every
9# python script. As of 2023-12-22, this writes ~2.7GB of data. An adequately
10# sized tmpfs /tmp or ramdisk is recommended if running this frequently.
11#
12# usage:    check-requirements.sh [<working_dir>]
13#           check-requirements.sh nocleanup [<working_dir>]
14#
15# where:
16#           - <working_dir> is a directory that can be used as the base for
17#               setting up the venvs. Defaults to `/tmp`.
18#           - 'nocleanup' as the first argument will disable automatic cleanup
19#               of the files created by this script.
20#
21# requires:
22#           - bash >= 3.2.57
23#           - shellcheck
24#
25# For each script, it creates a fresh venv, `pip install`s the requirements, and
26# finally imports the python script to check for `ImportError`.
27#
28
29log() {
30    local level=$1 msg=$2
31    printf >&2 '%s: %s\n' "$level" "$msg"
32}
33
34debug() {
35    log DEBUG "$@"
36}
37
38info() {
39    log INFO "$@"
40}
41
42fatal() {
43    log FATAL "$@"
44    exit 1
45}
46
47cleanup() {
48    if [[ -n ${workdir+x} && -d $workdir && -w $workdir ]]; then
49        info "Removing $workdir"
50        local count=0
51        rm -rfv -- "$workdir" | while read -r; do
52            if (( count++ > 750 )); then
53                printf .
54                count=0
55            fi
56        done
57        printf '\n'
58        info "Removed $workdir"
59    fi
60}
61
62do_cleanup=1
63if [[ ${1-} == nocleanup ]]; then
64    do_cleanup=0; shift
65fi
66
67if (( do_cleanup )); then
68    trap exit INT TERM
69    trap cleanup EXIT
70fi
71
72this=$(realpath -- "$0"); readonly this
73cd "$(dirname "$this")/.." # PWD should stay in llama.cpp project directory
74
75shellcheck "$this"
76
77readonly reqs_dir=requirements
78
79if [[ ${1+x} ]]; then
80    tmp_dir=$(realpath -- "$1")
81    if [[ ! ( -d $tmp_dir && -w $tmp_dir ) ]]; then
82        fatal "$tmp_dir is not a writable directory"
83    fi
84else
85    tmp_dir=/tmp
86fi
87
88workdir=$(mktemp -d "$tmp_dir/check-requirements.XXXX"); readonly workdir
89info "Working directory: $workdir"
90
91check_requirements() {
92    local reqs=$1
93
94    info "$reqs: beginning check"
95    pip --disable-pip-version-check install -qr "$reqs"
96    info "$reqs: OK"
97}
98
99check_convert_script() {
100    local py=$1             # e.g. ./convert_hf_to_gguf.py
101    local pyname=${py##*/}  # e.g. convert_hf_to_gguf.py
102    pyname=${pyname%.py}    # e.g. convert_hf_to_gguf
103
104    info "$py: beginning check"
105
106    local reqs="$reqs_dir/requirements-$pyname.txt"
107    if [[ ! -r $reqs ]]; then
108        fatal "$py missing requirements. Expected: $reqs"
109    fi
110
111    # Check that all sub-requirements are added to top-level requirements.txt
112    if ! grep -qF "$reqs" requirements.txt; then
113        fatal "$reqs needs to be added to requirements.txt"
114    fi
115
116    local venv="$workdir/$pyname-venv"
117    python3 -m venv "$venv"
118
119    (
120        # shellcheck source=/dev/null
121        source "$venv/bin/activate"
122
123        check_requirements "$reqs"
124
125        python - "$py" "$pyname" <<'EOF'
126import sys
127from importlib.machinery import SourceFileLoader
128py, pyname = sys.argv[1:]
129SourceFileLoader(pyname, py).load_module()
130EOF
131    )
132
133    if (( do_cleanup )); then
134        rm -rf -- "$venv"
135    fi
136
137    info "$py: imports OK"
138}
139
140readonly ignore_eq_eq='check_requirements: ignore "=="'
141
142for req in */**/requirements*.txt; do
143    # Make sure exact release versions aren't being pinned in the requirements
144    # Filters out the ignore string
145    if grep -vF "$ignore_eq_eq" "$req" | grep -q '=='; then
146        tab=$'\t'
147        cat >&2 <<EOF
148FATAL: Avoid pinning exact package versions. Use '~=' instead.
149You can suppress this error by appending the following to the line:
150$tab# $ignore_eq_eq
151EOF
152        exit 1
153    fi
154done
155
156all_venv="$workdir/all-venv"
157python3 -m venv "$all_venv"
158
159(
160    # shellcheck source=/dev/null
161    source "$all_venv/bin/activate"
162    check_requirements requirements.txt
163)
164
165if (( do_cleanup )); then
166    rm -rf -- "$all_venv"
167fi
168
169check_convert_script examples/convert_legacy_llama.py
170for py in convert_*.py; do
171    # skip convert_hf_to_gguf_update.py
172    # TODO: the check is failing for some reason:
173    #       https://github.com/ggml-org/llama.cpp/actions/runs/8875330981/job/24364557177?pr=6920
174    [[ $py == convert_hf_to_gguf_update.py ]] && continue
175
176    check_convert_script "$py"
177done
178
179info 'Done! No issues found.'