-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathwebui.py
289 lines (228 loc) · 13.1 KB
/
webui.py
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
import argparse
import glob
import re
import os
import site
import subprocess
import sys
script_dir = os.getcwd()
conda_env_path = os.path.join(script_dir, "installer_files", "env")
# Use this to set your command-line flags. For the full list, see:
# https://github.com/oobabooga/text-generation-webui/#starting-the-web-ui
# Example: CMD_FLAGS = '--chat --listen'
CMD_FLAGS = ''
if os.path.exists("CMD_FLAGS.txt"):
with open('CMD_FLAGS.txt', 'r') as file:
CMD_FLAGS = file.read()
# Allows users to set flags in "OOBABOOGA_FLAGS" environment variable
if "OOBABOOGA_FLAGS" in os.environ:
CMD_FLAGS = os.environ["OOBABOOGA_FLAGS"]
print("The following flags have been taken from the environment variable 'OOBABOOGA_FLAGS':")
print(CMD_FLAGS)
print("To use the CMD_FLAGS Inside webui.py, unset 'OOBABOOGA_FLAGS'.\n")
def print_big_message(message):
message = message.strip()
lines = message.split('\n')
print("\n\n*******************************************************************")
for line in lines:
if line.strip() != '':
print("*", line)
print("*******************************************************************\n\n")
def run_cmd(cmd, assert_success=False, environment=False, capture_output=False, env=None):
# Use the conda environment
if environment:
if sys.platform.startswith("win"):
conda_bat_path = os.path.join(script_dir, "installer_files", "conda", "condabin", "conda.bat")
cmd = "\"" + conda_bat_path + "\" activate \"" + conda_env_path + "\" >nul && " + cmd
else:
conda_sh_path = os.path.join(script_dir, "installer_files", "conda", "etc", "profile.d", "conda.sh")
cmd = ". \"" + conda_sh_path + "\" && conda activate \"" + conda_env_path + "\" && " + cmd
# Run shell commands
result = subprocess.run(cmd, shell=True, capture_output=capture_output, env=env)
# Assert the command ran successfully
if assert_success and result.returncode != 0:
print("Command '" + cmd + "' failed with exit status code '" + str(result.returncode) + "'. Exiting...")
sys.exit()
return result
def check_env():
# If we have access to conda, we are probably in an environment
conda_exist = run_cmd("conda", environment=True, capture_output=True).returncode == 0
if not conda_exist:
print("Conda is not installed. Exiting...")
sys.exit()
# Ensure this is a new environment and not the base environment
if os.environ["CONDA_DEFAULT_ENV"] == "base":
print("Create an environment for this project and activate it. Exiting...")
sys.exit()
def install_dependencies():
# Select your GPU or, choose to run in CPU mode
print("What is your GPU")
print()
print("A) NVIDIA")
print("B) AMD")
print("C) Apple M Series")
print("D) None (I want to run in CPU mode)")
print()
gpuchoice = input("Input> ").lower()
if gpuchoice == "d":
print_big_message("Once the installation ends, make sure to open webui.py with a text editor\nand add the --cpu flag to CMD_FLAGS.")
# Install the version of PyTorch needed
if gpuchoice == "a":
run_cmd('conda install -y -k cuda ninja git -c nvidia/label/cuda-11.7.0 -c nvidia && python -m pip install torch==2.0.1+cu117 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117', assert_success=True, environment=True)
elif gpuchoice == "b":
print("AMD GPUs are not supported. Exiting...")
sys.exit()
elif gpuchoice == "c":
run_cmd("conda install -y -k ninja git && python -m pip install torch torchvision torchaudio", assert_success=True, environment=True)
run_cmd("python -m pip install --upgrade --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cpu")
elif gpuchoice == "d":
if sys.platform.startswith("linux"):
run_cmd("conda install -y -k ninja git && python -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu", assert_success=True, environment=True)
else:
run_cmd("conda install -y -k ninja git && python -m pip install torch torchvision torchaudio", assert_success=True, environment=True)
else:
print("Invalid choice. Exiting...")
sys.exit()
# Clone webui to our computer
run_cmd("git clone https://github.com/oobabooga/text-generation-webui.git", assert_success=True, environment=True)
# Install the webui dependencies
update_dependencies()
def update_dependencies():
os.chdir("text-generation-webui")
run_cmd("git pull", assert_success=True, environment=True)
# Workaround for git+ packages not updating properly Also store requirements.txt for later use
with open("requirements.txt") as f:
textgen_requirements = f.read()
git_requirements = [req for req in textgen_requirements.splitlines() if req.startswith("git+")]
# Loop through each "git+" requirement and uninstall it
for req in git_requirements:
# Extract the package name from the "git+" requirement
url = req.replace("git+", "")
package_name = url.split("/")[-1].split("@")[0]
# Uninstall the package using pip
run_cmd("python -m pip uninstall -y " + package_name, environment=True)
print(f"Uninstalled {package_name}")
# Installs/Updates dependencies from all requirements.txt
run_cmd("python -m pip install -r requirements.txt --upgrade", assert_success=True, environment=True)
extensions = next(os.walk("extensions"))[1]
for extension in extensions:
if extension in ['superbooga']: # No wheels available for dependencies
continue
extension_req_path = os.path.join("extensions", extension, "requirements.txt")
if os.path.exists(extension_req_path):
run_cmd("python -m pip install -r " + extension_req_path + " --upgrade", assert_success=True, environment=True)
# Latest bitsandbytes requires minimum compute 7.0
# nvcc_device_query = "__nvcc_device_query" if not sys.platform.startswith("win") else "__nvcc_device_query.exe"
# min_compute = 70
# compute_array = run_cmd(os.path.join(conda_env_path, "bin", nvcc_device_query), environment=True, capture_output=True)
# old_bnb = "bitsandbytes==0.38.1" if not sys.platform.startswith("win") else "https://github.com/jllllll/bitsandbytes-windows-webui/raw/main/bitsandbytes-0.38.1-py3-none-any.whl"
# if compute_array.returncode == 0 and not any(int(compute) >= min_compute for compute in compute_array.stdout.decode('utf-8').split(',')):
# old_bnb_install = run_cmd(f"python -m pip install {old_bnb} --force-reinstall --no-deps", environment=True).returncode == 0
# message = "\n\nWARNING: GPU with compute < 7.0 detected!\n"
# if old_bnb_install:
# message += "Older version of bitsandbytes has been installed to maintain compatibility.\n"
# message += "You will be unable to use --load-in-4bit!\n"
# else:
# message += "You will be unable to use --load-in-8bit until you install bitsandbytes 0.38.1!\n"
# print_big_message(message)
# The following dependencies are for CUDA, not CPU
# Parse output of 'pip show torch' to determine torch version
torver_cmd = run_cmd("python -m pip show torch", assert_success=True, environment=True, capture_output=True)
torver = [v.split()[1] for v in torver_cmd.stdout.decode('utf-8').splitlines() if 'Version:' in v][0]
# Check for '+cu' in version string to determine if torch uses CUDA or not check for pytorch-cuda as well for backwards compatibility
if '+cu' not in torver and run_cmd("conda list -f pytorch-cuda | grep pytorch-cuda", environment=True, capture_output=True).returncode == 1:
return
# Install llama-cpp-python built with cuBLAS support for NVIDIA GPU acceleration
if '+cu' in torver:
llama_cpp = re.search('(?<=llama-cpp-python==)\d+(?:\.\d+)*', textgen_requirements)
if llama_cpp is not None:
run_cmd(f'python -m pip install llama-cpp-python=={llama_cpp[0]} --force-reinstall --no-deps --index-url=https://jllllll.github.io/llama-cpp-python-cuBLAS-wheels/AVX2/cu117', environment=True)
# Finds the path to your dependencies
for sitedir in site.getsitepackages():
if "site-packages" in sitedir:
site_packages_path = sitedir
break
# This path is critical to installing the following dependencies
if site_packages_path is None:
print("Could not find the path to your Python packages. Exiting...")
sys.exit()
# Fix a bitsandbytes compatibility issue with Linux
# if sys.platform.startswith("linux"):
# shutil.copy(os.path.join(site_packages_path, "bitsandbytes", "libbitsandbytes_cuda117.so"), os.path.join(site_packages_path, "bitsandbytes", "libbitsandbytes_cpu.so"))
if not os.path.exists("repositories/"):
os.mkdir("repositories")
os.chdir("repositories")
# Install or update exllama as needed
if not os.path.exists("exllama/"):
run_cmd("git clone https://github.com/turboderp/exllama.git", environment=True)
else:
os.chdir("exllama")
run_cmd("git pull", environment=True)
os.chdir("..")
# Fix build issue with exllama in Linux/WSL
if sys.platform.startswith("linux") and not os.path.exists(f"{conda_env_path}/lib64"):
run_cmd(f'ln -s "{conda_env_path}/lib" "{conda_env_path}/lib64"', environment=True)
# Install GPTQ-for-LLaMa which enables 4bit CUDA quantization
if not os.path.exists("GPTQ-for-LLaMa/"):
run_cmd("git clone https://github.com/oobabooga/GPTQ-for-LLaMa.git -b cuda", assert_success=True, environment=True)
# Install GPTQ-for-LLaMa dependencies
os.chdir("GPTQ-for-LLaMa")
run_cmd("git pull", assert_success=True, environment=True)
# On some Linux distributions, g++ may not exist or be the wrong version to compile GPTQ-for-LLaMa
if sys.platform.startswith("linux"):
gxx_output = run_cmd("g++ -dumpfullversion -dumpversion", environment=True, capture_output=True)
if gxx_output.returncode != 0 or int(gxx_output.stdout.strip().split(b".")[0]) > 11:
# Install the correct version of g++
run_cmd("conda install -y -k gxx_linux-64=11.2.0", environment=True)
# Compile and install GPTQ-for-LLaMa
if os.path.exists('setup_cuda.py'):
os.rename("setup_cuda.py", "setup.py")
run_cmd("python -m pip install .", environment=True)
# Wheel installation can fail while in the build directory of a package with the same name
os.chdir("..")
# If the path does not exist, then the install failed
quant_cuda_path_regex = os.path.join(site_packages_path, "quant_cuda*/")
if not glob.glob(quant_cuda_path_regex):
# Attempt installation via alternative, Windows/Linux-specific method
if sys.platform.startswith("win") or sys.platform.startswith("linux"):
print_big_message("WARNING: GPTQ-for-LLaMa compilation failed, but this is FINE and can be ignored!\nThe installer will proceed to install a pre-compiled wheel.")
url = "https://github.com/jllllll/GPTQ-for-LLaMa-Wheels/raw/main/quant_cuda-0.0.0-cp310-cp310-win_amd64.whl"
if sys.platform.startswith("linux"):
url = "https://github.com/jllllll/GPTQ-for-LLaMa-Wheels/raw/Linux-x64/quant_cuda-0.0.0-cp310-cp310-linux_x86_64.whl"
result = run_cmd("python -m pip install " + url, environment=True)
if result.returncode == 0:
print("Wheel installation success!")
else:
print("ERROR: GPTQ wheel installation failed. You will not be able to use GPTQ-based models.")
else:
print("ERROR: GPTQ CUDA kernel compilation failed.")
print("You will not be able to use GPTQ-based models.")
print("Continuing with install..")
def download_model():
os.chdir("text-generation-webui")
run_cmd("python download-model.py", environment=True)
def launch_webui():
os.chdir("text-generation-webui")
run_cmd(f"python server.py {CMD_FLAGS}", environment=True)
if __name__ == "__main__":
# Verifies we are in a conda environment
check_env()
parser = argparse.ArgumentParser()
parser.add_argument('--update', action='store_true', help='Update the web UI.')
args = parser.parse_args()
if args.update:
update_dependencies()
else:
# If webui has already been installed, skip and run
if not os.path.exists("text-generation-webui/"):
install_dependencies()
os.chdir(script_dir)
# Check if a model has been downloaded yet
if len([item for item in glob.glob('text-generation-webui/models/*') if not item.endswith(('.txt', '.yaml'))]) == 0:
print_big_message("WARNING: You haven't downloaded any model yet.\nOnce the web UI launches, head over to the bottom of the \"Model\" tab and download one.")
# Workaround for llama-cpp-python loading paths in CUDA env vars even if they do not exist
conda_path_bin = os.path.join(conda_env_path, "bin")
if not os.path.exists(conda_path_bin):
os.mkdir(conda_path_bin)
# Launch the webui
launch_webui()